summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim-Philipp Müller <tim.muller@collabora.co.uk>2011-04-12 21:47:14 +0100
committerTim-Philipp Müller <tim.muller@collabora.co.uk>2011-04-13 18:24:37 +0100
commit6b4e797513de059617bdd59b9eb237b9a1579942 (patch)
treeaedd8f83fdfb56e5f888a549f2dc58c0fc5be748
parent5af34d15f3afaf9d53043fb0773851aa67e61d36 (diff)
downloadgstreamer-plugins-bad-6b4e797513de059617bdd59b9eb237b9a1579942.tar.gz
qtmux: remove qtmux plugin, it has moved to -good
https://bugzilla.gnome.org/show_bug.cgi?id=636699
-rw-r--r--Android.mk2
-rw-r--r--Makefile.am3
-rw-r--r--configure.ac2
-rw-r--r--docs/plugins/Makefile.am1
-rw-r--r--docs/plugins/gst-plugins-bad-plugins-docs.sgml2
-rw-r--r--docs/plugins/gst-plugins-bad-plugins-sections.txt14
-rw-r--r--docs/plugins/inspect/plugin-qtmux.xml157
-rw-r--r--gst-plugins-bad.spec.in2
-rw-r--r--gst/qtmux/Makefile.am45
-rw-r--r--gst/qtmux/atoms.c4423
-rw-r--r--gst/qtmux/atoms.h956
-rw-r--r--gst/qtmux/atomsrecovery.c1095
-rw-r--r--gst/qtmux/atomsrecovery.h159
-rw-r--r--gst/qtmux/descriptors.c458
-rw-r--r--gst/qtmux/descriptors.h151
-rw-r--r--gst/qtmux/fourcc.h243
-rw-r--r--gst/qtmux/ftypcc.h68
-rw-r--r--gst/qtmux/gstqtmoovrecover.c390
-rw-r--r--gst/qtmux/gstqtmoovrecover.h88
-rw-r--r--gst/qtmux/gstqtmux.c3498
-rw-r--r--gst/qtmux/gstqtmux.h228
-rw-r--r--gst/qtmux/gstqtmuxmap.c368
-rw-r--r--gst/qtmux/gstqtmuxmap.h83
-rw-r--r--gst/qtmux/gstqtmuxplugin.c67
-rw-r--r--gst/qtmux/properties.c210
-rw-r--r--gst/qtmux/properties.h87
-rw-r--r--tests/check/Makefile.am2
-rw-r--r--tests/check/elements/.gitignore1
-rw-r--r--tests/check/elements/qtmux.c422
-rw-r--r--tests/check/pipelines/tagschecking.c350
30 files changed, 3 insertions, 13572 deletions
diff --git a/Android.mk b/Android.mk
index 35e93755b..c3a5ff346 100644
--- a/Android.mk
+++ b/Android.mk
@@ -10,7 +10,6 @@ GST_PLUGINS_BAD_BUILT_SOURCES := \
gst-libs/gst/basecamerabinsrc/Android.mk \
gst-libs/gst/interfaces/Android.mk \
gst/h264parse/Android.mk \
- gst/qtmux/Android.mk \
gst/videoparsers/Android.mk \
gst/audiobuffer/Android.mk \
gst/autoconvert/Android.mk \
@@ -102,7 +101,6 @@ CONFIGURE_TARGETS += gst-plugins-bad-configure
-include $(GST_PLUGINS_BAD_TOP)/gst-libs/gst/basecamerabinsrc/Android.mk
-include $(GST_PLUGINS_BAD_TOP)/gst-libs/gst/interfaces/Android.mk
-include $(GST_PLUGINS_BAD_TOP)/gst/h264parse/Android.mk
--include $(GST_PLUGINS_BAD_TOP)/gst/qtmux/Android.mk
-include $(GST_PLUGINS_BAD_TOP)/gst/audiobuffer/Android.mk
-include $(GST_PLUGINS_BAD_TOP)/gst/autoconvert/Android.mk
-include $(GST_PLUGINS_BAD_TOP)/gst/bayer/Android.mk
diff --git a/Makefile.am b/Makefile.am
index daeff6fe2..1c36d7d84 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -52,6 +52,7 @@ CRUFT_FILES = \
$(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/qtmux/.libs/*.{so,dll,DLL,dylib} \
$(top_builddir)/gst/selector/.libs/*.{so,dll,DLL,dylib} \
$(top_builddir)/gst/shapewipe/.libs/*.{so,dll,DLL,dylib} \
$(top_builddir)/gst/valve/.libs/*.{so,dll,DLL,dylib} \
@@ -62,6 +63,7 @@ CRUFT_FILES = \
$(top_builddir)/tests/check/elements/autocolorspace \
$(top_builddir)/tests/check/elements/capssetter \
$(top_builddir)/tests/check/elements/imagefreeze \
+ $(top_builddir)/tests/check/elements/qtmux \
$(top_builddir)/tests/check/elements/selector \
$(top_builddir)/tests/check/elements/valve \
$(top_builddir)/tests/check/pipelines/metadata \
@@ -76,6 +78,7 @@ CRUFT_DIRS = \
$(top_srcdir)/gst/amrparse \
$(top_srcdir)/gst/flacparse \
$(top_srcdir)/gst/imagefreeze \
+ $(top_srcdir)/gst/qtmux \
$(top_srcdir)/gst/selector \
$(top_srcdir)/gst/shapewipe \
$(top_srcdir)/gst/valve \
diff --git a/configure.ac b/configure.ac
index f19a122ff..d6d5a954a 100644
--- a/configure.ac
+++ b/configure.ac
@@ -341,7 +341,6 @@ AG_GST_CHECK_PLUGIN(nuvdemux)
AG_GST_CHECK_PLUGIN(patchdetect)
AG_GST_CHECK_PLUGIN(pcapparse)
AG_GST_CHECK_PLUGIN(pnm)
-AG_GST_CHECK_PLUGIN(qtmux)
AG_GST_CHECK_PLUGIN(rawparse)
AG_GST_CHECK_PLUGIN(real)
AG_GST_CHECK_PLUGIN(rtpmux)
@@ -1784,7 +1783,6 @@ gst/nuvdemux/Makefile
gst/patchdetect/Makefile
gst/pcapparse/Makefile
gst/pnm/Makefile
-gst/qtmux/Makefile
gst/rawparse/Makefile
gst/real/Makefile
gst/rtpmux/Makefile
diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am
index a939357ac..7d83b0e52 100644
--- a/docs/plugins/Makefile.am
+++ b/docs/plugins/Makefile.am
@@ -182,7 +182,6 @@ EXTRA_HFILES = \
$(top_srcdir)/gst/mxf/mxfmux.h \
$(top_srcdir)/gst/nuvdemux/gstnuvdemux.h \
$(top_srcdir)/gst/pcapparse/gstpcapparse.h \
- $(top_srcdir)/gst/qtmux/gstqtmux.h \
$(top_srcdir)/gst/rawparse/gstaudioparse.h \
$(top_srcdir)/gst/rawparse/gstvideoparse.h \
$(top_srcdir)/gst/rtpmux/gstrtpmux.h \
diff --git a/docs/plugins/gst-plugins-bad-plugins-docs.sgml b/docs/plugins/gst-plugins-bad-plugins-docs.sgml
index fd393a723..42bf40cfb 100644
--- a/docs/plugins/gst-plugins-bad-plugins-docs.sgml
+++ b/docs/plugins/gst-plugins-bad-plugins-docs.sgml
@@ -88,7 +88,6 @@
<xi:include href="xml/element-pcapparse.xml" />
<xi:include href="xml/element-pinch.xml" />
<xi:include href="xml/element-pyramidsegment.xml" />
- <xi:include href="xml/element-qtmux.xml" />
<xi:include href="xml/element-rsvgdec.xml" />
<xi:include href="xml/element-rsvgoverlay.xml" />
<xi:include href="xml/element-rtpdtmfdepay.xml" />
@@ -188,7 +187,6 @@
<xi:include href="xml/plugin-nuvdemux.xml" />
<xi:include href="xml/plugin-opencv.xml" />
<xi:include href="xml/plugin-pcapparse.xml" />
- <xi:include href="xml/plugin-qtmux.xml" />
<xi:include href="xml/plugin-rawparse.xml" />
<xi:include href="xml/plugin-real.xml" />
<xi:include href="xml/plugin-rfbsrc.xml" />
diff --git a/docs/plugins/gst-plugins-bad-plugins-sections.txt b/docs/plugins/gst-plugins-bad-plugins-sections.txt
index aa7a81dc6..8595dd3b7 100644
--- a/docs/plugins/gst-plugins-bad-plugins-sections.txt
+++ b/docs/plugins/gst-plugins-bad-plugins-sections.txt
@@ -1119,20 +1119,6 @@ gst_pyramidsegment_plugin_init
</SECTION>
<SECTION>
-<FILE>element-qtmux</FILE>
-<TITLE>qtmux</TITLE>
-GstQTMux
-<SUBSECTION Standard>
-GstQTMuxClass
-GST_QT_MUX
-GST_QT_MUX_CLASS
-GST_IS_QT_MUX
-GST_IS_QT_MUX_CLASS
-GST_TYPE_QT_MUX
-gst_qt_mux_get_type
-</SECTION>
-
-<SECTION>
<FILE>element-rsvgoverlay</FILE>
<TITLE>rsvgoverlay</TITLE>
GstRsvgOverlay
diff --git a/docs/plugins/inspect/plugin-qtmux.xml b/docs/plugins/inspect/plugin-qtmux.xml
deleted file mode 100644
index ea5a9ac81..000000000
--- a/docs/plugins/inspect/plugin-qtmux.xml
+++ /dev/null
@@ -1,157 +0,0 @@
-<plugin>
- <name>qtmux</name>
- <description>Quicktime Muxer plugin</description>
- <filename>../../gst/qtmux/.libs/libgstqtmux.so</filename>
- <basename>libgstqtmux.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>gppmux</name>
- <longname>3GPP Muxer</longname>
- <class>Codec/Muxer</class>
- <description>Multiplex audio and video into a 3GPP file</description>
- <author>Thiago Sousa Santos &lt;thiagoss@embedded.ufcg.edu.br&gt;</author>
- <pads>
- <caps>
- <name>audio_%d</name>
- <direction>sink</direction>
- <presence>request</presence>
- <details>audio/AMR, rate=(int)8000, channels=(int)[ 1, 2 ]; audio/AMR-WB, rate=(int)16000, channels=(int)[ 1, 2 ]; audio/mpeg, mpegversion=(int)1, layer=(int)3, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]; audio/mpeg, mpegversion=(int)4, stream-format=(string)raw, channels=(int)[ 1, 8 ], rate=(int)[ 1, 2147483647 ]</details>
- </caps>
- <caps>
- <name>video_%d</name>
- <direction>sink</direction>
- <presence>request</presence>
- <details>video/x-h263, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/mpeg, mpegversion=(int)4, systemstream=(boolean)false, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-divx, divxversion=(int)5, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-h264, stream-format=(string)avc, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
- </caps>
- <caps>
- <name>src</name>
- <direction>source</direction>
- <presence>always</presence>
- <details>video/quicktime, variant=(string)3gpp</details>
- </caps>
- </pads>
- </element>
- <element>
- <name>ismlmux</name>
- <longname>ISML Muxer</longname>
- <class>Codec/Muxer</class>
- <description>Multiplex audio and video into a ISML file</description>
- <author>Thiago Sousa Santos &lt;thiagoss@embedded.ufcg.edu.br&gt;</author>
- <pads>
- <caps>
- <name>audio_%d</name>
- <direction>sink</direction>
- <presence>request</presence>
- <details>audio/mpeg, mpegversion=(int)1, layer=(int)3, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]; audio/mpeg, mpegversion=(int)4, stream-format=(string)raw, channels=(int)[ 1, 8 ], rate=(int)[ 1, 2147483647 ]</details>
- </caps>
- <caps>
- <name>video_%d</name>
- <direction>sink</direction>
- <presence>request</presence>
- <details>video/mpeg, mpegversion=(int)4, systemstream=(boolean)false, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-divx, divxversion=(int)5, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-h264, stream-format=(string)avc, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
- </caps>
- <caps>
- <name>src</name>
- <direction>source</direction>
- <presence>always</presence>
- <details>video/quicktime, variant=(string)iso</details>
- </caps>
- </pads>
- </element>
- <element>
- <name>mj2mux</name>
- <longname>MJ2 Muxer</longname>
- <class>Codec/Muxer</class>
- <description>Multiplex audio and video into a MJ2 file</description>
- <author>Thiago Sousa Santos &lt;thiagoss@embedded.ufcg.edu.br&gt;</author>
- <pads>
- <caps>
- <name>audio_%d</name>
- <direction>sink</direction>
- <presence>request</presence>
- <details>audio/x-raw-int, width=(int)8, depth=(int)8, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ], signed=(boolean){ true, false }; audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int){ 4321, 1234 }, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ], signed=(boolean)true</details>
- </caps>
- <caps>
- <name>video_%d</name>
- <direction>sink</direction>
- <presence>request</presence>
- <details>image/x-j2c, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; image/x-jpc, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
- </caps>
- <caps>
- <name>src</name>
- <direction>source</direction>
- <presence>always</presence>
- <details>video/mj2</details>
- </caps>
- </pads>
- </element>
- <element>
- <name>mp4mux</name>
- <longname>MP4 Muxer</longname>
- <class>Codec/Muxer</class>
- <description>Multiplex audio and video into a MP4 file</description>
- <author>Thiago Sousa Santos &lt;thiagoss@embedded.ufcg.edu.br&gt;</author>
- <pads>
- <caps>
- <name>audio_%d</name>
- <direction>sink</direction>
- <presence>request</presence>
- <details>audio/mpeg, mpegversion=(int)1, layer=(int)3, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]; audio/mpeg, mpegversion=(int)4, stream-format=(string)raw, channels=(int)[ 1, 8 ], rate=(int)[ 1, 2147483647 ]; audio/x-alac, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]</details>
- </caps>
- <caps>
- <name>video_%d</name>
- <direction>sink</direction>
- <presence>request</presence>
- <details>video/mpeg, mpegversion=(int)4, systemstream=(boolean)false, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-divx, divxversion=(int)5, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-h264, stream-format=(string)avc, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-mp4-part, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
- </caps>
- <caps>
- <name>src</name>
- <direction>source</direction>
- <presence>always</presence>
- <details>video/quicktime, variant=(string)iso</details>
- </caps>
- </pads>
- </element>
- <element>
- <name>qtmoovrecover</name>
- <longname>QT Moov Recover</longname>
- <class>Util</class>
- <description>Recovers unfinished qtmux files</description>
- <author>Thiago Santos &lt;thiago.sousa.santos@collabora.co.uk&gt;</author>
- <pads>
- </pads>
- </element>
- <element>
- <name>qtmux</name>
- <longname>QuickTime Muxer</longname>
- <class>Codec/Muxer</class>
- <description>Multiplex audio and video into a QuickTime file</description>
- <author>Thiago Sousa Santos &lt;thiagoss@embedded.ufcg.edu.br&gt;</author>
- <pads>
- <caps>
- <name>audio_%d</name>
- <direction>sink</direction>
- <presence>request</presence>
- <details>audio/x-raw-int, width=(int)8, depth=(int)8, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ], signed=(boolean){ true, false }; audio/x-raw-int, width=(int)16, depth=(int)16, endianness=(int){ 4321, 1234 }, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ], signed=(boolean)true; audio/x-raw-int, width=(int)24, depth=(int)24, endianness=(int){ 4321, 1234 }, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ], signed=(boolean)true; audio/x-raw-int, width=(int)32, depth=(int)32, endianness=(int){ 4321, 1234 }, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ], signed=(boolean)true; audio/mpeg, mpegversion=(int)1, layer=(int)3, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]; audio/mpeg, mpegversion=(int)4, stream-format=(string)raw, channels=(int)[ 1, 8 ], rate=(int)[ 1, 2147483647 ]; audio/x-adpcm, layout=(string)dvi, block_align=(int)[ 64, 8096 ], channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]; audio/x-alaw, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]; audio/AMR, rate=(int)8000, channels=(int)[ 1, 2 ]; audio/AMR-WB, rate=(int)16000, channels=(int)[ 1, 2 ]; audio/x-alac, channels=(int)[ 1, 2 ], rate=(int)[ 1, 2147483647 ]</details>
- </caps>
- <caps>
- <name>video_%d</name>
- <direction>sink</direction>
- <presence>request</presence>
- <details>video/x-raw-rgb, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-raw-yuv, format=(fourcc)UYVY, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/mpeg, mpegversion=(int)4, systemstream=(boolean)false, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-divx, divxversion=(int)5, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-h263, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-h264, stream-format=(string)avc, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-svq, svqversion=(int)3, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-dv, systemstream=(boolean)false, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; image/jpeg, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ]; video/x-vp8, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]; video/x-qt-part, width=(int)[ 16, 4096 ], height=(int)[ 16, 4096 ], framerate=(fraction)[ 0/1, 2147483647/1 ]</details>
- </caps>
- <caps>
- <name>src</name>
- <direction>source</direction>
- <presence>always</presence>
- <details>video/quicktime, variant=(string)apple</details>
- </caps>
- </pads>
- </element>
- </elements>
-</plugin> \ No newline at end of file
diff --git a/gst-plugins-bad.spec.in b/gst-plugins-bad.spec.in
index 3b4fa9e27..6d780c5b3 100644
--- a/gst-plugins-bad.spec.in
+++ b/gst-plugins-bad.spec.in
@@ -106,7 +106,6 @@ rm -rf $RPM_BUILD_ROOT
%{_libdir}/gstreamer-%{majorminor}/libgstmpegtsdemux.so
%{_libdir}/gstreamer-%{majorminor}/libgstjp2k.so
%{_libdir}/gstreamer-%{majorminor}/libgstapexsink.so
-%{_libdir}/gstreamer-%{majorminor}/libgstqtmux.so
%{_libdir}/gstreamer-%{majorminor}/libgstlegacyresample.so
%{_libdir}/gstreamer-%{majorminor}/libgstmxf.so
%{_libdir}/gstreamer-%{majorminor}/libgstvmnc.so
@@ -124,7 +123,6 @@ rm -rf $RPM_BUILD_ROOT
%{_libdir}/gstreamer-%{majorminor}/libgstasfmux.so
%{_libdir}/gstreamer-%{majorminor}/libgstpnm.so
%{_libdir}/gstreamer-%{majorminor}/libgstvideomeasure.so
-%{_libdir}/gstreamer-%{majorminor}/libgstaudioparsersbad.so
%{_libdir}/gstreamer-%{majorminor}/libgstrsvg.so
%{_includedir}/gstreamer-%{majorminor}/gst/video/gstbasevideocodec.h
diff --git a/gst/qtmux/Makefile.am b/gst/qtmux/Makefile.am
deleted file mode 100644
index eb405c7b0..000000000
--- a/gst/qtmux/Makefile.am
+++ /dev/null
@@ -1,45 +0,0 @@
-# plugindir is set in configure
-
-plugin_LTLIBRARIES = libgstqtmux.la
-
-# sources used to compile this plug-in
-libgstqtmux_la_SOURCES = gstqtmux.c \
- gstqtmoovrecover.c \
- gstqtmuxplugin.c \
- atoms.c \
- atomsrecovery.c \
- descriptors.c \
- properties.c \
- gstqtmuxmap.c
-
-# flags used to compile this plugin
-# add other _CFLAGS and _LIBS as needed
-libgstqtmux_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS)
-libgstqtmux_la_LIBADD = -lgstinterfaces-$(GST_MAJORMINOR) $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) -lgsttag-$(GST_MAJORMINOR)
-libgstqtmux_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
-libgstqtmux_la_LIBTOOLFLAGS = --tag=disable-static
-
-# headers we need but don't want installed
-noinst_HEADERS = gstqtmux.h \
- gstqtmoovrecover.h \
- atoms.h \
- atomsrecovery.h \
- descriptors.h \
- properties.h \
- fourcc.h \
- ftypcc.h \
- gstqtmuxmap.h
-
-Android.mk: Makefile.am $(BUILT_SOURCES)
- androgenizer \
- -:PROJECT libgstqtmux -:SHARED libgstqtmux \
- -:TAGS eng debug \
- -:REL_TOP $(top_srcdir) -:ABS_TOP $(abs_top_srcdir) \
- -:SOURCES $(libgstqtmux_la_SOURCES) \
- -:CFLAGS $(DEFS) $(DEFAULT_INCLUDES) $(libgstqtmux_la_CFLAGS) \
- -:LDFLAGS $(libgstqtmux_la_LDFLAGS) \
- $(libgstqtmux_la_LIBADD) \
- -ldl \
- -:PASSTHROUGH LOCAL_ARM_MODE:=arm \
- LOCAL_MODULE_PATH:='$$(TARGET_OUT)/lib/gstreamer-0.10' \
- > $@
diff --git a/gst/qtmux/atoms.c b/gst/qtmux/atoms.c
deleted file mode 100644
index 5aebd6b69..000000000
--- a/gst/qtmux/atoms.c
+++ /dev/null
@@ -1,4423 +0,0 @@
-/* Quicktime muxer plugin for GStreamer
- * Copyright (C) 2008-2010 Thiago Santos <thiagoss@embedded.ufcg.edu.br>
- * Copyright (C) 2008 Mark Nauwelaerts <mnauw@users.sf.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.
- */
-/*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "atoms.h"
-#include <string.h>
-#include <glib.h>
-
-#include <gst/gst.h>
-#include <gst/base/gstbytewriter.h>
-#include <gst/tag/tag.h>
-
-/**
- * Creates a new AtomsContext for the given flavor.
- */
-AtomsContext *
-atoms_context_new (AtomsTreeFlavor flavor)
-{
- AtomsContext *context = g_new0 (AtomsContext, 1);
- context->flavor = flavor;
- return context;
-}
-
-/**
- * Frees an AtomsContext and all memory associated with it
- */
-void
-atoms_context_free (AtomsContext * context)
-{
- g_free (context);
-}
-
-/* -- creation, initialization, clear and free functions -- */
-
-#define SECS_PER_DAY (24 * 60 * 60)
-#define LEAP_YEARS_FROM_1904_TO_1970 17
-
-static guint64
-get_current_qt_time (void)
-{
- GTimeVal timeval;
-
- g_get_current_time (&timeval);
- /* FIXME this should use UTC coordinated time */
- return timeval.tv_sec + (((1970 - 1904) * (guint64) 365) +
- LEAP_YEARS_FROM_1904_TO_1970) * SECS_PER_DAY;
-}
-
-static void
-common_time_info_init (TimeInfo * ti)
-{
- ti->creation_time = ti->modification_time = get_current_qt_time ();
- ti->timescale = 0;
- ti->duration = 0;
-}
-
-static void
-atom_header_set (Atom * header, guint32 fourcc, gint32 size, gint64 ext_size)
-{
- header->type = fourcc;
- header->size = size;
- header->extended_size = ext_size;
-}
-
-static void
-atom_clear (Atom * atom)
-{
-}
-
-static void
-atom_full_init (AtomFull * full, guint32 fourcc, gint32 size, gint64 ext_size,
- guint8 version, guint8 flags[3])
-{
- atom_header_set (&(full->header), fourcc, size, ext_size);
- full->version = version;
- full->flags[0] = flags[0];
- full->flags[1] = flags[1];
- full->flags[2] = flags[2];
-}
-
-static void
-atom_full_clear (AtomFull * full)
-{
- atom_clear (&full->header);
-}
-
-static void
-atom_full_free (AtomFull * full)
-{
- atom_full_clear (full);
- g_free (full);
-}
-
-static guint32
-atom_full_get_flags_as_uint (AtomFull * full)
-{
- return full->flags[0] << 16 | full->flags[1] << 8 | full->flags[2];
-}
-
-static void
-atom_full_set_flags_as_uint (AtomFull * full, guint32 flags_as_uint)
-{
- full->flags[2] = flags_as_uint & 0xFF;
- full->flags[1] = (flags_as_uint & 0xFF00) >> 8;
- full->flags[0] = (flags_as_uint & 0xFF0000) >> 16;
-}
-
-static AtomInfo *
-build_atom_info_wrapper (Atom * atom, gpointer copy_func, gpointer free_func)
-{
- AtomInfo *info = NULL;
-
- if (atom) {
- info = g_new0 (AtomInfo, 1);
-
- info->atom = atom;
- info->copy_data_func = copy_func;
- info->free_func = free_func;
- }
-
- return info;
-}
-
-static GList *
-atom_info_list_prepend_atom (GList * ai, Atom * atom,
- AtomCopyDataFunc copy_func, AtomFreeFunc free_func)
-{
- if (atom)
- return g_list_prepend (ai,
- build_atom_info_wrapper (atom, copy_func, free_func));
- else
- return ai;
-}
-
-static void
-atom_info_list_free (GList * ai)
-{
- while (ai) {
- AtomInfo *info = (AtomInfo *) ai->data;
-
- info->free_func (info->atom);
- g_free (info);
- ai = g_list_delete_link (ai, ai);
- }
-}
-
-static AtomData *
-atom_data_new (guint32 fourcc)
-{
- AtomData *data = g_new0 (AtomData, 1);
-
- atom_header_set (&data->header, fourcc, 0, 0);
- return data;
-}
-
-static void
-atom_data_alloc_mem (AtomData * data, guint32 size)
-{
- if (data->data) {
- g_free (data->data);
- }
- data->data = g_new0 (guint8, size);
- data->datalen = size;
-}
-
-static AtomData *
-atom_data_new_from_gst_buffer (guint32 fourcc, const GstBuffer * buf)
-{
- AtomData *data = atom_data_new (fourcc);
-
- atom_data_alloc_mem (data, GST_BUFFER_SIZE (buf));
- g_memmove (data->data, GST_BUFFER_DATA (buf), GST_BUFFER_SIZE (buf));
- return data;
-}
-
-static void
-atom_data_free (AtomData * data)
-{
- atom_clear (&data->header);
- g_free (data->data);
- g_free (data);
-}
-
-static AtomUUID *
-atom_uuid_new (void)
-{
- AtomUUID *uuid = g_new0 (AtomUUID, 1);
-
- atom_header_set (&uuid->header, FOURCC_uuid, 0, 0);
- return uuid;
-}
-
-static void
-atom_uuid_free (AtomUUID * data)
-{
- atom_clear (&data->header);
- g_free (data->data);
- g_free (data);
-}
-
-static void
-atom_ftyp_init (AtomFTYP * ftyp, guint32 major, guint32 version, GList * brands)
-{
- gint index;
- GList *it = NULL;
-
- atom_header_set (&ftyp->header, FOURCC_ftyp, 16, 0);
- ftyp->major_brand = major;
- ftyp->version = version;
-
- /* always include major brand as compatible brand */
- ftyp->compatible_brands_size = g_list_length (brands) + 1;
- ftyp->compatible_brands = g_new (guint32, ftyp->compatible_brands_size);
-
- ftyp->compatible_brands[0] = major;
- index = 1;
- for (it = brands; it != NULL; it = g_list_next (it)) {
- ftyp->compatible_brands[index++] = GPOINTER_TO_UINT (it->data);
- }
-}
-
-AtomFTYP *
-atom_ftyp_new (AtomsContext * context, guint32 major, guint32 version,
- GList * brands)
-{
- AtomFTYP *ftyp = g_new0 (AtomFTYP, 1);
-
- atom_ftyp_init (ftyp, major, version, brands);
- return ftyp;
-}
-
-void
-atom_ftyp_free (AtomFTYP * ftyp)
-{
- atom_clear (&ftyp->header);
- g_free (ftyp->compatible_brands);
- ftyp->compatible_brands = NULL;
- g_free (ftyp);
-}
-
-static void
-atom_esds_init (AtomESDS * esds)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&esds->header, FOURCC_esds, 0, 0, 0, flags);
- desc_es_init (&esds->es);
-}
-
-static AtomESDS *
-atom_esds_new (void)
-{
- AtomESDS *esds = g_new0 (AtomESDS, 1);
-
- atom_esds_init (esds);
- return esds;
-}
-
-static void
-atom_esds_free (AtomESDS * esds)
-{
- atom_full_clear (&esds->header);
- desc_es_descriptor_clear (&esds->es);
- g_free (esds);
-}
-
-static AtomFRMA *
-atom_frma_new (void)
-{
- AtomFRMA *frma = g_new0 (AtomFRMA, 1);
-
- atom_header_set (&frma->header, FOURCC_frma, 0, 0);
- return frma;
-}
-
-static void
-atom_frma_free (AtomFRMA * frma)
-{
- atom_clear (&frma->header);
- g_free (frma);
-}
-
-static AtomWAVE *
-atom_wave_new (void)
-{
- AtomWAVE *wave = g_new0 (AtomWAVE, 1);
-
- atom_header_set (&wave->header, FOURCC_wave, 0, 0);
- return wave;
-}
-
-static void
-atom_wave_free (AtomWAVE * wave)
-{
- atom_clear (&wave->header);
- atom_info_list_free (wave->extension_atoms);
- g_free (wave);
-}
-
-static void
-atom_elst_init (AtomELST * elst)
-{
- guint8 flags[3] = { 0, 0, 0 };
- atom_full_init (&elst->header, FOURCC_elst, 0, 0, 0, flags);
- elst->entries = 0;
-}
-
-static void
-atom_elst_clear (AtomELST * elst)
-{
- GSList *walker;
-
- atom_full_clear (&elst->header);
- walker = elst->entries;
- while (walker) {
- g_free ((EditListEntry *) walker->data);
- walker = g_slist_next (walker);
- }
- g_slist_free (elst->entries);
-}
-
-static void
-atom_edts_init (AtomEDTS * edts)
-{
- atom_header_set (&edts->header, FOURCC_edts, 0, 0);
- atom_elst_init (&edts->elst);
-}
-
-static void
-atom_edts_clear (AtomEDTS * edts)
-{
- atom_clear (&edts->header);
- atom_elst_clear (&edts->elst);
-}
-
-static AtomEDTS *
-atom_edts_new (void)
-{
- AtomEDTS *edts = g_new0 (AtomEDTS, 1);
- atom_edts_init (edts);
- return edts;
-}
-
-static void
-atom_edts_free (AtomEDTS * edts)
-{
- atom_edts_clear (edts);
- g_free (edts);
-}
-
-static void
-atom_sample_entry_init (SampleTableEntry * se, guint32 type)
-{
- atom_header_set (&se->header, type, 0, 0);
-
- memset (se->reserved, 0, sizeof (guint8) * 6);
- se->data_reference_index = 0;
-}
-
-static void
-atom_sample_entry_free (SampleTableEntry * se)
-{
- atom_clear (&se->header);
-}
-
-static void
-sample_entry_mp4a_init (SampleTableEntryMP4A * mp4a)
-{
- atom_sample_entry_init (&mp4a->se, FOURCC_mp4a);
-
- mp4a->version = 0;
- mp4a->revision_level = 0;
- mp4a->vendor = 0;
- mp4a->channels = 2;
- mp4a->sample_size = 16;
- mp4a->compression_id = 0;
- mp4a->packet_size = 0;
- mp4a->sample_rate = 0;
- /* following only used if version is 1 */
- mp4a->samples_per_packet = 0;
- mp4a->bytes_per_packet = 0;
- mp4a->bytes_per_frame = 0;
- mp4a->bytes_per_sample = 0;
-
- mp4a->extension_atoms = NULL;
-}
-
-static SampleTableEntryMP4A *
-sample_entry_mp4a_new (void)
-{
- SampleTableEntryMP4A *mp4a = g_new0 (SampleTableEntryMP4A, 1);
-
- sample_entry_mp4a_init (mp4a);
- return mp4a;
-}
-
-static void
-sample_entry_mp4a_free (SampleTableEntryMP4A * mp4a)
-{
- atom_sample_entry_free (&mp4a->se);
- atom_info_list_free (mp4a->extension_atoms);
- g_free (mp4a);
-}
-
-static void
-sample_entry_mp4v_init (SampleTableEntryMP4V * mp4v, AtomsContext * context)
-{
- atom_sample_entry_init (&mp4v->se, FOURCC_mp4v);
-
- mp4v->version = 0;
- mp4v->revision_level = 0;
- mp4v->vendor = 0;
-
- mp4v->temporal_quality = 0;
- mp4v->spatial_quality = 0;
-
- /* qt and ISO base media do not contradict, and examples agree */
- mp4v->horizontal_resolution = 0x00480000;
- mp4v->vertical_resolution = 0x00480000;
-
- mp4v->datasize = 0;
- mp4v->frame_count = 1;
-
- memset (mp4v->compressor, 0, sizeof (guint8) * 32);
-
- mp4v->depth = 0;
- mp4v->color_table_id = 0;
-
- mp4v->extension_atoms = NULL;
-}
-
-static void
-sample_entry_mp4v_free (SampleTableEntryMP4V * mp4v)
-{
- atom_sample_entry_free (&mp4v->se);
- atom_info_list_free (mp4v->extension_atoms);
- g_free (mp4v);
-}
-
-static SampleTableEntryMP4V *
-sample_entry_mp4v_new (AtomsContext * context)
-{
- SampleTableEntryMP4V *mp4v = g_new0 (SampleTableEntryMP4V, 1);
-
- sample_entry_mp4v_init (mp4v, context);
- return mp4v;
-}
-
-static void
-atom_stsd_init (AtomSTSD * stsd)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&stsd->header, FOURCC_stsd, 0, 0, 0, flags);
- stsd->entries = NULL;
- stsd->n_entries = 0;
-}
-
-static void
-atom_stsd_remove_entries (AtomSTSD * stsd)
-{
- GList *walker;
-
- walker = stsd->entries;
- while (walker) {
- GList *aux = walker;
- SampleTableEntry *se = (SampleTableEntry *) aux->data;
-
- walker = g_list_next (walker);
- stsd->entries = g_list_remove_link (stsd->entries, aux);
-
- switch (se->kind) {
- case AUDIO:
- sample_entry_mp4a_free ((SampleTableEntryMP4A *) se);
- break;
- case VIDEO:
- sample_entry_mp4v_free ((SampleTableEntryMP4V *) se);
- break;
- default:
- /* best possible cleanup */
- atom_sample_entry_free (se);
- }
- g_list_free (aux);
- }
- stsd->n_entries = 0;
-}
-
-static void
-atom_stsd_clear (AtomSTSD * stsd)
-{
- atom_stsd_remove_entries (stsd);
- atom_full_clear (&stsd->header);
-}
-
-static void
-atom_ctts_init (AtomCTTS * ctts)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&ctts->header, FOURCC_ctts, 0, 0, 0, flags);
- atom_array_init (&ctts->entries, 128);
- ctts->do_pts = FALSE;
-}
-
-static AtomCTTS *
-atom_ctts_new (void)
-{
- AtomCTTS *ctts = g_new0 (AtomCTTS, 1);
-
- atom_ctts_init (ctts);
- return ctts;
-}
-
-static void
-atom_ctts_free (AtomCTTS * ctts)
-{
- atom_full_clear (&ctts->header);
- atom_array_clear (&ctts->entries);
- g_free (ctts);
-}
-
-static void
-atom_stts_init (AtomSTTS * stts)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&stts->header, FOURCC_stts, 0, 0, 0, flags);
- atom_array_init (&stts->entries, 512);
-}
-
-static void
-atom_stts_clear (AtomSTTS * stts)
-{
- atom_full_clear (&stts->header);
- atom_array_clear (&stts->entries);
-}
-
-static void
-atom_stsz_init (AtomSTSZ * stsz)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&stsz->header, FOURCC_stsz, 0, 0, 0, flags);
- atom_array_init (&stsz->entries, 1024);
- stsz->sample_size = 0;
- stsz->table_size = 0;
-}
-
-static void
-atom_stsz_clear (AtomSTSZ * stsz)
-{
- atom_full_clear (&stsz->header);
- atom_array_clear (&stsz->entries);
- stsz->table_size = 0;
-}
-
-static void
-atom_stsc_init (AtomSTSC * stsc)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&stsc->header, FOURCC_stsc, 0, 0, 0, flags);
- atom_array_init (&stsc->entries, 128);
-}
-
-static void
-atom_stsc_clear (AtomSTSC * stsc)
-{
- atom_full_clear (&stsc->header);
- atom_array_clear (&stsc->entries);
-}
-
-static void
-atom_co64_init (AtomSTCO64 * co64)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&co64->header, FOURCC_stco, 0, 0, 0, flags);
- atom_array_init (&co64->entries, 256);
-}
-
-static void
-atom_stco64_clear (AtomSTCO64 * stco64)
-{
- atom_full_clear (&stco64->header);
- atom_array_clear (&stco64->entries);
-}
-
-static void
-atom_stss_init (AtomSTSS * stss)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&stss->header, FOURCC_stss, 0, 0, 0, flags);
- atom_array_init (&stss->entries, 128);
-}
-
-static void
-atom_stss_clear (AtomSTSS * stss)
-{
- atom_full_clear (&stss->header);
- atom_array_clear (&stss->entries);
-}
-
-void
-atom_stbl_init (AtomSTBL * stbl)
-{
- atom_header_set (&stbl->header, FOURCC_stbl, 0, 0);
-
- atom_stts_init (&stbl->stts);
- atom_stss_init (&stbl->stss);
- atom_stsd_init (&stbl->stsd);
- atom_stsz_init (&stbl->stsz);
- atom_stsc_init (&stbl->stsc);
- stbl->ctts = NULL;
-
- atom_co64_init (&stbl->stco64);
-}
-
-void
-atom_stbl_clear (AtomSTBL * stbl)
-{
- atom_clear (&stbl->header);
- atom_stsd_clear (&stbl->stsd);
- atom_stts_clear (&stbl->stts);
- atom_stss_clear (&stbl->stss);
- atom_stsc_clear (&stbl->stsc);
- atom_stsz_clear (&stbl->stsz);
- if (stbl->ctts) {
- atom_ctts_free (stbl->ctts);
- }
- atom_stco64_clear (&stbl->stco64);
-}
-
-static void
-atom_vmhd_init (AtomVMHD * vmhd, AtomsContext * context)
-{
- guint8 flags[3] = { 0, 0, 1 };
-
- atom_full_init (&vmhd->header, FOURCC_vmhd, 0, 0, 0, flags);
- vmhd->graphics_mode = 0x0;
- memset (vmhd->opcolor, 0, sizeof (guint16) * 3);
-
- if (context->flavor == ATOMS_TREE_FLAVOR_MOV) {
- vmhd->graphics_mode = 0x40;
- vmhd->opcolor[0] = 32768;
- vmhd->opcolor[1] = 32768;
- vmhd->opcolor[2] = 32768;
- }
-}
-
-static AtomVMHD *
-atom_vmhd_new (AtomsContext * context)
-{
- AtomVMHD *vmhd = g_new0 (AtomVMHD, 1);
-
- atom_vmhd_init (vmhd, context);
- return vmhd;
-}
-
-static void
-atom_vmhd_free (AtomVMHD * vmhd)
-{
- atom_full_clear (&vmhd->header);
- g_free (vmhd);
-}
-
-static void
-atom_smhd_init (AtomSMHD * smhd)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&smhd->header, FOURCC_smhd, 0, 0, 0, flags);
- smhd->balance = 0;
- smhd->reserved = 0;
-}
-
-static AtomSMHD *
-atom_smhd_new (void)
-{
- AtomSMHD *smhd = g_new0 (AtomSMHD, 1);
-
- atom_smhd_init (smhd);
- return smhd;
-}
-
-static void
-atom_smhd_free (AtomSMHD * smhd)
-{
- atom_full_clear (&smhd->header);
- g_free (smhd);
-}
-
-static void
-atom_hmhd_free (AtomHMHD * hmhd)
-{
- atom_full_clear (&hmhd->header);
- g_free (hmhd);
-}
-
-static void
-atom_hdlr_init (AtomHDLR * hdlr)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&hdlr->header, FOURCC_hdlr, 0, 0, 0, flags);
-
- hdlr->component_type = 0;
- hdlr->handler_type = 0;
- hdlr->manufacturer = 0;
- hdlr->flags = 0;
- hdlr->flags_mask = 0;
- hdlr->name = g_strdup ("");
-}
-
-static AtomHDLR *
-atom_hdlr_new (void)
-{
- AtomHDLR *hdlr = g_new0 (AtomHDLR, 1);
-
- atom_hdlr_init (hdlr);
- return hdlr;
-}
-
-static void
-atom_hdlr_clear (AtomHDLR * hdlr)
-{
- atom_full_clear (&hdlr->header);
- if (hdlr->name) {
- g_free (hdlr->name);
- hdlr->name = NULL;
- }
-}
-
-static void
-atom_hdlr_free (AtomHDLR * hdlr)
-{
- atom_hdlr_clear (hdlr);
- g_free (hdlr);
-}
-
-static void
-atom_url_init (AtomURL * url)
-{
- guint8 flags[3] = { 0, 0, 1 };
-
- atom_full_init (&url->header, FOURCC_url_, 0, 0, 0, flags);
- url->location = NULL;
-}
-
-static void
-atom_url_free (AtomURL * url)
-{
- atom_full_clear (&url->header);
- if (url->location) {
- g_free (url->location);
- url->location = NULL;
- }
- g_free (url);
-}
-
-static AtomURL *
-atom_url_new (void)
-{
- AtomURL *url = g_new0 (AtomURL, 1);
-
- atom_url_init (url);
- return url;
-}
-
-static AtomFull *
-atom_alis_new (void)
-{
- guint8 flags[3] = { 0, 0, 1 };
- AtomFull *alis = g_new0 (AtomFull, 1);
-
- atom_full_init (alis, FOURCC_alis, 0, 0, 0, flags);
- return alis;
-}
-
-static void
-atom_dref_init (AtomDREF * dref, AtomsContext * context)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&dref->header, FOURCC_dref, 0, 0, 0, flags);
-
- /* in either case, alis or url init arranges to set self-contained flag */
- if (context->flavor == ATOMS_TREE_FLAVOR_MOV) {
- /* alis dref for qt */
- AtomFull *alis = atom_alis_new ();
- dref->entries = g_list_append (dref->entries, alis);
- } else {
- /* url for iso spec, as 'alis' not specified there */
- AtomURL *url = atom_url_new ();
- dref->entries = g_list_append (dref->entries, url);
- }
-}
-
-static void
-atom_dref_clear (AtomDREF * dref)
-{
- GList *walker;
-
- atom_full_clear (&dref->header);
- walker = dref->entries;
- while (walker) {
- GList *aux = walker;
- Atom *atom = (Atom *) aux->data;
-
- walker = g_list_next (walker);
- dref->entries = g_list_remove_link (dref->entries, aux);
- switch (atom->type) {
- case FOURCC_alis:
- atom_full_free ((AtomFull *) atom);
- break;
- case FOURCC_url_:
- atom_url_free ((AtomURL *) atom);
- break;
- default:
- /* we do nothing, better leak than crash */
- break;
- }
- g_list_free (aux);
- }
-}
-
-static void
-atom_dinf_init (AtomDINF * dinf, AtomsContext * context)
-{
- atom_header_set (&dinf->header, FOURCC_dinf, 0, 0);
- atom_dref_init (&dinf->dref, context);
-}
-
-static void
-atom_dinf_clear (AtomDINF * dinf)
-{
- atom_clear (&dinf->header);
- atom_dref_clear (&dinf->dref);
-}
-
-static void
-atom_minf_init (AtomMINF * minf, AtomsContext * context)
-{
- atom_header_set (&minf->header, FOURCC_minf, 0, 0);
-
- minf->vmhd = NULL;
- minf->smhd = NULL;
- minf->hmhd = NULL;
-
- if (context->flavor == ATOMS_TREE_FLAVOR_MOV) {
- minf->hdlr = atom_hdlr_new ();
- minf->hdlr->component_type = FOURCC_dhlr;
- minf->hdlr->handler_type = FOURCC_alis;
- } else {
- minf->hdlr = NULL;
- }
- atom_dinf_init (&minf->dinf, context);
- atom_stbl_init (&minf->stbl);
-}
-
-static void
-atom_minf_clear_handlers (AtomMINF * minf)
-{
- if (minf->vmhd) {
- atom_vmhd_free (minf->vmhd);
- minf->vmhd = NULL;
- }
- if (minf->smhd) {
- atom_smhd_free (minf->smhd);
- minf->smhd = NULL;
- }
- if (minf->hmhd) {
- atom_hmhd_free (minf->hmhd);
- minf->hmhd = NULL;
- }
-}
-
-static void
-atom_minf_clear (AtomMINF * minf)
-{
- atom_clear (&minf->header);
- atom_minf_clear_handlers (minf);
- if (minf->hdlr) {
- atom_hdlr_free (minf->hdlr);
- }
- atom_dinf_clear (&minf->dinf);
- atom_stbl_clear (&minf->stbl);
-}
-
-static void
-atom_mdhd_init (AtomMDHD * mdhd)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&mdhd->header, FOURCC_mdhd, 0, 0, 0, flags);
- common_time_info_init (&mdhd->time_info);
- mdhd->language_code = 0;
- mdhd->quality = 0;
-}
-
-static void
-atom_mdhd_clear (AtomMDHD * mdhd)
-{
- atom_full_clear (&mdhd->header);
-}
-
-static void
-atom_mdia_init (AtomMDIA * mdia, AtomsContext * context)
-{
- atom_header_set (&mdia->header, FOURCC_mdia, 0, 0);
-
- atom_mdhd_init (&mdia->mdhd);
- atom_hdlr_init (&mdia->hdlr);
- atom_minf_init (&mdia->minf, context);
-}
-
-static void
-atom_mdia_clear (AtomMDIA * mdia)
-{
- atom_clear (&mdia->header);
- atom_mdhd_clear (&mdia->mdhd);
- atom_hdlr_clear (&mdia->hdlr);
- atom_minf_clear (&mdia->minf);
-}
-
-static void
-atom_tkhd_init (AtomTKHD * tkhd, AtomsContext * context)
-{
- /*
- * flags info
- * 1 -> track enabled
- * 2 -> track in movie
- * 4 -> track in preview
- */
- guint8 flags[3] = { 0, 0, 7 };
-
- atom_full_init (&tkhd->header, FOURCC_tkhd, 0, 0, 0, flags);
-
- tkhd->creation_time = tkhd->modification_time = get_current_qt_time ();
- tkhd->duration = 0;
- tkhd->track_ID = 0;
- tkhd->reserved = 0;
-
- tkhd->reserved2[0] = tkhd->reserved2[1] = 0;
- tkhd->layer = 0;
- tkhd->alternate_group = 0;
- tkhd->volume = 0;
- tkhd->reserved3 = 0;
- memset (tkhd->matrix, 0, sizeof (guint32) * 9);
- tkhd->matrix[0] = 1 << 16;
- tkhd->matrix[4] = 1 << 16;
- tkhd->matrix[8] = 16384 << 16;
- tkhd->width = 0;
- tkhd->height = 0;
-}
-
-static void
-atom_tkhd_clear (AtomTKHD * tkhd)
-{
- atom_full_clear (&tkhd->header);
-}
-
-static void
-atom_trak_init (AtomTRAK * trak, AtomsContext * context)
-{
- atom_header_set (&trak->header, FOURCC_trak, 0, 0);
-
- atom_tkhd_init (&trak->tkhd, context);
- trak->edts = NULL;
- atom_mdia_init (&trak->mdia, context);
-}
-
-AtomTRAK *
-atom_trak_new (AtomsContext * context)
-{
- AtomTRAK *trak = g_new0 (AtomTRAK, 1);
-
- atom_trak_init (trak, context);
- return trak;
-}
-
-static void
-atom_trak_clear (AtomTRAK * trak)
-{
- atom_clear (&trak->header);
- atom_tkhd_clear (&trak->tkhd);
- if (trak->edts)
- atom_edts_free (trak->edts);
- atom_mdia_clear (&trak->mdia);
-}
-
-static void
-atom_trak_free (AtomTRAK * trak)
-{
- atom_trak_clear (trak);
- g_free (trak);
-}
-
-static void
-atom_ilst_init (AtomILST * ilst)
-{
- atom_header_set (&ilst->header, FOURCC_ilst, 0, 0);
- ilst->entries = NULL;
-}
-
-static AtomILST *
-atom_ilst_new (void)
-{
- AtomILST *ilst = g_new0 (AtomILST, 1);
-
- atom_ilst_init (ilst);
- return ilst;
-}
-
-static void
-atom_ilst_free (AtomILST * ilst)
-{
- if (ilst->entries)
- atom_info_list_free (ilst->entries);
- atom_clear (&ilst->header);
- g_free (ilst);
-}
-
-static void
-atom_meta_init (AtomMETA * meta)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&meta->header, FOURCC_meta, 0, 0, 0, flags);
- atom_hdlr_init (&meta->hdlr);
- /* FIXME (ISOM says this is always 0) */
- meta->hdlr.component_type = FOURCC_mhlr;
- meta->hdlr.handler_type = FOURCC_mdir;
- meta->ilst = NULL;
-}
-
-static AtomMETA *
-atom_meta_new (void)
-{
- AtomMETA *meta = g_new0 (AtomMETA, 1);
-
- atom_meta_init (meta);
- return meta;
-}
-
-static void
-atom_meta_free (AtomMETA * meta)
-{
- atom_full_clear (&meta->header);
- atom_hdlr_clear (&meta->hdlr);
- if (meta->ilst)
- atom_ilst_free (meta->ilst);
- meta->ilst = NULL;
- g_free (meta);
-}
-
-static void
-atom_udta_init (AtomUDTA * udta)
-{
- atom_header_set (&udta->header, FOURCC_udta, 0, 0);
- udta->meta = NULL;
-}
-
-static AtomUDTA *
-atom_udta_new (void)
-{
- AtomUDTA *udta = g_new0 (AtomUDTA, 1);
-
- atom_udta_init (udta);
- return udta;
-}
-
-static void
-atom_udta_free (AtomUDTA * udta)
-{
- atom_clear (&udta->header);
- if (udta->meta)
- atom_meta_free (udta->meta);
- udta->meta = NULL;
- if (udta->entries)
- atom_info_list_free (udta->entries);
- g_free (udta);
-}
-
-static void
-atom_tag_data_init (AtomTagData * data)
-{
- guint8 flags[] = { 0, 0, 0 };
-
- atom_full_init (&data->header, FOURCC_data, 0, 0, 0, flags);
-}
-
-static void
-atom_tag_data_clear (AtomTagData * data)
-{
- atom_full_clear (&data->header);
- g_free (data->data);
- data->datalen = 0;
-}
-
-/*
- * Fourcc is the tag fourcc
- * flags will be truncated to 24bits
- */
-static AtomTag *
-atom_tag_new (guint32 fourcc, guint32 flags_as_uint)
-{
- AtomTag *tag = g_new0 (AtomTag, 1);
-
- tag->header.type = fourcc;
- atom_tag_data_init (&tag->data);
- atom_full_set_flags_as_uint (&tag->data.header, flags_as_uint);
- return tag;
-}
-
-static void
-atom_tag_free (AtomTag * tag)
-{
- atom_clear (&tag->header);
- atom_tag_data_clear (&tag->data);
- g_free (tag);
-}
-
-static void
-atom_mvhd_init (AtomMVHD * mvhd)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&(mvhd->header), FOURCC_mvhd, sizeof (AtomMVHD), 0, 0, flags);
-
- common_time_info_init (&mvhd->time_info);
-
- mvhd->prefered_rate = 1 << 16;
- mvhd->volume = 1 << 8;
- mvhd->reserved3 = 0;
- memset (mvhd->reserved4, 0, sizeof (guint32[2]));
-
- memset (mvhd->matrix, 0, sizeof (guint32[9]));
- mvhd->matrix[0] = 1 << 16;
- mvhd->matrix[4] = 1 << 16;
- mvhd->matrix[8] = 16384 << 16;
-
- mvhd->preview_time = 0;
- mvhd->preview_duration = 0;
- mvhd->poster_time = 0;
- mvhd->selection_time = 0;
- mvhd->selection_duration = 0;
- mvhd->current_time = 0;
-
- mvhd->next_track_id = 1;
-}
-
-static void
-atom_mvhd_clear (AtomMVHD * mvhd)
-{
- atom_full_clear (&mvhd->header);
-}
-
-static void
-atom_mehd_init (AtomMEHD * mehd)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&mehd->header, FOURCC_mehd, 0, 0, 1, flags);
- mehd->fragment_duration = 0;
-}
-
-static void
-atom_mvex_init (AtomMVEX * mvex)
-{
- atom_header_set (&mvex->header, FOURCC_mvex, 0, 0);
- atom_mehd_init (&mvex->mehd);
- mvex->trexs = NULL;
-}
-
-static void
-atom_moov_init (AtomMOOV * moov, AtomsContext * context)
-{
- atom_header_set (&(moov->header), FOURCC_moov, 0, 0);
- atom_mvhd_init (&(moov->mvhd));
- atom_mvex_init (&(moov->mvex));
- moov->udta = NULL;
- moov->traks = NULL;
- moov->context = *context;
-}
-
-AtomMOOV *
-atom_moov_new (AtomsContext * context)
-{
- AtomMOOV *moov = g_new0 (AtomMOOV, 1);
-
- atom_moov_init (moov, context);
- return moov;
-}
-
-static void
-atom_trex_free (AtomTREX * trex)
-{
- atom_full_clear (&trex->header);
- g_free (trex);
-}
-
-static void
-atom_mvex_clear (AtomMVEX * mvex)
-{
- GList *walker;
-
- atom_clear (&mvex->header);
- walker = mvex->trexs;
- while (walker) {
- atom_trex_free ((AtomTREX *) walker->data);
- walker = g_list_next (walker);
- }
- g_list_free (mvex->trexs);
- mvex->trexs = NULL;
-}
-
-void
-atom_moov_free (AtomMOOV * moov)
-{
- GList *walker;
-
- atom_clear (&moov->header);
- atom_mvhd_clear (&moov->mvhd);
-
- walker = moov->traks;
- while (walker) {
- atom_trak_free ((AtomTRAK *) walker->data);
- walker = g_list_next (walker);
- }
- g_list_free (moov->traks);
- moov->traks = NULL;
-
- if (moov->udta) {
- atom_udta_free (moov->udta);
- moov->udta = NULL;
- }
-
- atom_mvex_clear (&moov->mvex);
-
- g_free (moov);
-}
-
-/* -- end of init / free -- */
-
-/* -- copy data functions -- */
-
-static guint8
-atom_full_get_version (AtomFull * full)
-{
- return full->version;
-}
-
-static guint64
-common_time_info_copy_data (TimeInfo * ti, gboolean trunc_to_32,
- guint8 ** buffer, guint64 * size, guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (trunc_to_32) {
- prop_copy_uint32 ((guint32) ti->creation_time, buffer, size, offset);
- prop_copy_uint32 ((guint32) ti->modification_time, buffer, size, offset);
- prop_copy_uint32 (ti->timescale, buffer, size, offset);
- prop_copy_uint32 ((guint32) ti->duration, buffer, size, offset);
- } else {
- prop_copy_uint64 (ti->creation_time, buffer, size, offset);
- prop_copy_uint64 (ti->modification_time, buffer, size, offset);
- prop_copy_uint32 (ti->timescale, buffer, size, offset);
- prop_copy_uint64 (ti->duration, buffer, size, offset);
- }
- return *offset - original_offset;
-}
-
-static void
-atom_write_size (guint8 ** buffer, guint64 * size, guint64 * offset,
- guint64 atom_pos)
-{
- /* this only works for non-extended atom size, which is OK
- * (though it could be made to do mem_move, etc and write extended size) */
- prop_copy_uint32 (*offset - atom_pos, buffer, size, &atom_pos);
-}
-
-guint64
-atom_copy_data (Atom * atom, guint8 ** buffer, guint64 * size, guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- /* copies type and size */
- prop_copy_uint32 (atom->size, buffer, size, offset);
- prop_copy_fourcc (atom->type, buffer, size, offset);
-
- /* extended size needed */
- if (atom->size == 1) {
- /* really should not happen other than with mdat atom;
- * would be a problem for size (re)write code, not to mention memory */
- g_return_val_if_fail (atom->type == FOURCC_mdat, 0);
- prop_copy_uint64 (atom->extended_size, buffer, size, offset);
- }
-
- return *offset - original_offset;
-}
-
-static guint64
-atom_full_copy_data (AtomFull * atom, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_copy_data (&atom->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint8 (atom->version, buffer, size, offset);
- prop_copy_uint8_array (atom->flags, 3, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_info_list_copy_data (GList * ai, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- while (ai) {
- AtomInfo *info = (AtomInfo *) ai->data;
-
- if (!info->copy_data_func (info->atom, buffer, size, offset)) {
- return 0;
- }
- ai = g_list_next (ai);
- }
-
- return *offset - original_offset;
-}
-
-static guint64
-atom_data_copy_data (AtomData * data, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_copy_data (&data->header, buffer, size, offset)) {
- return 0;
- }
- if (data->datalen)
- prop_copy_uint8_array (data->data, data->datalen, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_uuid_copy_data (AtomUUID * uuid, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_copy_data (&uuid->header, buffer, size, offset)) {
- return 0;
- }
- prop_copy_uint8_array (uuid->uuid, 16, buffer, size, offset);
- if (uuid->datalen)
- prop_copy_uint8_array (uuid->data, uuid->datalen, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-guint64
-atom_ftyp_copy_data (AtomFTYP * ftyp, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_copy_data (&ftyp->header, buffer, size, offset)) {
- return 0;
- }
- prop_copy_fourcc (ftyp->major_brand, buffer, size, offset);
- prop_copy_uint32 (ftyp->version, buffer, size, offset);
-
- prop_copy_fourcc_array (ftyp->compatible_brands, ftyp->compatible_brands_size,
- buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-guint64
-atom_mvhd_copy_data (AtomMVHD * atom, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint8 version;
- guint64 original_offset = *offset;
-
- if (!atom_full_copy_data (&(atom->header), buffer, size, offset)) {
- return 0;
- }
-
- version = atom_full_get_version (&(atom->header));
- if (version == 0) {
- common_time_info_copy_data (&atom->time_info, TRUE, buffer, size, offset);
- } else if (version == 1) {
- common_time_info_copy_data (&atom->time_info, FALSE, buffer, size, offset);
- } else {
- *offset = original_offset;
- return 0;
- }
-
- prop_copy_uint32 (atom->prefered_rate, buffer, size, offset);
- prop_copy_uint16 (atom->volume, buffer, size, offset);
- prop_copy_uint16 (atom->reserved3, buffer, size, offset);
- prop_copy_uint32_array (atom->reserved4, 2, buffer, size, offset);
- prop_copy_uint32_array (atom->matrix, 9, buffer, size, offset);
- prop_copy_uint32 (atom->preview_time, buffer, size, offset);
- prop_copy_uint32 (atom->preview_duration, buffer, size, offset);
- prop_copy_uint32 (atom->poster_time, buffer, size, offset);
- prop_copy_uint32 (atom->selection_time, buffer, size, offset);
- prop_copy_uint32 (atom->selection_duration, buffer, size, offset);
- prop_copy_uint32 (atom->current_time, buffer, size, offset);
-
- prop_copy_uint32 (atom->next_track_id, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_tkhd_copy_data (AtomTKHD * tkhd, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_full_copy_data (&tkhd->header, buffer, size, offset)) {
- return 0;
- }
-
- if (atom_full_get_version (&tkhd->header) == 0) {
- prop_copy_uint32 ((guint32) tkhd->creation_time, buffer, size, offset);
- prop_copy_uint32 ((guint32) tkhd->modification_time, buffer, size, offset);
- prop_copy_uint32 (tkhd->track_ID, buffer, size, offset);
- prop_copy_uint32 (tkhd->reserved, buffer, size, offset);
- prop_copy_uint32 ((guint32) tkhd->duration, buffer, size, offset);
- } else {
- prop_copy_uint64 (tkhd->creation_time, buffer, size, offset);
- prop_copy_uint64 (tkhd->modification_time, buffer, size, offset);
- prop_copy_uint32 (tkhd->track_ID, buffer, size, offset);
- prop_copy_uint32 (tkhd->reserved, buffer, size, offset);
- prop_copy_uint64 (tkhd->duration, buffer, size, offset);
- }
-
- prop_copy_uint32_array (tkhd->reserved2, 2, buffer, size, offset);
- prop_copy_uint16 (tkhd->layer, buffer, size, offset);
- prop_copy_uint16 (tkhd->alternate_group, buffer, size, offset);
- prop_copy_uint16 (tkhd->volume, buffer, size, offset);
- prop_copy_uint16 (tkhd->reserved3, buffer, size, offset);
- prop_copy_uint32_array (tkhd->matrix, 9, buffer, size, offset);
-
- prop_copy_uint32 (tkhd->width, buffer, size, offset);
- prop_copy_uint32 (tkhd->height, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_hdlr_copy_data (AtomHDLR * hdlr, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_full_copy_data (&hdlr->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_fourcc (hdlr->component_type, buffer, size, offset);
- prop_copy_fourcc (hdlr->handler_type, buffer, size, offset);
- prop_copy_fourcc (hdlr->manufacturer, buffer, size, offset);
- prop_copy_uint32 (hdlr->flags, buffer, size, offset);
- prop_copy_uint32 (hdlr->flags_mask, buffer, size, offset);
-
- prop_copy_size_string ((guint8 *) hdlr->name, strlen (hdlr->name), buffer,
- size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_vmhd_copy_data (AtomVMHD * vmhd, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_full_copy_data (&vmhd->header, buffer, size, offset)) {
- return 0;
- }
- prop_copy_uint16 (vmhd->graphics_mode, buffer, size, offset);
- prop_copy_uint16_array (vmhd->opcolor, 3, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return original_offset - *offset;
-}
-
-static guint64
-atom_smhd_copy_data (AtomSMHD * smhd, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_full_copy_data (&smhd->header, buffer, size, offset)) {
- return 0;
- }
- prop_copy_uint16 (smhd->balance, buffer, size, offset);
- prop_copy_uint16 (smhd->reserved, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return original_offset - *offset;
-}
-
-static guint64
-atom_hmhd_copy_data (AtomHMHD * hmhd, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_full_copy_data (&hmhd->header, buffer, size, offset)) {
- return 0;
- }
- prop_copy_uint16 (hmhd->max_pdu_size, buffer, size, offset);
- prop_copy_uint16 (hmhd->avg_pdu_size, buffer, size, offset);
- prop_copy_uint32 (hmhd->max_bitrate, buffer, size, offset);
- prop_copy_uint32 (hmhd->avg_bitrate, buffer, size, offset);
- prop_copy_uint32 (hmhd->sliding_avg_bitrate, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return original_offset - *offset;
-}
-
-static gboolean
-atom_url_same_file_flag (AtomURL * url)
-{
- return (url->header.flags[2] & 0x1) == 1;
-}
-
-static guint64
-atom_url_copy_data (AtomURL * url, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_full_copy_data (&url->header, buffer, size, offset)) {
- return 0;
- }
-
- if (!atom_url_same_file_flag (url)) {
- prop_copy_null_terminated_string (url->location, buffer, size, offset);
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return original_offset - *offset;
-}
-
-guint64
-atom_stts_copy_data (AtomSTTS * stts, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
- guint i;
-
- if (!atom_full_copy_data (&stts->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (atom_array_get_len (&stts->entries), buffer, size, offset);
- /* minimize realloc */
- prop_copy_ensure_buffer (buffer, size, offset,
- 8 * atom_array_get_len (&stts->entries));
- for (i = 0; i < atom_array_get_len (&stts->entries); i++) {
- STTSEntry *entry = &atom_array_index (&stts->entries, i);
-
- prop_copy_uint32 (entry->sample_count, buffer, size, offset);
- prop_copy_int32 (entry->sample_delta, buffer, size, offset);
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_sample_entry_copy_data (SampleTableEntry * se, guint8 ** buffer,
- guint64 * size, guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_copy_data (&se->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint8_array (se->reserved, 6, buffer, size, offset);
- prop_copy_uint16 (se->data_reference_index, buffer, size, offset);
-
- return *offset - original_offset;
-}
-
-static guint64
-atom_esds_copy_data (AtomESDS * esds, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_full_copy_data (&esds->header, buffer, size, offset)) {
- return 0;
- }
- if (!desc_es_descriptor_copy_data (&esds->es, buffer, size, offset)) {
- return 0;
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_frma_copy_data (AtomFRMA * frma, guint8 ** buffer,
- guint64 * size, guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_copy_data (&(frma->header), buffer, size, offset))
- return 0;
-
- prop_copy_fourcc (frma->media_type, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_mp4s_copy_data (SampleTableEntryMP4S * mp4s, guint8 ** buffer,
- guint64 * size, guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_sample_entry_copy_data (&mp4s->se, buffer, size, offset)) {
- return 0;
- }
- if (!atom_esds_copy_data (&mp4s->es, buffer, size, offset)) {
- return 0;
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_hint_sample_entry_copy_data (AtomHintSampleEntry * hse, guint8 ** buffer,
- guint64 * size, guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_sample_entry_copy_data (&hse->se, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (hse->size, buffer, size, offset);
- prop_copy_uint8_array (hse->data, hse->size, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-sample_entry_mp4a_copy_data (SampleTableEntryMP4A * mp4a, guint8 ** buffer,
- guint64 * size, guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_sample_entry_copy_data (&mp4a->se, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint16 (mp4a->version, buffer, size, offset);
- prop_copy_uint16 (mp4a->revision_level, buffer, size, offset);
- prop_copy_uint32 (mp4a->vendor, buffer, size, offset);
- prop_copy_uint16 (mp4a->channels, buffer, size, offset);
- prop_copy_uint16 (mp4a->sample_size, buffer, size, offset);
- prop_copy_uint16 (mp4a->compression_id, buffer, size, offset);
- prop_copy_uint16 (mp4a->packet_size, buffer, size, offset);
- prop_copy_uint32 (mp4a->sample_rate, buffer, size, offset);
-
- /* this should always be 0 for mp4 flavor */
- if (mp4a->version == 1) {
- prop_copy_uint32 (mp4a->samples_per_packet, buffer, size, offset);
- prop_copy_uint32 (mp4a->bytes_per_packet, buffer, size, offset);
- prop_copy_uint32 (mp4a->bytes_per_frame, buffer, size, offset);
- prop_copy_uint32 (mp4a->bytes_per_sample, buffer, size, offset);
- }
-
- if (mp4a->extension_atoms) {
- if (!atom_info_list_copy_data (mp4a->extension_atoms, buffer, size, offset))
- return 0;
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-sample_entry_mp4v_copy_data (SampleTableEntryMP4V * mp4v, guint8 ** buffer,
- guint64 * size, guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_sample_entry_copy_data (&mp4v->se, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint16 (mp4v->version, buffer, size, offset);
- prop_copy_uint16 (mp4v->revision_level, buffer, size, offset);
- prop_copy_fourcc (mp4v->vendor, buffer, size, offset);
- prop_copy_uint32 (mp4v->temporal_quality, buffer, size, offset);
- prop_copy_uint32 (mp4v->spatial_quality, buffer, size, offset);
-
- prop_copy_uint16 (mp4v->width, buffer, size, offset);
- prop_copy_uint16 (mp4v->height, buffer, size, offset);
-
- prop_copy_uint32 (mp4v->horizontal_resolution, buffer, size, offset);
- prop_copy_uint32 (mp4v->vertical_resolution, buffer, size, offset);
- prop_copy_uint32 (mp4v->datasize, buffer, size, offset);
-
- prop_copy_uint16 (mp4v->frame_count, buffer, size, offset);
-
- prop_copy_fixed_size_string ((guint8 *) mp4v->compressor, 32, buffer, size,
- offset);
-
- prop_copy_uint16 (mp4v->depth, buffer, size, offset);
- prop_copy_uint16 (mp4v->color_table_id, buffer, size, offset);
-
- /* extra atoms */
- if (mp4v->extension_atoms &&
- !atom_info_list_copy_data (mp4v->extension_atoms, buffer, size, offset))
- return 0;
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-guint64
-atom_stsz_copy_data (AtomSTSZ * stsz, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
- guint i;
-
- if (!atom_full_copy_data (&stsz->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (stsz->sample_size, buffer, size, offset);
- prop_copy_uint32 (stsz->table_size, buffer, size, offset);
- if (stsz->sample_size == 0) {
- /* minimize realloc */
- prop_copy_ensure_buffer (buffer, size, offset, 4 * stsz->table_size);
- /* entry count must match sample count */
- g_assert (atom_array_get_len (&stsz->entries) == stsz->table_size);
- for (i = 0; i < atom_array_get_len (&stsz->entries); i++) {
- prop_copy_uint32 (atom_array_index (&stsz->entries, i), buffer, size,
- offset);
- }
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-guint64
-atom_stsc_copy_data (AtomSTSC * stsc, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
- guint i;
-
- if (!atom_full_copy_data (&stsc->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (atom_array_get_len (&stsc->entries), buffer, size, offset);
- /* minimize realloc */
- prop_copy_ensure_buffer (buffer, size, offset,
- 12 * atom_array_get_len (&stsc->entries));
-
- for (i = 0; i < atom_array_get_len (&stsc->entries); i++) {
- STSCEntry *entry = &atom_array_index (&stsc->entries, i);
-
- prop_copy_uint32 (entry->first_chunk, buffer, size, offset);
- prop_copy_uint32 (entry->samples_per_chunk, buffer, size, offset);
- prop_copy_uint32 (entry->sample_description_index, buffer, size, offset);
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-guint64
-atom_ctts_copy_data (AtomCTTS * ctts, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
- guint i;
-
- if (!atom_full_copy_data (&ctts->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (atom_array_get_len (&ctts->entries), buffer, size, offset);
- /* minimize realloc */
- prop_copy_ensure_buffer (buffer, size, offset,
- 8 * atom_array_get_len (&ctts->entries));
- for (i = 0; i < atom_array_get_len (&ctts->entries); i++) {
- CTTSEntry *entry = &atom_array_index (&ctts->entries, i);
-
- prop_copy_uint32 (entry->samplecount, buffer, size, offset);
- prop_copy_uint32 (entry->sampleoffset, buffer, size, offset);
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-guint64
-atom_stco64_copy_data (AtomSTCO64 * stco64, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
- guint i;
- gboolean trunc_to_32 = stco64->header.header.type == FOURCC_stco;
-
- if (!atom_full_copy_data (&stco64->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (atom_array_get_len (&stco64->entries), buffer, size,
- offset);
-
- /* minimize realloc */
- prop_copy_ensure_buffer (buffer, size, offset,
- 8 * atom_array_get_len (&stco64->entries));
- for (i = 0; i < atom_array_get_len (&stco64->entries); i++) {
- guint64 *value = &atom_array_index (&stco64->entries, i);
-
- if (trunc_to_32) {
- prop_copy_uint32 ((guint32) * value, buffer, size, offset);
- } else {
- prop_copy_uint64 (*value, buffer, size, offset);
- }
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-guint64
-atom_stss_copy_data (AtomSTSS * stss, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
- guint i;
-
- if (atom_array_get_len (&stss->entries) == 0) {
- /* FIXME not needing this atom might be confused with error while copying */
- return 0;
- }
-
- if (!atom_full_copy_data (&stss->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (atom_array_get_len (&stss->entries), buffer, size, offset);
- /* minimize realloc */
- prop_copy_ensure_buffer (buffer, size, offset,
- 4 * atom_array_get_len (&stss->entries));
- for (i = 0; i < atom_array_get_len (&stss->entries); i++) {
- prop_copy_uint32 (atom_array_index (&stss->entries, i), buffer, size,
- offset);
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_stsd_copy_data (AtomSTSD * stsd, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
- GList *walker;
-
- if (!atom_full_copy_data (&stsd->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (stsd->n_entries, buffer, size, offset);
-
- for (walker = g_list_last (stsd->entries); walker != NULL;
- walker = g_list_previous (walker)) {
- SampleTableEntry *se = (SampleTableEntry *) walker->data;
-
- switch (((Atom *) walker->data)->type) {
- case FOURCC_mp4a:
- if (!sample_entry_mp4a_copy_data ((SampleTableEntryMP4A *) walker->data,
- buffer, size, offset)) {
- return 0;
- }
- break;
- case FOURCC_mp4s:
- if (!atom_mp4s_copy_data ((SampleTableEntryMP4S *) walker->data,
- buffer, size, offset)) {
- return 0;
- }
- break;
- case FOURCC_mp4v:
- if (!sample_entry_mp4v_copy_data ((SampleTableEntryMP4V *) walker->data,
- buffer, size, offset)) {
- return 0;
- }
- break;
- default:
- if (se->kind == VIDEO) {
- if (!sample_entry_mp4v_copy_data ((SampleTableEntryMP4V *)
- walker->data, buffer, size, offset)) {
- return 0;
- }
- } else if (se->kind == AUDIO) {
- if (!sample_entry_mp4a_copy_data ((SampleTableEntryMP4A *)
- walker->data, buffer, size, offset)) {
- return 0;
- }
- } else {
- if (!atom_hint_sample_entry_copy_data (
- (AtomHintSampleEntry *) walker->data, buffer, size, offset)) {
- return 0;
- }
- }
- break;
- }
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_stbl_copy_data (AtomSTBL * stbl, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_copy_data (&stbl->header, buffer, size, offset)) {
- return 0;
- }
-
- if (!atom_stsd_copy_data (&stbl->stsd, buffer, size, offset)) {
- return 0;
- }
- if (!atom_stts_copy_data (&stbl->stts, buffer, size, offset)) {
- return 0;
- }
- /* this atom is optional, so let's check if we need it
- * (to avoid false error) */
- if (atom_array_get_len (&stbl->stss.entries)) {
- if (!atom_stss_copy_data (&stbl->stss, buffer, size, offset)) {
- return 0;
- }
- }
-
- if (!atom_stsc_copy_data (&stbl->stsc, buffer, size, offset)) {
- return 0;
- }
- if (!atom_stsz_copy_data (&stbl->stsz, buffer, size, offset)) {
- return 0;
- }
- if (stbl->ctts && stbl->ctts->do_pts) {
- if (!atom_ctts_copy_data (stbl->ctts, buffer, size, offset)) {
- return 0;
- }
- }
- if (!atom_stco64_copy_data (&stbl->stco64, buffer, size, offset)) {
- return 0;
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return original_offset - *offset;
-}
-
-
-static guint64
-atom_dref_copy_data (AtomDREF * dref, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
- GList *walker;
-
- if (!atom_full_copy_data (&dref->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (g_list_length (dref->entries), buffer, size, offset);
-
- walker = dref->entries;
- while (walker != NULL) {
- Atom *atom = (Atom *) walker->data;
-
- if (atom->type == FOURCC_url_) {
- atom_url_copy_data ((AtomURL *) atom, buffer, size, offset);
- } else if (atom->type == FOURCC_alis) {
- atom_full_copy_data ((AtomFull *) atom, buffer, size, offset);
- } else {
- g_error ("Unsupported atom used inside dref atom");
- }
- walker = g_list_next (walker);
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_dinf_copy_data (AtomDINF * dinf, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_copy_data (&dinf->header, buffer, size, offset)) {
- return 0;
- }
-
- if (!atom_dref_copy_data (&dinf->dref, buffer, size, offset)) {
- return 0;
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return original_offset - *offset;
-}
-
-static guint64
-atom_minf_copy_data (AtomMINF * minf, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_copy_data (&minf->header, buffer, size, offset)) {
- return 0;
- }
-
- if (minf->vmhd) {
- if (!atom_vmhd_copy_data (minf->vmhd, buffer, size, offset)) {
- return 0;
- }
- } else if (minf->smhd) {
- if (!atom_smhd_copy_data (minf->smhd, buffer, size, offset)) {
- return 0;
- }
- } else if (minf->hmhd) {
- if (!atom_hmhd_copy_data (minf->hmhd, buffer, size, offset)) {
- return 0;
- }
- }
-
- if (minf->hdlr) {
- if (!atom_hdlr_copy_data (minf->hdlr, buffer, size, offset)) {
- return 0;
- }
- }
-
- if (!atom_dinf_copy_data (&minf->dinf, buffer, size, offset)) {
- return 0;
- }
- if (!atom_stbl_copy_data (&minf->stbl, buffer, size, offset)) {
- return 0;
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_mdhd_copy_data (AtomMDHD * mdhd, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_full_copy_data (&mdhd->header, buffer, size, offset)) {
- return 0;
- }
-
- if (!common_time_info_copy_data (&mdhd->time_info,
- atom_full_get_version (&mdhd->header) == 0, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint16 (mdhd->language_code, buffer, size, offset);
- prop_copy_uint16 (mdhd->quality, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_mdia_copy_data (AtomMDIA * mdia, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_copy_data (&mdia->header, buffer, size, offset)) {
- return 0;
- }
- if (!atom_mdhd_copy_data (&mdia->mdhd, buffer, size, offset)) {
- return 0;
- }
- if (!atom_hdlr_copy_data (&mdia->hdlr, buffer, size, offset)) {
- return 0;
- }
-
- if (!atom_minf_copy_data (&mdia->minf, buffer, size, offset)) {
- return 0;
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_elst_copy_data (AtomELST * elst, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
- GSList *walker;
-
- if (!atom_full_copy_data (&elst->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (g_slist_length (elst->entries), buffer, size, offset);
-
- for (walker = elst->entries; walker != NULL; walker = g_slist_next (walker)) {
- EditListEntry *entry = (EditListEntry *) walker->data;
- prop_copy_uint32 (entry->duration, buffer, size, offset);
- prop_copy_uint32 (entry->media_time, buffer, size, offset);
- prop_copy_uint32 (entry->media_rate, buffer, size, offset);
- }
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_edts_copy_data (AtomEDTS * edts, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_copy_data (&(edts->header), buffer, size, offset))
- return 0;
-
- if (!atom_elst_copy_data (&(edts->elst), buffer, size, offset))
- return 0;
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-guint64
-atom_trak_copy_data (AtomTRAK * trak, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_copy_data (&trak->header, buffer, size, offset)) {
- return 0;
- }
- if (!atom_tkhd_copy_data (&trak->tkhd, buffer, size, offset)) {
- return 0;
- }
- if (trak->edts) {
- if (!atom_edts_copy_data (trak->edts, buffer, size, offset)) {
- return 0;
- }
- }
-
- if (!atom_mdia_copy_data (&trak->mdia, buffer, size, offset)) {
- return 0;
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_tag_data_copy_data (AtomTagData * data, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_full_copy_data (&data->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (data->reserved, buffer, size, offset);
- prop_copy_uint8_array (data->data, data->datalen, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_tag_copy_data (AtomTag * tag, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_copy_data (&tag->header, buffer, size, offset)) {
- return 0;
- }
-
- if (!atom_tag_data_copy_data (&tag->data, buffer, size, offset)) {
- return 0;
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_ilst_copy_data (AtomILST * ilst, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_copy_data (&ilst->header, buffer, size, offset)) {
- return 0;
- }
- /* extra atoms */
- if (ilst->entries &&
- !atom_info_list_copy_data (ilst->entries, buffer, size, offset))
- return 0;
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_meta_copy_data (AtomMETA * meta, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_full_copy_data (&meta->header, buffer, size, offset)) {
- return 0;
- }
- if (!atom_hdlr_copy_data (&meta->hdlr, buffer, size, offset)) {
- return 0;
- }
- if (meta->ilst) {
- if (!atom_ilst_copy_data (meta->ilst, buffer, size, offset)) {
- return 0;
- }
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_udta_copy_data (AtomUDTA * udta, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_copy_data (&udta->header, buffer, size, offset)) {
- return 0;
- }
- if (udta->meta) {
- if (!atom_meta_copy_data (udta->meta, buffer, size, offset)) {
- return 0;
- }
- }
- if (udta->entries) {
- /* extra atoms */
- if (!atom_info_list_copy_data (udta->entries, buffer, size, offset))
- return 0;
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_mehd_copy_data (AtomMEHD * mehd, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_full_copy_data (&mehd->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint64 (mehd->fragment_duration, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_trex_copy_data (AtomTREX * trex, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_full_copy_data (&trex->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (trex->track_ID, buffer, size, offset);
- prop_copy_uint32 (trex->default_sample_description_index, buffer, size,
- offset);
- prop_copy_uint32 (trex->default_sample_duration, buffer, size, offset);
- prop_copy_uint32 (trex->default_sample_size, buffer, size, offset);
- prop_copy_uint32 (trex->default_sample_flags, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_mvex_copy_data (AtomMVEX * mvex, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
- GList *walker;
-
- if (!atom_copy_data (&mvex->header, buffer, size, offset)) {
- return 0;
- }
-
- if (!atom_mehd_copy_data (&mvex->mehd, buffer, size, offset)) {
- return 0;
- }
-
- walker = g_list_first (mvex->trexs);
- while (walker != NULL) {
- if (!atom_trex_copy_data ((AtomTREX *) walker->data, buffer, size, offset)) {
- return 0;
- }
- walker = g_list_next (walker);
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-guint64
-atom_moov_copy_data (AtomMOOV * atom, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
- GList *walker;
-
- if (!atom_copy_data (&(atom->header), buffer, size, offset))
- return 0;
-
- if (!atom_mvhd_copy_data (&(atom->mvhd), buffer, size, offset))
- return 0;
-
- walker = g_list_first (atom->traks);
- while (walker != NULL) {
- if (!atom_trak_copy_data ((AtomTRAK *) walker->data, buffer, size, offset)) {
- return 0;
- }
- walker = g_list_next (walker);
- }
-
- if (atom->udta) {
- if (!atom_udta_copy_data (atom->udta, buffer, size, offset)) {
- return 0;
- }
- }
-
- if (atom->fragmented) {
- if (!atom_mvex_copy_data (&atom->mvex, buffer, size, offset)) {
- return 0;
- }
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_wave_copy_data (AtomWAVE * wave, guint8 ** buffer,
- guint64 * size, guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_copy_data (&(wave->header), buffer, size, offset))
- return 0;
-
- if (wave->extension_atoms) {
- if (!atom_info_list_copy_data (wave->extension_atoms, buffer, size, offset))
- return 0;
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-/* -- end of copy data functions -- */
-
-/* -- general functions, API and support functions */
-
-/* add samples to tables */
-
-static void
-atom_stsc_add_new_entry (AtomSTSC * stsc, guint32 first_chunk, guint32 nsamples)
-{
- STSCEntry nentry;
- gint len;
-
- if ((len = atom_array_get_len (&stsc->entries)) &&
- ((atom_array_index (&stsc->entries, len - 1)).samples_per_chunk ==
- nsamples))
- return;
-
- nentry.first_chunk = first_chunk;
- nentry.samples_per_chunk = nsamples;
- nentry.sample_description_index = 1;
- atom_array_append (&stsc->entries, nentry, 128);
-}
-
-static void
-atom_stts_add_entry (AtomSTTS * stts, guint32 sample_count, gint32 sample_delta)
-{
- STTSEntry *entry = NULL;
-
- if (G_LIKELY (atom_array_get_len (&stts->entries) != 0))
- entry = &atom_array_index (&stts->entries,
- atom_array_get_len (&stts->entries) - 1);
-
- if (entry && entry->sample_delta == sample_delta) {
- entry->sample_count += sample_count;
- } else {
- STTSEntry nentry;
-
- nentry.sample_count = sample_count;
- nentry.sample_delta = sample_delta;
- atom_array_append (&stts->entries, nentry, 256);
- }
-}
-
-static void
-atom_stsz_add_entry (AtomSTSZ * stsz, guint32 nsamples, guint32 size)
-{
- guint32 i;
-
- stsz->table_size += nsamples;
- if (stsz->sample_size != 0) {
- /* it is constant size, we don't need entries */
- return;
- }
- for (i = 0; i < nsamples; i++) {
- atom_array_append (&stsz->entries, size, 1024);
- }
-}
-
-static guint32
-atom_stco64_get_entry_count (AtomSTCO64 * stco64)
-{
- return atom_array_get_len (&stco64->entries);
-}
-
-static void
-atom_stco64_add_entry (AtomSTCO64 * stco64, guint64 entry)
-{
- atom_array_append (&stco64->entries, entry, 256);
- if (entry > G_MAXUINT32)
- stco64->header.header.type = FOURCC_co64;
-}
-
-static void
-atom_stss_add_entry (AtomSTSS * stss, guint32 sample)
-{
- atom_array_append (&stss->entries, sample, 512);
-}
-
-static void
-atom_stbl_add_stss_entry (AtomSTBL * stbl)
-{
- guint32 sample_index = stbl->stsz.table_size;
-
- atom_stss_add_entry (&stbl->stss, sample_index);
-}
-
-static void
-atom_ctts_add_entry (AtomCTTS * ctts, guint32 nsamples, guint32 offset)
-{
- CTTSEntry *entry = NULL;
-
- if (G_LIKELY (atom_array_get_len (&ctts->entries) != 0))
- entry = &atom_array_index (&ctts->entries,
- atom_array_get_len (&ctts->entries) - 1);
-
- if (entry == NULL || entry->sampleoffset != offset) {
- CTTSEntry nentry;
-
- nentry.samplecount = nsamples;
- nentry.sampleoffset = offset;
- atom_array_append (&ctts->entries, nentry, 256);
- if (offset != 0)
- ctts->do_pts = TRUE;
- } else {
- entry->samplecount += nsamples;
- }
-}
-
-static void
-atom_stbl_add_ctts_entry (AtomSTBL * stbl, guint32 nsamples, guint32 offset)
-{
- if (stbl->ctts == NULL) {
- stbl->ctts = atom_ctts_new ();
- }
- atom_ctts_add_entry (stbl->ctts, nsamples, offset);
-}
-
-void
-atom_stbl_add_samples (AtomSTBL * stbl, guint32 nsamples, guint32 delta,
- guint32 size, guint64 chunk_offset, gboolean sync, gint64 pts_offset)
-{
- atom_stts_add_entry (&stbl->stts, nsamples, delta);
- atom_stsz_add_entry (&stbl->stsz, nsamples, size);
- atom_stco64_add_entry (&stbl->stco64, chunk_offset);
- atom_stsc_add_new_entry (&stbl->stsc,
- atom_stco64_get_entry_count (&stbl->stco64), nsamples);
- if (sync)
- atom_stbl_add_stss_entry (stbl);
- /* always store to arrange for consistent content */
- atom_stbl_add_ctts_entry (stbl, nsamples, pts_offset);
-}
-
-void
-atom_trak_add_samples (AtomTRAK * trak, guint32 nsamples, guint32 delta,
- guint32 size, guint64 chunk_offset, gboolean sync, gint64 pts_offset)
-{
- AtomSTBL *stbl = &trak->mdia.minf.stbl;
- atom_stbl_add_samples (stbl, nsamples, delta, size, chunk_offset, sync,
- pts_offset);
-}
-
-/* trak and moov molding */
-
-guint32
-atom_trak_get_timescale (AtomTRAK * trak)
-{
- return trak->mdia.mdhd.time_info.timescale;
-}
-
-guint32
-atom_trak_get_id (AtomTRAK * trak)
-{
- return trak->tkhd.track_ID;
-}
-
-static void
-atom_trak_set_id (AtomTRAK * trak, guint32 id)
-{
- trak->tkhd.track_ID = id;
-}
-
-static void
-atom_moov_add_trex (AtomMOOV * moov, AtomTREX * trex)
-{
- moov->mvex.trexs = g_list_append (moov->mvex.trexs, trex);
-}
-
-static AtomTREX *
-atom_trex_new (AtomTRAK * trak)
-{
- guint8 flags[3] = { 0, 0, 0 };
- AtomTREX *trex = g_new0 (AtomTREX, 1);
-
- atom_full_init (&trex->header, FOURCC_trex, 0, 0, 0, flags);
-
- trex->track_ID = trak->tkhd.track_ID;
- trex->default_sample_description_index = 1;
- trex->default_sample_duration = 0;
- trex->default_sample_size = 0;
- trex->default_sample_flags = 0;
-
- return trex;
-}
-
-void
-atom_moov_add_trak (AtomMOOV * moov, AtomTRAK * trak)
-{
- atom_trak_set_id (trak, moov->mvhd.next_track_id++);
- moov->traks = g_list_append (moov->traks, trak);
- /* additional trak means also new trex */
- atom_moov_add_trex (moov, atom_trex_new (trak));
-}
-
-static guint64
-atom_trak_get_duration (AtomTRAK * trak)
-{
- return trak->tkhd.duration;
-}
-
-static guint64
-atom_stts_get_total_duration (AtomSTTS * stts)
-{
- guint i;
- guint64 sum = 0;
-
- for (i = 0; i < atom_array_get_len (&stts->entries); i++) {
- STTSEntry *entry = &atom_array_index (&stts->entries, i);
-
- sum += (guint64) (entry->sample_count) * entry->sample_delta;
- }
- return sum;
-}
-
-static void
-atom_trak_update_duration (AtomTRAK * trak, guint64 moov_timescale)
-{
- trak->mdia.mdhd.time_info.duration =
- atom_stts_get_total_duration (&trak->mdia.minf.stbl.stts);
- if (trak->mdia.mdhd.time_info.timescale != 0) {
- trak->tkhd.duration =
- gst_util_uint64_scale (trak->mdia.mdhd.time_info.duration,
- moov_timescale, trak->mdia.mdhd.time_info.timescale);
- } else {
- trak->tkhd.duration = 0;
- }
-}
-
-static guint32
-atom_moov_get_timescale (AtomMOOV * moov)
-{
- return moov->mvhd.time_info.timescale;
-}
-
-void
-atom_moov_update_timescale (AtomMOOV * moov, guint32 timescale)
-{
- moov->mvhd.time_info.timescale = timescale;
-}
-
-void
-atom_moov_update_duration (AtomMOOV * moov)
-{
- GList *traks = moov->traks;
- guint64 dur, duration = 0;
-
- while (traks) {
- AtomTRAK *trak = (AtomTRAK *) traks->data;
-
- atom_trak_update_duration (trak, atom_moov_get_timescale (moov));
- dur = atom_trak_get_duration (trak);
- if (dur > duration)
- duration = dur;
- traks = g_list_next (traks);
- }
- moov->mvhd.time_info.duration = duration;
- moov->mvex.mehd.fragment_duration = duration;
-}
-
-void
-atom_moov_set_fragmented (AtomMOOV * moov, gboolean fragmented)
-{
- moov->fragmented = fragmented;
-}
-
-void
-atom_stco64_chunks_add_offset (AtomSTCO64 * stco64, guint32 offset)
-{
- guint i;
-
- for (i = 0; i < atom_array_get_len (&stco64->entries); i++) {
- guint64 *value = &atom_array_index (&stco64->entries, i);
-
- *value += offset;
- }
-}
-
-void
-atom_moov_chunks_add_offset (AtomMOOV * moov, guint32 offset)
-{
- GList *traks = moov->traks;
-
- while (traks) {
- AtomTRAK *trak = (AtomTRAK *) traks->data;
-
- atom_stco64_chunks_add_offset (&trak->mdia.minf.stbl.stco64, offset);
- traks = g_list_next (traks);
- }
-}
-
-/*
- * Meta tags functions
- */
-static void
-atom_moov_init_metatags (AtomMOOV * moov, AtomsContext * context)
-{
- if (!moov->udta) {
- moov->udta = atom_udta_new ();
- }
- if (context->flavor != ATOMS_TREE_FLAVOR_3GP) {
- if (!moov->udta->meta) {
- moov->udta->meta = atom_meta_new ();
- }
- if (!moov->udta->meta->ilst) {
- moov->udta->meta->ilst = atom_ilst_new ();
- }
- }
-}
-
-static void
-atom_tag_data_alloc_data (AtomTagData * data, guint size)
-{
- if (data->data != NULL) {
- g_free (data->data);
- }
- data->data = g_new0 (guint8, size);
- data->datalen = size;
-}
-
-static void
-atom_moov_append_tag (AtomMOOV * moov, AtomInfo * tag)
-{
- GList **entries;
-
- atom_moov_init_metatags (moov, &moov->context);
- if (moov->udta->meta)
- entries = &moov->udta->meta->ilst->entries;
- else
- entries = &moov->udta->entries;
- *entries = g_list_append (*entries, tag);
-}
-
-void
-atom_moov_add_tag (AtomMOOV * moov, guint32 fourcc, guint32 flags,
- const guint8 * data, guint size)
-{
- AtomTag *tag;
- AtomTagData *tdata;
-
- tag = atom_tag_new (fourcc, flags);
- tdata = &tag->data;
- atom_tag_data_alloc_data (tdata, size);
- g_memmove (tdata->data, data, size);
-
- atom_moov_append_tag (moov,
- build_atom_info_wrapper ((Atom *) tag, atom_tag_copy_data,
- atom_tag_free));
-}
-
-void
-atom_moov_add_str_tag (AtomMOOV * moov, guint32 fourcc, const gchar * value)
-{
- gint len = strlen (value);
-
- if (len > 0)
- atom_moov_add_tag (moov, fourcc, METADATA_TEXT_FLAG, (guint8 *) value, len);
-}
-
-void
-atom_moov_add_uint_tag (AtomMOOV * moov, guint32 fourcc, guint32 flags,
- guint32 value)
-{
- guint8 data[8] = { 0, };
-
- if (flags) {
- GST_WRITE_UINT16_BE (data, value);
- atom_moov_add_tag (moov, fourcc, flags, data, 2);
- } else {
- GST_WRITE_UINT32_BE (data + 2, value);
- atom_moov_add_tag (moov, fourcc, flags, data, 8);
- }
-}
-
-void
-atom_moov_add_blob_tag (AtomMOOV * moov, guint8 * data, guint size)
-{
- AtomData *data_atom;
- GstBuffer *buf;
- guint len;
- guint32 fourcc;
-
- if (size < 8)
- return;
-
- /* blob is unparsed atom;
- * extract size and fourcc, and wrap remainder in data atom */
- len = GST_READ_UINT32_BE (data);
- fourcc = GST_READ_UINT32_LE (data + 4);
- if (len > size)
- return;
-
- buf = gst_buffer_new ();
- GST_BUFFER_SIZE (buf) = len - 8;
- GST_BUFFER_DATA (buf) = data + 8;
-
- data_atom = atom_data_new_from_gst_buffer (fourcc, buf);
- gst_buffer_unref (buf);
-
- atom_moov_append_tag (moov,
- build_atom_info_wrapper ((Atom *) data_atom, atom_data_copy_data,
- atom_data_free));
-}
-
-void
-atom_moov_add_3gp_tag (AtomMOOV * moov, guint32 fourcc, guint8 * data,
- guint size)
-{
- AtomData *data_atom;
- GstBuffer *buf;
- guint8 *bdata;
-
- /* need full atom */
- buf = gst_buffer_new_and_alloc (size + 4);
- bdata = GST_BUFFER_DATA (buf);
- /* full atom: version and flags */
- GST_WRITE_UINT32_BE (bdata, 0);
- memcpy (bdata + 4, data, size);
-
- data_atom = atom_data_new_from_gst_buffer (fourcc, buf);
- gst_buffer_unref (buf);
-
- atom_moov_append_tag (moov,
- build_atom_info_wrapper ((Atom *) data_atom, atom_data_copy_data,
- atom_data_free));
-}
-
-guint16
-language_code (const char *lang)
-{
- g_return_val_if_fail (lang != NULL, 0);
- g_return_val_if_fail (strlen (lang) == 3, 0);
-
- return (((lang[0] - 0x60) & 0x1F) << 10) + (((lang[1] - 0x60) & 0x1F) << 5) +
- ((lang[2] - 0x60) & 0x1F);
-}
-
-void
-atom_moov_add_3gp_str_int_tag (AtomMOOV * moov, guint32 fourcc,
- const gchar * value, gint16 ivalue)
-{
- gint len = 0, size = 0;
- guint8 *data;
-
- if (value) {
- len = strlen (value);
- size = len + 3;
- }
-
- if (ivalue >= 0)
- size += 2;
-
- data = g_malloc (size + 3);
- /* language tag and null-terminated UTF-8 string */
- if (value) {
- GST_WRITE_UINT16_BE (data, language_code (GST_QT_MUX_DEFAULT_TAG_LANGUAGE));
- /* include 0 terminator */
- memcpy (data + 2, value, len + 1);
- }
- /* 16-bit unsigned int if standalone, otherwise 8-bit */
- if (ivalue >= 0) {
- if (size == 2)
- GST_WRITE_UINT16_BE (data + size - 2, ivalue);
- else {
- GST_WRITE_UINT8 (data + size - 2, ivalue & 0xFF);
- size--;
- }
- }
-
- atom_moov_add_3gp_tag (moov, fourcc, data, size);
- g_free (data);
-}
-
-void
-atom_moov_add_3gp_str_tag (AtomMOOV * moov, guint32 fourcc, const gchar * value)
-{
- atom_moov_add_3gp_str_int_tag (moov, fourcc, value, -1);
-}
-
-void
-atom_moov_add_3gp_uint_tag (AtomMOOV * moov, guint32 fourcc, guint16 value)
-{
- atom_moov_add_3gp_str_int_tag (moov, fourcc, NULL, value);
-}
-
-void
-atom_moov_add_xmp_tags (AtomMOOV * moov, GstBuffer * xmpbuffer)
-{
- AtomData *data_atom = NULL;
-
- if (moov->context.flavor == ATOMS_TREE_FLAVOR_MOV) {
- if (xmpbuffer) {
- data_atom = atom_data_new_from_gst_buffer (FOURCC_XMP_, xmpbuffer);
- atom_moov_init_metatags (moov, &moov->context);
- moov->udta->entries = g_list_append (moov->udta->entries,
- build_atom_info_wrapper ((Atom *) data_atom, atom_data_copy_data,
- atom_data_free));
- }
- } else {
- GST_DEBUG ("Not adding xmp to moov atom, it is only used in 'mov' format");
- }
-
-}
-
-/*
- * Functions for specifying media types
- */
-
-static void
-atom_minf_set_audio (AtomMINF * minf)
-{
- atom_minf_clear_handlers (minf);
- minf->smhd = atom_smhd_new ();
-}
-
-static void
-atom_minf_set_video (AtomMINF * minf, AtomsContext * context)
-{
- atom_minf_clear_handlers (minf);
- minf->vmhd = atom_vmhd_new (context);
-}
-
-static void
-atom_hdlr_set_type (AtomHDLR * hdlr, AtomsContext * context, guint32 comp_type,
- guint32 hdlr_type)
-{
- if (context->flavor == ATOMS_TREE_FLAVOR_MOV) {
- hdlr->component_type = comp_type;
- }
- hdlr->handler_type = hdlr_type;
-}
-
-static void
-atom_hdlr_set_name (AtomHDLR * hdlr, const char *name)
-{
- if (hdlr->name)
- g_free (hdlr->name);
- hdlr->name = g_strdup (name);
-}
-
-static void
-atom_mdia_set_hdlr_type_audio (AtomMDIA * mdia, AtomsContext * context)
-{
- atom_hdlr_set_type (&mdia->hdlr, context, FOURCC_mhlr, FOURCC_soun);
- /* Some players (low-end hardware) check for this name, which is what
- * QuickTime itself sets */
- atom_hdlr_set_name (&mdia->hdlr, "SoundHandler");
-}
-
-static void
-atom_mdia_set_hdlr_type_video (AtomMDIA * mdia, AtomsContext * context)
-{
- atom_hdlr_set_type (&mdia->hdlr, context, FOURCC_mhlr, FOURCC_vide);
- /* Some players (low-end hardware) check for this name, which is what
- * QuickTime itself sets */
- atom_hdlr_set_name (&mdia->hdlr, "VideoHandler");
-}
-
-static void
-atom_mdia_set_audio (AtomMDIA * mdia, AtomsContext * context)
-{
- atom_mdia_set_hdlr_type_audio (mdia, context);
- atom_minf_set_audio (&mdia->minf);
-}
-
-static void
-atom_mdia_set_video (AtomMDIA * mdia, AtomsContext * context)
-{
- atom_mdia_set_hdlr_type_video (mdia, context);
- atom_minf_set_video (&mdia->minf, context);
-}
-
-static void
-atom_tkhd_set_audio (AtomTKHD * tkhd)
-{
- tkhd->volume = 0x0100;
- tkhd->width = tkhd->height = 0;
-}
-
-static void
-atom_tkhd_set_video (AtomTKHD * tkhd, AtomsContext * context, guint32 width,
- guint32 height)
-{
- tkhd->volume = 0;
-
- /* qt and ISO base media do not contradict, and examples agree */
- tkhd->width = width;
- tkhd->height = height;
-}
-
-static void
-atom_edts_add_entry (AtomEDTS * edts, EditListEntry * entry)
-{
- edts->elst.entries = g_slist_append (edts->elst.entries, entry);
-}
-
-/*
- * Adds a new entry to this trak edits list
- * duration is in the moov's timescale
- * media_time is the offset in the media time to start from (media's timescale)
- * rate is a 32 bits fixed-point
- */
-void
-atom_trak_add_elst_entry (AtomTRAK * trak, guint32 duration, guint32 media_time,
- guint32 rate)
-{
- EditListEntry *entry = g_new (EditListEntry, 1);
-
- entry->duration = duration;
- entry->media_time = media_time;
- entry->media_rate = rate;
-
- if (trak->edts == NULL) {
- trak->edts = atom_edts_new ();
- }
- atom_edts_add_entry (trak->edts, entry);
-}
-
-/* re-negotiation is prevented at top-level, so only 1 entry expected.
- * Quite some more care here and elsewhere may be needed to
- * support several entries */
-static SampleTableEntryMP4A *
-atom_trak_add_audio_entry (AtomTRAK * trak, AtomsContext * context,
- guint32 type)
-{
- AtomSTSD *stsd = &trak->mdia.minf.stbl.stsd;
- SampleTableEntryMP4A *mp4a = sample_entry_mp4a_new ();
-
- mp4a->se.header.type = type;
- mp4a->se.kind = AUDIO;
- mp4a->compression_id = -1;
- mp4a->se.data_reference_index = 1;
-
- stsd->entries = g_list_prepend (stsd->entries, mp4a);
- stsd->n_entries++;
- return mp4a;
-}
-
-static SampleTableEntryMP4V *
-atom_trak_add_video_entry (AtomTRAK * trak, AtomsContext * context,
- guint32 type)
-{
- SampleTableEntryMP4V *mp4v = sample_entry_mp4v_new (context);
- AtomSTSD *stsd = &trak->mdia.minf.stbl.stsd;
-
- mp4v->se.header.type = type;
- mp4v->se.kind = VIDEO;
- mp4v->se.data_reference_index = 1;
- mp4v->horizontal_resolution = 72 << 16;
- mp4v->vertical_resolution = 72 << 16;
- if (context->flavor == ATOMS_TREE_FLAVOR_MOV) {
- mp4v->spatial_quality = 512;
- mp4v->temporal_quality = 512;
- }
-
- stsd->entries = g_list_prepend (stsd->entries, mp4v);
- stsd->n_entries++;
- return mp4v;
-}
-
-static void
-atom_trak_set_constant_size_samples (AtomTRAK * trak, guint32 sample_size)
-{
- trak->mdia.minf.stbl.stsz.sample_size = sample_size;
-}
-
-static void
-atom_trak_set_audio (AtomTRAK * trak, AtomsContext * context)
-{
- atom_tkhd_set_audio (&trak->tkhd);
- atom_mdia_set_audio (&trak->mdia, context);
-}
-
-static void
-atom_trak_set_video (AtomTRAK * trak, AtomsContext * context, guint32 width,
- guint32 height)
-{
- atom_tkhd_set_video (&trak->tkhd, context, width, height);
- atom_mdia_set_video (&trak->mdia, context);
-}
-
-static void
-atom_trak_set_audio_commons (AtomTRAK * trak, AtomsContext * context,
- guint32 rate)
-{
- atom_trak_set_audio (trak, context);
- trak->mdia.mdhd.time_info.timescale = rate;
-}
-
-static void
-atom_trak_set_video_commons (AtomTRAK * trak, AtomsContext * context,
- guint32 rate, guint32 width, guint32 height)
-{
- atom_trak_set_video (trak, context, width, height);
- trak->mdia.mdhd.time_info.timescale = rate;
- trak->tkhd.width = width << 16;
- trak->tkhd.height = height << 16;
-}
-
-void
-atom_trak_set_audio_type (AtomTRAK * trak, AtomsContext * context,
- AudioSampleEntry * entry, guint32 scale, AtomInfo * ext, gint sample_size)
-{
- SampleTableEntryMP4A *ste;
-
- atom_trak_set_audio_commons (trak, context, scale);
- atom_stsd_remove_entries (&trak->mdia.minf.stbl.stsd);
- ste = atom_trak_add_audio_entry (trak, context, entry->fourcc);
-
- trak->is_video = FALSE;
- trak->is_h264 = FALSE;
-
- ste->version = entry->version;
- ste->compression_id = entry->compression_id;
- ste->sample_size = entry->sample_size;
- ste->sample_rate = entry->sample_rate << 16;
- ste->channels = entry->channels;
-
- ste->samples_per_packet = entry->samples_per_packet;
- ste->bytes_per_sample = entry->bytes_per_sample;
- ste->bytes_per_packet = entry->bytes_per_packet;
- ste->bytes_per_frame = entry->bytes_per_frame;
-
- if (ext)
- ste->extension_atoms = g_list_prepend (ste->extension_atoms, ext);
-
- /* 0 size means variable size */
- atom_trak_set_constant_size_samples (trak, sample_size);
-}
-
-static AtomInfo *
-build_pasp_extension (AtomTRAK * trak, gint par_width, gint par_height)
-{
- AtomData *atom_data;
- GstBuffer *buf;
- guint8 *data;
-
- buf = gst_buffer_new_and_alloc (8);
- data = GST_BUFFER_DATA (buf);
-
- /* ihdr = image header box */
- GST_WRITE_UINT32_BE (data, par_width);
- GST_WRITE_UINT32_BE (data + 4, par_height);
-
- atom_data = atom_data_new_from_gst_buffer (FOURCC_pasp, buf);
- gst_buffer_unref (buf);
-
- return build_atom_info_wrapper ((Atom *) atom_data, atom_data_copy_data,
- atom_data_free);
-}
-
-void
-atom_trak_set_video_type (AtomTRAK * trak, AtomsContext * context,
- VisualSampleEntry * entry, guint32 scale, GList * ext_atoms_list)
-{
- SampleTableEntryMP4V *ste;
- gint dwidth, dheight;
- gint par_n = 0, par_d = 0;
-
- if ((entry->par_n != 1 || entry->par_d != 1) &&
- (entry->par_n != entry->par_d)) {
- par_n = entry->par_n;
- par_d = entry->par_d;
- }
-
- dwidth = entry->width;
- dheight = entry->height;
- /* ISO file spec says track header w/h indicates track's visual presentation
- * (so this together with pixels w/h implicitly defines PAR) */
- if (par_n && (context->flavor != ATOMS_TREE_FLAVOR_MOV)) {
- if (par_n > par_d) {
- dwidth = entry->width * par_n / par_d;
- dheight = entry->height;
- } else {
- dwidth = entry->width * par_n / par_d;
- dheight = entry->height;
- }
- }
-
- atom_trak_set_video_commons (trak, context, scale, dwidth, dheight);
- atom_stsd_remove_entries (&trak->mdia.minf.stbl.stsd);
- ste = atom_trak_add_video_entry (trak, context, entry->fourcc);
-
- trak->is_video = TRUE;
- trak->is_h264 = (entry->fourcc == FOURCC_avc1);
-
- ste->version = entry->version;
- ste->width = entry->width;
- ste->height = entry->height;
- ste->depth = entry->depth;
- ste->color_table_id = entry->color_table_id;
- ste->frame_count = entry->frame_count;
-
- if (ext_atoms_list)
- ste->extension_atoms = g_list_concat (ste->extension_atoms, ext_atoms_list);
-
- /* QT spec has a pasp extension atom in stsd that can hold PAR */
- if (par_n && (context->flavor == ATOMS_TREE_FLAVOR_MOV)) {
- ste->extension_atoms = g_list_append (ste->extension_atoms,
- build_pasp_extension (trak, par_n, par_d));
- }
-}
-
-static void
-atom_mfhd_init (AtomMFHD * mfhd, guint32 sequence_number)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&(mfhd->header), FOURCC_mfhd, 0, 0, 0, flags);
- mfhd->sequence_number = sequence_number;
-}
-
-static void
-atom_moof_init (AtomMOOF * moof, AtomsContext * context,
- guint32 sequence_number)
-{
- atom_header_set (&moof->header, FOURCC_moof, 0, 0);
- atom_mfhd_init (&moof->mfhd, sequence_number);
- moof->trafs = NULL;
-}
-
-AtomMOOF *
-atom_moof_new (AtomsContext * context, guint32 sequence_number)
-{
- AtomMOOF *moof = g_new0 (AtomMOOF, 1);
-
- atom_moof_init (moof, context, sequence_number);
- return moof;
-}
-
-static void
-atom_trun_free (AtomTRUN * trun)
-{
- atom_full_clear (&trun->header);
- atom_array_clear (&trun->entries);
- g_free (trun);
-}
-
-static void
-atom_sdtp_free (AtomSDTP * sdtp)
-{
- atom_full_clear (&sdtp->header);
- atom_array_clear (&sdtp->entries);
- g_free (sdtp);
-}
-
-void
-atom_traf_free (AtomTRAF * traf)
-{
- GList *walker;
-
- walker = traf->truns;
- while (walker) {
- atom_trun_free ((AtomTRUN *) walker->data);
- walker = g_list_next (walker);
- }
- g_list_free (traf->truns);
- traf->truns = NULL;
-
- walker = traf->sdtps;
- while (walker) {
- atom_sdtp_free ((AtomSDTP *) walker->data);
- walker = g_list_next (walker);
- }
- g_list_free (traf->sdtps);
- traf->sdtps = NULL;
-
- g_free (traf);
-}
-
-void
-atom_moof_free (AtomMOOF * moof)
-{
- GList *walker;
-
- walker = moof->trafs;
- while (walker) {
- atom_traf_free ((AtomTRAF *) walker->data);
- walker = g_list_next (walker);
- }
- g_list_free (moof->trafs);
- moof->trafs = NULL;
-
- g_free (moof);
-}
-
-static guint64
-atom_mfhd_copy_data (AtomMFHD * mfhd, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_full_copy_data (&mfhd->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (mfhd->sequence_number, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_tfhd_copy_data (AtomTFHD * tfhd, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
- guint32 flags;
-
- if (!atom_full_copy_data (&tfhd->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (tfhd->track_ID, buffer, size, offset);
-
- flags = atom_full_get_flags_as_uint (&tfhd->header);
-
- if (flags & TF_BASE_DATA_OFFSET)
- prop_copy_uint64 (tfhd->base_data_offset, buffer, size, offset);
- if (flags & TF_SAMPLE_DESCRIPTION_INDEX)
- prop_copy_uint32 (tfhd->sample_description_index, buffer, size, offset);
- if (flags & TF_DEFAULT_SAMPLE_DURATION)
- prop_copy_uint32 (tfhd->default_sample_duration, buffer, size, offset);
- if (flags & TF_DEFAULT_SAMPLE_SIZE)
- prop_copy_uint32 (tfhd->default_sample_size, buffer, size, offset);
- if (flags & TF_DEFAULT_SAMPLE_FLAGS)
- prop_copy_uint32 (tfhd->default_sample_flags, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_trun_copy_data (AtomTRUN * trun, guint8 ** buffer, guint64 * size,
- guint64 * offset, guint32 * data_offset)
-{
- guint64 original_offset = *offset;
- guint32 flags, i;
-
- flags = atom_full_get_flags_as_uint (&trun->header);
-
- /* if first trun in moof, forcibly add data_offset and record
- * where it must be written later on */
- if (data_offset && !*data_offset) {
- flags |= TR_DATA_OFFSET;
- } else {
- flags &= ~TR_DATA_OFFSET;
- }
-
- atom_full_set_flags_as_uint (&trun->header, flags);
-
- if (!atom_full_copy_data (&trun->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (trun->sample_count, buffer, size, offset);
-
- if (flags & TR_DATA_OFFSET) {
- *data_offset = *offset;
- prop_copy_int32 (trun->data_offset, buffer, size, offset);
- }
- if (flags & TR_FIRST_SAMPLE_FLAGS)
- prop_copy_uint32 (trun->first_sample_flags, buffer, size, offset);
-
- for (i = 0; i < atom_array_get_len (&trun->entries); i++) {
- TRUNSampleEntry *entry = &atom_array_index (&trun->entries, i);
-
- if (flags & TR_SAMPLE_DURATION)
- prop_copy_uint32 (entry->sample_duration, buffer, size, offset);
- if (flags & TR_SAMPLE_SIZE)
- prop_copy_uint32 (entry->sample_size, buffer, size, offset);
- if (flags & TR_SAMPLE_FLAGS)
- prop_copy_uint32 (entry->sample_flags, buffer, size, offset);
- if (flags & TR_COMPOSITION_TIME_OFFSETS)
- prop_copy_uint32 (entry->sample_composition_time_offset,
- buffer, size, offset);
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_sdtp_copy_data (AtomSDTP * sdtp, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!atom_full_copy_data (&sdtp->header, buffer, size, offset)) {
- return 0;
- }
-
- /* all entries at once */
- prop_copy_fixed_size_string (&atom_array_index (&sdtp->entries, 0),
- atom_array_get_len (&sdtp->entries), buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_traf_copy_data (AtomTRAF * traf, guint8 ** buffer, guint64 * size,
- guint64 * offset, guint32 * data_offset)
-{
- guint64 original_offset = *offset;
- GList *walker;
-
- if (!atom_copy_data (&traf->header, buffer, size, offset)) {
- return 0;
- }
- if (!atom_tfhd_copy_data (&traf->tfhd, buffer, size, offset)) {
- return 0;
- }
-
- walker = g_list_first (traf->truns);
- while (walker != NULL) {
- if (!atom_trun_copy_data ((AtomTRUN *) walker->data, buffer, size, offset,
- data_offset)) {
- return 0;
- }
- walker = g_list_next (walker);
- }
-
- walker = g_list_first (traf->sdtps);
- while (walker != NULL) {
- if (!atom_sdtp_copy_data ((AtomSDTP *) walker->data, buffer, size, offset)) {
- return 0;
- }
- walker = g_list_next (walker);
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-/* creates moof atom; metadata is written expecting actual buffer data
- * is in mdata directly after moof, and is consecutively written per trak */
-guint64
-atom_moof_copy_data (AtomMOOF * moof, guint8 ** buffer,
- guint64 * size, guint64 * offset)
-{
- guint64 original_offset = *offset;
- GList *walker;
- guint32 data_offset = 0;
-
- if (!atom_copy_data (&moof->header, buffer, size, offset))
- return 0;
-
- if (!atom_mfhd_copy_data (&moof->mfhd, buffer, size, offset))
- return 0;
-
- walker = g_list_first (moof->trafs);
- while (walker != NULL) {
- if (!atom_traf_copy_data ((AtomTRAF *) walker->data, buffer, size, offset,
- &data_offset)) {
- return 0;
- }
- walker = g_list_next (walker);
- }
-
- atom_write_size (buffer, size, offset, original_offset);
-
- if (*buffer && data_offset) {
- /* first trun needs a data-offset relative to moof start
- * = moof size + mdat prefix */
- GST_WRITE_UINT32_BE (*buffer + data_offset, *offset - original_offset + 8);
- }
-
- return *offset - original_offset;
-}
-
-static void
-atom_tfhd_init (AtomTFHD * tfhd, guint32 track_ID)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&tfhd->header, FOURCC_tfhd, 0, 0, 0, flags);
- tfhd->track_ID = track_ID;
- tfhd->base_data_offset = 0;
- tfhd->sample_description_index = 1;
- tfhd->default_sample_duration = 0;
- tfhd->default_sample_size = 0;
- tfhd->default_sample_flags = 0;
-}
-
-static void
-atom_trun_init (AtomTRUN * trun)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&trun->header, FOURCC_trun, 0, 0, 0, flags);
- trun->sample_count = 0;
- trun->data_offset = 0;
- trun->first_sample_flags = 0;
- atom_array_init (&trun->entries, 512);
-}
-
-static AtomTRUN *
-atom_trun_new (void)
-{
- AtomTRUN *trun = g_new0 (AtomTRUN, 1);
-
- atom_trun_init (trun);
- return trun;
-}
-
-static void
-atom_sdtp_init (AtomSDTP * sdtp)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&sdtp->header, FOURCC_sdtp, 0, 0, 0, flags);
- atom_array_init (&sdtp->entries, 512);
-}
-
-static AtomSDTP *
-atom_sdtp_new (AtomsContext * context)
-{
- AtomSDTP *sdtp = g_new0 (AtomSDTP, 1);
-
- atom_sdtp_init (sdtp);
- return sdtp;
-}
-
-static void
-atom_traf_add_sdtp (AtomTRAF * traf, AtomSDTP * sdtp)
-{
- traf->sdtps = g_list_append (traf->sdtps, sdtp);
-}
-
-static void
-atom_sdtp_add_samples (AtomSDTP * sdtp, guint8 val)
-{
- /* it does not make much/any sense according to specs,
- * but that's how MS isml samples seem to do it */
- atom_array_append (&sdtp->entries, val, 256);
-}
-
-static void
-atom_trun_add_samples (AtomTRUN * trun, guint32 delta, guint32 size,
- guint32 flags, gint64 pts_offset)
-{
- TRUNSampleEntry nentry;
-
- if (pts_offset != 0)
- trun->header.flags[1] |= TR_COMPOSITION_TIME_OFFSETS;
-
- nentry.sample_duration = delta;
- nentry.sample_size = size;
- nentry.sample_flags = flags;
- nentry.sample_composition_time_offset = pts_offset;
- atom_array_append (&trun->entries, nentry, 256);
- trun->sample_count++;
-}
-
-static void
-atom_traf_init (AtomTRAF * traf, AtomsContext * context, guint32 track_ID)
-{
- atom_header_set (&traf->header, FOURCC_traf, 0, 0);
- atom_tfhd_init (&traf->tfhd, track_ID);
- traf->truns = NULL;
-
- if (context->flavor == ATOMS_TREE_FLAVOR_ISML)
- atom_traf_add_sdtp (traf, atom_sdtp_new (context));
-}
-
-AtomTRAF *
-atom_traf_new (AtomsContext * context, guint32 track_ID)
-{
- AtomTRAF *traf = g_new0 (AtomTRAF, 1);
-
- atom_traf_init (traf, context, track_ID);
- return traf;
-}
-
-static void
-atom_traf_add_trun (AtomTRAF * traf, AtomTRUN * trun)
-{
- traf->truns = g_list_append (traf->truns, trun);
-}
-
-void
-atom_traf_add_samples (AtomTRAF * traf, guint32 delta, guint32 size,
- gboolean sync, gint64 pts_offset, gboolean sdtp_sync)
-{
- AtomTRUN *trun;
- guint32 flags;
-
- /* 0x10000 is sample-is-difference-sample flag
- * low byte stuff is what ismv uses */
- flags = (sync ? 0x0 : 0x10000) | (sdtp_sync ? 0x40 : 0xc0);
-
- if (G_UNLIKELY (!traf->truns)) {
- trun = atom_trun_new ();
- atom_traf_add_trun (traf, trun);
- /* optimistic; indicate all defaults present in tfhd */
- traf->tfhd.header.flags[2] = TF_DEFAULT_SAMPLE_DURATION |
- TF_DEFAULT_SAMPLE_SIZE | TF_DEFAULT_SAMPLE_FLAGS;
- traf->tfhd.default_sample_duration = delta;
- traf->tfhd.default_sample_size = size;
- traf->tfhd.default_sample_flags = flags;
- trun->first_sample_flags = flags;
- }
-
- trun = traf->truns->data;
-
- /* check if still matching defaults,
- * if not, abandon default and need entry for each sample */
- if (traf->tfhd.default_sample_duration != delta) {
- traf->tfhd.header.flags[2] &= ~TF_DEFAULT_SAMPLE_DURATION;
- trun->header.flags[1] |= (TR_SAMPLE_DURATION >> 8);
- }
- if (traf->tfhd.default_sample_size != size) {
- traf->tfhd.header.flags[2] &= ~TF_DEFAULT_SAMPLE_SIZE;
- trun->header.flags[1] |= (TR_SAMPLE_SIZE >> 8);
- }
- if (traf->tfhd.default_sample_flags != flags) {
- if (trun->sample_count == 1) {
- /* at least will need first sample flag */
- traf->tfhd.default_sample_flags = flags;
- trun->header.flags[2] |= TR_FIRST_SAMPLE_FLAGS;
- } else {
- /* now we need sample flags for each sample */
- traf->tfhd.header.flags[2] &= ~TF_DEFAULT_SAMPLE_FLAGS;
- trun->header.flags[1] |= (TR_SAMPLE_FLAGS >> 8);
- trun->header.flags[2] &= ~TR_FIRST_SAMPLE_FLAGS;
- }
- }
-
- atom_trun_add_samples (traf->truns->data, delta, size, flags, pts_offset);
-
- if (traf->sdtps)
- atom_sdtp_add_samples (traf->sdtps->data, 0x10 | ((flags & 0xff) >> 4));
-}
-
-guint32
-atom_traf_get_sample_num (AtomTRAF * traf)
-{
- AtomTRUN *trun;
-
- if (G_UNLIKELY (!traf->truns))
- return 0;
-
- trun = traf->truns->data;
- return atom_array_get_len (&trun->entries);
-}
-
-void
-atom_moof_add_traf (AtomMOOF * moof, AtomTRAF * traf)
-{
- moof->trafs = g_list_append (moof->trafs, traf);
-}
-
-static void
-atom_tfra_free (AtomTFRA * tfra)
-{
- atom_full_clear (&tfra->header);
- atom_array_clear (&tfra->entries);
- g_free (tfra);
-}
-
-AtomMFRA *
-atom_mfra_new (AtomsContext * context)
-{
- AtomMFRA *mfra = g_new0 (AtomMFRA, 1);
-
- atom_header_set (&mfra->header, FOURCC_mfra, 0, 0);
- return mfra;
-}
-
-void
-atom_mfra_add_tfra (AtomMFRA * mfra, AtomTFRA * tfra)
-{
- mfra->tfras = g_list_append (mfra->tfras, tfra);
-}
-
-void
-atom_mfra_free (AtomMFRA * mfra)
-{
- GList *walker;
-
- walker = mfra->tfras;
- while (walker) {
- atom_tfra_free ((AtomTFRA *) walker->data);
- walker = g_list_next (walker);
- }
- g_list_free (mfra->tfras);
- mfra->tfras = NULL;
-
- atom_clear (&mfra->header);
- g_free (mfra);
-}
-
-static void
-atom_tfra_init (AtomTFRA * tfra, guint32 track_ID)
-{
- guint8 flags[3] = { 0, 0, 0 };
-
- atom_full_init (&tfra->header, FOURCC_tfra, 0, 0, 0, flags);
- tfra->track_ID = track_ID;
- atom_array_init (&tfra->entries, 512);
-}
-
-AtomTFRA *
-atom_tfra_new (AtomsContext * context, guint32 track_ID)
-{
- AtomTFRA *tfra = g_new0 (AtomTFRA, 1);
-
- atom_tfra_init (tfra, track_ID);
- return tfra;
-
-}
-
-static inline gint
-need_bytes (guint32 num)
-{
- gint n = 0;
-
- while (num >>= 8)
- n++;
-
- return n;
-}
-
-void
-atom_tfra_add_entry (AtomTFRA * tfra, guint64 dts, guint32 sample_num)
-{
- TFRAEntry entry;
-
- entry.time = dts;
- /* fill in later */
- entry.moof_offset = 0;
- /* always write a single trun in a single traf */
- entry.traf_number = 1;
- entry.trun_number = 1;
- entry.sample_number = sample_num;
-
- /* auto-use 64 bits if needed */
- if (dts > G_MAXUINT32)
- tfra->header.version = 1;
-
- /* 1 byte will always do for traf and trun number,
- * check how much sample_num needs */
- tfra->lengths = (tfra->lengths & 0xfc) ||
- MAX (tfra->lengths, need_bytes (sample_num));
-
- atom_array_append (&tfra->entries, entry, 256);
-}
-
-void
-atom_tfra_update_offset (AtomTFRA * tfra, guint64 offset)
-{
- gint i;
-
- /* auto-use 64 bits if needed */
- if (offset > G_MAXUINT32)
- tfra->header.version = 1;
-
- for (i = atom_array_get_len (&tfra->entries) - 1; i >= 0; i--) {
- TFRAEntry *entry = &atom_array_index (&tfra->entries, i);
-
- if (entry->moof_offset)
- break;
- entry->moof_offset = offset;
- }
-}
-
-static guint64
-atom_tfra_copy_data (AtomTFRA * tfra, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
- guint32 i;
- TFRAEntry *entry;
- guint32 data;
- guint bytes;
- guint version;
-
- if (!atom_full_copy_data (&tfra->header, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (tfra->track_ID, buffer, size, offset);
- prop_copy_uint32 (tfra->lengths, buffer, size, offset);
- prop_copy_uint32 (atom_array_get_len (&tfra->entries), buffer, size, offset);
-
- version = tfra->header.version;
- for (i = 0; i < atom_array_get_len (&tfra->entries); ++i) {
- entry = &atom_array_index (&tfra->entries, i);
- if (version) {
- prop_copy_uint64 (entry->time, buffer, size, offset);
- prop_copy_uint64 (entry->moof_offset, buffer, size, offset);
- } else {
- prop_copy_uint32 (entry->time, buffer, size, offset);
- prop_copy_uint32 (entry->moof_offset, buffer, size, offset);
- }
-
- bytes = (tfra->lengths & (0x3 << 4)) + 1;
- data = GUINT32_TO_BE (entry->traf_number);
- prop_copy_fixed_size_string (((guint8 *) & data) + 4 - bytes, bytes,
- buffer, size, offset);
-
- bytes = (tfra->lengths & (0x3 << 2)) + 1;
- data = GUINT32_TO_BE (entry->trun_number);
- prop_copy_fixed_size_string (((guint8 *) & data) + 4 - bytes, bytes,
- buffer, size, offset);
-
- bytes = (tfra->lengths & (0x3)) + 1;
- data = GUINT32_TO_BE (entry->sample_number);
- prop_copy_fixed_size_string (((guint8 *) & data) + 4 - bytes, bytes,
- buffer, size, offset);
-
- }
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-static guint64
-atom_mfro_copy_data (guint32 s, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
- guint8 flags[3] = { 0, 0, 0 };
- AtomFull mfro;
-
- atom_full_init (&mfro, FOURCC_mfro, 0, 0, 0, flags);
-
- if (!atom_full_copy_data (&mfro, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint32 (s, buffer, size, offset);
-
- atom_write_size (buffer, size, offset, original_offset);
-
- return *offset - original_offset;
-}
-
-
-guint64
-atom_mfra_copy_data (AtomMFRA * mfra, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- guint64 original_offset = *offset;
- GList *walker;
-
- if (!atom_copy_data (&mfra->header, buffer, size, offset))
- return 0;
-
- walker = g_list_first (mfra->tfras);
- while (walker != NULL) {
- if (!atom_tfra_copy_data ((AtomTFRA *) walker->data, buffer, size, offset)) {
- return 0;
- }
- walker = g_list_next (walker);
- }
-
- /* 16 is the size of the mfro atom */
- if (!atom_mfro_copy_data (*offset - original_offset + 16, buffer,
- size, offset))
- return 0;
-
- atom_write_size (buffer, size, offset, original_offset);
- return *offset - original_offset;
-}
-
-/* some sample description construction helpers */
-
-AtomInfo *
-build_esds_extension (AtomTRAK * trak, guint8 object_type, guint8 stream_type,
- const GstBuffer * codec_data, guint32 avg_bitrate, guint32 max_bitrate)
-{
- guint32 track_id;
- AtomESDS *esds;
-
- track_id = trak->tkhd.track_ID;
-
- esds = atom_esds_new ();
- esds->es.id = track_id & 0xFFFF;
- esds->es.dec_conf_desc.object_type = object_type;
- esds->es.dec_conf_desc.stream_type = stream_type << 2 | 0x01;
-
- if (avg_bitrate > 0)
- esds->es.dec_conf_desc.avg_bitrate = avg_bitrate;
- if (max_bitrate > 0)
- esds->es.dec_conf_desc.max_bitrate = max_bitrate;
-
- /* optional DecoderSpecificInfo */
- if (codec_data) {
- DecoderSpecificInfoDescriptor *desc;
-
- esds->es.dec_conf_desc.dec_specific_info = desc =
- desc_dec_specific_info_new ();
- desc_dec_specific_info_alloc_data (desc, GST_BUFFER_SIZE (codec_data));
-
- memcpy (desc->data, GST_BUFFER_DATA (codec_data),
- GST_BUFFER_SIZE (codec_data));
- }
-
- return build_atom_info_wrapper ((Atom *) esds, atom_esds_copy_data,
- atom_esds_free);
-}
-
-AtomInfo *
-build_btrt_extension (guint32 buffer_size_db, guint32 avg_bitrate,
- guint32 max_bitrate)
-{
- AtomData *atom_data;
- GstBuffer *buf;
-
- if (buffer_size_db == 0 && avg_bitrate == 0 && max_bitrate == 0)
- return 0;
-
- buf = gst_buffer_new_and_alloc (12);
-
- GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), buffer_size_db);
- GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + 4, max_bitrate);
- GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + 8, avg_bitrate);
-
- atom_data =
- atom_data_new_from_gst_buffer (GST_MAKE_FOURCC ('b', 't', 'r', 't'), buf);
- gst_buffer_unref (buf);
-
- return build_atom_info_wrapper ((Atom *) atom_data, atom_data_copy_data,
- atom_data_free);
-}
-
-static AtomInfo *
-build_mov_wave_extension (AtomTRAK * trak, guint32 fourcc, AtomInfo * atom1,
- AtomInfo * atom2, gboolean terminator)
-{
- AtomWAVE *wave;
- AtomFRMA *frma;
- Atom *ext_atom;
-
- /* Build WAVE atom for sample table entry */
- wave = atom_wave_new ();
-
- /* Prepend Terminator atom to the WAVE list first, so it ends up last */
- if (terminator) {
- ext_atom = (Atom *) atom_data_new (FOURCC_null);
- wave->extension_atoms =
- atom_info_list_prepend_atom (wave->extension_atoms, (Atom *) ext_atom,
- (AtomCopyDataFunc) atom_data_copy_data, (AtomFreeFunc) atom_data_free);
- }
-
- /* Add supplied atoms to WAVE */
- if (atom2)
- wave->extension_atoms = g_list_prepend (wave->extension_atoms, atom2);
- if (atom1)
- wave->extension_atoms = g_list_prepend (wave->extension_atoms, atom1);
-
- /* Add FRMA to the WAVE */
- frma = atom_frma_new ();
- frma->media_type = fourcc;
-
- wave->extension_atoms =
- atom_info_list_prepend_atom (wave->extension_atoms, (Atom *) frma,
- (AtomCopyDataFunc) atom_frma_copy_data, (AtomFreeFunc) atom_frma_free);
-
- return build_atom_info_wrapper ((Atom *) wave, atom_wave_copy_data,
- atom_wave_free);
-}
-
-AtomInfo *
-build_mov_aac_extension (AtomTRAK * trak, const GstBuffer * codec_data,
- guint32 avg_bitrate, guint32 max_bitrate)
-{
- AtomInfo *esds, *mp4a;
- GstBuffer *buf;
-
- /* Add ESDS atom to WAVE */
- esds = build_esds_extension (trak, ESDS_OBJECT_TYPE_MPEG4_P3,
- ESDS_STREAM_TYPE_AUDIO, codec_data, avg_bitrate, max_bitrate);
-
- /* Add MP4A atom to the WAVE:
- * not really in spec, but makes offset based players happy */
- buf = gst_buffer_new_and_alloc (4);
- *((guint32 *) GST_BUFFER_DATA (buf)) = 0;
- mp4a = build_codec_data_extension (FOURCC_mp4a, buf);
- gst_buffer_unref (buf);
-
- return build_mov_wave_extension (trak, FOURCC_mp4a, mp4a, esds, TRUE);
-}
-
-AtomInfo *
-build_mov_alac_extension (AtomTRAK * trak, const GstBuffer * codec_data)
-{
- AtomInfo *alac;
-
- alac = build_codec_data_extension (FOURCC_alac, codec_data);
-
- return build_mov_wave_extension (trak, FOURCC_alac, NULL, alac, TRUE);
-}
-
-AtomInfo *
-build_fiel_extension (gint fields)
-{
- AtomData *atom_data;
- GstBuffer *buf;
-
- if (fields == 1) {
- return NULL;
- }
-
- buf = gst_buffer_new_and_alloc (1);
- GST_BUFFER_DATA (buf)[0] = (guint8) fields;
-
- atom_data =
- atom_data_new_from_gst_buffer (GST_MAKE_FOURCC ('f', 'i', 'e', 'l'), buf);
- gst_buffer_unref (buf);
-
- return build_atom_info_wrapper ((Atom *) atom_data, atom_data_copy_data,
- atom_data_free);
-}
-
-AtomInfo *
-build_jp2x_extension (const GstBuffer * prefix)
-{
- AtomData *atom_data;
-
- if (!prefix) {
- return NULL;
- }
-
- atom_data =
- atom_data_new_from_gst_buffer (GST_MAKE_FOURCC ('j', 'p', '2', 'x'),
- prefix);
-
- return build_atom_info_wrapper ((Atom *) atom_data, atom_data_copy_data,
- atom_data_free);
-}
-
-AtomInfo *
-build_jp2h_extension (AtomTRAK * trak, gint width, gint height, guint32 fourcc,
- gint ncomp, const GValue * cmap_array, const GValue * cdef_array)
-{
- AtomData *atom_data;
- GstBuffer *buf;
- guint8 cenum;
- gint i;
- gint idhr_size = 22;
- gint colr_size = 15;
- gint cmap_size = 0, cdef_size = 0;
- gint cmap_array_size = 0;
- gint cdef_array_size = 0;
- GstByteWriter writer;
-
- g_return_val_if_fail (cmap_array == NULL ||
- GST_VALUE_HOLDS_ARRAY (cmap_array), NULL);
- g_return_val_if_fail (cdef_array == NULL ||
- GST_VALUE_HOLDS_ARRAY (cdef_array), NULL);
-
- if (fourcc == GST_MAKE_FOURCC ('s', 'R', 'G', 'B')) {
- cenum = 0x10;
- if (ncomp == 0)
- ncomp = 3;
- } else if (fourcc == GST_MAKE_FOURCC ('G', 'R', 'A', 'Y')) {
- cenum = 0x11;
- if (ncomp == 0)
- ncomp = 1;
- } else if (fourcc == GST_MAKE_FOURCC ('s', 'Y', 'U', 'V')) {
- cenum = 0x12;
- if (ncomp == 0)
- ncomp = 3;
- } else
- return NULL;
-
- if (cmap_array) {
- cmap_array_size = gst_value_array_get_size (cmap_array);
- cmap_size = 8 + cmap_array_size * 4;
- }
- if (cdef_array) {
- cdef_array_size = gst_value_array_get_size (cdef_array);
- cdef_size = 8 + 2 + cdef_array_size * 6;
- }
-
- buf = gst_buffer_new_and_alloc (idhr_size + colr_size + cmap_size +
- cdef_size);
- gst_byte_writer_init_with_buffer (&writer, buf, FALSE);
-
- /* ihdr = image header box */
- gst_byte_writer_put_uint32_be (&writer, 22);
- gst_byte_writer_put_uint32_le (&writer, GST_MAKE_FOURCC ('i', 'h', 'd', 'r'));
- gst_byte_writer_put_uint32_be (&writer, height);
- gst_byte_writer_put_uint32_be (&writer, width);
- gst_byte_writer_put_uint16_be (&writer, ncomp);
- /* 8 bits per component, unsigned */
- gst_byte_writer_put_uint8 (&writer, 0x7);
- /* compression type; reserved */
- gst_byte_writer_put_uint8 (&writer, 0x7);
- /* colour space (un)known */
- gst_byte_writer_put_uint8 (&writer, 0x0);
- /* intellectual property right (box present) */
- gst_byte_writer_put_uint8 (&writer, 0x0);
-
- /* colour specification box */
- gst_byte_writer_put_uint32_be (&writer, 15);
- gst_byte_writer_put_uint32_le (&writer, GST_MAKE_FOURCC ('c', 'o', 'l', 'r'));
-
- /* specification method: enumerated */
- gst_byte_writer_put_uint8 (&writer, 0x1);
- /* precedence; reserved */
- gst_byte_writer_put_uint8 (&writer, 0x0);
- /* approximation; reserved */
- gst_byte_writer_put_uint8 (&writer, 0x0);
- /* enumerated colourspace */
- gst_byte_writer_put_uint32_be (&writer, cenum);
-
- if (cmap_array) {
- gst_byte_writer_put_uint32_be (&writer, cmap_size);
- gst_byte_writer_put_uint32_le (&writer,
- GST_MAKE_FOURCC ('c', 'm', 'a', 'p'));
- for (i = 0; i < cmap_array_size; i++) {
- const GValue *item;
- gint value;
- guint16 cmp;
- guint8 mtyp;
- guint8 pcol;
- item = gst_value_array_get_value (cmap_array, i);
- value = g_value_get_int (item);
-
- /* value is '(mtyp << 24) | (pcol << 16) | cmp' */
- cmp = value & 0xFFFF;
- mtyp = value >> 24;
- pcol = (value >> 16) & 0xFF;
-
- if (mtyp == 1)
- GST_WARNING ("MTYP of cmap atom signals Pallete Mapping, but we don't "
- "handle Pallete mapping atoms yet");
-
- gst_byte_writer_put_uint16_be (&writer, cmp);
- gst_byte_writer_put_uint8 (&writer, mtyp);
- gst_byte_writer_put_uint8 (&writer, pcol);
- }
- }
-
- if (cdef_array) {
- gst_byte_writer_put_uint32_be (&writer, cdef_size);
- gst_byte_writer_put_uint32_le (&writer,
- GST_MAKE_FOURCC ('c', 'd', 'e', 'f'));
- gst_byte_writer_put_uint16_be (&writer, cdef_array_size);
- for (i = 0; i < cdef_array_size; i++) {
- const GValue *item;
- gint value;
- item = gst_value_array_get_value (cdef_array, i);
- value = g_value_get_int (item);
-
- gst_byte_writer_put_uint16_be (&writer, i);
- if (value > 0) {
- gst_byte_writer_put_uint16_be (&writer, 0);
- gst_byte_writer_put_uint16_be (&writer, value);
- } else if (value < 0) {
- gst_byte_writer_put_uint16_be (&writer, -value);
- gst_byte_writer_put_uint16_be (&writer, 0); /* TODO what here? */
- } else {
- gst_byte_writer_put_uint16_be (&writer, 1);
- gst_byte_writer_put_uint16_be (&writer, 0);
- }
- }
- }
-
- g_assert (gst_byte_writer_get_remaining (&writer) == 0);
-
- atom_data = atom_data_new_from_gst_buffer (FOURCC_jp2h, buf);
- gst_buffer_unref (buf);
-
- return build_atom_info_wrapper ((Atom *) atom_data, atom_data_copy_data,
- atom_data_free);
-}
-
-AtomInfo *
-build_codec_data_extension (guint32 fourcc, const GstBuffer * codec_data)
-{
- AtomData *data;
- AtomInfo *result = NULL;
-
- if (codec_data) {
- data = atom_data_new_from_gst_buffer (fourcc, codec_data);
- result = build_atom_info_wrapper ((Atom *) data, atom_data_copy_data,
- atom_data_free);
- }
-
- return result;
-}
-
-AtomInfo *
-build_amr_extension (void)
-{
- guint8 ext[9];
- GstBuffer *buf;
- AtomInfo *res;
-
- buf = gst_buffer_new ();
- GST_BUFFER_DATA (buf) = ext;
- GST_BUFFER_SIZE (buf) = sizeof (ext);
-
- /* vendor */
- GST_WRITE_UINT32_LE (ext, 0);
- /* decoder version */
- GST_WRITE_UINT8 (ext + 4, 0);
- /* mode set (all modes) */
- GST_WRITE_UINT16_BE (ext + 5, 0x81FF);
- /* mode change period (no restriction) */
- GST_WRITE_UINT8 (ext + 7, 0);
- /* frames per sample */
- GST_WRITE_UINT8 (ext + 8, 1);
-
- res = build_codec_data_extension (GST_MAKE_FOURCC ('d', 'a', 'm', 'r'), buf);
- gst_buffer_unref (buf);
- return res;
-}
-
-AtomInfo *
-build_h263_extension (void)
-{
- guint8 ext[7];
- GstBuffer *buf;
- AtomInfo *res;
-
- buf = gst_buffer_new ();
- GST_BUFFER_DATA (buf) = ext;
- GST_BUFFER_SIZE (buf) = sizeof (ext);
-
- /* vendor */
- GST_WRITE_UINT32_LE (ext, 0);
- /* decoder version */
- GST_WRITE_UINT8 (ext + 4, 0);
- /* level / profile */
- /* FIXME ? maybe ? obtain somewhere; baseline for now */
- GST_WRITE_UINT8 (ext + 5, 10);
- GST_WRITE_UINT8 (ext + 6, 0);
-
- res = build_codec_data_extension (GST_MAKE_FOURCC ('d', '2', '6', '3'), buf);
- gst_buffer_unref (buf);
- return res;
-}
-
-AtomInfo *
-build_gama_atom (gdouble gamma)
-{
- AtomInfo *res;
- guint32 gamma_fp;
- GstBuffer *buf;
-
- /* convert to uint32 from fixed point */
- gamma_fp = (guint32) 65536 *gamma;
-
- buf = gst_buffer_new_and_alloc (4);
- GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf), gamma_fp);
- res = build_codec_data_extension (FOURCC_gama, buf);
- gst_buffer_unref (buf);
- return res;
-}
-
-AtomInfo *
-build_SMI_atom (const GstBuffer * seqh)
-{
- AtomInfo *res;
- GstBuffer *buf;
-
- /* the seqh plus its size and fourcc */
- buf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (seqh) + 8);
-
- GST_WRITE_UINT32_LE (GST_BUFFER_DATA (buf), FOURCC_SEQH);
- GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + 4, GST_BUFFER_SIZE (seqh));
- memcpy (GST_BUFFER_DATA (buf) + 8, GST_BUFFER_DATA (seqh),
- GST_BUFFER_SIZE (seqh));
- res = build_codec_data_extension (FOURCC_SMI_, buf);
- gst_buffer_unref (buf);
- return res;
-}
-
-static AtomInfo *
-build_ima_adpcm_atom (gint channels, gint rate, gint blocksize)
-{
- AtomData *atom_data;
- GstBuffer *buf;
- guint8 *data;
- const gint ima_adpcm_atom_size = 20;
- guint32 fourcc;
- gint samplesperblock;
- gint bytespersec;
-
- /* The FOURCC for WAV codecs in QT is 'ms' followed by the 16 bit wave codec
- identifier. Note that the identifier here is big-endian, but when used
- within the WAVE header (below), it's little endian. */
- fourcc = MS_WAVE_FOURCC (0x11);
-
- buf = gst_buffer_new_and_alloc (ima_adpcm_atom_size);
- data = GST_BUFFER_DATA (buf);
-
- /* This atom's content is a WAVE header, including 2 bytes of extra data.
- Note that all of this is little-endian, unlike most stuff in qt. */
- /* 4 bytes header per channel (including 1 sample). Then 2 samples per byte
- for the rest. Simplifies to this. */
- samplesperblock = 2 * blocksize / channels - 7;
- bytespersec = rate * blocksize / samplesperblock;
- GST_WRITE_UINT16_LE (data, 0x11);
- GST_WRITE_UINT16_LE (data + 2, channels);
- GST_WRITE_UINT32_LE (data + 4, rate);
- GST_WRITE_UINT32_LE (data + 8, bytespersec);
- GST_WRITE_UINT16_LE (data + 12, blocksize);
- GST_WRITE_UINT16_LE (data + 14, 4);
- GST_WRITE_UINT16_LE (data + 16, 2); /* Two extra bytes */
- GST_WRITE_UINT16_LE (data + 18, samplesperblock);
-
- atom_data = atom_data_new_from_gst_buffer (fourcc, buf);
- gst_buffer_unref (buf);
-
- return build_atom_info_wrapper ((Atom *) atom_data, atom_data_copy_data,
- atom_data_free);
-}
-
-AtomInfo *
-build_ima_adpcm_extension (gint channels, gint rate, gint blocksize)
-{
- AtomWAVE *wave;
- AtomFRMA *frma;
- Atom *ext_atom;
-
- /* Add WAVE atom */
- wave = atom_wave_new ();
-
- /* Prepend Terminator atom to the WAVE list first, so it ends up last */
- ext_atom = (Atom *) atom_data_new (FOURCC_null);
- wave->extension_atoms =
- atom_info_list_prepend_atom (wave->extension_atoms, (Atom *) ext_atom,
- (AtomCopyDataFunc) atom_data_copy_data, (AtomFreeFunc) atom_data_free);
-
- /* Add wave ima adpcm atom to WAVE */
- wave->extension_atoms = g_list_prepend (wave->extension_atoms,
- build_ima_adpcm_atom (channels, rate, blocksize));
-
- /* Add FRMA to the WAVE */
- frma = atom_frma_new ();
- frma->media_type = MS_WAVE_FOURCC (0x11);
-
- wave->extension_atoms =
- atom_info_list_prepend_atom (wave->extension_atoms, (Atom *) frma,
- (AtomCopyDataFunc) atom_frma_copy_data, (AtomFreeFunc) atom_frma_free);
-
- return build_atom_info_wrapper ((Atom *) wave, atom_wave_copy_data,
- atom_wave_free);
-}
-
-AtomInfo *
-build_uuid_xmp_atom (GstBuffer * xmp_data)
-{
- AtomUUID *uuid;
- static guint8 xmp_uuid[] = { 0xBE, 0x7A, 0xCF, 0xCB,
- 0x97, 0xA9, 0x42, 0xE8,
- 0x9C, 0x71, 0x99, 0x94,
- 0x91, 0xE3, 0xAF, 0xAC
- };
-
- if (xmp_data == NULL)
- return NULL;
-
- uuid = atom_uuid_new ();
- memcpy (uuid->uuid, xmp_uuid, 16);
-
- uuid->data = g_malloc (GST_BUFFER_SIZE (xmp_data));
- uuid->datalen = GST_BUFFER_SIZE (xmp_data);
- memcpy (uuid->data, GST_BUFFER_DATA (xmp_data), GST_BUFFER_SIZE (xmp_data));
-
- return build_atom_info_wrapper ((Atom *) uuid, atom_uuid_copy_data,
- atom_uuid_free);
-}
diff --git a/gst/qtmux/atoms.h b/gst/qtmux/atoms.h
deleted file mode 100644
index 5aeb5f8f6..000000000
--- a/gst/qtmux/atoms.h
+++ /dev/null
@@ -1,956 +0,0 @@
-/* Quicktime muxer plugin for GStreamer
- * Copyright (C) 2008-2010 Thiago Santos <thiagoss@embedded.ufcg.edu.br>
- *
- * 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.
- */
-/*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __ATOMS_H__
-#define __ATOMS_H__
-
-#include <glib.h>
-#include <string.h>
-
-#include "descriptors.h"
-#include "properties.h"
-#include "fourcc.h"
-#include "ftypcc.h"
-
-/* helper storage struct */
-#define ATOM_ARRAY(struct_type) \
-struct { \
- guint size; \
- guint len; \
- struct_type *data; \
-}
-
-/* storage helpers */
-
-#define atom_array_init(array, reserve) \
-G_STMT_START { \
- (array)->len = 0; \
- (array)->size = reserve; \
- (array)->data = g_malloc (sizeof (*(array)->data) * reserve); \
-} G_STMT_END
-
-#define atom_array_append(array, elmt, inc) \
-G_STMT_START { \
- g_assert ((array)->data); \
- g_assert (inc > 0); \
- if (G_UNLIKELY ((array)->len == (array)->size)) { \
- (array)->size += inc; \
- (array)->data = \
- g_realloc ((array)->data, sizeof (*((array)->data)) * (array)->size); \
- } \
- (array)->data[(array)->len] = elmt; \
- (array)->len++; \
-} G_STMT_END
-
-#define atom_array_get_len(array) ((array)->len)
-#define atom_array_index(array, index) ((array)->data[index])
-
-#define atom_array_clear(array) \
-G_STMT_START { \
- (array)->size = (array)->len = 0; \
- g_free ((array)->data); \
- (array)->data = NULL; \
-} G_STMT_END
-
-/* light-weight context that may influence header atom tree construction */
-typedef enum _AtomsTreeFlavor
-{
- ATOMS_TREE_FLAVOR_MOV,
- ATOMS_TREE_FLAVOR_ISOM,
- ATOMS_TREE_FLAVOR_3GP,
- ATOMS_TREE_FLAVOR_ISML
-} AtomsTreeFlavor;
-
-typedef struct _AtomsContext
-{
- AtomsTreeFlavor flavor;
-} AtomsContext;
-
-AtomsContext* atoms_context_new (AtomsTreeFlavor flavor);
-void atoms_context_free (AtomsContext *context);
-
-#define METADATA_DATA_FLAG 0x0
-#define METADATA_TEXT_FLAG 0x1
-
-/* atom defs and functions */
-
-/**
- * Used for storing time related values for some atoms.
- */
-typedef struct _TimeInfo
-{
- guint64 creation_time;
- guint64 modification_time;
- guint32 timescale;
- guint64 duration;
-} TimeInfo;
-
-typedef struct _Atom
-{
- guint32 size;
- guint32 type;
- guint64 extended_size;
-} Atom;
-
-typedef struct _AtomFull
-{
- Atom header;
-
- guint8 version;
- guint8 flags[3];
-} AtomFull;
-
-/*
- * Generic extension atom
- */
-typedef struct _AtomData
-{
- Atom header;
-
- /* not written */
- guint32 datalen;
-
- guint8 *data;
-} AtomData;
-
-typedef struct _AtomUUID
-{
- Atom header;
-
- guint8 uuid[16];
-
- /* not written */
- guint32 datalen;
-
- guint8 *data;
-} AtomUUID;
-
-typedef struct _AtomFTYP
-{
- Atom header;
- guint32 major_brand;
- guint32 version;
- guint32 *compatible_brands;
-
- /* not written */
- guint32 compatible_brands_size;
-} AtomFTYP;
-
-typedef struct _AtomMVHD
-{
- AtomFull header;
-
- /* version 0: 32 bits */
- TimeInfo time_info;
-
- guint32 prefered_rate; /* ISO: 0x00010000 */
- guint16 volume; /* ISO: 0x0100 */
- guint16 reserved3; /* ISO: 0x0 */
- guint32 reserved4[2]; /* ISO: 0, 0 */
- /* ISO: identity matrix =
- * { 0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000 } */
- guint32 matrix[9];
-
- /* ISO: all 0 */
- guint32 preview_time;
- guint32 preview_duration;
- guint32 poster_time;
- guint32 selection_time;
- guint32 selection_duration;
- guint32 current_time;
-
- guint32 next_track_id;
-} AtomMVHD;
-
-typedef struct _AtomTKHD
-{
- AtomFull header;
-
- /* version 0: 32 bits */
- /* like the TimeInfo struct, but it has this track_ID inside */
- guint64 creation_time;
- guint64 modification_time;
- guint32 track_ID;
- guint32 reserved;
- guint64 duration;
-
- guint32 reserved2[2];
- guint16 layer;
- guint16 alternate_group;
- guint16 volume;
- guint16 reserved3;
-
- /* ISO: identity matrix =
- * { 0x00010000, 0, 0, 0, 0x00010000, 0, 0, 0, 0x40000000 } */
- guint32 matrix[9];
- guint32 width;
- guint32 height;
-} AtomTKHD;
-
-typedef struct _AtomMDHD
-{
- AtomFull header;
-
- /* version 0: 32 bits */
- TimeInfo time_info;
-
- /* ISO: packed ISO-639-2/T language code (first bit must be 0) */
- guint16 language_code;
- /* ISO: 0 */
- guint16 quality;
-} AtomMDHD;
-
-typedef struct _AtomHDLR
-{
- AtomFull header;
-
- /* ISO: 0 */
- guint32 component_type;
- guint32 handler_type;
- guint32 manufacturer;
- guint32 flags;
- guint32 flags_mask;
- gchar *name;
-} AtomHDLR;
-
-typedef struct _AtomVMHD
-{
- AtomFull header; /* ISO: flags = 1 */
-
- guint16 graphics_mode;
- /* RGB */
- guint16 opcolor[3];
-} AtomVMHD;
-
-typedef struct _AtomSMHD
-{
- AtomFull header;
-
- guint16 balance;
- guint16 reserved;
-} AtomSMHD;
-
-typedef struct _AtomHMHD
-{
- AtomFull header;
-
- guint16 max_pdu_size;
- guint16 avg_pdu_size;
- guint32 max_bitrate;
- guint32 avg_bitrate;
- guint32 sliding_avg_bitrate;
-} AtomHMHD;
-
-typedef struct _AtomURL
-{
- AtomFull header;
-
- gchar *location;
-} AtomURL;
-
-typedef struct _AtomDREF
-{
- AtomFull header;
-
- GList *entries;
-} AtomDREF;
-
-typedef struct _AtomDINF
-{
- Atom header;
-
- AtomDREF dref;
-} AtomDINF;
-
-typedef struct _STTSEntry
-{
- guint32 sample_count;
- gint32 sample_delta;
-} STTSEntry;
-
-typedef struct _AtomSTTS
-{
- AtomFull header;
-
- ATOM_ARRAY (STTSEntry) entries;
-} AtomSTTS;
-
-typedef struct _AtomSTSS
-{
- AtomFull header;
-
- ATOM_ARRAY (guint32) entries;
-} AtomSTSS;
-
-typedef struct _AtomESDS
-{
- AtomFull header;
-
- ESDescriptor es;
-} AtomESDS;
-
-typedef struct _AtomFRMA
-{
- Atom header;
-
- guint32 media_type;
-} AtomFRMA;
-
-typedef enum _SampleEntryKind
-{
- UNKNOWN,
- AUDIO,
- VIDEO
-} SampleEntryKind;
-
-typedef struct _SampleTableEntry
-{
- Atom header;
-
- guint8 reserved[6];
- guint16 data_reference_index;
-
- /* sort of entry */
- SampleEntryKind kind;
-} SampleTableEntry;
-
-typedef struct _AtomHintSampleEntry
-{
- SampleTableEntry se;
- guint32 size;
- guint8 *data;
-} AtomHintSampleEntry;
-
-typedef struct _SampleTableEntryMP4V
-{
- SampleTableEntry se;
-
- guint16 version;
- guint16 revision_level;
-
- guint32 vendor; /* fourcc code */
- guint32 temporal_quality;
- guint32 spatial_quality;
-
- guint16 width;
- guint16 height;
-
- guint32 horizontal_resolution;
- guint32 vertical_resolution;
- guint32 datasize;
-
- guint16 frame_count; /* usually 1 */
-
- guint8 compressor[32]; /* pascal string, i.e. first byte = length */
-
- guint16 depth;
- guint16 color_table_id;
-
- /* (optional) list of AtomInfo */
- GList *extension_atoms;
-} SampleTableEntryMP4V;
-
-typedef struct _SampleTableEntryMP4A
-{
- SampleTableEntry se;
-
- guint16 version;
- guint16 revision_level;
- guint32 vendor;
-
- guint16 channels;
- guint16 sample_size;
- guint16 compression_id;
- guint16 packet_size;
-
- guint32 sample_rate; /* fixed point 16.16 */
-
- guint32 samples_per_packet;
- guint32 bytes_per_packet;
- guint32 bytes_per_frame;
- guint32 bytes_per_sample;
-
- /* (optional) list of AtomInfo */
- GList *extension_atoms;
-} SampleTableEntryMP4A;
-
-typedef struct _SampleTableEntryMP4S
-{
- SampleTableEntry se;
-
- AtomESDS es;
-} SampleTableEntryMP4S;
-
-typedef struct _AtomSTSD
-{
- AtomFull header;
-
- guint n_entries;
- /* list of subclasses of SampleTableEntry */
- GList *entries;
-} AtomSTSD;
-
-typedef struct _AtomSTSZ
-{
- AtomFull header;
-
- guint32 sample_size;
-
- /* need the size here because when sample_size is constant,
- * the list is empty */
- guint32 table_size;
- ATOM_ARRAY (guint32) entries;
-} AtomSTSZ;
-
-typedef struct _STSCEntry
-{
- guint32 first_chunk;
- guint32 samples_per_chunk;
- guint32 sample_description_index;
-} STSCEntry;
-
-typedef struct _AtomSTSC
-{
- AtomFull header;
-
- ATOM_ARRAY (STSCEntry) entries;
-} AtomSTSC;
-
-
-/*
- * used for both STCO and CO64
- * if used as STCO, entries should be truncated to use only 32bits
- */
-typedef struct _AtomSTCO64
-{
- AtomFull header;
-
- ATOM_ARRAY (guint64) entries;
-} AtomSTCO64;
-
-typedef struct _CTTSEntry
-{
- guint32 samplecount;
- guint32 sampleoffset;
-} CTTSEntry;
-
-typedef struct _AtomCTTS
-{
- AtomFull header;
-
- /* also entry count here */
- ATOM_ARRAY (CTTSEntry) entries;
- gboolean do_pts;
-} AtomCTTS;
-
-typedef struct _AtomSTBL
-{
- Atom header;
-
- AtomSTSD stsd;
- AtomSTTS stts;
- AtomSTSS stss;
- AtomSTSC stsc;
- AtomSTSZ stsz;
- /* NULL if not present */
- AtomCTTS *ctts;
-
- AtomSTCO64 stco64;
-} AtomSTBL;
-
-typedef struct _AtomMINF
-{
- Atom header;
-
- /* only (exactly) one of those must be present */
- AtomVMHD *vmhd;
- AtomSMHD *smhd;
- AtomHMHD *hmhd;
-
- AtomHDLR *hdlr;
- AtomDINF dinf;
- AtomSTBL stbl;
-} AtomMINF;
-
-typedef struct _EditListEntry
-{
- /* duration in movie's timescale */
- guint32 duration;
- /* start time in media's timescale, -1 for empty */
- guint32 media_time;
- guint32 media_rate; /* fixed point 32 bit */
-} EditListEntry;
-
-typedef struct _AtomELST
-{
- AtomFull header;
-
- /* number of entries is implicit */
- GSList *entries;
-} AtomELST;
-
-typedef struct _AtomEDTS
-{
- Atom header;
- AtomELST elst;
-} AtomEDTS;
-
-typedef struct _AtomMDIA
-{
- Atom header;
-
- AtomMDHD mdhd;
- AtomHDLR hdlr;
- AtomMINF minf;
-} AtomMDIA;
-
-typedef struct _AtomILST
-{
- Atom header;
-
- /* list of AtomInfo */
- GList* entries;
-} AtomILST;
-
-typedef struct _AtomTagData
-{
- AtomFull header;
- guint32 reserved;
-
- guint32 datalen;
- guint8* data;
-} AtomTagData;
-
-typedef struct _AtomTag
-{
- Atom header;
-
- AtomTagData data;
-} AtomTag;
-
-typedef struct _AtomMETA
-{
- AtomFull header;
- AtomHDLR hdlr;
- AtomILST *ilst;
-} AtomMETA;
-
-typedef struct _AtomUDTA
-{
- Atom header;
-
- /* list of AtomInfo */
- GList* entries;
- /* or list is further down */
- AtomMETA *meta;
-} AtomUDTA;
-
-enum TrFlags
-{
- TR_DATA_OFFSET = 0x01, /* data-offset-present */
- TR_FIRST_SAMPLE_FLAGS = 0x04, /* first-sample-flags-present */
- TR_SAMPLE_DURATION = 0x0100, /* sample-duration-present */
- TR_SAMPLE_SIZE = 0x0200, /* sample-size-present */
- TR_SAMPLE_FLAGS = 0x0400, /* sample-flags-present */
- TR_COMPOSITION_TIME_OFFSETS = 0x0800 /* sample-composition-time-offsets-presents */
-};
-
-enum TfFlags
-{
- TF_BASE_DATA_OFFSET = 0x01, /* base-data-offset-present */
- TF_SAMPLE_DESCRIPTION_INDEX = 0x02, /* sample-description-index-present */
- TF_DEFAULT_SAMPLE_DURATION = 0x08, /* default-sample-duration-present */
- TF_DEFAULT_SAMPLE_SIZE = 0x010, /* default-sample-size-present */
- TF_DEFAULT_SAMPLE_FLAGS = 0x020, /* default-sample-flags-present */
- TF_DURATION_IS_EMPTY = 0x010000 /* sample-composition-time-offsets-presents */
-};
-
-typedef struct _AtomTRAK
-{
- Atom header;
-
- AtomTKHD tkhd;
- AtomEDTS *edts;
- AtomMDIA mdia;
-
- /* some helper info for structural conformity checks */
- gboolean is_video;
- gboolean is_h264;
-} AtomTRAK;
-
-typedef struct _AtomTREX
-{
- AtomFull header;
-
- guint32 track_ID;
- guint32 default_sample_description_index;
- guint32 default_sample_duration;
- guint32 default_sample_size;
- guint32 default_sample_flags;
-} AtomTREX;
-
-typedef struct _AtomMEHD
-{
- AtomFull header;
-
- guint64 fragment_duration;
-} AtomMEHD;
-
-
-typedef struct _AtomMVEX
-{
- Atom header;
-
- AtomMEHD mehd;
-
- /* list of AtomTREX */
- GList *trexs;
-} AtomMVEX;
-
-typedef struct _AtomMFHD
-{
- AtomFull header;
-
- guint32 sequence_number;
-} AtomMFHD;
-
-typedef struct _AtomTFHD
-{
- AtomFull header;
-
- guint32 track_ID;
- guint64 base_data_offset;
- guint32 sample_description_index;
- guint32 default_sample_duration;
- guint32 default_sample_size;
- guint32 default_sample_flags;
-} AtomTFHD;
-
-typedef struct _TRUNSampleEntry
-{
- guint32 sample_duration;
- guint32 sample_size;
- guint32 sample_flags;
- guint32 sample_composition_time_offset;
-} TRUNSampleEntry;
-
-typedef struct _AtomTRUN
-{
- AtomFull header;
-
- guint32 sample_count;
- gint32 data_offset;
- guint32 first_sample_flags;
-
- /* array of fields */
- ATOM_ARRAY (TRUNSampleEntry) entries;
-} AtomTRUN;
-
-typedef struct _AtomSDTP
-{
- AtomFull header;
-
- /* not serialized */
- guint32 sample_count;
-
- /* array of fields */
- ATOM_ARRAY (guint8) entries;
-} AtomSDTP;
-
-typedef struct _AtomTRAF
-{
- Atom header;
-
- AtomTFHD tfhd;
-
- /* list of AtomTRUN */
- GList *truns;
- /* list of AtomSDTP */
- GList *sdtps;
-} AtomTRAF;
-
-typedef struct _AtomMOOF
-{
- Atom header;
-
- AtomMFHD mfhd;
-
- /* list of AtomTRAF */
- GList *trafs;
-} AtomMOOF;
-
-
-typedef struct _AtomMOOV
-{
- /* style */
- AtomsContext context;
-
- Atom header;
-
- AtomMVHD mvhd;
- AtomMVEX mvex;
-
- /* list of AtomTRAK */
- GList *traks;
- AtomUDTA *udta;
-
- gboolean fragmented;
-} AtomMOOV;
-
-typedef struct _AtomWAVE
-{
- Atom header;
-
- /* list of AtomInfo */
- GList *extension_atoms;
-} AtomWAVE;
-
-typedef struct _TFRAEntry
-{
- guint64 time;
- guint64 moof_offset;
- guint32 traf_number;
- guint32 trun_number;
- guint32 sample_number;
-} TFRAEntry;
-
-typedef struct _AtomTFRA
-{
- AtomFull header;
-
- guint32 track_ID;
- guint32 lengths;
- /* array of entries */
- ATOM_ARRAY (TFRAEntry) entries;
-} AtomTFRA;
-
-typedef struct _AtomMFRA
-{
- Atom header;
-
- /* list of tfra */
- GList *tfras;
-} AtomMFRA;
-
-/*
- * Function to serialize an atom
- */
-typedef guint64 (*AtomCopyDataFunc) (Atom *atom, guint8 **buffer, guint64 *size, guint64 *offset);
-
-/*
- * Releases memory allocated by an atom
- */
-typedef guint64 (*AtomFreeFunc) (Atom *atom);
-
-/*
- * Some atoms might have many optional different kinds of child atoms, so this
- * is useful for enabling generic handling of any atom.
- * All we need are the two functions (copying it to an array
- * for serialization and the memory releasing function).
- */
-typedef struct _AtomInfo
-{
- Atom *atom;
- AtomCopyDataFunc copy_data_func;
- AtomFreeFunc free_func;
-} AtomInfo;
-
-
-guint64 atom_copy_data (Atom *atom, guint8 **buffer,
- guint64 *size, guint64* offset);
-
-AtomFTYP* atom_ftyp_new (AtomsContext *context, guint32 major,
- guint32 version, GList *brands);
-guint64 atom_ftyp_copy_data (AtomFTYP *ftyp, guint8 **buffer,
- guint64 *size, guint64 *offset);
-void atom_ftyp_free (AtomFTYP *ftyp);
-
-AtomTRAK* atom_trak_new (AtomsContext *context);
-void atom_trak_add_samples (AtomTRAK * trak, guint32 nsamples, guint32 delta,
- guint32 size, guint64 chunk_offset, gboolean sync,
- gint64 pts_offset);
-void atom_trak_add_elst_entry (AtomTRAK * trak, guint32 duration,
- guint32 media_time, guint32 rate);
-guint32 atom_trak_get_timescale (AtomTRAK *trak);
-guint32 atom_trak_get_id (AtomTRAK * trak);
-void atom_stbl_add_samples (AtomSTBL * stbl, guint32 nsamples,
- guint32 delta, guint32 size,
- guint64 chunk_offset, gboolean sync,
- gint64 pts_offset);
-
-AtomMOOV* atom_moov_new (AtomsContext *context);
-void atom_moov_free (AtomMOOV *moov);
-guint64 atom_moov_copy_data (AtomMOOV *atom, guint8 **buffer, guint64 *size, guint64* offset);
-void atom_moov_update_timescale (AtomMOOV *moov, guint32 timescale);
-void atom_moov_update_duration (AtomMOOV *moov);
-void atom_moov_set_fragmented (AtomMOOV *moov, gboolean fragmented);
-void atom_moov_chunks_add_offset (AtomMOOV *moov, guint32 offset);
-void atom_moov_add_trak (AtomMOOV *moov, AtomTRAK *trak);
-
-guint64 atom_mvhd_copy_data (AtomMVHD * atom, guint8 ** buffer,
- guint64 * size, guint64 * offset);
-void atom_stco64_chunks_add_offset (AtomSTCO64 * stco64, guint32 offset);
-guint64 atom_trak_copy_data (AtomTRAK * atom, guint8 ** buffer,
- guint64 * size, guint64 * offset);
-void atom_stbl_clear (AtomSTBL * stbl);
-void atom_stbl_init (AtomSTBL * stbl);
-guint64 atom_stss_copy_data (AtomSTSS *atom, guint8 **buffer,
- guint64 *size, guint64* offset);
-guint64 atom_stts_copy_data (AtomSTTS *atom, guint8 **buffer,
- guint64 *size, guint64* offset);
-guint64 atom_stsc_copy_data (AtomSTSC *atom, guint8 **buffer,
- guint64 *size, guint64* offset);
-guint64 atom_stsz_copy_data (AtomSTSZ *atom, guint8 **buffer,
- guint64 *size, guint64* offset);
-guint64 atom_ctts_copy_data (AtomCTTS *atom, guint8 **buffer,
- guint64 *size, guint64* offset);
-guint64 atom_stco64_copy_data (AtomSTCO64 *atom, guint8 **buffer,
- guint64 *size, guint64* offset);
-AtomMOOF* atom_moof_new (AtomsContext *context, guint32 sequence_number);
-void atom_moof_free (AtomMOOF *moof);
-guint64 atom_moof_copy_data (AtomMOOF *moof, guint8 **buffer, guint64 *size, guint64* offset);
-AtomTRAF * atom_traf_new (AtomsContext * context, guint32 track_ID);
-void atom_traf_free (AtomTRAF * traf);
-void atom_traf_add_samples (AtomTRAF * traf, guint32 delta,
- guint32 size, gboolean sync, gint64 pts_offset,
- gboolean sdtp_sync);
-guint32 atom_traf_get_sample_num (AtomTRAF * traf);
-void atom_moof_add_traf (AtomMOOF *moof, AtomTRAF *traf);
-
-AtomMFRA* atom_mfra_new (AtomsContext *context);
-void atom_mfra_free (AtomMFRA *mfra);
-AtomTFRA* atom_tfra_new (AtomsContext *context, guint32 track_ID);
-void atom_tfra_add_entry (AtomTFRA *tfra, guint64 dts, guint32 sample_num);
-void atom_tfra_update_offset (AtomTFRA * tfra, guint64 offset);
-void atom_mfra_add_tfra (AtomMFRA *mfra, AtomTFRA *tfra);
-guint64 atom_mfra_copy_data (AtomMFRA *mfra, guint8 **buffer, guint64 *size, guint64* offset);
-
-
-/* media sample description related helpers */
-
-typedef struct
-{
- guint16 version;
- guint32 fourcc;
- guint width;
- guint height;
- guint depth;
- guint frame_count;
- gint color_table_id;
- guint par_n;
- guint par_d;
-
- GstBuffer *codec_data;
-} VisualSampleEntry;
-
-typedef struct
-{
- guint32 fourcc;
- guint version;
- gint compression_id;
- guint sample_rate;
- guint channels;
- guint sample_size;
- guint bytes_per_packet;
- guint samples_per_packet;
- guint bytes_per_sample;
- guint bytes_per_frame;
-
- GstBuffer *codec_data;
-} AudioSampleEntry;
-
-void atom_trak_set_audio_type (AtomTRAK * trak, AtomsContext * context,
- AudioSampleEntry * entry, guint32 scale,
- AtomInfo * ext, gint sample_size);
-
-void atom_trak_set_video_type (AtomTRAK * trak, AtomsContext * context,
- VisualSampleEntry * entry, guint32 rate,
- GList * ext_atoms_list);
-
-AtomInfo * build_codec_data_extension (guint32 fourcc, const GstBuffer * codec_data);
-AtomInfo * build_mov_aac_extension (AtomTRAK * trak, const GstBuffer * codec_data,
- guint32 avg_bitrate, guint32 max_bitrate);
-AtomInfo * build_mov_alac_extension (AtomTRAK * trak, const GstBuffer * codec_data);
-AtomInfo * build_esds_extension (AtomTRAK * trak, guint8 object_type,
- guint8 stream_type, const GstBuffer * codec_data,
- guint32 avg_bitrate, guint32 max_bitrate);
-AtomInfo * build_btrt_extension (guint32 buffer_size_db, guint32 avg_bitrate,
- guint32 max_bitrate);
-AtomInfo * build_jp2h_extension (AtomTRAK * trak, gint width, gint height,
- guint32 fourcc, gint ncomp,
- const GValue * cmap_array,
- const GValue * cdef_array);
-
-AtomInfo * build_jp2x_extension (const GstBuffer * prefix);
-AtomInfo * build_fiel_extension (gint fields);
-AtomInfo * build_amr_extension (void);
-AtomInfo * build_h263_extension (void);
-AtomInfo * build_gama_atom (gdouble gamma);
-AtomInfo * build_SMI_atom (const GstBuffer *seqh);
-AtomInfo * build_ima_adpcm_extension (gint channels, gint rate,
- gint blocksize);
-AtomInfo * build_uuid_xmp_atom (GstBuffer * xmp);
-
-
-/*
- * Meta tags functions
- */
-void atom_moov_add_str_tag (AtomMOOV *moov, guint32 fourcc, const gchar *value);
-void atom_moov_add_uint_tag (AtomMOOV *moov, guint32 fourcc, guint32 flags,
- guint32 value);
-void atom_moov_add_tag (AtomMOOV *moov, guint32 fourcc, guint32 flags,
- const guint8 * data, guint size);
-void atom_moov_add_blob_tag (AtomMOOV *moov, guint8 *data, guint size);
-
-void atom_moov_add_3gp_str_tag (AtomMOOV * moov, guint32 fourcc, const gchar * value);
-void atom_moov_add_3gp_uint_tag (AtomMOOV * moov, guint32 fourcc, guint16 value);
-void atom_moov_add_3gp_str_int_tag (AtomMOOV * moov, guint32 fourcc, const gchar * value,
- gint16 ivalue);
-void atom_moov_add_3gp_tag (AtomMOOV * moov, guint32 fourcc, guint8 * data,
- guint size);
-
-void atom_moov_add_xmp_tags (AtomMOOV * moov, GstBuffer * xmp);
-
-#define GST_QT_MUX_DEFAULT_TAG_LANGUAGE "eng"
-guint16 language_code (const char * lang);
-
-#endif /* __ATOMS_H__ */
diff --git a/gst/qtmux/atomsrecovery.c b/gst/qtmux/atomsrecovery.c
deleted file mode 100644
index 1f5a287d1..000000000
--- a/gst/qtmux/atomsrecovery.c
+++ /dev/null
@@ -1,1095 +0,0 @@
-/* Quicktime muxer plugin for GStreamer
- * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
- *
- * 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.
- */
-/*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-/**
- * This module contains functions for serializing partial information from
- * a mux in progress (by qtmux elements). This enables reconstruction of the
- * moov box if a crash happens and thus recovering the movie file.
- *
- * Usage:
- * 1) pipeline: ...yourelements ! qtmux moov-recovery-file=path.mrf ! \
- * filesink location=moovie.mov
- *
- * 2) CRASH!
- *
- * 3) gst-launch qtmoovrecover recovery-input=path.mrf broken-input=moovie.mov \
- fixed-output=recovered.mov
- *
- * 4) (Hopefully) enjoy recovered.mov.
- *
- * --- Recovery file layout ---
- * 1) Version (a guint16)
- * 2) Prefix atom (if present)
- * 3) ftyp atom
- * 4) MVHD atom (without timescale/duration set)
- * 5) moovie timescale
- * 6) number of traks
- * 7) list of trak atoms (stbl data is ignored, except for the stsd atom)
- * 8) Buffers metadata (metadata that is relevant to the container)
- * Buffers metadata are stored in the order they are added to the mdat,
- * each entre has a fixed size and is stored in BE. booleans are stored
- * as a single byte where 0 means false, otherwise is true.
- * Metadata:
- * - guint32 track_id;
- * - guint32 nsamples;
- * - guint32 delta;
- * - guint32 size;
- * - guint64 chunk_offset;
- * - gboolean sync;
- * - gboolean do_pts;
- * - guint64 pts_offset; (always present, ignored if do_pts is false)
- *
- * The mdat file might contain ftyp and then mdat, in case this is the faststart
- * temporary file there is no ftyp and no mdat header, only the buffers data.
- *
- * Notes about recovery file layout: We still don't store tags nor EDTS data.
- *
- * IMPORTANT: this is still at a experimental state.
- */
-
-#include "atomsrecovery.h"
-
-#define ATOMS_RECOV_OUTPUT_WRITE_ERROR(err) \
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE, \
- "Failed to write to output file: %s", g_strerror (errno))
-
-static gboolean
-atoms_recov_write_version (FILE * f)
-{
- guint8 data[2];
- GST_WRITE_UINT16_BE (data, ATOMS_RECOV_FILE_VERSION);
- return fwrite (data, 2, 1, f) == 1;
-}
-
-static gboolean
-atoms_recov_write_ftyp_info (FILE * f, AtomFTYP * ftyp, GstBuffer * prefix)
-{
- guint8 *data = NULL;
- guint64 offset = 0;
- guint64 size = 0;
-
- if (prefix) {
- if (fwrite (GST_BUFFER_DATA (prefix), 1, GST_BUFFER_SIZE (prefix), f) !=
- GST_BUFFER_SIZE (prefix)) {
- return FALSE;
- }
- }
- if (!atom_ftyp_copy_data (ftyp, &data, &size, &offset)) {
- return FALSE;
- }
- if (fwrite (data, 1, offset, f) != offset) {
- return FALSE;
- }
- return TRUE;
-}
-
-/**
- * Writes important info on the 'moov' atom (non-trak related)
- * to be able to recover the moov structure after a crash.
- *
- * Currently, it writes the MVHD atom.
- */
-static gboolean
-atoms_recov_write_moov_info (FILE * f, AtomMOOV * moov)
-{
- guint8 *data;
- guint64 size;
- guint64 offset = 0;
- guint64 atom_size = 0;
- gint writen = 0;
-
- /* likely enough */
- size = 256;
- data = g_malloc (size);
- atom_size = atom_mvhd_copy_data (&moov->mvhd, &data, &size, &offset);
- if (atom_size > 0)
- writen = fwrite (data, 1, atom_size, f);
- g_free (data);
- return atom_size > 0 && writen == atom_size;
-}
-
-/**
- * Writes the number of traks to the file.
- * This simply writes a guint32 in BE.
- */
-static gboolean
-atoms_recov_write_traks_number (FILE * f, guint32 traks)
-{
- guint8 data[4];
- GST_WRITE_UINT32_BE (data, traks);
- return fwrite (data, 4, 1, f) == 1;
-}
-
-/**
- * Writes the moov's timescale to the file
- * This simply writes a guint32 in BE.
- */
-static gboolean
-atoms_recov_write_moov_timescale (FILE * f, guint32 timescale)
-{
- guint8 data[4];
- GST_WRITE_UINT32_BE (data, timescale);
- return fwrite (data, 4, 1, f) == 1;
-}
-
-/**
- * Writes the trak atom to the file.
- */
-gboolean
-atoms_recov_write_trak_info (FILE * f, AtomTRAK * trak)
-{
- guint8 *data;
- guint64 size;
- guint64 offset = 0;
- guint64 atom_size = 0;
- gint writen = 0;
-
- /* buffer is realloced to a larger size if needed */
- size = 4 * 1024;
- data = g_malloc (size);
- atom_size = atom_trak_copy_data (trak, &data, &size, &offset);
- if (atom_size > 0)
- writen = fwrite (data, atom_size, 1, f);
- g_free (data);
- return atom_size > 0 && writen == atom_size;
-}
-
-gboolean
-atoms_recov_write_trak_samples (FILE * f, AtomTRAK * trak, guint32 nsamples,
- guint32 delta, guint32 size, guint64 chunk_offset, gboolean sync,
- gboolean do_pts, gint64 pts_offset)
-{
- guint8 data[TRAK_BUFFER_ENTRY_INFO_SIZE];
- /*
- * We have to write a TrakBufferEntryInfo
- */
- GST_WRITE_UINT32_BE (data + 0, trak->tkhd.track_ID);
- GST_WRITE_UINT32_BE (data + 4, nsamples);
- GST_WRITE_UINT32_BE (data + 8, delta);
- GST_WRITE_UINT32_BE (data + 12, size);
- GST_WRITE_UINT64_BE (data + 16, chunk_offset);
- if (sync)
- GST_WRITE_UINT8 (data + 24, 1);
- else
- GST_WRITE_UINT8 (data + 24, 0);
- if (do_pts) {
- GST_WRITE_UINT8 (data + 25, 1);
- GST_WRITE_UINT64_BE (data + 26, pts_offset);
- } else {
- GST_WRITE_UINT8 (data + 25, 0);
- GST_WRITE_UINT64_BE (data + 26, 0);
- }
-
- return fwrite (data, 1, TRAK_BUFFER_ENTRY_INFO_SIZE, f) ==
- TRAK_BUFFER_ENTRY_INFO_SIZE;
-}
-
-gboolean
-atoms_recov_write_headers (FILE * f, AtomFTYP * ftyp, GstBuffer * prefix,
- AtomMOOV * moov, guint32 timescale, guint32 traks_number)
-{
- if (!atoms_recov_write_version (f)) {
- return FALSE;
- }
-
- if (!atoms_recov_write_ftyp_info (f, ftyp, prefix)) {
- return FALSE;
- }
-
- if (!atoms_recov_write_moov_info (f, moov)) {
- return FALSE;
- }
-
- if (!atoms_recov_write_moov_timescale (f, timescale)) {
- return FALSE;
- }
-
- if (!atoms_recov_write_traks_number (f, traks_number)) {
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-read_atom_header (FILE * f, guint32 * fourcc, guint32 * size)
-{
- guint8 aux[8];
-
- if (fread (aux, 1, 8, f) != 8)
- return FALSE;
- *size = GST_READ_UINT32_BE (aux);
- *fourcc = GST_READ_UINT32_LE (aux + 4);
- return TRUE;
-}
-
-static gboolean
-moov_recov_file_parse_prefix (MoovRecovFile * moovrf)
-{
- guint32 fourcc;
- guint32 size;
- guint32 total_size = 0;
- if (fseek (moovrf->file, 2, SEEK_SET) != 0)
- return FALSE;
- if (!read_atom_header (moovrf->file, &fourcc, &size)) {
- return FALSE;
- }
-
- if (fourcc != FOURCC_ftyp) {
- /* we might have a prefix here */
- if (fseek (moovrf->file, size - 8, SEEK_CUR) != 0)
- return FALSE;
-
- total_size += size;
-
- /* now read the ftyp */
- if (!read_atom_header (moovrf->file, &fourcc, &size))
- return FALSE;
- }
-
- /* this has to be the ftyp */
- if (fourcc != FOURCC_ftyp)
- return FALSE;
- total_size += size;
- moovrf->prefix_size = total_size;
- return fseek (moovrf->file, size - 8, SEEK_CUR) == 0;
-}
-
-static gboolean
-moov_recov_file_parse_mvhd (MoovRecovFile * moovrf)
-{
- guint32 fourcc;
- guint32 size;
- if (!read_atom_header (moovrf->file, &fourcc, &size)) {
- return FALSE;
- }
- /* check for sanity */
- if (fourcc != FOURCC_mvhd)
- return FALSE;
-
- moovrf->mvhd_size = size;
- moovrf->mvhd_pos = ftell (moovrf->file) - 8;
-
- /* skip the remaining of the mvhd in the file */
- return fseek (moovrf->file, size - 8, SEEK_CUR) == 0;
-}
-
-static gboolean
-mdat_recov_file_parse_mdat_start (MdatRecovFile * mdatrf)
-{
- guint32 fourcc, size;
-
- if (!read_atom_header (mdatrf->file, &fourcc, &size)) {
- return FALSE;
- }
- if (size == 1) {
- mdatrf->mdat_header_size = 16;
- mdatrf->mdat_size = 16;
- } else {
- mdatrf->mdat_header_size = 8;
- mdatrf->mdat_size = 8;
- }
- mdatrf->mdat_start = ftell (mdatrf->file) - 8;
-
- return fourcc == FOURCC_mdat;
-}
-
-MdatRecovFile *
-mdat_recov_file_create (FILE * file, gboolean datafile, GError ** err)
-{
- MdatRecovFile *mrf = g_new0 (MdatRecovFile, 1);
- guint32 fourcc, size;
-
- g_return_val_if_fail (file != NULL, NULL);
-
- mrf->file = file;
- mrf->rawfile = datafile;
-
- /* get the file/data length */
- if (fseek (file, 0, SEEK_END) != 0)
- goto file_length_error;
- /* still needs to deduce the mdat header and ftyp size */
- mrf->data_size = ftell (file);
- if (mrf->data_size == -1L)
- goto file_length_error;
-
- if (fseek (file, 0, SEEK_SET) != 0)
- goto file_seek_error;
-
- if (datafile) {
- /* this file contains no atoms, only raw data to be placed on the mdat
- * this happens when faststart mode is used */
- mrf->mdat_start = 0;
- mrf->mdat_header_size = 16;
- mrf->mdat_size = 16;
- return mrf;
- }
-
- if (!read_atom_header (file, &fourcc, &size)) {
- goto parse_error;
- }
- if (fourcc != FOURCC_ftyp) {
- /* this could be a prefix atom, let's skip it and try again */
- if (fseek (file, size - 8, SEEK_CUR) != 0) {
- goto file_seek_error;
- }
- if (!read_atom_header (file, &fourcc, &size)) {
- goto parse_error;
- }
- }
-
- if (fourcc != FOURCC_ftyp) {
- goto parse_error;
- }
- if (fseek (file, size - 8, SEEK_CUR) != 0)
- goto file_seek_error;
-
- /* we don't parse this if we have a tmpdatafile */
- if (!mdat_recov_file_parse_mdat_start (mrf)) {
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_PARSING,
- "Error while parsing mdat atom");
- goto fail;
- }
-
- return mrf;
-
-parse_error:
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
- "Failed to parse atom");
- goto fail;
-
-file_seek_error:
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
- "Failed to seek to start of the file");
- goto fail;
-
-file_length_error:
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
- "Failed to determine file size");
- goto fail;
-
-fail:
- mdat_recov_file_free (mrf);
- return NULL;
-}
-
-void
-mdat_recov_file_free (MdatRecovFile * mrf)
-{
- fclose (mrf->file);
- g_free (mrf);
-}
-
-static gboolean
-moov_recov_parse_num_traks (MoovRecovFile * moovrf)
-{
- guint8 traks[4];
- if (fread (traks, 1, 4, moovrf->file) != 4)
- return FALSE;
- moovrf->num_traks = GST_READ_UINT32_BE (traks);
- return TRUE;
-}
-
-static gboolean
-moov_recov_parse_moov_timescale (MoovRecovFile * moovrf)
-{
- guint8 ts[4];
- if (fread (ts, 1, 4, moovrf->file) != 4)
- return FALSE;
- moovrf->timescale = GST_READ_UINT32_BE (ts);
- return TRUE;
-}
-
-static gboolean
-skip_atom (MoovRecovFile * moovrf, guint32 expected_fourcc)
-{
- guint32 size;
- guint32 fourcc;
-
- if (!read_atom_header (moovrf->file, &fourcc, &size))
- return FALSE;
- if (fourcc != expected_fourcc)
- return FALSE;
-
- return (fseek (moovrf->file, size - 8, SEEK_CUR) == 0);
-}
-
-static gboolean
-moov_recov_parse_tkhd (MoovRecovFile * moovrf, TrakRecovData * trakrd)
-{
- guint32 size;
- guint32 fourcc;
- guint8 data[4];
-
- /* make sure we are on a tkhd atom */
- if (!read_atom_header (moovrf->file, &fourcc, &size))
- return FALSE;
- if (fourcc != FOURCC_tkhd)
- return FALSE;
-
- trakrd->tkhd_file_offset = ftell (moovrf->file) - 8;
-
- /* move 8 bytes forward to the trak_id pos */
- if (fseek (moovrf->file, 12, SEEK_CUR) != 0)
- return FALSE;
- if (fread (data, 1, 4, moovrf->file) != 4)
- return FALSE;
-
- /* advance the rest of tkhd */
- fseek (moovrf->file, 68, SEEK_CUR);
-
- trakrd->trak_id = GST_READ_UINT32_BE (data);
- return TRUE;
-}
-
-static gboolean
-moov_recov_parse_stbl (MoovRecovFile * moovrf, TrakRecovData * trakrd)
-{
- guint32 size;
- guint32 fourcc;
- guint32 auxsize;
-
- if (!read_atom_header (moovrf->file, &fourcc, &size))
- return FALSE;
- if (fourcc != FOURCC_stbl)
- return FALSE;
-
- trakrd->stbl_file_offset = ftell (moovrf->file) - 8;
- trakrd->stbl_size = size;
-
- /* skip the stsd */
- if (!read_atom_header (moovrf->file, &fourcc, &auxsize))
- return FALSE;
- if (fourcc != FOURCC_stsd)
- return FALSE;
- if (fseek (moovrf->file, auxsize - 8, SEEK_CUR) != 0)
- return FALSE;
-
- trakrd->stsd_size = auxsize;
- trakrd->post_stsd_offset = ftell (moovrf->file);
-
- /* as this is the last atom we parse, we don't skip forward */
-
- return TRUE;
-}
-
-static gboolean
-moov_recov_parse_minf (MoovRecovFile * moovrf, TrakRecovData * trakrd)
-{
- guint32 size;
- guint32 fourcc;
- guint32 auxsize;
-
- if (!read_atom_header (moovrf->file, &fourcc, &size))
- return FALSE;
- if (fourcc != FOURCC_minf)
- return FALSE;
-
- trakrd->minf_file_offset = ftell (moovrf->file) - 8;
- trakrd->minf_size = size;
-
- /* skip either of vmhd, smhd, hmhd that might follow */
- if (!read_atom_header (moovrf->file, &fourcc, &auxsize))
- return FALSE;
- if (fourcc != FOURCC_vmhd && fourcc != FOURCC_smhd && fourcc != FOURCC_hmhd &&
- fourcc != FOURCC_gmhd)
- return FALSE;
- if (fseek (moovrf->file, auxsize - 8, SEEK_CUR))
- return FALSE;
-
- /* skip a possible hdlr and the following dinf */
- if (!read_atom_header (moovrf->file, &fourcc, &auxsize))
- return FALSE;
- if (fourcc == FOURCC_hdlr) {
- if (fseek (moovrf->file, auxsize - 8, SEEK_CUR))
- return FALSE;
- if (!read_atom_header (moovrf->file, &fourcc, &auxsize))
- return FALSE;
- }
- if (fourcc != FOURCC_dinf)
- return FALSE;
- if (fseek (moovrf->file, auxsize - 8, SEEK_CUR))
- return FALSE;
-
- /* now we are ready to read the stbl */
- if (!moov_recov_parse_stbl (moovrf, trakrd))
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-moov_recov_parse_mdhd (MoovRecovFile * moovrf, TrakRecovData * trakrd)
-{
- guint32 size;
- guint32 fourcc;
- guint8 data[4];
-
- /* make sure we are on a tkhd atom */
- if (!read_atom_header (moovrf->file, &fourcc, &size))
- return FALSE;
- if (fourcc != FOURCC_mdhd)
- return FALSE;
-
- trakrd->mdhd_file_offset = ftell (moovrf->file) - 8;
-
- /* get the timescale */
- if (fseek (moovrf->file, 12, SEEK_CUR) != 0)
- return FALSE;
- if (fread (data, 1, 4, moovrf->file) != 4)
- return FALSE;
- trakrd->timescale = GST_READ_UINT32_BE (data);
- if (fseek (moovrf->file, 8, SEEK_CUR) != 0)
- return FALSE;
- return TRUE;
-}
-
-static gboolean
-moov_recov_parse_mdia (MoovRecovFile * moovrf, TrakRecovData * trakrd)
-{
- guint32 size;
- guint32 fourcc;
-
- /* make sure we are on a tkhd atom */
- if (!read_atom_header (moovrf->file, &fourcc, &size))
- return FALSE;
- if (fourcc != FOURCC_mdia)
- return FALSE;
-
- trakrd->mdia_file_offset = ftell (moovrf->file) - 8;
- trakrd->mdia_size = size;
-
- if (!moov_recov_parse_mdhd (moovrf, trakrd))
- return FALSE;
-
- if (!skip_atom (moovrf, FOURCC_hdlr))
- return FALSE;
- if (!moov_recov_parse_minf (moovrf, trakrd))
- return FALSE;
- return TRUE;
-}
-
-static gboolean
-moov_recov_parse_trak (MoovRecovFile * moovrf, TrakRecovData * trakrd)
-{
- guint64 offset;
- guint32 size;
- guint32 fourcc;
-
- offset = ftell (moovrf->file);
- if (offset == -1) {
- return FALSE;
- }
-
- /* make sure we are on a trak atom */
- if (!read_atom_header (moovrf->file, &fourcc, &size)) {
- return FALSE;
- }
- if (fourcc != FOURCC_trak) {
- return FALSE;
- }
- trakrd->trak_size = size;
-
- /* now we should have a trak header 'tkhd' */
- if (!moov_recov_parse_tkhd (moovrf, trakrd))
- return FALSE;
-
- /* FIXME add edts handling here and in qtmux, as this is only detected
- * after buffers start flowing */
-
- if (!moov_recov_parse_mdia (moovrf, trakrd))
- return FALSE;
-
- trakrd->file_offset = offset;
- /* position after the trak */
- return fseek (moovrf->file, (long int) offset + size, SEEK_SET) == 0;
-}
-
-MoovRecovFile *
-moov_recov_file_create (FILE * file, GError ** err)
-{
- gint i;
- MoovRecovFile *moovrf = g_new0 (MoovRecovFile, 1);
-
- g_return_val_if_fail (file != NULL, NULL);
-
- moovrf->file = file;
-
- /* look for ftyp and prefix at the start */
- if (!moov_recov_file_parse_prefix (moovrf)) {
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_PARSING,
- "Error while parsing prefix atoms");
- goto fail;
- }
-
- /* parse the mvhd */
- if (!moov_recov_file_parse_mvhd (moovrf)) {
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_PARSING,
- "Error while parsing mvhd atom");
- goto fail;
- }
-
- if (!moov_recov_parse_moov_timescale (moovrf)) {
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_PARSING,
- "Error while parsing timescale");
- goto fail;
- }
- if (!moov_recov_parse_num_traks (moovrf)) {
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_PARSING,
- "Error while parsing parsing number of traks");
- goto fail;
- }
-
- /* init the traks */
- moovrf->traks_rd = g_new0 (TrakRecovData, moovrf->num_traks);
- for (i = 0; i < moovrf->num_traks; i++) {
- atom_stbl_init (&(moovrf->traks_rd[i].stbl));
- }
- for (i = 0; i < moovrf->num_traks; i++) {
- if (!moov_recov_parse_trak (moovrf, &(moovrf->traks_rd[i]))) {
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_PARSING,
- "Error while parsing trak atom");
- goto fail;
- }
- }
-
- return moovrf;
-
-fail:
- moov_recov_file_free (moovrf);
- return NULL;
-}
-
-void
-moov_recov_file_free (MoovRecovFile * moovrf)
-{
- gint i;
- fclose (moovrf->file);
- if (moovrf->traks_rd) {
- for (i = 0; i < moovrf->num_traks; i++) {
- atom_stbl_clear (&(moovrf->traks_rd[i].stbl));
- }
- g_free (moovrf->traks_rd);
- }
- g_free (moovrf);
-}
-
-static gboolean
-moov_recov_parse_buffer_entry (MoovRecovFile * moovrf, TrakBufferEntryInfo * b)
-{
- guint8 data[TRAK_BUFFER_ENTRY_INFO_SIZE];
- gint read;
-
- read = fread (data, 1, TRAK_BUFFER_ENTRY_INFO_SIZE, moovrf->file);
- if (read != TRAK_BUFFER_ENTRY_INFO_SIZE)
- return FALSE;
-
- b->track_id = GST_READ_UINT32_BE (data);
- b->nsamples = GST_READ_UINT32_BE (data + 4);
- b->delta = GST_READ_UINT32_BE (data + 8);
- b->size = GST_READ_UINT32_BE (data + 12);
- b->chunk_offset = GST_READ_UINT64_BE (data + 16);
- b->sync = data[24] != 0;
- b->do_pts = data[25] != 0;
- b->pts_offset = GST_READ_UINT64_BE (data + 26);
- return TRUE;
-}
-
-static gboolean
-mdat_recov_add_sample (MdatRecovFile * mdatrf, guint32 size)
-{
- /* test if this data exists */
- if (mdatrf->mdat_size - mdatrf->mdat_header_size + size > mdatrf->data_size)
- return FALSE;
-
- mdatrf->mdat_size += size;
- return TRUE;
-}
-
-static TrakRecovData *
-moov_recov_get_trak (MoovRecovFile * moovrf, guint32 id)
-{
- gint i;
- for (i = 0; i < moovrf->num_traks; i++) {
- if (moovrf->traks_rd[i].trak_id == id)
- return &(moovrf->traks_rd[i]);
- }
- return NULL;
-}
-
-static void
-trak_recov_data_add_sample (TrakRecovData * trak, TrakBufferEntryInfo * b)
-{
- trak->duration += b->nsamples * b->delta;
- atom_stbl_add_samples (&trak->stbl, b->nsamples, b->delta, b->size,
- b->chunk_offset, b->sync, b->pts_offset);
-}
-
-/**
- * Parses the buffer entries in the MoovRecovFile and matches the inputs
- * with the data in the MdatRecovFile. Whenever a buffer entry of that
- * represents 'x' bytes of data, the same amount of data is 'validated' in
- * the MdatRecovFile and will be inluded in the generated moovie file.
- */
-gboolean
-moov_recov_parse_buffers (MoovRecovFile * moovrf, MdatRecovFile * mdatrf,
- GError ** err)
-{
- TrakBufferEntryInfo entry;
- TrakRecovData *trak;
-
- /* we assume both moovrf and mdatrf are at the starting points of their
- * data reading */
- while (moov_recov_parse_buffer_entry (moovrf, &entry)) {
- /* be sure we still have this data in mdat */
- trak = moov_recov_get_trak (moovrf, entry.track_id);
- if (trak == NULL) {
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_PARSING,
- "Invalid trak id found in buffer entry");
- return FALSE;
- }
- if (!mdat_recov_add_sample (mdatrf, entry.size))
- break;
- trak_recov_data_add_sample (trak, &entry);
- }
- return TRUE;
-}
-
-static guint32
-trak_recov_data_get_trak_atom_size (TrakRecovData * trak)
-{
- AtomSTBL *stbl = &trak->stbl;
- guint64 offset;
-
- /* write out our stbl child atoms */
- offset = 0;
-
- if (!atom_stts_copy_data (&stbl->stts, NULL, NULL, &offset)) {
- goto fail;
- }
- if (atom_array_get_len (&stbl->stss.entries) > 0) {
- if (!atom_stss_copy_data (&stbl->stss, NULL, NULL, &offset)) {
- goto fail;
- }
- }
- if (!atom_stsc_copy_data (&stbl->stsc, NULL, NULL, &offset)) {
- goto fail;
- }
- if (!atom_stsz_copy_data (&stbl->stsz, NULL, NULL, &offset)) {
- goto fail;
- }
- if (stbl->ctts) {
- if (!atom_ctts_copy_data (stbl->ctts, NULL, NULL, &offset)) {
- goto fail;
- }
- }
- if (!atom_stco64_copy_data (&stbl->stco64, NULL, NULL, &offset)) {
- goto fail;
- }
-
- return trak->trak_size + ((trak->stsd_size + offset + 8) - trak->stbl_size);
-
-fail:
- return 0;
-}
-
-static guint8 *
-moov_recov_get_stbl_children_data (MoovRecovFile * moovrf, TrakRecovData * trak,
- guint64 * p_size)
-{
- AtomSTBL *stbl = &trak->stbl;
- guint8 *buffer;
- guint64 size;
- guint64 offset;
-
- /* write out our stbl child atoms
- *
- * Use 1MB as a starting size, *_copy_data functions
- * will grow the buffer if needed.
- */
- size = 1024 * 1024;
- buffer = g_malloc0 (size);
- offset = 0;
-
- if (!atom_stts_copy_data (&stbl->stts, &buffer, &size, &offset)) {
- goto fail;
- }
- if (atom_array_get_len (&stbl->stss.entries) > 0) {
- if (!atom_stss_copy_data (&stbl->stss, &buffer, &size, &offset)) {
- goto fail;
- }
- }
- if (!atom_stsc_copy_data (&stbl->stsc, &buffer, &size, &offset)) {
- goto fail;
- }
- if (!atom_stsz_copy_data (&stbl->stsz, &buffer, &size, &offset)) {
- goto fail;
- }
- if (stbl->ctts) {
- if (!atom_ctts_copy_data (stbl->ctts, &buffer, &size, &offset)) {
- goto fail;
- }
- }
- if (!atom_stco64_copy_data (&stbl->stco64, &buffer, &size, &offset)) {
- goto fail;
- }
- *p_size = offset;
- return buffer;
-
-fail:
- g_free (buffer);
- return NULL;
-}
-
-gboolean
-moov_recov_write_file (MoovRecovFile * moovrf, MdatRecovFile * mdatrf,
- FILE * outf, GError ** err)
-{
- guint8 auxdata[16];
- guint8 *data = NULL;
- guint8 *prefix_data = NULL;
- guint8 *mvhd_data = NULL;
- guint8 *trak_data = NULL;
- guint32 moov_size = 0;
- gint i;
- guint64 stbl_children_size = 0;
- guint8 *stbl_children = NULL;
- guint32 longest_duration = 0;
- guint16 version;
-
- /* check the version */
- if (fseek (moovrf->file, 0, SEEK_SET) != 0) {
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
- "Failed to seek to the start of the moov recovery file");
- goto fail;
- }
- if (fread (auxdata, 1, 2, moovrf->file) != 2) {
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
- "Failed to read version from file");
- }
-
- version = GST_READ_UINT16_BE (auxdata);
- if (version != ATOMS_RECOV_FILE_VERSION) {
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_VERSION,
- "Input file version (%u) is not supported in this version (%u)",
- version, ATOMS_RECOV_FILE_VERSION);
- return FALSE;
- }
-
- /* write the ftyp */
- prefix_data = g_malloc (moovrf->prefix_size);
- if (fread (prefix_data, 1, moovrf->prefix_size,
- moovrf->file) != moovrf->prefix_size) {
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
- "Failed to read the ftyp atom from file");
- goto fail;
- }
- if (fwrite (prefix_data, 1, moovrf->prefix_size, outf) != moovrf->prefix_size) {
- ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
- goto fail;
- }
- g_free (prefix_data);
- prefix_data = NULL;
-
- /* need to calculate the moov size beforehand to add the offset to
- * chunk offset entries */
- moov_size += moovrf->mvhd_size + 8; /* mvhd + moov size + fourcc */
- for (i = 0; i < moovrf->num_traks; i++) {
- TrakRecovData *trak = &(moovrf->traks_rd[i]);
- guint32 duration; /* in moov's timescale */
- guint32 trak_size;
-
- /* convert trak duration to moov's duration */
- duration = gst_util_uint64_scale_round (trak->duration, moovrf->timescale,
- trak->timescale);
-
- if (duration > longest_duration)
- longest_duration = duration;
- trak_size = trak_recov_data_get_trak_atom_size (trak);
- if (trak_size == 0) {
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_GENERIC,
- "Failed to estimate trak atom size");
- goto fail;
- }
- moov_size += trak_size;
- }
-
- /* add chunks offsets */
- for (i = 0; i < moovrf->num_traks; i++) {
- TrakRecovData *trak = &(moovrf->traks_rd[i]);
- /* 16 for the mdat header */
- gint64 offset = moov_size + ftell (outf) + 16;
- atom_stco64_chunks_add_offset (&trak->stbl.stco64, offset);
- }
-
- /* write the moov */
- GST_WRITE_UINT32_BE (auxdata, moov_size);
- GST_WRITE_UINT32_LE (auxdata + 4, FOURCC_moov);
- if (fwrite (auxdata, 1, 8, outf) != 8) {
- ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
- goto fail;
- }
-
- /* write the mvhd */
- mvhd_data = g_malloc (moovrf->mvhd_size);
- if (fseek (moovrf->file, moovrf->mvhd_pos, SEEK_SET) != 0)
- goto fail;
- if (fread (mvhd_data, 1, moovrf->mvhd_size,
- moovrf->file) != moovrf->mvhd_size)
- goto fail;
- GST_WRITE_UINT32_BE (mvhd_data + 20, moovrf->timescale);
- GST_WRITE_UINT32_BE (mvhd_data + 24, longest_duration);
- if (fwrite (mvhd_data, 1, moovrf->mvhd_size, outf) != moovrf->mvhd_size) {
- ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
- goto fail;
- }
- g_free (mvhd_data);
- mvhd_data = NULL;
-
- /* write the traks, this is the tough part because we need to update:
- * - stbl atom
- * - sizes of atoms from stbl to trak
- * - trak duration
- */
- for (i = 0; i < moovrf->num_traks; i++) {
- TrakRecovData *trak = &(moovrf->traks_rd[i]);
- guint trak_data_size;
- guint32 stbl_new_size;
- guint32 minf_new_size;
- guint32 mdia_new_size;
- guint32 trak_new_size;
- guint32 size_diff;
- guint32 duration; /* in moov's timescale */
-
- /* convert trak duration to moov's duration */
- duration = gst_util_uint64_scale_round (trak->duration, moovrf->timescale,
- trak->timescale);
-
- stbl_children = moov_recov_get_stbl_children_data (moovrf, trak,
- &stbl_children_size);
- if (stbl_children == NULL)
- goto fail;
-
- /* calc the new size of the atoms from stbl to trak in the atoms tree */
- stbl_new_size = trak->stsd_size + stbl_children_size + 8;
- size_diff = stbl_new_size - trak->stbl_size;
- minf_new_size = trak->minf_size + size_diff;
- mdia_new_size = trak->mdia_size + size_diff;
- trak_new_size = trak->trak_size + size_diff;
-
- if (fseek (moovrf->file, trak->file_offset, SEEK_SET) != 0)
- goto fail;
- trak_data_size = trak->post_stsd_offset - trak->file_offset;
- trak_data = g_malloc (trak_data_size);
- if (fread (trak_data, 1, trak_data_size, moovrf->file) != trak_data_size) {
- goto fail;
- }
- /* update the size values in those read atoms before writing */
- GST_WRITE_UINT32_BE (trak_data, trak_new_size);
- GST_WRITE_UINT32_BE (trak_data + (trak->mdia_file_offset -
- trak->file_offset), mdia_new_size);
- GST_WRITE_UINT32_BE (trak_data + (trak->minf_file_offset -
- trak->file_offset), minf_new_size);
- GST_WRITE_UINT32_BE (trak_data + (trak->stbl_file_offset -
- trak->file_offset), stbl_new_size);
-
- /* update duration values in tkhd and mdhd */
- GST_WRITE_UINT32_BE (trak_data + (trak->tkhd_file_offset -
- trak->file_offset) + 28, duration);
- GST_WRITE_UINT32_BE (trak_data + (trak->mdhd_file_offset -
- trak->file_offset) + 24, trak->duration);
-
- if (fwrite (trak_data, 1, trak_data_size, outf) != trak_data_size) {
- ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
- goto fail;
- }
- if (fwrite (stbl_children, 1, stbl_children_size, outf) !=
- stbl_children_size) {
- ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
- goto fail;
- }
- g_free (trak_data);
- trak_data = NULL;
- g_free (stbl_children);
- stbl_children = NULL;
- }
-
- /* write the mdat */
- /* write the header first */
- GST_WRITE_UINT32_BE (auxdata, 1);
- GST_WRITE_UINT32_LE (auxdata + 4, FOURCC_mdat);
- GST_WRITE_UINT64_BE (auxdata + 8, mdatrf->mdat_size);
- if (fwrite (auxdata, 1, 16, outf) != 16) {
- ATOMS_RECOV_OUTPUT_WRITE_ERROR (err);
- goto fail;
- }
-
- /* now read the mdat data and output to the file */
- if (fseek (mdatrf->file, mdatrf->mdat_start +
- (mdatrf->rawfile ? 0 : mdatrf->mdat_header_size), SEEK_SET) != 0)
- goto fail;
-
- data = g_malloc (4096);
- while (!feof (mdatrf->file)) {
- gint read, write;
-
- read = fread (data, 1, 4096, mdatrf->file);
- write = fwrite (data, 1, read, outf);
-
- if (write != read) {
- g_set_error (err, ATOMS_RECOV_QUARK, ATOMS_RECOV_ERR_FILE,
- "Failed to copy data to output file: %s", g_strerror (errno));
- goto fail;
- }
- }
- g_free (data);
-
- return TRUE;
-
-fail:
- g_free (stbl_children);
- g_free (mvhd_data);
- g_free (prefix_data);
- g_free (trak_data);
- g_free (data);
- return FALSE;
-}
diff --git a/gst/qtmux/atomsrecovery.h b/gst/qtmux/atomsrecovery.h
deleted file mode 100644
index 4dffc48d3..000000000
--- a/gst/qtmux/atomsrecovery.h
+++ /dev/null
@@ -1,159 +0,0 @@
-/* Quicktime muxer plugin for GStreamer
- * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
- *
- * 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.
- */
-/*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __ATOMS_RECOVERY_H__
-#define __ATOMS_RECOVERY_H__
-
-#include <glib.h>
-#include <string.h>
-#include <stdio.h>
-#include <gst/gst.h>
-
-#include "atoms.h"
-
-/* Version to be incremented each time we decide
- * to change the file layout */
-#define ATOMS_RECOV_FILE_VERSION 1
-
-#define ATOMS_RECOV_QUARK (g_quark_from_string ("qtmux-atoms-recovery"))
-
-/* gerror error codes */
-#define ATOMS_RECOV_ERR_GENERIC 1
-#define ATOMS_RECOV_ERR_FILE 2
-#define ATOMS_RECOV_ERR_PARSING 3
-#define ATOMS_RECOV_ERR_VERSION 4
-
-/* this struct represents each buffer in a moov file, containing the info
- * that is placed in the stsd children atoms
- * Fields should be writen in BE order, and booleans should be writen as
- * 1byte with 0 for false, anything otherwise */
-#define TRAK_BUFFER_ENTRY_INFO_SIZE 34
-typedef struct
-{
- guint32 track_id;
- guint32 nsamples;
- guint32 delta;
- guint32 size;
- guint64 chunk_offset;
- guint64 pts_offset;
- gboolean sync;
- gboolean do_pts;
-} TrakBufferEntryInfo;
-
-typedef struct
-{
- guint32 trak_id;
- guint32 duration; /* duration in trak timescale */
- guint32 timescale; /* trak's timescale */
-
- guint64 file_offset;
-
- /* need for later updating duration */
- guint64 tkhd_file_offset;
- guint64 mdhd_file_offset;
-
- /* need these offsets to update size */
- guint32 trak_size;
- guint64 mdia_file_offset;
- guint32 mdia_size;
- guint64 minf_file_offset;
- guint32 minf_size;
- guint64 stbl_file_offset;
- guint32 stbl_size;
-
- guint64 post_stsd_offset;
- guint32 stsd_size;
-
- /* for storing the samples info */
- AtomSTBL stbl;
-} TrakRecovData;
-
-typedef struct
-{
- FILE * file;
- gboolean rawfile;
-
- /* results from parsing the input file */
- guint64 data_size;
- guint32 mdat_header_size;
- guint mdat_start;
-
- guint64 mdat_size;
-} MdatRecovFile;
-
-typedef struct
-{
- FILE * file;
- guint32 timescale;
-
- guint32 mvhd_pos;
- guint32 mvhd_size;
- guint32 prefix_size; /* prefix + ftyp total size */
-
- gint num_traks;
- TrakRecovData *traks_rd;
-} MoovRecovFile;
-
-gboolean atoms_recov_write_trak_info (FILE * f, AtomTRAK * trak);
-gboolean atoms_recov_write_headers (FILE * f, AtomFTYP * ftyp,
- GstBuffer * prefix, AtomMOOV * moov,
- guint32 timescale,
- guint32 traks_number);
-gboolean atoms_recov_write_trak_samples (FILE * f, AtomTRAK * trak,
- guint32 nsamples, guint32 delta,
- guint32 size, guint64 chunk_offset,
- gboolean sync, gboolean do_pts,
- gint64 pts_offset);
-
-MdatRecovFile * mdat_recov_file_create (FILE * file, gboolean datafile,
- GError ** err);
-void mdat_recov_file_free (MdatRecovFile * mrf);
-MoovRecovFile * moov_recov_file_create (FILE * file, GError ** err);
-void moov_recov_file_free (MoovRecovFile * moovrf);
-gboolean moov_recov_parse_buffers (MoovRecovFile * moovrf,
- MdatRecovFile * mdatrf,
- GError ** err);
-gboolean moov_recov_write_file (MoovRecovFile * moovrf,
- MdatRecovFile * mdatrf, FILE * outf,
- GError ** err);
-
-#endif /* __ATOMS_RECOVERY_H__ */
diff --git a/gst/qtmux/descriptors.c b/gst/qtmux/descriptors.c
deleted file mode 100644
index d1e99c21e..000000000
--- a/gst/qtmux/descriptors.c
+++ /dev/null
@@ -1,458 +0,0 @@
-/* Quicktime muxer plugin for GStreamer
- * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
- *
- * 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.
- */
-/*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "descriptors.h"
-
-/*
- * Some mp4 structures (descriptors) use a coding scheme for
- * representing its size.
- * It is grouped in bytes. The 1st bit set to 1 means we need another byte,
- * 0 otherwise. The remaining 7 bits are the useful values.
- *
- * The next set of functions handle those values
- */
-
-/*
- * Gets an unsigned integer and packs it into a 'expandable size' format
- * (as used by mp4 descriptors)
- * @size: the integer to be parsed
- * @ptr: the array to place the result
- * @array_size: the size of ptr array
- */
-static void
-expandable_size_parse (guint64 size, guint8 * ptr, guint32 array_size)
-{
- int index = 0;
-
- memset (ptr, 0, sizeof (array_size));
- while (size > 0 && index < array_size) {
- ptr[index++] = (size > 0x7F ? 0x80 : 0x0) | (size & 0x7F);
- size = size >> 7;
- }
-}
-
-/*
- * Gets how many positions in an array holding an 'expandable size'
- * are really used
- *
- * @ptr: the array with the 'expandable size'
- * @array_size: the size of ptr array
- *
- * Returns: the number of really used positions
- */
-static guint64
-expandable_size_get_length (guint8 * ptr, guint32 array_size)
-{
- gboolean next = TRUE;
- guint32 index = 0;
-
- while (next && index < array_size) {
- next = ((ptr[index] & 0x80) == 1);
- index++;
- }
- return index;
-}
-
-/*
- * Initializers below
- */
-
-static void
-desc_base_descriptor_init (BaseDescriptor * bd, guint8 tag, guint32 size)
-{
- bd->tag = tag;
- expandable_size_parse (size, bd->size, 4);
-}
-
-static void
-desc_dec_specific_info_init (DecoderSpecificInfoDescriptor * dsid)
-{
- desc_base_descriptor_init (&dsid->base, DECODER_SPECIFIC_INFO_TAG, 0);
- dsid->length = 0;
- dsid->data = NULL;
-}
-
-DecoderSpecificInfoDescriptor *
-desc_dec_specific_info_new (void)
-{
- DecoderSpecificInfoDescriptor *desc =
- g_new0 (DecoderSpecificInfoDescriptor, 1);
- desc_dec_specific_info_init (desc);
- return desc;
-}
-
-static void
-desc_dec_conf_desc_init (DecoderConfigDescriptor * dcd)
-{
- desc_base_descriptor_init (&dcd->base, DECODER_CONFIG_DESC_TAG, 0);
- dcd->dec_specific_info = NULL;
-}
-
-static void
-desc_sl_conf_desc_init (SLConfigDescriptor * sl)
-{
- desc_base_descriptor_init (&sl->base, SL_CONFIG_DESC_TAG, 0);
- sl->predefined = 0x2;
-}
-
-void
-desc_es_init (ESDescriptor * es)
-{
- desc_base_descriptor_init (&es->base, ES_DESCRIPTOR_TAG, 0);
-
- es->id = 0;
- es->flags = 0;
- es->depends_on_es_id = 0;
- es->ocr_es_id = 0;
- es->url_length = 0;
- es->url_string = NULL;
-
- desc_dec_conf_desc_init (&es->dec_conf_desc);
- desc_sl_conf_desc_init (&es->sl_conf_desc);
-}
-
-ESDescriptor *
-desc_es_descriptor_new (void)
-{
- ESDescriptor *es = g_new0 (ESDescriptor, 1);
-
- desc_es_init (es);
- return es;
-}
-
-/*
- * Deinitializers/Destructors below
- */
-
-static void
-desc_base_descriptor_clear (BaseDescriptor * base)
-{
-}
-
-void
-desc_dec_specific_info_free (DecoderSpecificInfoDescriptor * dsid)
-{
- desc_base_descriptor_clear (&dsid->base);
- if (dsid->data) {
- g_free (dsid->data);
- dsid->data = NULL;
- }
- g_free (dsid);
-}
-
-static void
-desc_dec_conf_desc_clear (DecoderConfigDescriptor * dec)
-{
- desc_base_descriptor_clear (&dec->base);
- if (dec->dec_specific_info) {
- desc_dec_specific_info_free (dec->dec_specific_info);
- }
-}
-
-static void
-desc_sl_config_descriptor_clear (SLConfigDescriptor * sl)
-{
- desc_base_descriptor_clear (&sl->base);
-}
-
-void
-desc_es_descriptor_clear (ESDescriptor * es)
-{
- desc_base_descriptor_clear (&es->base);
- if (es->url_string) {
- g_free (es->url_string);
- es->url_string = NULL;
- }
- desc_dec_conf_desc_clear (&es->dec_conf_desc);
- desc_sl_config_descriptor_clear (&es->sl_conf_desc);
-}
-
-/*
- * Size handling functions below
- */
-
-void
-desc_dec_specific_info_alloc_data (DecoderSpecificInfoDescriptor * dsid,
- guint32 size)
-{
- if (dsid->data) {
- g_free (dsid->data);
- }
- dsid->data = g_new0 (guint8, size);
- dsid->length = size;
-}
-
-static void
-desc_base_descriptor_set_size (BaseDescriptor * bd, guint32 size)
-{
- expandable_size_parse (size, bd->size, 4);
-}
-
-static guint64
-desc_base_descriptor_get_size (BaseDescriptor * bd)
-{
- guint64 size = 0;
-
- size += sizeof (guint8);
- size += expandable_size_get_length (bd->size, 4) * sizeof (guint8);
- return size;
-}
-
-static guint64
-desc_sl_config_descriptor_get_size (SLConfigDescriptor * sl_desc)
-{
- guint64 size = 0;
- guint64 extra_size = 0;
-
- size += desc_base_descriptor_get_size (&sl_desc->base);
- /* predefined */
- extra_size += sizeof (guint8);
-
- desc_base_descriptor_set_size (&sl_desc->base, extra_size);
-
- return size + extra_size;
-}
-
-static guint64
-desc_dec_specific_info_get_size (DecoderSpecificInfoDescriptor * dsid)
-{
- guint64 size = 0;
- guint64 extra_size = 0;
-
- size += desc_base_descriptor_get_size (&dsid->base);
- extra_size += sizeof (guint8) * dsid->length;
- desc_base_descriptor_set_size (&dsid->base, extra_size);
- return size + extra_size;
-}
-
-static guint64
-desc_dec_config_descriptor_get_size (DecoderConfigDescriptor * dec_desc)
-{
- guint64 size = 0;
- guint64 extra_size = 0;
-
- size += desc_base_descriptor_get_size (&dec_desc->base);
- /* object type */
- extra_size += sizeof (guint8);
- /* stream type */
- extra_size += sizeof (guint8);
- /* buffer size */
- extra_size += sizeof (guint8) * 3;
- /* max bitrate */
- extra_size += sizeof (guint32);
- /* avg bitrate */
- extra_size += sizeof (guint32);
- if (dec_desc->dec_specific_info) {
- extra_size += desc_dec_specific_info_get_size (dec_desc->dec_specific_info);
- }
-
- desc_base_descriptor_set_size (&dec_desc->base, extra_size);
- return size + extra_size;
-}
-
-static guint64
-desc_es_descriptor_get_size (ESDescriptor * es)
-{
- guint64 size = 0;
- guint64 extra_size = 0;
-
- size += desc_base_descriptor_get_size (&es->base);
- /* id */
- extra_size += sizeof (guint16);
- /* flags */
- extra_size += sizeof (guint8);
- /* depends_on_es_id */
- if (es->flags & 0x80) {
- extra_size += sizeof (guint16);
- }
- if (es->flags & 0x40) {
- /* url_length */
- extra_size += sizeof (guint8);
- /* url */
- extra_size += sizeof (gchar) * es->url_length;
- }
- if (es->flags & 0x20) {
- /* ocr_es_id */
- extra_size += sizeof (guint16);
- }
-
- extra_size += desc_dec_config_descriptor_get_size (&es->dec_conf_desc);
- extra_size += desc_sl_config_descriptor_get_size (&es->sl_conf_desc);
-
- desc_base_descriptor_set_size (&es->base, extra_size);
-
- return size + extra_size;
-}
-
-static gboolean
-desc_es_descriptor_check_stream_dependency (ESDescriptor * es)
-{
- return es->flags & 0x80;
-}
-
-static gboolean
-desc_es_descriptor_check_url_flag (ESDescriptor * es)
-{
- return es->flags & 0x40;
-}
-
-static gboolean
-desc_es_descriptor_check_ocr (ESDescriptor * es)
-{
- return es->flags & 0x20;
-}
-
-/* Copy/Serializations Functions below */
-
-static guint64
-desc_base_descriptor_copy_data (BaseDescriptor * desc, guint8 ** buffer,
- guint64 * size, guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- prop_copy_uint8 (desc->tag, buffer, size, offset);
- prop_copy_uint8_array (desc->size, expandable_size_get_length (desc->size, 4),
- buffer, size, offset);
- return original_offset - *offset;
-}
-
-static guint64
-desc_sl_config_descriptor_copy_data (SLConfigDescriptor * desc,
- guint8 ** buffer, guint64 * size, guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
- return 0;
- }
- /* predefined attribute */
- prop_copy_uint8 (desc->predefined, buffer, size, offset);
-
- return *offset - original_offset;
-}
-
-static guint64
-desc_dec_specific_info_copy_data (DecoderSpecificInfoDescriptor * desc,
- guint8 ** buffer, guint64 * size, guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
- return 0;
- }
- prop_copy_uint8_array (desc->data, desc->length, buffer, size, offset);
-
- return *offset - original_offset;
-}
-
-static guint64
-desc_dec_config_descriptor_copy_data (DecoderConfigDescriptor * desc,
- guint8 ** buffer, guint64 * size, guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
- return 0;
- }
-
- prop_copy_uint8 (desc->object_type, buffer, size, offset);
-
- prop_copy_uint8 (desc->stream_type, buffer, size, offset);
- prop_copy_uint8_array (desc->buffer_size_DB, 3, buffer, size, offset);
-
- prop_copy_uint32 (desc->max_bitrate, buffer, size, offset);
- prop_copy_uint32 (desc->avg_bitrate, buffer, size, offset);
-
- if (desc->dec_specific_info) {
- if (!desc_dec_specific_info_copy_data (desc->dec_specific_info, buffer,
- size, offset)) {
- return 0;
- }
- }
-
- return *offset - original_offset;
-}
-
-guint64
-desc_es_descriptor_copy_data (ESDescriptor * desc, guint8 ** buffer,
- guint64 * size, guint64 * offset)
-{
- guint64 desc_size;
- guint64 original_offset = *offset;
-
- /* must call this twice to have size fields of all contained descriptors set
- * correctly, and to have the size of the size fields taken into account */
- desc_size = desc_es_descriptor_get_size (desc);
- desc_size = desc_es_descriptor_get_size (desc);
-
- if (!desc_base_descriptor_copy_data (&desc->base, buffer, size, offset)) {
- return 0;
- }
- /* id and flags */
- prop_copy_uint16 (desc->id, buffer, size, offset);
- prop_copy_uint8 (desc->flags, buffer, size, offset);
-
- if (desc_es_descriptor_check_stream_dependency (desc)) {
- prop_copy_uint16 (desc->depends_on_es_id, buffer, size, offset);
- }
-
- if (desc_es_descriptor_check_url_flag (desc)) {
- prop_copy_size_string (desc->url_string, desc->url_length, buffer, size,
- offset);
- }
-
- if (desc_es_descriptor_check_ocr (desc)) {
- prop_copy_uint16 (desc->ocr_es_id, buffer, size, offset);
- }
-
- if (!desc_dec_config_descriptor_copy_data (&desc->dec_conf_desc, buffer, size,
- offset)) {
- return 0;
- }
-
- if (!desc_sl_config_descriptor_copy_data (&desc->sl_conf_desc, buffer, size,
- offset)) {
- return 0;
- }
-
- return *offset - original_offset;
-}
diff --git a/gst/qtmux/descriptors.h b/gst/qtmux/descriptors.h
deleted file mode 100644
index cc633a305..000000000
--- a/gst/qtmux/descriptors.h
+++ /dev/null
@@ -1,151 +0,0 @@
-/* Quicktime muxer plugin for GStreamer
- * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
- *
- * 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.
- */
-/*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __DESCRIPTORS_H__
-#define __DESCRIPTORS_H__
-
-#include <glib.h>
-#include <string.h>
-#include "properties.h"
-
-/*
- * Tags for descriptor (each kind is represented by a number, instead of fourcc as in atoms)
- */
-#define OBJECT_DESC_TAG 0x01
-#define INIT_OBJECT_DESC_TAG 0x02
-#define ES_DESCRIPTOR_TAG 0x03
-#define DECODER_CONFIG_DESC_TAG 0x04
-#define DECODER_SPECIFIC_INFO_TAG 0x05
-#define SL_CONFIG_DESC_TAG 0x06
-#define ES_ID_INC_TAG 0x0E
-#define MP4_INIT_OBJECT_DESC_TAG 0x10
-
-#define ESDS_OBJECT_TYPE_MPEG1_P3 0x6B
-#define ESDS_OBJECT_TYPE_MPEG2_P7_MAIN 0x66
-#define ESDS_OBJECT_TYPE_MPEG4_P7_LC 0x67
-#define ESDS_OBJECT_TYPE_MPEG4_P7_SSR 0x68
-#define ESDS_OBJECT_TYPE_MPEG4_P2 0x20
-#define ESDS_OBJECT_TYPE_MPEG4_P3 0x40
-
-#define ESDS_STREAM_TYPE_VISUAL 0x04
-#define ESDS_STREAM_TYPE_AUDIO 0x05
-
-
-typedef struct _BaseDescriptor
-{
- guint8 tag;
- /* the first bit of each byte indicates if the next byte should be used */
- guint8 size[4];
-} BaseDescriptor;
-
-typedef struct _SLConfigDescriptor
-{
- BaseDescriptor base;
-
- guint8 predefined; /* everything is supposed predefined */
-} SLConfigDescriptor;
-
-typedef struct _DecoderSpecificInfoDescriptor
-{
- BaseDescriptor base;
- guint32 length;
- guint8 *data;
-} DecoderSpecificInfoDescriptor;
-
-typedef struct _DecoderConfigDescriptor {
- BaseDescriptor base;
-
- guint8 object_type;
-
- /* following are condensed into streamType:
- * bit(6) streamType;
- * bit(1) upStream;
- * const bit(1) reserved=1;
- */
- guint8 stream_type;
-
- guint8 buffer_size_DB[3];
- guint32 max_bitrate;
- guint32 avg_bitrate;
-
- DecoderSpecificInfoDescriptor *dec_specific_info;
-} DecoderConfigDescriptor;
-
-typedef struct _ESDescriptor
-{
- BaseDescriptor base;
-
- guint16 id;
-
- /* flags contains the following:
- * bit(1) streamDependenceFlag;
- * bit(1) URL_Flag;
- * bit(1) OCRstreamFlag;
- * bit(5) streamPriority;
- */
- guint8 flags;
-
- guint16 depends_on_es_id;
- guint8 url_length; /* only if URL_flag is set */
- guint8 *url_string; /* size is url_length */
-
- guint16 ocr_es_id; /* only if OCRstreamFlag is set */
-
- DecoderConfigDescriptor dec_conf_desc;
- SLConfigDescriptor sl_conf_desc;
-
- /* optional remainder of ESDescriptor is not used */
-} ESDescriptor;
-
-/* --- FUNCTIONS --- */
-void desc_es_init (ESDescriptor *es);
-ESDescriptor *desc_es_descriptor_new (void);
-guint64 desc_es_descriptor_copy_data (ESDescriptor *es, guint8 **buffer,
- guint64 *size, guint64 *offset);
-void desc_es_descriptor_clear (ESDescriptor *es);
-
-DecoderSpecificInfoDescriptor *desc_dec_specific_info_new(void);
-void desc_dec_specific_info_free (DecoderSpecificInfoDescriptor *dsid);
-void desc_dec_specific_info_alloc_data (DecoderSpecificInfoDescriptor *dsid,
- guint32 size);
-
-#endif /* __DESCRIPTORS_H__ */
diff --git a/gst/qtmux/fourcc.h b/gst/qtmux/fourcc.h
deleted file mode 100644
index 188e20275..000000000
--- a/gst/qtmux/fourcc.h
+++ /dev/null
@@ -1,243 +0,0 @@
-/* GStreamer
- * Copyright (C) <1999> Erik Walthinsen <omega@cse.ogi.edu>
- *
- * 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.
- */
- /*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-
-#ifndef __FOURCC_H__
-#define __FOURCC_H__
-
-#include <gst/gst.h>
-
-G_BEGIN_DECLS
-
-#define FOURCC_null 0x0
-
-#define FOURCC_moov GST_MAKE_FOURCC('m','o','o','v')
-#define FOURCC_mvhd GST_MAKE_FOURCC('m','v','h','d')
-#define FOURCC_clip GST_MAKE_FOURCC('c','l','i','p')
-#define FOURCC_trak GST_MAKE_FOURCC('t','r','a','k')
-#define FOURCC_udta GST_MAKE_FOURCC('u','d','t','a')
-#define FOURCC_ctab GST_MAKE_FOURCC('c','t','a','b')
-#define FOURCC_tkhd GST_MAKE_FOURCC('t','k','h','d')
-#define FOURCC_crgn GST_MAKE_FOURCC('c','r','g','n')
-#define FOURCC_matt GST_MAKE_FOURCC('m','a','t','t')
-#define FOURCC_kmat GST_MAKE_FOURCC('k','m','a','t')
-#define FOURCC_edts GST_MAKE_FOURCC('e','d','t','s')
-#define FOURCC_elst GST_MAKE_FOURCC('e','l','s','t')
-#define FOURCC_load GST_MAKE_FOURCC('l','o','a','d')
-#define FOURCC_tref GST_MAKE_FOURCC('t','r','e','f')
-#define FOURCC_imap GST_MAKE_FOURCC('i','m','a','p')
-#define FOURCC___in GST_MAKE_FOURCC(' ',' ','i','n')
-#define FOURCC___ty GST_MAKE_FOURCC(' ',' ','t','y')
-#define FOURCC_mdia GST_MAKE_FOURCC('m','d','i','a')
-#define FOURCC_mdhd GST_MAKE_FOURCC('m','d','h','d')
-#define FOURCC_hdlr GST_MAKE_FOURCC('h','d','l','r')
-#define FOURCC_dhlr GST_MAKE_FOURCC('d','h','l','r')
-#define FOURCC_mhlr GST_MAKE_FOURCC('m','h','l','r')
-#define FOURCC_minf GST_MAKE_FOURCC('m','i','n','f')
-#define FOURCC_mdir GST_MAKE_FOURCC('m','d','i','r')
-#define FOURCC_vmhd GST_MAKE_FOURCC('v','m','h','d')
-#define FOURCC_smhd GST_MAKE_FOURCC('s','m','h','d')
-#define FOURCC_gmhd GST_MAKE_FOURCC('g','m','h','d')
-#define FOURCC_hmhd GST_MAKE_FOURCC('h','m','h','d')
-#define FOURCC_gmin GST_MAKE_FOURCC('g','m','i','n')
-#define FOURCC_dinf GST_MAKE_FOURCC('d','i','n','f')
-#define FOURCC_dref GST_MAKE_FOURCC('d','r','e','f')
-#define FOURCC_stbl GST_MAKE_FOURCC('s','t','b','l')
-#define FOURCC_stsd GST_MAKE_FOURCC('s','t','s','d')
-#define FOURCC_stts GST_MAKE_FOURCC('s','t','t','s')
-#define FOURCC_stss GST_MAKE_FOURCC('s','t','s','s')
-#define FOURCC_stsc GST_MAKE_FOURCC('s','t','s','c')
-#define FOURCC_stsz GST_MAKE_FOURCC('s','t','s','z')
-#define FOURCC_stco GST_MAKE_FOURCC('s','t','c','o')
-#define FOURCC_vide GST_MAKE_FOURCC('v','i','d','e')
-#define FOURCC_soun GST_MAKE_FOURCC('s','o','u','n')
-#define FOURCC_strm GST_MAKE_FOURCC('s','t','r','m')
-#define FOURCC_rtsp GST_MAKE_FOURCC('r','t','s','p')
-#define FOURCC_co64 GST_MAKE_FOURCC('c','o','6','4')
-#define FOURCC_cmov GST_MAKE_FOURCC('c','m','o','v')
-#define FOURCC_dcom GST_MAKE_FOURCC('d','c','o','m')
-#define FOURCC_cmvd GST_MAKE_FOURCC('c','m','v','d')
-#define FOURCC_hint GST_MAKE_FOURCC('h','i','n','t')
-#define FOURCC_mp4a GST_MAKE_FOURCC('m','p','4','a')
-#define FOURCC__mp3 GST_MAKE_FOURCC('.','m','p','3')
-#define FOURCC_mp4s GST_MAKE_FOURCC('m','p','4','s')
-#define FOURCC_mp4v GST_MAKE_FOURCC('m','p','4','v')
-#define FOURCC_2vuy GST_MAKE_FOURCC('2','v','u','y')
-#define FOURCC_wave GST_MAKE_FOURCC('w','a','v','e')
-#define FOURCC_appl GST_MAKE_FOURCC('a','p','p','l')
-#define FOURCC_esds GST_MAKE_FOURCC('e','s','d','s')
-#define FOURCC_pasp GST_MAKE_FOURCC('p','a','s','p')
-#define FOURCC_hnti GST_MAKE_FOURCC('h','n','t','i')
-#define FOURCC_rtp_ GST_MAKE_FOURCC('r','t','p',' ')
-#define FOURCC_sdp_ GST_MAKE_FOURCC('s','d','p',' ')
-#define FOURCC_meta GST_MAKE_FOURCC('m','e','t','a')
-#define FOURCC_ilst GST_MAKE_FOURCC('i','l','s','t')
-#define FOURCC__nam GST_MAKE_FOURCC(0xa9,'n','a','m')
-#define FOURCC__ART GST_MAKE_FOURCC(0xa9,'A','R','T')
-#define FOURCC_aART GST_MAKE_FOURCC('a','A','R','T')
-#define FOURCC__wrt GST_MAKE_FOURCC(0xa9,'w','r','t')
-#define FOURCC__grp GST_MAKE_FOURCC(0xa9,'g','r','p')
-#define FOURCC__alb GST_MAKE_FOURCC(0xa9,'a','l','b')
-#define FOURCC__day GST_MAKE_FOURCC(0xa9,'d','a','y')
-#define FOURCC__des GST_MAKE_FOURCC(0xa9,'d','e','s')
-#define FOURCC__lyr GST_MAKE_FOURCC(0xa9,'l','y','r')
-#define FOURCC_gnre GST_MAKE_FOURCC('g','n','r','e')
-#define FOURCC_disc GST_MAKE_FOURCC('d','i','s','c')
-#define FOURCC_disk GST_MAKE_FOURCC('d','i','s','k')
-#define FOURCC_trkn GST_MAKE_FOURCC('t','r','k','n')
-#define FOURCC_cprt GST_MAKE_FOURCC('c','p','r','t')
-#define FOURCC_covr GST_MAKE_FOURCC('c','o','v','r')
-#define FOURCC_cpil GST_MAKE_FOURCC('c','p','i','l')
-#define FOURCC_tmpo GST_MAKE_FOURCC('t','m','p','o')
-#define FOURCC__too GST_MAKE_FOURCC(0xa9,'t','o','o')
-#define FOURCC_keyw GST_MAKE_FOURCC('k','e','y','w')
-#define FOURCC_____ GST_MAKE_FOURCC('-','-','-','-')
-#define FOURCC_free GST_MAKE_FOURCC('f','r','e','e')
-#define FOURCC_data GST_MAKE_FOURCC('d','a','t','a')
-#define FOURCC_SVQ3 GST_MAKE_FOURCC('S','V','Q','3')
-#define FOURCC_rmra GST_MAKE_FOURCC('r','m','r','a')
-#define FOURCC_rmda GST_MAKE_FOURCC('r','m','d','a')
-#define FOURCC_rdrf GST_MAKE_FOURCC('r','d','r','f')
-#define FOURCC__gen GST_MAKE_FOURCC(0xa9, 'g', 'e', 'n')
-#define FOURCC_rmdr GST_MAKE_FOURCC('r','m','d','r')
-#define FOURCC_rmvc GST_MAKE_FOURCC('r','m','v','c')
-#define FOURCC_qtim GST_MAKE_FOURCC('q','t','i','m')
-#define FOURCC_drms GST_MAKE_FOURCC('d','r','m','s')
-#define FOURCC_avc1 GST_MAKE_FOURCC('a','v','c','1')
-#define FOURCC_h263 GST_MAKE_FOURCC('h','2','6','3')
-#define FOURCC_s263 GST_MAKE_FOURCC('s','2','6','3')
-#define FOURCC_avcC GST_MAKE_FOURCC('a','v','c','C')
-#define FOURCC_VP31 GST_MAKE_FOURCC('V','P','3','1')
-#define FOURCC_VP80 GST_MAKE_FOURCC('V','P','8','0')
-#define FOURCC_rle_ GST_MAKE_FOURCC('r','l','e',' ')
-#define FOURCC_MAC6 GST_MAKE_FOURCC('M','A','C','6')
-#define FOURCC_MAC3 GST_MAKE_FOURCC('M','A','C','3')
-#define FOURCC_ima4 GST_MAKE_FOURCC('i','m','a','4')
-#define FOURCC_ulaw GST_MAKE_FOURCC('u','l','a','w')
-#define FOURCC_alaw GST_MAKE_FOURCC('a','l','a','w')
-#define FOURCC_twos GST_MAKE_FOURCC('t','w','o','s')
-#define FOURCC_sowt GST_MAKE_FOURCC('s','o','w','t')
-#define FOURCC_raw_ GST_MAKE_FOURCC('r','a','w',' ')
-#define FOURCC_QDM2 GST_MAKE_FOURCC('Q','D','M','2')
-#define FOURCC_alac GST_MAKE_FOURCC('a','l','a','c')
-#define FOURCC_samr GST_MAKE_FOURCC('s','a','m','r')
-#define FOURCC_sawb GST_MAKE_FOURCC('s','a','w','b')
-#define FOURCC_mdat GST_MAKE_FOURCC('m','d','a','t')
-#define FOURCC_wide GST_MAKE_FOURCC('w','i','d','e')
-#define FOURCC_PICT GST_MAKE_FOURCC('P','I','C','T')
-#define FOURCC_pnot GST_MAKE_FOURCC('p','n','o','t')
-#define FOURCC_zlib GST_MAKE_FOURCC('z','l','i','b')
-#define FOURCC_alis GST_MAKE_FOURCC('a','l','i','s')
-#define FOURCC_url_ GST_MAKE_FOURCC('u','r','l',' ')
-#define FOURCC_frma GST_MAKE_FOURCC('f','r','m','a')
-#define FOURCC_ctts GST_MAKE_FOURCC('c','t','t','s')
-#define FOURCC_drac GST_MAKE_FOURCC('d','r','a','c')
-#define FOURCC_jpeg GST_MAKE_FOURCC('j','p','e','g')
-#define FOURCC_mjp2 GST_MAKE_FOURCC('m','j','p','2')
-#define FOURCC_jp2h GST_MAKE_FOURCC('j','p','2','h')
-#define FOURCC_jp2c GST_MAKE_FOURCC('j','p','2','c')
-#define FOURCC_gama GST_MAKE_FOURCC('g','a','m','a')
-#define FOURCC_tvsh GST_MAKE_FOURCC('t','v','s','h')
-#define FOURCC_tven GST_MAKE_FOURCC('t','v','e','n')
-#define FOURCC_tvsn GST_MAKE_FOURCC('t','v','s','n')
-#define FOURCC_tves GST_MAKE_FOURCC('t','v','e','s')
-#define FOURCC_sonm GST_MAKE_FOURCC('s','o','n','m')
-#define FOURCC_soal GST_MAKE_FOURCC('s','o','a','l')
-#define FOURCC_soar GST_MAKE_FOURCC('s','o','a','r')
-#define FOURCC_soaa GST_MAKE_FOURCC('s','o','a','a')
-#define FOURCC_soco GST_MAKE_FOURCC('s','o','c','o')
-#define FOURCC_sosn GST_MAKE_FOURCC('s','o','s','n')
-#define FOURCC_XMP_ GST_MAKE_FOURCC('X','M','P','_')
-#define FOURCC_uuid GST_MAKE_FOURCC('u','u','i','d')
-
-
-/* SVQ3 fourcc */
-#define FOURCC_SEQH GST_MAKE_FOURCC('S','E','Q','H')
-#define FOURCC_SMI_ GST_MAKE_FOURCC('S','M','I',' ')
-
-/* fragmented mp4 */
-#define FOURCC_mvex GST_MAKE_FOURCC('m','v','e','x')
-#define FOURCC_mehd GST_MAKE_FOURCC('m','e','h','d')
-#define FOURCC_trex GST_MAKE_FOURCC('t','r','e','x')
-#define FOURCC_mfra GST_MAKE_FOURCC('m','f','r','a')
-#define FOURCC_moof GST_MAKE_FOURCC('m','o','o','f')
-#define FOURCC_tfra GST_MAKE_FOURCC('t','f','r','a')
-#define FOURCC_tfhd GST_MAKE_FOURCC('t','f','h','d')
-#define FOURCC_trun GST_MAKE_FOURCC('t','r','u','n')
-#define FOURCC_sdtp GST_MAKE_FOURCC('s','d','t','p')
-#define FOURCC_mfro GST_MAKE_FOURCC('m','f','r','o')
-#define FOURCC_mfhd GST_MAKE_FOURCC('m','f','h','d')
-#define FOURCC_mvhd GST_MAKE_FOURCC('m','v','h','d')
-#define FOURCC_traf GST_MAKE_FOURCC('t','r','a','f')
-
-/* Xiph fourcc */
-#define FOURCC_XiTh GST_MAKE_FOURCC('X','i','T','h')
-#define FOURCC_XdxT GST_MAKE_FOURCC('X','d','x','T')
-#define FOURCC_tCtH GST_MAKE_FOURCC('t','C','t','H')
-#define FOURCC_tCt_ GST_MAKE_FOURCC('t','C','t','#')
-#define FOURCC_tCtC GST_MAKE_FOURCC('t','C','t','C')
-
-/* ilst metatags */
-#define FOURCC_titl GST_MAKE_FOURCC('t','i','t','l')
-#define FOURCC__cmt GST_MAKE_FOURCC(0xa9, 'c','m','t')
-
-/* 3gp tags */
-#define FOURCC_dscp GST_MAKE_FOURCC('d','s','c','p')
-#define FOURCC_perf GST_MAKE_FOURCC('p','e','r','f')
-#define FOURCC_auth GST_MAKE_FOURCC('a','u','t','h')
-#define FOURCC_yrrc GST_MAKE_FOURCC('y','r','r','c')
-#define FOURCC_albm GST_MAKE_FOURCC('a','l','b','m')
-#define FOURCC_loci GST_MAKE_FOURCC('l','o','c','i')
-#define FOURCC_kywd GST_MAKE_FOURCC('k','y','w','d')
-#define FOURCC_clsf GST_MAKE_FOURCC('c','l','s','f')
-
-/* For Microsoft Wave formats embedded in quicktime, the FOURCC is
- 'm', 's', then the 16 bit wave codec id */
-#define MS_WAVE_FOURCC(codecid) GST_MAKE_FOURCC( \
- 'm', 's', ((codecid)>>8)&0xff, ((codecid)&0xff))
-
-#define FOURCC_owma GST_MAKE_FOURCC('o','w','m','a')
-#define FOURCC_ovc1 GST_MAKE_FOURCC('o','v','c','1')
-
-G_END_DECLS
-
-#endif /* __FOURCC_H__ */
diff --git a/gst/qtmux/ftypcc.h b/gst/qtmux/ftypcc.h
deleted file mode 100644
index 3d31b6dd0..000000000
--- a/gst/qtmux/ftypcc.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/* GStreamer
- * Copyright (C) <2008> Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
- *
- * 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.
- */
-/*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __FTYP_CC_H__
-#define __FTYP_CC_H__
-
-#include <gst/gst.h>
-
-G_BEGIN_DECLS
-
-#define FOURCC_ftyp GST_MAKE_FOURCC('f','t','y','p')
-#define FOURCC_isom GST_MAKE_FOURCC('i','s','o','m')
-#define FOURCC_iso2 GST_MAKE_FOURCC('i','s','o','2')
-#define FOURCC_mp41 GST_MAKE_FOURCC('m','p','4','1')
-#define FOURCC_mp42 GST_MAKE_FOURCC('m','p','4','2')
-#define FOURCC_mjp2 GST_MAKE_FOURCC('m','j','p','2')
-#define FOURCC_3gp4 GST_MAKE_FOURCC('3','g','p','4')
-#define FOURCC_3gp6 GST_MAKE_FOURCC('3','g','p','6')
-#define FOURCC_3gg6 GST_MAKE_FOURCC('3','g','g','6')
-#define FOURCC_3gr6 GST_MAKE_FOURCC('3','g','r','6')
-#define FOURCC_3gg7 GST_MAKE_FOURCC('3','g','g','7')
-#define FOURCC_avc1 GST_MAKE_FOURCC('a','v','c','1')
-#define FOURCC_qt__ GST_MAKE_FOURCC('q','t',' ',' ')
-#define FOURCC_isml GST_MAKE_FOURCC('i','s','m','l')
-#define FOURCC_piff GST_MAKE_FOURCC('p','i','f','f')
-
-G_END_DECLS
-
-#endif /* __FTYP_CC_H__ */
diff --git a/gst/qtmux/gstqtmoovrecover.c b/gst/qtmux/gstqtmoovrecover.c
deleted file mode 100644
index 889b2cc4b..000000000
--- a/gst/qtmux/gstqtmoovrecover.c
+++ /dev/null
@@ -1,390 +0,0 @@
-/* Quicktime muxer plugin for GStreamer
- * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
- *
- * 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.
- */
-/*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-
-/**
- * SECTION:gstqtmoovrecover
- * @short_description: Utility element for recovering unfinished quicktime files
- *
- * <refsect2>
- * <para>
- * This element recovers quicktime files created with qtmux using the moov recovery feature.
- * </para>
- * <title>Example pipelines</title>
- * <para>
- * <programlisting>
- * TODO
- * </programlisting>
- * </refsect2>
- *
- * Last reviewed on 2010-02-01
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib/gstdio.h>
-#include <gst/gst.h>
-
-#include "gstqtmoovrecover.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_qt_moov_recover_debug);
-#define GST_CAT_DEFAULT gst_qt_moov_recover_debug
-
-/* QTMoovRecover signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-
-enum
-{
- PROP_0,
- PROP_RECOVERY_INPUT,
- PROP_BROKEN_INPUT,
- PROP_FIXED_OUTPUT,
- PROP_FAST_START_MODE
-};
-
-GST_BOILERPLATE (GstQTMoovRecover, gst_qt_moov_recover, GstPipeline,
- GST_TYPE_PIPELINE);
-
-/* property functions */
-static void gst_qt_moov_recover_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_qt_moov_recover_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec);
-
-static GstStateChangeReturn gst_qt_moov_recover_change_state (GstElement *
- element, GstStateChange transition);
-
-static void gst_qt_moov_recover_finalize (GObject * object);
-
-static void
-gst_qt_moov_recover_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
-#if 0
- GstQTMoovRecoverClass *klass = (GstQTMoovRecoverClass *) g_class;
-#endif
- gst_element_class_set_details_simple (element_class, "QT Moov Recover",
- "Util", "Recovers unfinished qtmux files",
- "Thiago Santos <thiago.sousa.santos@collabora.co.uk>");
-}
-
-static void
-gst_qt_moov_recover_class_init (GstQTMoovRecoverClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
-
- parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->finalize = gst_qt_moov_recover_finalize;
- gobject_class->get_property = gst_qt_moov_recover_get_property;
- gobject_class->set_property = gst_qt_moov_recover_set_property;
-
- gstelement_class->change_state = gst_qt_moov_recover_change_state;
-
- g_object_class_install_property (gobject_class, PROP_FIXED_OUTPUT,
- g_param_spec_string ("fixed-output",
- "Path to write the fixed file",
- "Path to write the fixed file to (used as output)",
- NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_BROKEN_INPUT,
- g_param_spec_string ("broken-input",
- "Path to broken input file",
- "Path to broken input file. (If qtmux was on faststart mode, this "
- "file is the faststart file)", NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_RECOVERY_INPUT,
- g_param_spec_string ("recovery-input",
- "Path to recovery file",
- "Path to recovery file (used as input)", NULL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_FAST_START_MODE,
- g_param_spec_boolean ("faststart-mode",
- "If the broken input is from faststart mode",
- "If the broken input is from faststart mode",
- FALSE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- GST_DEBUG_CATEGORY_INIT (gst_qt_moov_recover_debug, "qtmoovrecover", 0,
- "QT Moovie Recover");
-}
-
-static void
-gst_qt_moov_recover_init (GstQTMoovRecover * qtmr,
- GstQTMoovRecoverClass * qtmr_klass)
-{
-}
-
-static void
-gst_qt_moov_recover_finalize (GObject * object)
-{
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static void
-gst_qt_moov_recover_run (void *data)
-{
- FILE *moovrec = NULL;
- FILE *mdatinput = NULL;
- FILE *output = NULL;
- MdatRecovFile *mdat_recov = NULL;
- MoovRecovFile *moov_recov = NULL;
- GstQTMoovRecover *qtmr = GST_QT_MOOV_RECOVER_CAST (data);
- GError *err = NULL;
-
- GST_LOG_OBJECT (qtmr, "Starting task");
-
- GST_DEBUG_OBJECT (qtmr, "Validating properties");
- GST_OBJECT_LOCK (qtmr);
- /* validate properties */
- if (qtmr->broken_input == NULL) {
- GST_OBJECT_UNLOCK (qtmr);
- GST_ELEMENT_ERROR (qtmr, RESOURCE, SETTINGS,
- ("Please set broken-input property"), (NULL));
- goto end;
- }
- if (qtmr->recovery_input == NULL) {
- GST_OBJECT_UNLOCK (qtmr);
- GST_ELEMENT_ERROR (qtmr, RESOURCE, SETTINGS,
- ("Please set recovery-input property"), (NULL));
- goto end;
- }
- if (qtmr->fixed_output == NULL) {
- GST_OBJECT_UNLOCK (qtmr);
- GST_ELEMENT_ERROR (qtmr, RESOURCE, SETTINGS,
- ("Please set fixed-output property"), (NULL));
- goto end;
- }
-
- GST_DEBUG_OBJECT (qtmr, "Opening input/output files");
- /* open files */
- moovrec = g_fopen (qtmr->recovery_input, "rb");
- if (moovrec == NULL) {
- GST_OBJECT_UNLOCK (qtmr);
- GST_ELEMENT_ERROR (qtmr, RESOURCE, OPEN_READ,
- ("Failed to open recovery-input file"), (NULL));
- goto end;
- }
-
- mdatinput = g_fopen (qtmr->broken_input, "rb");
- if (mdatinput == NULL) {
- GST_OBJECT_UNLOCK (qtmr);
- GST_ELEMENT_ERROR (qtmr, RESOURCE, OPEN_READ,
- ("Failed to open broken-input file"), (NULL));
- goto end;
- }
- output = g_fopen (qtmr->fixed_output, "wb+");
- if (output == NULL) {
- GST_OBJECT_UNLOCK (qtmr);
- GST_ELEMENT_ERROR (qtmr, RESOURCE, OPEN_READ_WRITE,
- ("Failed to open fixed-output file"), (NULL));
- goto end;
- }
- GST_OBJECT_UNLOCK (qtmr);
-
- GST_DEBUG_OBJECT (qtmr, "Parsing input files");
- /* now create our structures */
- mdat_recov = mdat_recov_file_create (mdatinput, qtmr->faststart_mode, &err);
- mdatinput = NULL;
- if (mdat_recov == NULL) {
- GST_ELEMENT_ERROR (qtmr, RESOURCE, FAILED,
- ("Broken file could not be parsed correctly"), (NULL));
- goto end;
- }
- moov_recov = moov_recov_file_create (moovrec, &err);
- moovrec = NULL;
- if (moov_recov == NULL) {
- GST_ELEMENT_ERROR (qtmr, RESOURCE, FAILED,
- ("Recovery file could not be parsed correctly"), (NULL));
- goto end;
- }
-
- /* now parse the buffers data from moovrec */
- if (!moov_recov_parse_buffers (moov_recov, mdat_recov, &err)) {
- goto end;
- }
-
- GST_DEBUG_OBJECT (qtmr, "Writing fixed file to output");
- if (!moov_recov_write_file (moov_recov, mdat_recov, output, &err)) {
- goto end;
- }
-
- /* here means success */
- GST_DEBUG_OBJECT (qtmr, "Finished successfully, posting EOS");
- gst_element_post_message (GST_ELEMENT_CAST (qtmr),
- gst_message_new_eos (GST_OBJECT_CAST (qtmr)));
-
-end:
- GST_LOG_OBJECT (qtmr, "Finalizing task");
- if (err) {
- GST_ELEMENT_ERROR (qtmr, RESOURCE, FAILED, ("%s", err->message), (NULL));
- g_error_free (err);
- }
-
- if (moov_recov)
- moov_recov_file_free (moov_recov);
- if (moovrec)
- fclose (moovrec);
-
- if (mdat_recov)
- mdat_recov_file_free (mdat_recov);
- if (mdatinput)
- fclose (mdatinput);
-
- if (output)
- fclose (output);
- GST_LOG_OBJECT (qtmr, "Leaving task");
- gst_task_stop (qtmr->task);
-}
-
-static void
-gst_qt_moov_recover_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec)
-{
- GstQTMoovRecover *qtmr = GST_QT_MOOV_RECOVER_CAST (object);
-
- GST_OBJECT_LOCK (qtmr);
- switch (prop_id) {
- case PROP_FAST_START_MODE:
- g_value_set_boolean (value, qtmr->faststart_mode);
- break;
- case PROP_BROKEN_INPUT:
- g_value_set_string (value, qtmr->broken_input);
- break;
- case PROP_RECOVERY_INPUT:
- g_value_set_string (value, qtmr->recovery_input);
- break;
- case PROP_FIXED_OUTPUT:
- g_value_set_string (value, qtmr->fixed_output);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
- GST_OBJECT_UNLOCK (qtmr);
-}
-
-static void
-gst_qt_moov_recover_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec)
-{
- GstQTMoovRecover *qtmr = GST_QT_MOOV_RECOVER_CAST (object);
-
- GST_OBJECT_LOCK (qtmr);
- switch (prop_id) {
- case PROP_FAST_START_MODE:
- qtmr->faststart_mode = g_value_get_boolean (value);
- break;
- case PROP_BROKEN_INPUT:
- g_free (qtmr->broken_input);
- qtmr->broken_input = g_value_dup_string (value);
- break;
- case PROP_RECOVERY_INPUT:
- g_free (qtmr->recovery_input);
- qtmr->recovery_input = g_value_dup_string (value);
- break;
- case PROP_FIXED_OUTPUT:
- g_free (qtmr->fixed_output);
- qtmr->fixed_output = g_value_dup_string (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
- GST_OBJECT_UNLOCK (qtmr);
-}
-
-static GstStateChangeReturn
-gst_qt_moov_recover_change_state (GstElement * element,
- GstStateChange transition)
-{
- GstStateChangeReturn ret;
- GstQTMoovRecover *qtmr = GST_QT_MOOV_RECOVER_CAST (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- qtmr->task = gst_task_create (gst_qt_moov_recover_run, qtmr);
- qtmr->task_mutex = g_new (GStaticRecMutex, 1);
- g_static_rec_mutex_init (qtmr->task_mutex);
- gst_task_set_lock (qtmr->task, qtmr->task_mutex);
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- gst_task_start (qtmr->task);
- break;
- default:
- break;
- }
-
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- gst_task_stop (qtmr->task);
- gst_task_join (qtmr->task);
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- g_assert (gst_task_get_state (qtmr->task) == GST_TASK_STOPPED);
- gst_object_unref (qtmr->task);
- qtmr->task = NULL;
- g_static_rec_mutex_free (qtmr->task_mutex);
- break;
- default:
- break;
- }
- return ret;
-}
-
-
-gboolean
-gst_qt_moov_recover_register (GstPlugin * plugin)
-{
- return gst_element_register (plugin, "qtmoovrecover", GST_RANK_NONE,
- GST_TYPE_QT_MOOV_RECOVER);
-}
diff --git a/gst/qtmux/gstqtmoovrecover.h b/gst/qtmux/gstqtmoovrecover.h
deleted file mode 100644
index 07dc9d937..000000000
--- a/gst/qtmux/gstqtmoovrecover.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/* Quicktime muxer plugin for GStreamer
- * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
- *
- * 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.
- */
-/*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __GST_QT_MOOV_RECOVER_H__
-#define __GST_QT_MOOV_RECOVER_H__
-
-#include <gst/gst.h>
-
-#include "atoms.h"
-#include "atomsrecovery.h"
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_QT_MOOV_RECOVER (gst_qt_moov_recover_get_type())
-#define GST_QT_MOOV_RECOVER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_QT_MOOV_RECOVER, GstQTMoovRecover))
-#define GST_QT_MOOV_RECOVER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_QT_MOOV_RECOVER, GstQTMoovRecover))
-#define GST_IS_QT_MOOV_RECOVER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_QT_MOOV_RECOVER))
-#define GST_IS_QT_MOOV_RECOVER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_QT_MOOV_RECOVER))
-#define GST_QT_MOOV_RECOVER_CAST(obj) ((GstQTMoovRecover*)(obj))
-
-
-typedef struct _GstQTMoovRecover GstQTMoovRecover;
-typedef struct _GstQTMoovRecoverClass GstQTMoovRecoverClass;
-
-struct _GstQTMoovRecover
-{
- GstPipeline pipeline;
-
- GstTask *task;
- GStaticRecMutex *task_mutex;
-
- /* properties */
- gboolean faststart_mode;
- gchar *recovery_input;
- gchar *fixed_output;
- gchar *broken_input;
-};
-
-struct _GstQTMoovRecoverClass
-{
- GstPipelineClass parent_class;
-};
-
-GType gst_qt_moov_recover_get_type (void);
-gboolean gst_qt_moov_recover_register (GstPlugin * plugin);
-
-G_END_DECLS
-
-#endif /* __GST_QT_MOOV_RECOVER_H__ */
diff --git a/gst/qtmux/gstqtmux.c b/gst/qtmux/gstqtmux.c
deleted file mode 100644
index 39110d846..000000000
--- a/gst/qtmux/gstqtmux.c
+++ /dev/null
@@ -1,3498 +0,0 @@
-/* Quicktime muxer plugin for GStreamer
- * Copyright (C) 2008-2010 Thiago Santos <thiagoss@embedded.ufcg.edu.br>
- * Copyright (C) 2008 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.
- */
-/*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-
-/**
- * SECTION:element-qtmux
- * @short_description: Muxer for quicktime(.mov) files
- *
- * This element merges streams (audio and video) into QuickTime(.mov) files.
- *
- * The following background intends to explain why various similar muxers
- * are present in this plugin.
- *
- * The <ulink url="http://www.apple.com/quicktime/resources/qtfileformat.pdf">
- * QuickTime file format specification</ulink> served as basis for the MP4 file
- * format specification (mp4mux), and as such the QuickTime file structure is
- * nearly identical to the so-called ISO Base Media file format defined in
- * ISO 14496-12 (except for some media specific parts).
- * In turn, the latter ISO Base Media format was further specialized as a
- * Motion JPEG-2000 file format in ISO 15444-3 (mj2mux)
- * and in various 3GPP(2) specs (gppmux).
- * The fragmented file features defined (only) in ISO Base Media are used by
- * ISMV files making up (a.o.) Smooth Streaming (ismlmux).
- *
- * A few properties (<link linkend="GstQTMux--movie-timescale">movie-timescale</link>,
- * <link linkend="GstQTMux--trak-timescale">trak-timescale</link>) allow adjusting
- * some technical parameters, which might be useful in (rare) cases to resolve
- * compatibility issues in some situations.
- *
- * Some other properties influence the result more fundamentally.
- * A typical mov/mp4 file's metadata (aka moov) is located at the end of the file,
- * somewhat contrary to this usually being called "the header".
- * However, a <link linkend="GstQTMux--faststart">faststart</link> file will
- * (with some effort) arrange this to be located near start of the file,
- * which then allows it e.g. to be played while downloading.
- * Alternatively, rather than having one chunk of metadata at start (or end),
- * there can be some metadata at start and most of the other data can be spread
- * out into fragments of <link linkend="GstQTMux--fragment-duration">fragment-duration</link>.
- * If such fragmented layout is intended for streaming purposes, then
- * <link linkend="GstQTMux--streamable">streamable</link> allows foregoing to add
- * index metadata (at the end of file).
- *
- * <link linkend="GstQTMux--dts-method">dts-method</link> allows selecting a
- * method for managing input timestamps (stay tuned for 0.11 to have this
- * automagically settled). The default delta/duration method should handle nice
- * (aka perfect streams) just fine, but may experience problems otherwise
- * (e.g. input stream with re-ordered B-frames and/or with frame dropping).
- * The re-ordering approach re-assigns incoming timestamps in ascending order
- * to incoming buffers and offers an alternative in such cases. In cases where
- * that might fail, the remaining method can be tried, which is exact and
- * according to specs, but might experience playback on not so spec-wise players.
- * Note that this latter approach also requires one to enable
- * <link linkend="GstQTMux--presentation-timestamp">presentation-timestamp</link>.
- *
- * <refsect2>
- * <title>Example pipelines</title>
- * |[
- * gst-launch v4l2src num-buffers=500 ! video/x-raw-yuv,width=320,height=240 ! ffmpegcolorspace ! qtmux ! filesink location=video.mov
- * ]|
- * Records a video stream captured from a v4l2 device and muxes it into a qt file.
- * </refsect2>
- *
- * Last reviewed on 2010-12-03
- */
-
-/*
- * Based on avimux
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include <glib/gstdio.h>
-
-#include <gst/gst.h>
-#include <gst/base/gstcollectpads.h>
-#include <gst/tag/xmpwriter.h>
-
-#include <sys/types.h>
-#ifdef G_OS_WIN32
-#include <io.h> /* lseek, open, close, read */
-#undef lseek
-#define lseek _lseeki64
-#undef off_t
-#define off_t guint64
-#endif
-
-#ifdef _MSC_VER
-#define ftruncate g_win32_ftruncate
-#endif
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
-
-#include "gstqtmux.h"
-
-GST_DEBUG_CATEGORY_STATIC (gst_qt_mux_debug);
-#define GST_CAT_DEFAULT gst_qt_mux_debug
-
-enum
-{
- DTS_METHOD_DD,
- DTS_METHOD_REORDER,
- DTS_METHOD_ASC
-};
-
-static GType
-gst_qt_mux_dts_method_get_type (void)
-{
- static GType gst_qt_mux_dts_method = 0;
-
- if (!gst_qt_mux_dts_method) {
- static const GEnumValue dts_methods[] = {
- {DTS_METHOD_DD, "delta/duration", "dd"},
- {DTS_METHOD_REORDER, "reorder", "reorder"},
- {DTS_METHOD_ASC, "ascending", "asc"},
- {0, NULL, NULL},
- };
-
- gst_qt_mux_dts_method =
- g_enum_register_static ("GstQTMuxDtsMethods", dts_methods);
- }
-
- return gst_qt_mux_dts_method;
-}
-
-#define GST_TYPE_QT_MUX_DTS_METHOD \
- (gst_qt_mux_dts_method_get_type ())
-
-/* QTMux signals and args */
-enum
-{
- /* FILL ME */
- LAST_SIGNAL
-};
-
-enum
-{
- PROP_0,
- PROP_MOVIE_TIMESCALE,
- PROP_TRAK_TIMESCALE,
- PROP_FAST_START,
- PROP_FAST_START_TEMP_FILE,
- PROP_MOOV_RECOV_FILE,
- PROP_FRAGMENT_DURATION,
- PROP_STREAMABLE,
- PROP_DTS_METHOD,
- PROP_DO_CTTS,
-};
-
-/* some spare for header size as well */
-#define MDAT_LARGE_FILE_LIMIT ((guint64) 1024 * 1024 * 1024 * 2)
-#define MAX_TOLERATED_LATENESS (GST_SECOND / 10)
-
-#define DEFAULT_MOVIE_TIMESCALE 1000
-#define DEFAULT_TRAK_TIMESCALE 0
-#define DEFAULT_DO_CTTS FALSE
-#define DEFAULT_FAST_START FALSE
-#define DEFAULT_FAST_START_TEMP_FILE NULL
-#define DEFAULT_MOOV_RECOV_FILE NULL
-#define DEFAULT_FRAGMENT_DURATION 0
-#define DEFAULT_STREAMABLE FALSE
-#define DEFAULT_DTS_METHOD DTS_METHOD_DD
-
-
-static void gst_qt_mux_finalize (GObject * object);
-
-static GstStateChangeReturn gst_qt_mux_change_state (GstElement * element,
- GstStateChange transition);
-
-/* property functions */
-static void gst_qt_mux_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec);
-static void gst_qt_mux_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec);
-
-/* pad functions */
-static GstPad *gst_qt_mux_request_new_pad (GstElement * element,
- GstPadTemplate * templ, const gchar * name);
-static void gst_qt_mux_release_pad (GstElement * element, GstPad * pad);
-
-/* event */
-static gboolean gst_qt_mux_sink_event (GstPad * pad, GstEvent * event);
-
-static GstFlowReturn gst_qt_mux_collected (GstCollectPads * pads,
- gpointer user_data);
-static GstFlowReturn gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad,
- GstBuffer * buf);
-
-static GstElementClass *parent_class = NULL;
-
-static void
-gst_qt_mux_base_init (gpointer g_class)
-{
- GstElementClass *element_class = GST_ELEMENT_CLASS (g_class);
- GstQTMuxClass *klass = (GstQTMuxClass *) g_class;
- GstQTMuxClassParams *params;
- GstPadTemplate *videosinktempl, *audiosinktempl, *srctempl;
- gchar *longname, *description;
-
- params =
- (GstQTMuxClassParams *) g_type_get_qdata (G_OBJECT_CLASS_TYPE (g_class),
- GST_QT_MUX_PARAMS_QDATA);
- g_assert (params != NULL);
-
- /* construct the element details struct */
- longname = g_strdup_printf ("%s Muxer", params->prop->long_name);
- description = g_strdup_printf ("Multiplex audio and video into a %s file",
- params->prop->long_name);
- gst_element_class_set_details_simple (element_class, longname,
- "Codec/Muxer", description,
- "Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>");
- g_free (longname);
- g_free (description);
-
- /* pad templates */
- srctempl = gst_pad_template_new ("src", GST_PAD_SRC,
- GST_PAD_ALWAYS, params->src_caps);
- gst_element_class_add_pad_template (element_class, srctempl);
-
- if (params->audio_sink_caps) {
- audiosinktempl = gst_pad_template_new ("audio_%d",
- GST_PAD_SINK, GST_PAD_REQUEST, params->audio_sink_caps);
- gst_element_class_add_pad_template (element_class, audiosinktempl);
- }
-
- if (params->video_sink_caps) {
- videosinktempl = gst_pad_template_new ("video_%d",
- GST_PAD_SINK, GST_PAD_REQUEST, params->video_sink_caps);
- gst_element_class_add_pad_template (element_class, videosinktempl);
- }
-
- klass->format = params->prop->format;
-}
-
-static void
-gst_qt_mux_class_init (GstQTMuxClass * klass)
-{
- GObjectClass *gobject_class;
- GstElementClass *gstelement_class;
-
- gobject_class = (GObjectClass *) klass;
- gstelement_class = (GstElementClass *) klass;
-
- parent_class = g_type_class_peek_parent (klass);
-
- gobject_class->finalize = gst_qt_mux_finalize;
- gobject_class->get_property = gst_qt_mux_get_property;
- gobject_class->set_property = gst_qt_mux_set_property;
-
- g_object_class_install_property (gobject_class, PROP_MOVIE_TIMESCALE,
- g_param_spec_uint ("movie-timescale", "Movie timescale",
- "Timescale to use in the movie (units per second)",
- 1, G_MAXUINT32, DEFAULT_MOVIE_TIMESCALE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_TRAK_TIMESCALE,
- g_param_spec_uint ("trak-timescale", "Track timescale",
- "Timescale to use for the tracks (units per second, 0 is automatic)",
- 0, G_MAXUINT32, DEFAULT_TRAK_TIMESCALE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_DO_CTTS,
- g_param_spec_boolean ("presentation-time",
- "Include presentation-time info",
- "Calculate and include presentation/composition time "
- "(in addition to decoding time) (use with caution)",
- DEFAULT_DO_CTTS,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_DTS_METHOD,
- g_param_spec_enum ("dts-method", "dts-method",
- "Method to determine DTS time",
- GST_TYPE_QT_MUX_DTS_METHOD, DEFAULT_DTS_METHOD,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_FAST_START,
- g_param_spec_boolean ("faststart", "Format file to faststart",
- "If the file should be formated for faststart (headers first). ",
- DEFAULT_FAST_START, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_FAST_START_TEMP_FILE,
- g_param_spec_string ("faststart-file", "File to use for storing buffers",
- "File that will be used temporarily to store data from the stream "
- "when creating a faststart file. If null a filepath will be "
- "created automatically", DEFAULT_FAST_START_TEMP_FILE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_MOOV_RECOV_FILE,
- g_param_spec_string ("moov-recovery-file",
- "File to store data for posterior moov atom recovery",
- "File to be used to store "
- "data for moov atom making movie file recovery possible in case "
- "of a crash during muxing. Null for disabled. (Experimental)",
- DEFAULT_MOOV_RECOV_FILE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_FRAGMENT_DURATION,
- g_param_spec_uint ("fragment-duration", "Fragment duration",
- "Fragment durations in ms (produce a fragmented file if > 0)",
- 0, G_MAXUINT32, klass->format == GST_QT_MUX_FORMAT_ISML ?
- 2000 : DEFAULT_FRAGMENT_DURATION,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
- g_object_class_install_property (gobject_class, PROP_STREAMABLE,
- g_param_spec_boolean ("streamable", "Streamable",
- "If set to true, the output should be as if it is to be streamed "
- "and hence no indexes written or duration written.",
- DEFAULT_STREAMABLE,
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT | G_PARAM_STATIC_STRINGS));
-
- gstelement_class->request_new_pad =
- GST_DEBUG_FUNCPTR (gst_qt_mux_request_new_pad);
- gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_qt_mux_change_state);
- gstelement_class->release_pad = GST_DEBUG_FUNCPTR (gst_qt_mux_release_pad);
-}
-
-static void
-gst_qt_mux_pad_reset (GstQTPad * qtpad)
-{
- gint i;
-
- qtpad->fourcc = 0;
- qtpad->is_out_of_order = FALSE;
- qtpad->have_dts = FALSE;
- qtpad->sample_size = 0;
- qtpad->sync = FALSE;
- qtpad->last_dts = 0;
- qtpad->first_ts = GST_CLOCK_TIME_NONE;
- qtpad->prepare_buf_func = NULL;
- qtpad->avg_bitrate = 0;
- qtpad->max_bitrate = 0;
- qtpad->ts_n_entries = 0;
-
- qtpad->buf_head = 0;
- qtpad->buf_tail = 0;
- for (i = 0; i < G_N_ELEMENTS (qtpad->buf_entries); i++) {
- if (qtpad->buf_entries[i]) {
- gst_buffer_unref (qtpad->buf_entries[i]);
- qtpad->buf_entries[i] = NULL;
- }
- }
-
- if (qtpad->last_buf)
- gst_buffer_replace (&qtpad->last_buf, NULL);
-
- /* reference owned elsewhere */
- qtpad->trak = NULL;
-
- if (qtpad->traf) {
- atom_traf_free (qtpad->traf);
- qtpad->traf = NULL;
- }
- atom_array_clear (&qtpad->fragment_buffers);
-
- /* reference owned elsewhere */
- qtpad->tfra = NULL;
-}
-
-/*
- * Takes GstQTMux back to its initial state
- */
-static void
-gst_qt_mux_reset (GstQTMux * qtmux, gboolean alloc)
-{
- GSList *walk;
-
- qtmux->state = GST_QT_MUX_STATE_NONE;
- qtmux->header_size = 0;
- qtmux->mdat_size = 0;
- qtmux->mdat_pos = 0;
- qtmux->longest_chunk = GST_CLOCK_TIME_NONE;
- qtmux->video_pads = 0;
- qtmux->audio_pads = 0;
- qtmux->fragment_sequence = 0;
-
- if (qtmux->ftyp) {
- atom_ftyp_free (qtmux->ftyp);
- qtmux->ftyp = NULL;
- }
- if (qtmux->moov) {
- atom_moov_free (qtmux->moov);
- qtmux->moov = NULL;
- }
- if (qtmux->mfra) {
- atom_mfra_free (qtmux->mfra);
- qtmux->mfra = NULL;
- }
- if (qtmux->fast_start_file) {
- fclose (qtmux->fast_start_file);
- g_remove (qtmux->fast_start_file_path);
- qtmux->fast_start_file = NULL;
- }
- if (qtmux->moov_recov_file) {
- fclose (qtmux->moov_recov_file);
- qtmux->moov_recov_file = NULL;
- }
- for (walk = qtmux->extra_atoms; walk; walk = g_slist_next (walk)) {
- AtomInfo *ainfo = (AtomInfo *) walk->data;
- ainfo->free_func (ainfo->atom);
- g_free (ainfo);
- }
- g_slist_free (qtmux->extra_atoms);
- qtmux->extra_atoms = NULL;
-
- GST_OBJECT_LOCK (qtmux);
- gst_tag_setter_reset_tags (GST_TAG_SETTER (qtmux));
- GST_OBJECT_UNLOCK (qtmux);
-
- /* reset pad data */
- for (walk = qtmux->sinkpads; walk; walk = g_slist_next (walk)) {
- GstQTPad *qtpad = (GstQTPad *) walk->data;
- gst_qt_mux_pad_reset (qtpad);
-
- /* hm, moov_free above yanked the traks away from us,
- * so do not free, but do clear */
- qtpad->trak = NULL;
- }
-
- if (alloc) {
- qtmux->moov = atom_moov_new (qtmux->context);
- /* ensure all is as nice and fresh as request_new_pad would provide it */
- for (walk = qtmux->sinkpads; walk; walk = g_slist_next (walk)) {
- GstQTPad *qtpad = (GstQTPad *) walk->data;
-
- qtpad->trak = atom_trak_new (qtmux->context);
- atom_moov_add_trak (qtmux->moov, qtpad->trak);
- }
- }
-}
-
-static void
-gst_qt_mux_init (GstQTMux * qtmux, GstQTMuxClass * qtmux_klass)
-{
- GstElementClass *klass = GST_ELEMENT_CLASS (qtmux_klass);
- GstPadTemplate *templ;
-
- templ = gst_element_class_get_pad_template (klass, "src");
- qtmux->srcpad = gst_pad_new_from_template (templ, "src");
- gst_pad_use_fixed_caps (qtmux->srcpad);
- gst_element_add_pad (GST_ELEMENT (qtmux), qtmux->srcpad);
-
- qtmux->sinkpads = NULL;
- qtmux->collect = gst_collect_pads_new ();
- gst_collect_pads_set_function (qtmux->collect,
- (GstCollectPadsFunction) GST_DEBUG_FUNCPTR (gst_qt_mux_collected), qtmux);
-
- /* properties set to default upon construction */
-
- /* always need this */
- qtmux->context =
- atoms_context_new (gst_qt_mux_map_format_to_flavor (qtmux_klass->format));
-
- /* internals to initial state */
- gst_qt_mux_reset (qtmux, TRUE);
-}
-
-
-static void
-gst_qt_mux_finalize (GObject * object)
-{
- GstQTMux *qtmux = GST_QT_MUX_CAST (object);
-
- gst_qt_mux_reset (qtmux, FALSE);
-
- g_free (qtmux->fast_start_file_path);
- g_free (qtmux->moov_recov_file_path);
-
- atoms_context_free (qtmux->context);
- gst_object_unref (qtmux->collect);
-
- g_slist_free (qtmux->sinkpads);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
-}
-
-static GstBuffer *
-gst_qt_mux_prepare_jpc_buffer (GstQTPad * qtpad, GstBuffer * buf,
- GstQTMux * qtmux)
-{
- GstBuffer *newbuf;
-
- GST_LOG_OBJECT (qtmux, "Preparing jpc buffer");
-
- if (buf == NULL)
- return NULL;
-
- newbuf = gst_buffer_new_and_alloc (GST_BUFFER_SIZE (buf) + 8);
- gst_buffer_copy_metadata (newbuf, buf, GST_BUFFER_COPY_ALL);
-
- GST_WRITE_UINT32_BE (GST_BUFFER_DATA (newbuf), GST_BUFFER_SIZE (newbuf));
- GST_WRITE_UINT32_LE (GST_BUFFER_DATA (newbuf) + 4, FOURCC_jp2c);
-
- memcpy (GST_BUFFER_DATA (newbuf) + 8, GST_BUFFER_DATA (buf),
- GST_BUFFER_SIZE (buf));
- gst_buffer_unref (buf);
-
- return newbuf;
-}
-
-static void
-gst_qt_mux_add_mp4_tag (GstQTMux * qtmux, const GstTagList * list,
- const char *tag, const char *tag2, guint32 fourcc)
-{
- switch (gst_tag_get_type (tag)) {
- /* strings */
- case G_TYPE_STRING:
- {
- gchar *str = NULL;
-
- if (!gst_tag_list_get_string (list, tag, &str) || !str)
- break;
- GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %s",
- GST_FOURCC_ARGS (fourcc), str);
- atom_moov_add_str_tag (qtmux->moov, fourcc, str);
- g_free (str);
- break;
- }
- /* double */
- case G_TYPE_DOUBLE:
- {
- gdouble value;
-
- if (!gst_tag_list_get_double (list, tag, &value))
- break;
- GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %u",
- GST_FOURCC_ARGS (fourcc), (gint) value);
- atom_moov_add_uint_tag (qtmux->moov, fourcc, 21, (gint) value);
- break;
- }
- case G_TYPE_UINT:
- {
- guint value = 0;
- if (tag2) {
- /* paired unsigned integers */
- guint count = 0;
-
- if (!(gst_tag_list_get_uint (list, tag, &value) ||
- gst_tag_list_get_uint (list, tag2, &count)))
- break;
- GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %u/%u",
- GST_FOURCC_ARGS (fourcc), value, count);
- atom_moov_add_uint_tag (qtmux->moov, fourcc, 0,
- value << 16 | (count & 0xFFFF));
- } else {
- /* unpaired unsigned integers */
- if (!gst_tag_list_get_uint (list, tag, &value))
- break;
- GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %u",
- GST_FOURCC_ARGS (fourcc), value);
- atom_moov_add_uint_tag (qtmux->moov, fourcc, 1, value);
- }
- break;
- }
- default:
- g_assert_not_reached ();
- break;
- }
-}
-
-static void
-gst_qt_mux_add_mp4_date (GstQTMux * qtmux, const GstTagList * list,
- const char *tag, const char *tag2, guint32 fourcc)
-{
- GDate *date = NULL;
- GDateYear year;
- GDateMonth month;
- GDateDay day;
- gchar *str;
-
- g_return_if_fail (gst_tag_get_type (tag) == GST_TYPE_DATE);
-
- if (!gst_tag_list_get_date (list, tag, &date) || !date)
- return;
-
- year = g_date_get_year (date);
- month = g_date_get_month (date);
- day = g_date_get_day (date);
-
- if (year == G_DATE_BAD_YEAR && month == G_DATE_BAD_MONTH &&
- day == G_DATE_BAD_DAY) {
- GST_WARNING_OBJECT (qtmux, "invalid date in tag");
- return;
- }
-
- str = g_strdup_printf ("%u-%u-%u", year, month, day);
- GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %s",
- GST_FOURCC_ARGS (fourcc), str);
- atom_moov_add_str_tag (qtmux->moov, fourcc, str);
- g_free (str);
-}
-
-static void
-gst_qt_mux_add_mp4_cover (GstQTMux * qtmux, const GstTagList * list,
- const char *tag, const char *tag2, guint32 fourcc)
-{
- GValue value = { 0, };
- GstBuffer *buf;
- GstCaps *caps;
- GstStructure *structure;
- gint flags = 0;
-
- g_return_if_fail (gst_tag_get_type (tag) == GST_TYPE_BUFFER);
-
- if (!gst_tag_list_copy_value (&value, list, tag))
- return;
-
- buf = gst_value_get_buffer (&value);
- if (!buf)
- goto done;
-
- caps = gst_buffer_get_caps (buf);
- if (!caps) {
- GST_WARNING_OBJECT (qtmux, "preview image without caps");
- goto done;
- }
-
- GST_DEBUG_OBJECT (qtmux, "preview image caps %" GST_PTR_FORMAT, caps);
-
- structure = gst_caps_get_structure (caps, 0);
- if (gst_structure_has_name (structure, "image/jpeg"))
- flags = 13;
- else if (gst_structure_has_name (structure, "image/png"))
- flags = 14;
- gst_caps_unref (caps);
-
- if (!flags) {
- GST_WARNING_OBJECT (qtmux, "preview image format not supported");
- goto done;
- }
-
- GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT
- " -> image size %d", GST_FOURCC_ARGS (fourcc), GST_BUFFER_SIZE (buf));
- atom_moov_add_tag (qtmux->moov, fourcc, flags, GST_BUFFER_DATA (buf),
- GST_BUFFER_SIZE (buf));
-done:
- g_value_unset (&value);
-}
-
-static void
-gst_qt_mux_add_3gp_str (GstQTMux * qtmux, const GstTagList * list,
- const char *tag, const char *tag2, guint32 fourcc)
-{
- gchar *str = NULL;
- guint number;
-
- g_return_if_fail (gst_tag_get_type (tag) == G_TYPE_STRING);
- g_return_if_fail (!tag2 || gst_tag_get_type (tag2) == G_TYPE_UINT);
-
- if (!gst_tag_list_get_string (list, tag, &str) || !str)
- return;
-
- if (tag2)
- if (!gst_tag_list_get_uint (list, tag2, &number))
- tag2 = NULL;
-
- if (!tag2) {
- GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %s",
- GST_FOURCC_ARGS (fourcc), str);
- atom_moov_add_3gp_str_tag (qtmux->moov, fourcc, str);
- } else {
- GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %s/%d",
- GST_FOURCC_ARGS (fourcc), str, number);
- atom_moov_add_3gp_str_int_tag (qtmux->moov, fourcc, str, number);
- }
-
- g_free (str);
-}
-
-static void
-gst_qt_mux_add_3gp_date (GstQTMux * qtmux, const GstTagList * list,
- const char *tag, const char *tag2, guint32 fourcc)
-{
- GDate *date = NULL;
- GDateYear year;
-
- g_return_if_fail (gst_tag_get_type (tag) == GST_TYPE_DATE);
-
- if (!gst_tag_list_get_date (list, tag, &date) || !date)
- return;
-
- year = g_date_get_year (date);
-
- if (year == G_DATE_BAD_YEAR) {
- GST_WARNING_OBJECT (qtmux, "invalid date in tag");
- return;
- }
-
- GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %d",
- GST_FOURCC_ARGS (fourcc), year);
- atom_moov_add_3gp_uint_tag (qtmux->moov, fourcc, year);
-}
-
-static void
-gst_qt_mux_add_3gp_location (GstQTMux * qtmux, const GstTagList * list,
- const char *tag, const char *tag2, guint32 fourcc)
-{
- gdouble latitude = -360, longitude = -360, altitude = 0;
- gchar *location = NULL;
- guint8 *data, *ddata;
- gint size = 0, len = 0;
- gboolean ret = FALSE;
-
- g_return_if_fail (strcmp (tag, GST_TAG_GEO_LOCATION_NAME) == 0);
-
- ret = gst_tag_list_get_string (list, tag, &location);
- ret |= gst_tag_list_get_double (list, GST_TAG_GEO_LOCATION_LONGITUDE,
- &longitude);
- ret |= gst_tag_list_get_double (list, GST_TAG_GEO_LOCATION_LATITUDE,
- &latitude);
- ret |= gst_tag_list_get_double (list, GST_TAG_GEO_LOCATION_ELEVATION,
- &altitude);
-
- if (!ret)
- return;
-
- if (location)
- len = strlen (location);
- size += len + 1 + 2;
-
- /* role + (long, lat, alt) + body + notes */
- size += 1 + 3 * 4 + 1 + 1;
-
- data = ddata = g_malloc (size);
-
- /* language tag */
- GST_WRITE_UINT16_BE (data, language_code (GST_QT_MUX_DEFAULT_TAG_LANGUAGE));
- /* location */
- if (location)
- memcpy (data + 2, location, len);
- GST_WRITE_UINT8 (data + 2 + len, 0);
- data += len + 1 + 2;
- /* role */
- GST_WRITE_UINT8 (data, 0);
- /* long, lat, alt */
- GST_WRITE_UINT32_BE (data + 1, (guint32) (longitude * 65536.0));
- GST_WRITE_UINT32_BE (data + 5, (guint32) (latitude * 65536.0));
- GST_WRITE_UINT32_BE (data + 9, (guint32) (altitude * 65536.0));
- /* neither astronomical body nor notes */
- GST_WRITE_UINT16_BE (data + 13, 0);
-
- GST_DEBUG_OBJECT (qtmux, "Adding tag 'loci'");
- atom_moov_add_3gp_tag (qtmux->moov, fourcc, ddata, size);
- g_free (ddata);
-}
-
-static void
-gst_qt_mux_add_3gp_keywords (GstQTMux * qtmux, const GstTagList * list,
- const char *tag, const char *tag2, guint32 fourcc)
-{
- gchar *keywords = NULL;
- guint8 *data, *ddata;
- gint size = 0, i;
- gchar **kwds;
-
- g_return_if_fail (strcmp (tag, GST_TAG_KEYWORDS) == 0);
-
- if (!gst_tag_list_get_string (list, tag, &keywords) || !keywords)
- return;
-
- kwds = g_strsplit (keywords, ",", 0);
- g_free (keywords);
-
- size = 0;
- for (i = 0; kwds[i]; i++) {
- /* size byte + null-terminator */
- size += strlen (kwds[i]) + 1 + 1;
- }
-
- /* language tag + count + keywords */
- size += 2 + 1;
-
- data = ddata = g_malloc (size);
-
- /* language tag */
- GST_WRITE_UINT16_BE (data, language_code (GST_QT_MUX_DEFAULT_TAG_LANGUAGE));
- /* count */
- GST_WRITE_UINT8 (data + 2, i);
- data += 3;
- /* keywords */
- for (i = 0; kwds[i]; ++i) {
- gint len = strlen (kwds[i]);
-
- GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %s",
- GST_FOURCC_ARGS (fourcc), kwds[i]);
- /* size */
- GST_WRITE_UINT8 (data, len + 1);
- memcpy (data + 1, kwds[i], len + 1);
- data += len + 2;
- }
-
- g_strfreev (kwds);
-
- atom_moov_add_3gp_tag (qtmux->moov, fourcc, ddata, size);
- g_free (ddata);
-}
-
-static gboolean
-gst_qt_mux_parse_classification_string (GstQTMux * qtmux, const gchar * input,
- guint32 * p_fourcc, guint16 * p_table, gchar ** p_content)
-{
- guint32 fourcc;
- gint table;
- gint size;
- const gchar *data;
-
- data = input;
- size = strlen (input);
-
- if (size < 4 + 3 + 1 + 1 + 1) {
- /* at least the minimum xxxx://y/z */
- GST_WARNING_OBJECT (qtmux, "Classification tag input (%s) too short, "
- "ignoring", input);
- return FALSE;
- }
-
- /* read the fourcc */
- memcpy (&fourcc, data, 4);
- size -= 4;
- data += 4;
-
- if (strncmp (data, "://", 3) != 0) {
- goto mismatch;
- }
- data += 3;
- size -= 3;
-
- /* read the table number */
- if (sscanf (data, "%d", &table) != 1) {
- goto mismatch;
- }
- if (table < 0) {
- GST_WARNING_OBJECT (qtmux, "Invalid table number in classification tag (%d)"
- ", table numbers should be positive, ignoring tag", table);
- return FALSE;
- }
-
- /* find the next / */
- while (size > 0 && data[0] != '/') {
- data += 1;
- size -= 1;
- }
- if (size == 0) {
- goto mismatch;
- }
- g_assert (data[0] == '/');
-
- /* skip the '/' */
- data += 1;
- size -= 1;
- if (size == 0) {
- goto mismatch;
- }
-
- /* read up the rest of the string */
- *p_content = g_strdup (data);
- *p_table = (guint16) table;
- *p_fourcc = fourcc;
- return TRUE;
-
-mismatch:
- {
- GST_WARNING_OBJECT (qtmux, "Ignoring classification tag as "
- "input (%s) didn't match the expected entitycode://table/content",
- input);
- return FALSE;
- }
-}
-
-static void
-gst_qt_mux_add_3gp_classification (GstQTMux * qtmux, const GstTagList * list,
- const char *tag, const char *tag2, guint32 fourcc)
-{
- gchar *clsf_data = NULL;
- gint size = 0;
- guint32 entity = 0;
- guint16 table = 0;
- gchar *content = NULL;
- guint8 *data;
-
- g_return_if_fail (strcmp (tag, GST_TAG_3GP_CLASSIFICATION) == 0);
-
- if (!gst_tag_list_get_string (list, tag, &clsf_data) || !clsf_data)
- return;
-
- GST_DEBUG_OBJECT (qtmux, "Adding tag %" GST_FOURCC_FORMAT " -> %s",
- GST_FOURCC_ARGS (fourcc), clsf_data);
-
- /* parse the string, format is:
- * entityfourcc://table/content
- */
- gst_qt_mux_parse_classification_string (qtmux, clsf_data, &entity, &table,
- &content);
- g_free (clsf_data);
- /* +1 for the \0 */
- size = strlen (content) + 1;
-
- /* now we have everything, build the atom
- * atom description is at 3GPP TS 26.244 V8.2.0 (2009-09) */
- data = g_malloc (4 + 2 + 2 + size);
- GST_WRITE_UINT32_LE (data, entity);
- GST_WRITE_UINT16_BE (data + 4, (guint16) table);
- GST_WRITE_UINT16_BE (data + 6, 0);
- memcpy (data + 8, content, size);
- g_free (content);
-
- atom_moov_add_3gp_tag (qtmux->moov, fourcc, data, 4 + 2 + 2 + size);
- g_free (data);
-}
-
-typedef void (*GstQTMuxAddTagFunc) (GstQTMux * mux, const GstTagList * list,
- const char *tag, const char *tag2, guint32 fourcc);
-
-/*
- * Struct to record mappings from gstreamer tags to fourcc codes
- */
-typedef struct _GstTagToFourcc
-{
- guint32 fourcc;
- const gchar *gsttag;
- const gchar *gsttag2;
- const GstQTMuxAddTagFunc func;
-} GstTagToFourcc;
-
-/* tag list tags to fourcc matching */
-static const GstTagToFourcc tag_matches_mp4[] = {
- {FOURCC__alb, GST_TAG_ALBUM, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC_soal, GST_TAG_ALBUM_SORTNAME, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC__ART, GST_TAG_ARTIST, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC_soar, GST_TAG_ARTIST_SORTNAME, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC_aART, GST_TAG_ALBUM_ARTIST, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC_soaa, GST_TAG_ALBUM_ARTIST_SORTNAME, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC__cmt, GST_TAG_COMMENT, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC__wrt, GST_TAG_COMPOSER, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC_soco, GST_TAG_COMPOSER_SORTNAME, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC_tvsh, GST_TAG_SHOW_NAME, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC_sosn, GST_TAG_SHOW_SORTNAME, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC_tvsn, GST_TAG_SHOW_SEASON_NUMBER, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC_tves, GST_TAG_SHOW_EPISODE_NUMBER, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC__gen, GST_TAG_GENRE, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC__nam, GST_TAG_TITLE, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC_sonm, GST_TAG_TITLE_SORTNAME, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC_perf, GST_TAG_PERFORMER, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC__grp, GST_TAG_GROUPING, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC__des, GST_TAG_DESCRIPTION, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC__lyr, GST_TAG_LYRICS, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC__too, GST_TAG_ENCODER, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC_keyw, GST_TAG_KEYWORDS, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC__day, GST_TAG_DATE, NULL, gst_qt_mux_add_mp4_date},
- {FOURCC_tmpo, GST_TAG_BEATS_PER_MINUTE, NULL, gst_qt_mux_add_mp4_tag},
- {FOURCC_trkn, GST_TAG_TRACK_NUMBER, GST_TAG_TRACK_COUNT,
- gst_qt_mux_add_mp4_tag},
- {FOURCC_disk, GST_TAG_ALBUM_VOLUME_NUMBER, GST_TAG_ALBUM_VOLUME_COUNT,
- gst_qt_mux_add_mp4_tag},
- {FOURCC_covr, GST_TAG_PREVIEW_IMAGE, NULL, gst_qt_mux_add_mp4_cover},
- {0, NULL,}
-};
-
-static const GstTagToFourcc tag_matches_3gp[] = {
- {FOURCC_titl, GST_TAG_TITLE, NULL, gst_qt_mux_add_3gp_str},
- {FOURCC_dscp, GST_TAG_DESCRIPTION, NULL, gst_qt_mux_add_3gp_str},
- {FOURCC_cprt, GST_TAG_COPYRIGHT, NULL, gst_qt_mux_add_3gp_str},
- {FOURCC_perf, GST_TAG_ARTIST, NULL, gst_qt_mux_add_3gp_str},
- {FOURCC_auth, GST_TAG_COMPOSER, NULL, gst_qt_mux_add_3gp_str},
- {FOURCC_gnre, GST_TAG_GENRE, NULL, gst_qt_mux_add_3gp_str},
- {FOURCC_kywd, GST_TAG_KEYWORDS, NULL, gst_qt_mux_add_3gp_keywords},
- {FOURCC_yrrc, GST_TAG_DATE, NULL, gst_qt_mux_add_3gp_date},
- {FOURCC_albm, GST_TAG_ALBUM, GST_TAG_TRACK_NUMBER, gst_qt_mux_add_3gp_str},
- {FOURCC_loci, GST_TAG_GEO_LOCATION_NAME, NULL, gst_qt_mux_add_3gp_location},
- {FOURCC_clsf, GST_TAG_3GP_CLASSIFICATION, NULL,
- gst_qt_mux_add_3gp_classification},
- {0, NULL,}
-};
-
-/* qtdemux produces these for atoms it cannot parse */
-#define GST_QT_DEMUX_PRIVATE_TAG "private-qt-tag"
-
-static void
-gst_qt_mux_add_xmp_tags (GstQTMux * qtmux, const GstTagList * list)
-{
- GstQTMuxClass *qtmux_klass = (GstQTMuxClass *) (G_OBJECT_GET_CLASS (qtmux));
- GstBuffer *xmp = NULL;
-
- /* adobe specs only have 'quicktime' and 'mp4',
- * but I guess we can extrapolate to gpp.
- * Keep mj2 out for now as we don't add any tags for it yet.
- * If you have further info about xmp on these formats, please share */
- if (qtmux_klass->format == GST_QT_MUX_FORMAT_MJ2)
- return;
-
- GST_DEBUG_OBJECT (qtmux, "Adding xmp tags");
-
- if (qtmux_klass->format == GST_QT_MUX_FORMAT_QT) {
- xmp = gst_tag_xmp_writer_tag_list_to_xmp_buffer (GST_TAG_XMP_WRITER (qtmux),
- list, TRUE);
- if (xmp)
- atom_moov_add_xmp_tags (qtmux->moov, xmp);
- } else {
- AtomInfo *ainfo;
- /* for isom/mp4, it is a top level uuid atom */
- xmp = gst_tag_xmp_writer_tag_list_to_xmp_buffer (GST_TAG_XMP_WRITER (qtmux),
- list, TRUE);
- if (xmp) {
- ainfo = build_uuid_xmp_atom (xmp);
- if (ainfo) {
- qtmux->extra_atoms = g_slist_prepend (qtmux->extra_atoms, ainfo);
- }
- }
- }
- if (xmp)
- gst_buffer_unref (xmp);
-}
-
-static void
-gst_qt_mux_add_metadata_tags (GstQTMux * qtmux, const GstTagList * list)
-{
- GstQTMuxClass *qtmux_klass = (GstQTMuxClass *) (G_OBJECT_GET_CLASS (qtmux));
- guint32 fourcc;
- gint i;
- const gchar *tag, *tag2;
- const GstTagToFourcc *tag_matches;
-
- switch (qtmux_klass->format) {
- case GST_QT_MUX_FORMAT_3GP:
- tag_matches = tag_matches_3gp;
- break;
- case GST_QT_MUX_FORMAT_MJ2:
- tag_matches = NULL;
- break;
- default:
- /* sort of iTunes style for mp4 and QT (?) */
- tag_matches = tag_matches_mp4;
- break;
- }
-
- if (!tag_matches)
- return;
-
- for (i = 0; tag_matches[i].fourcc; i++) {
- fourcc = tag_matches[i].fourcc;
- tag = tag_matches[i].gsttag;
- tag2 = tag_matches[i].gsttag2;
-
- g_assert (tag_matches[i].func);
- tag_matches[i].func (qtmux, list, tag, tag2, fourcc);
- }
-
- /* add unparsed blobs if present */
- if (gst_tag_exists (GST_QT_DEMUX_PRIVATE_TAG)) {
- guint num_tags;
-
- num_tags = gst_tag_list_get_tag_size (list, GST_QT_DEMUX_PRIVATE_TAG);
- for (i = 0; i < num_tags; ++i) {
- const GValue *val;
- GstBuffer *buf;
- GstCaps *caps = NULL;
-
- val = gst_tag_list_get_value_index (list, GST_QT_DEMUX_PRIVATE_TAG, i);
- buf = (GstBuffer *) gst_value_get_mini_object (val);
-
- if (buf && (caps = gst_buffer_get_caps (buf))) {
- GstStructure *s;
- const gchar *style = NULL;
-
- GST_DEBUG_OBJECT (qtmux, "Found private tag %d/%d; size %d, caps %"
- GST_PTR_FORMAT, i, num_tags, GST_BUFFER_SIZE (buf), caps);
- s = gst_caps_get_structure (caps, 0);
- if (s && (style = gst_structure_get_string (s, "style"))) {
- /* try to prevent some style tag ending up into another variant
- * (todo: make into a list if more cases) */
- if ((strcmp (style, "itunes") == 0 &&
- qtmux_klass->format == GST_QT_MUX_FORMAT_MP4) ||
- (strcmp (style, "iso") == 0 &&
- qtmux_klass->format == GST_QT_MUX_FORMAT_3GP)) {
- GST_DEBUG_OBJECT (qtmux, "Adding private tag");
- atom_moov_add_blob_tag (qtmux->moov, GST_BUFFER_DATA (buf),
- GST_BUFFER_SIZE (buf));
- }
- }
- gst_caps_unref (caps);
- }
- }
- }
-
- return;
-}
-
-/*
- * Gets the tagsetter iface taglist and puts the known tags
- * into the output stream
- */
-static void
-gst_qt_mux_setup_metadata (GstQTMux * qtmux)
-{
- const GstTagList *tags;
-
- GST_OBJECT_LOCK (qtmux);
- tags = gst_tag_setter_get_tag_list (GST_TAG_SETTER (qtmux));
- GST_OBJECT_UNLOCK (qtmux);
-
- GST_LOG_OBJECT (qtmux, "tags: %" GST_PTR_FORMAT, tags);
-
- if (tags && !gst_tag_list_is_empty (tags)) {
- GstTagList *copy = gst_tag_list_copy (tags);
-
- GST_DEBUG_OBJECT (qtmux, "Removing bogus tags");
- gst_tag_list_remove_tag (copy, GST_TAG_VIDEO_CODEC);
- gst_tag_list_remove_tag (copy, GST_TAG_AUDIO_CODEC);
- gst_tag_list_remove_tag (copy, GST_TAG_CONTAINER_FORMAT);
-
- GST_DEBUG_OBJECT (qtmux, "Formatting tags");
- gst_qt_mux_add_metadata_tags (qtmux, copy);
- gst_qt_mux_add_xmp_tags (qtmux, copy);
- gst_tag_list_free (copy);
- } else {
- GST_DEBUG_OBJECT (qtmux, "No tags received");
- }
-}
-
-static inline GstBuffer *
-_gst_buffer_new_take_data (guint8 * data, guint size)
-{
- GstBuffer *buf;
-
- buf = gst_buffer_new ();
- GST_BUFFER_DATA (buf) = GST_BUFFER_MALLOCDATA (buf) = data;
- GST_BUFFER_SIZE (buf) = size;
-
- return buf;
-}
-
-static GstFlowReturn
-gst_qt_mux_send_buffer (GstQTMux * qtmux, GstBuffer * buf, guint64 * offset,
- gboolean mind_fast)
-{
- GstFlowReturn res;
- guint8 *data;
- guint size;
-
- g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR);
-
- data = GST_BUFFER_DATA (buf);
- size = GST_BUFFER_SIZE (buf);
-
- GST_LOG_OBJECT (qtmux, "sending buffer size %d", size);
-
- if (mind_fast && qtmux->fast_start_file) {
- gint ret;
-
- GST_LOG_OBJECT (qtmux, "to temporary file");
- ret = fwrite (data, sizeof (guint8), size, qtmux->fast_start_file);
- gst_buffer_unref (buf);
- if (ret != size)
- goto write_error;
- else
- res = GST_FLOW_OK;
- } else {
- GST_LOG_OBJECT (qtmux, "downstream");
-
- buf = gst_buffer_make_metadata_writable (buf);
- gst_buffer_set_caps (buf, GST_PAD_CAPS (qtmux->srcpad));
- res = gst_pad_push (qtmux->srcpad, buf);
- }
-
- if (G_LIKELY (offset))
- *offset += size;
-
- return res;
-
- /* ERRORS */
-write_error:
- {
- GST_ELEMENT_ERROR (qtmux, RESOURCE, WRITE,
- ("Failed to write to temporary file"), GST_ERROR_SYSTEM);
- return GST_FLOW_ERROR;
- }
-}
-
-static gboolean
-gst_qt_mux_seek_to_beginning (FILE * f)
-{
-#ifdef HAVE_FSEEKO
- if (fseeko (f, (off_t) 0, SEEK_SET) != 0)
- return FALSE;
-#elif defined (G_OS_UNIX) || defined (G_OS_WIN32)
- if (lseek (fileno (f), (off_t) 0, SEEK_SET) == (off_t) - 1)
- return FALSE;
-#else
- if (fseek (f, (long) 0, SEEK_SET) != 0)
- return FALSE;
-#endif
- return TRUE;
-}
-
-static GstFlowReturn
-gst_qt_mux_send_buffered_data (GstQTMux * qtmux, guint64 * offset)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- GstBuffer *buf = NULL;
-
- if (fflush (qtmux->fast_start_file))
- goto flush_failed;
-
- if (!gst_qt_mux_seek_to_beginning (qtmux->fast_start_file))
- goto seek_failed;
-
- /* hm, this could all take a really really long time,
- * but there may not be another way to get moov atom first
- * (somehow optimize copy?) */
- GST_DEBUG_OBJECT (qtmux, "Sending buffered data");
- while (ret == GST_FLOW_OK) {
- gint r;
- const int bufsize = 4096;
-
- buf = gst_buffer_new_and_alloc (bufsize);
- r = fread (GST_BUFFER_DATA (buf), sizeof (guint8), bufsize,
- qtmux->fast_start_file);
- if (r == 0)
- break;
- GST_BUFFER_SIZE (buf) = r;
- GST_LOG_OBJECT (qtmux, "Pushing buffered buffer of size %d", r);
- ret = gst_qt_mux_send_buffer (qtmux, buf, offset, FALSE);
- buf = NULL;
- }
- if (buf)
- gst_buffer_unref (buf);
-
- if (ftruncate (fileno (qtmux->fast_start_file), 0))
- goto seek_failed;
- if (!gst_qt_mux_seek_to_beginning (qtmux->fast_start_file))
- goto seek_failed;
-
- return ret;
-
- /* ERRORS */
-flush_failed:
- {
- GST_ELEMENT_ERROR (qtmux, RESOURCE, WRITE,
- ("Failed to flush temporary file"), GST_ERROR_SYSTEM);
- ret = GST_FLOW_ERROR;
- goto fail;
- }
-seek_failed:
- {
- GST_ELEMENT_ERROR (qtmux, RESOURCE, SEEK,
- ("Failed to seek temporary file"), GST_ERROR_SYSTEM);
- ret = GST_FLOW_ERROR;
- goto fail;
- }
-fail:
- {
- /* clear descriptor so we don't remove temp file later on,
- * might be possible to recover */
- fclose (qtmux->fast_start_file);
- qtmux->fast_start_file = NULL;
- return ret;
- }
-}
-
-/*
- * Sends the initial mdat atom fields (size fields and fourcc type),
- * the subsequent buffers are considered part of it's data.
- * As we can't predict the amount of data that we are going to place in mdat
- * we need to record the position of the size field in the stream so we can
- * seek back to it later and update when the streams have finished.
- */
-static GstFlowReturn
-gst_qt_mux_send_mdat_header (GstQTMux * qtmux, guint64 * off, guint64 size,
- gboolean extended)
-{
- Atom *node_header;
- GstBuffer *buf;
- guint8 *data = NULL;
- guint64 offset = 0;
-
- GST_DEBUG_OBJECT (qtmux, "Sending mdat's atom header, "
- "size %" G_GUINT64_FORMAT, size);
-
- node_header = g_malloc0 (sizeof (Atom));
- node_header->type = FOURCC_mdat;
- if (extended) {
- /* use extended size */
- node_header->size = 1;
- node_header->extended_size = 0;
- if (size)
- node_header->extended_size = size + 16;
- } else {
- node_header->size = size + 8;
- }
-
- size = offset = 0;
- if (atom_copy_data (node_header, &data, &size, &offset) == 0)
- goto serialize_error;
-
- buf = _gst_buffer_new_take_data (data, offset);
- g_free (node_header);
-
- GST_LOG_OBJECT (qtmux, "Pushing mdat start");
- return gst_qt_mux_send_buffer (qtmux, buf, off, FALSE);
-
- /* ERRORS */
-serialize_error:
- {
- GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL),
- ("Failed to serialize mdat"));
- return GST_FLOW_ERROR;
- }
-}
-
-/*
- * We get the position of the mdat size field, seek back to it
- * and overwrite with the real value
- */
-static GstFlowReturn
-gst_qt_mux_update_mdat_size (GstQTMux * qtmux, guint64 mdat_pos,
- guint64 mdat_size, guint64 * offset)
-{
- GstEvent *event;
- GstBuffer *buf;
- gboolean large_file;
-
- large_file = (mdat_size > MDAT_LARGE_FILE_LIMIT);
-
- if (large_file)
- mdat_pos += 8;
-
- /* seek and rewrite the header */
- event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
- mdat_pos, GST_CLOCK_TIME_NONE, 0);
- gst_pad_push_event (qtmux->srcpad, event);
-
- if (large_file) {
- buf = gst_buffer_new_and_alloc (sizeof (guint64));
- GST_WRITE_UINT64_BE (GST_BUFFER_DATA (buf), mdat_size + 16);
- } else {
- guint8 *data;
-
- buf = gst_buffer_new_and_alloc (16);
- data = GST_BUFFER_DATA (buf);
- GST_WRITE_UINT32_BE (data, 8);
- GST_WRITE_UINT32_LE (data + 4, FOURCC_free);
- GST_WRITE_UINT32_BE (data + 8, mdat_size + 8);
- GST_WRITE_UINT32_LE (data + 12, FOURCC_mdat);
- }
-
- return gst_qt_mux_send_buffer (qtmux, buf, offset, FALSE);
-}
-
-static GstFlowReturn
-gst_qt_mux_send_ftyp (GstQTMux * qtmux, guint64 * off)
-{
- GstBuffer *buf;
- guint64 size = 0, offset = 0;
- guint8 *data = NULL;
-
- GST_DEBUG_OBJECT (qtmux, "Sending ftyp atom");
-
- if (!atom_ftyp_copy_data (qtmux->ftyp, &data, &size, &offset))
- goto serialize_error;
-
- buf = _gst_buffer_new_take_data (data, offset);
-
- GST_LOG_OBJECT (qtmux, "Pushing ftyp");
- return gst_qt_mux_send_buffer (qtmux, buf, off, FALSE);
-
- /* ERRORS */
-serialize_error:
- {
- GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL),
- ("Failed to serialize ftyp"));
- return GST_FLOW_ERROR;
- }
-}
-
-static void
-gst_qt_mux_prepare_ftyp (GstQTMux * qtmux, AtomFTYP ** p_ftyp,
- GstBuffer ** p_prefix)
-{
- GstQTMuxClass *qtmux_klass = (GstQTMuxClass *) (G_OBJECT_GET_CLASS (qtmux));
- guint32 major, version;
- GList *comp;
- GstBuffer *prefix = NULL;
- AtomFTYP *ftyp = NULL;
-
- GST_DEBUG_OBJECT (qtmux, "Preparing ftyp and possible prefix atom");
-
- /* init and send context and ftyp based on current property state */
- gst_qt_mux_map_format_to_header (qtmux_klass->format, &prefix, &major,
- &version, &comp, qtmux->moov, qtmux->longest_chunk,
- qtmux->fast_start_file != NULL);
- ftyp = atom_ftyp_new (qtmux->context, major, version, comp);
- if (comp)
- g_list_free (comp);
- if (prefix) {
- if (p_prefix)
- *p_prefix = prefix;
- else
- gst_buffer_unref (prefix);
- }
- *p_ftyp = ftyp;
-}
-
-static GstFlowReturn
-gst_qt_mux_prepare_and_send_ftyp (GstQTMux * qtmux)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- GstBuffer *prefix = NULL;
-
- GST_DEBUG_OBJECT (qtmux, "Preparing to send ftyp atom");
-
- /* init and send context and ftyp based on current property state */
- if (qtmux->ftyp) {
- atom_ftyp_free (qtmux->ftyp);
- qtmux->ftyp = NULL;
- }
- gst_qt_mux_prepare_ftyp (qtmux, &qtmux->ftyp, &prefix);
- if (prefix) {
- ret = gst_qt_mux_send_buffer (qtmux, prefix, &qtmux->header_size, FALSE);
- if (ret != GST_FLOW_OK)
- return ret;
- }
- return gst_qt_mux_send_ftyp (qtmux, &qtmux->header_size);
-}
-
-static void
-gst_qt_mux_set_header_on_caps (GstQTMux * mux, GstBuffer * buf)
-{
- GstStructure *structure;
- GValue array = { 0 };
- GValue value = { 0 };
- GstCaps *caps = GST_PAD_CAPS (mux->srcpad);
-
- caps = gst_caps_copy (GST_PAD_CAPS (mux->srcpad));
- structure = gst_caps_get_structure (caps, 0);
-
- g_value_init (&array, GST_TYPE_ARRAY);
-
- GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
- g_value_init (&value, GST_TYPE_BUFFER);
- gst_value_take_buffer (&value, gst_buffer_ref (buf));
- gst_value_array_append_value (&array, &value);
- g_value_unset (&value);
-
- gst_structure_set_value (structure, "streamheader", &array);
- g_value_unset (&array);
- gst_pad_set_caps (mux->srcpad, caps);
- gst_caps_unref (caps);
-}
-
-static void
-gst_qt_mux_configure_moov (GstQTMux * qtmux, guint32 * _timescale)
-{
- gboolean fragmented;
- guint32 timescale;
-
- GST_OBJECT_LOCK (qtmux);
- timescale = qtmux->timescale;
- fragmented = qtmux->fragment_sequence > 0;
- GST_OBJECT_UNLOCK (qtmux);
-
- /* inform lower layers of our property wishes, and determine duration.
- * Let moov take care of this using its list of traks;
- * so that released pads are also included */
- GST_DEBUG_OBJECT (qtmux, "Updating timescale to %" G_GUINT32_FORMAT,
- timescale);
- atom_moov_update_timescale (qtmux->moov, timescale);
- atom_moov_set_fragmented (qtmux->moov, fragmented);
-
- atom_moov_update_duration (qtmux->moov);
-
- if (_timescale)
- *_timescale = timescale;
-}
-
-static GstFlowReturn
-gst_qt_mux_send_moov (GstQTMux * qtmux, guint64 * _offset, gboolean mind_fast)
-{
- guint64 offset = 0, size = 0;
- guint8 *data;
- GstBuffer *buf;
- GstFlowReturn ret = GST_FLOW_OK;
-
- /* serialize moov */
- offset = size = 0;
- data = NULL;
- GST_LOG_OBJECT (qtmux, "Copying movie header into buffer");
- if (!atom_moov_copy_data (qtmux->moov, &data, &size, &offset))
- goto serialize_error;
-
- buf = _gst_buffer_new_take_data (data, offset);
- GST_DEBUG_OBJECT (qtmux, "Pushing moov atoms");
- gst_qt_mux_set_header_on_caps (qtmux, buf);
- ret = gst_qt_mux_send_buffer (qtmux, buf, _offset, mind_fast);
-
- return ret;
-
-serialize_error:
- {
- g_free (data);
- return GST_FLOW_ERROR;
- }
-}
-
-/* either calculates size of extra atoms or pushes them */
-static GstFlowReturn
-gst_qt_mux_send_extra_atoms (GstQTMux * qtmux, gboolean send, guint64 * offset,
- gboolean mind_fast)
-{
- GSList *walk;
- guint64 loffset = 0, size = 0;
- guint8 *data;
- GstFlowReturn ret = GST_FLOW_OK;
-
- for (walk = qtmux->extra_atoms; walk; walk = g_slist_next (walk)) {
- AtomInfo *ainfo = (AtomInfo *) walk->data;
-
- loffset = size = 0;
- data = NULL;
- if (!ainfo->copy_data_func (ainfo->atom,
- send ? &data : NULL, &size, &loffset))
- goto serialize_error;
-
- if (send) {
- GstBuffer *buf;
-
- GST_DEBUG_OBJECT (qtmux,
- "Pushing extra top-level atom %" GST_FOURCC_FORMAT,
- GST_FOURCC_ARGS (ainfo->atom->type));
- buf = _gst_buffer_new_take_data (data, loffset);
- ret = gst_qt_mux_send_buffer (qtmux, buf, offset, FALSE);
- if (ret != GST_FLOW_OK)
- break;
- } else {
- if (offset)
- *offset += loffset;
- }
- }
-
- return ret;
-
-serialize_error:
- {
- g_free (data);
- return GST_FLOW_ERROR;
- }
-}
-
-static GstFlowReturn
-gst_qt_mux_start_file (GstQTMux * qtmux)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- GstCaps *caps;
-
- GST_DEBUG_OBJECT (qtmux, "starting file");
-
- caps = gst_caps_copy (gst_pad_get_pad_template_caps (qtmux->srcpad));
- gst_pad_set_caps (qtmux->srcpad, caps);
- gst_caps_unref (caps);
-
- /* let downstream know we think in BYTES and expect to do seeking later on */
- gst_pad_push_event (qtmux->srcpad,
- gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES, 0, -1, 0));
-
- /* initialize our moov recovery file */
- GST_OBJECT_LOCK (qtmux);
- if (qtmux->moov_recov_file_path) {
- GST_DEBUG_OBJECT (qtmux, "Openning moov recovery file: %s",
- qtmux->moov_recov_file_path);
- qtmux->moov_recov_file = g_fopen (qtmux->moov_recov_file_path, "wb+");
- if (qtmux->moov_recov_file == NULL) {
- GST_WARNING_OBJECT (qtmux, "Failed to open moov recovery file in %s",
- qtmux->moov_recov_file_path);
- } else {
- GSList *walk;
- gboolean fail = FALSE;
- AtomFTYP *ftyp = NULL;
- GstBuffer *prefix = NULL;
-
- gst_qt_mux_prepare_ftyp (qtmux, &ftyp, &prefix);
-
- if (!atoms_recov_write_headers (qtmux->moov_recov_file, ftyp, prefix,
- qtmux->moov, qtmux->timescale,
- g_slist_length (qtmux->sinkpads))) {
- GST_WARNING_OBJECT (qtmux, "Failed to write moov recovery file "
- "headers");
- fail = TRUE;
- }
-
- atom_ftyp_free (ftyp);
- if (prefix)
- gst_buffer_unref (prefix);
-
- for (walk = qtmux->sinkpads; walk && !fail; walk = g_slist_next (walk)) {
- GstCollectData *cdata = (GstCollectData *) walk->data;
- GstQTPad *qpad = (GstQTPad *) cdata;
- /* write info for each stream */
- fail = atoms_recov_write_trak_info (qtmux->moov_recov_file, qpad->trak);
- if (fail) {
- GST_WARNING_OBJECT (qtmux, "Failed to write trak info to recovery "
- "file");
- }
- }
- if (fail) {
- /* cleanup */
- fclose (qtmux->moov_recov_file);
- qtmux->moov_recov_file = NULL;
- GST_WARNING_OBJECT (qtmux, "An error was detected while writing to "
- "recover file, moov recovery won't work");
- }
- }
- }
- GST_OBJECT_UNLOCK (qtmux);
-
- /*
- * send mdat header if already needed, and mark position for later update.
- * We don't send ftyp now if we are on fast start mode, because we can
- * better fine tune using the information we gather to create the whole moov
- * atom.
- */
- if (qtmux->fast_start) {
- GST_OBJECT_LOCK (qtmux);
- qtmux->fast_start_file = g_fopen (qtmux->fast_start_file_path, "wb+");
- if (!qtmux->fast_start_file)
- goto open_failed;
- GST_OBJECT_UNLOCK (qtmux);
-
- /* send a dummy buffer for preroll */
- ret = gst_qt_mux_send_buffer (qtmux, gst_buffer_new (), NULL, FALSE);
- if (ret != GST_FLOW_OK)
- goto exit;
-
- } else {
- ret = gst_qt_mux_prepare_and_send_ftyp (qtmux);
- if (ret != GST_FLOW_OK) {
- goto exit;
- }
-
- /* well, it's moov pos if fragmented ... */
- qtmux->mdat_pos = qtmux->header_size;
-
- if (qtmux->fragment_duration) {
- GST_DEBUG_OBJECT (qtmux, "fragment duration %d ms, writing headers",
- qtmux->fragment_duration);
- /* also used as snapshot marker to indicate fragmented file */
- qtmux->fragment_sequence = 1;
- /* prepare moov and/or tags */
- gst_qt_mux_configure_moov (qtmux, NULL);
- gst_qt_mux_setup_metadata (qtmux);
- ret = gst_qt_mux_send_moov (qtmux, &qtmux->header_size, FALSE);
- if (ret != GST_FLOW_OK)
- return ret;
- /* extra atoms */
- ret =
- gst_qt_mux_send_extra_atoms (qtmux, TRUE, &qtmux->header_size, FALSE);
- if (ret != GST_FLOW_OK)
- return ret;
- /* prepare index */
- if (!qtmux->streamable)
- qtmux->mfra = atom_mfra_new (qtmux->context);
- } else {
- /* extended to ensure some spare space */
- ret = gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, 0, TRUE);
- }
- }
-
-exit:
- return ret;
-
- /* ERRORS */
-open_failed:
- {
- GST_ELEMENT_ERROR (qtmux, RESOURCE, OPEN_READ_WRITE,
- (("Could not open temporary file \"%s\""), qtmux->fast_start_file_path),
- GST_ERROR_SYSTEM);
- GST_OBJECT_UNLOCK (qtmux);
- return GST_FLOW_ERROR;
- }
-}
-
-static GstFlowReturn
-gst_qt_mux_stop_file (GstQTMux * qtmux)
-{
- gboolean ret = GST_FLOW_OK;
- guint64 offset = 0, size = 0;
- GSList *walk;
- gboolean large_file;
- guint32 timescale;
- GstClockTime first_ts = GST_CLOCK_TIME_NONE;
-
- GST_DEBUG_OBJECT (qtmux, "Updating remaining values and sending last data");
-
- /* pushing last buffers for each pad */
- for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) {
- GstCollectData *cdata = (GstCollectData *) walk->data;
- GstQTPad *qtpad = (GstQTPad *) cdata;
-
- if (!qtpad->last_buf) {
- GST_DEBUG_OBJECT (qtmux, "Pad %s has no buffers",
- GST_PAD_NAME (qtpad->collect.pad));
- continue;
- }
- /* send last buffer */
- GST_DEBUG_OBJECT (qtmux, "Sending the last buffer for pad %s",
- GST_PAD_NAME (qtpad->collect.pad));
- ret = gst_qt_mux_add_buffer (qtmux, qtpad, NULL);
- if (ret != GST_FLOW_OK)
- GST_WARNING_OBJECT (qtmux, "Failed to send last buffer for %s, "
- "flow return: %s", GST_PAD_NAME (qtpad->collect.pad),
- gst_flow_get_name (ret));
- /* determine max stream duration */
- if (!GST_CLOCK_TIME_IS_VALID (first_ts) ||
- (GST_CLOCK_TIME_IS_VALID (qtpad->first_ts) &&
- qtpad->last_dts > first_ts)) {
- first_ts = qtpad->last_dts;
- }
- }
-
- if (qtmux->fragment_sequence) {
- GstEvent *event;
-
- if (qtmux->mfra) {
- guint8 *data = NULL;
- GstBuffer *buf;
-
- size = offset = 0;
- GST_DEBUG_OBJECT (qtmux, "adding mfra");
- if (!atom_mfra_copy_data (qtmux->mfra, &data, &size, &offset))
- goto serialize_error;
- buf = _gst_buffer_new_take_data (data, offset);
- ret = gst_qt_mux_send_buffer (qtmux, buf, NULL, FALSE);
- if (ret != GST_FLOW_OK)
- return ret;
- } else {
- /* must have been streamable; no need to write duration */
- GST_DEBUG_OBJECT (qtmux, "streamable file; nothing to stop");
- return GST_FLOW_OK;
- }
-
-
- timescale = qtmux->timescale;
- /* only mvex duration is updated,
- * mvhd should be consistent with empty moov
- * (but TODO maybe some clients do not handle that well ?) */
- qtmux->moov->mvex.mehd.fragment_duration =
- gst_util_uint64_scale (first_ts, timescale, GST_SECOND);
- GST_DEBUG_OBJECT (qtmux, "rewriting moov with mvex duration %"
- GST_TIME_FORMAT, GST_TIME_ARGS (first_ts));
- /* seek and rewrite the header */
- event = gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_BYTES,
- qtmux->mdat_pos, GST_CLOCK_TIME_NONE, 0);
- gst_pad_push_event (qtmux->srcpad, event);
- /* no need to seek back */
- return gst_qt_mux_send_moov (qtmux, NULL, FALSE);
- }
-
- gst_qt_mux_configure_moov (qtmux, &timescale);
-
- /* check for late streams */
- first_ts = GST_CLOCK_TIME_NONE;
- for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) {
- GstCollectData *cdata = (GstCollectData *) walk->data;
- GstQTPad *qtpad = (GstQTPad *) cdata;
-
- if (!GST_CLOCK_TIME_IS_VALID (first_ts) ||
- (GST_CLOCK_TIME_IS_VALID (qtpad->first_ts) &&
- qtpad->first_ts < first_ts)) {
- first_ts = qtpad->first_ts;
- }
- }
- GST_DEBUG_OBJECT (qtmux, "Media first ts selected: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (first_ts));
- /* add EDTSs for late streams */
- for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) {
- GstCollectData *cdata = (GstCollectData *) walk->data;
- GstQTPad *qtpad = (GstQTPad *) cdata;
- guint32 lateness;
- guint32 duration;
-
- if (GST_CLOCK_TIME_IS_VALID (qtpad->first_ts) &&
- qtpad->first_ts > first_ts + MAX_TOLERATED_LATENESS) {
- GST_DEBUG_OBJECT (qtmux, "Pad %s is a late stream by %" GST_TIME_FORMAT,
- GST_PAD_NAME (qtpad->collect.pad),
- GST_TIME_ARGS (qtpad->first_ts - first_ts));
- lateness = gst_util_uint64_scale_round (qtpad->first_ts - first_ts,
- timescale, GST_SECOND);
- duration = qtpad->trak->tkhd.duration;
- atom_trak_add_elst_entry (qtpad->trak, lateness, (guint32) - 1,
- (guint32) (1 * 65536.0));
- atom_trak_add_elst_entry (qtpad->trak, duration, 0,
- (guint32) (1 * 65536.0));
-
- /* need to add the empty time to the trak duration */
- qtpad->trak->tkhd.duration += lateness;
- }
- }
-
- /* tags into file metadata */
- gst_qt_mux_setup_metadata (qtmux);
-
- large_file = (qtmux->mdat_size > MDAT_LARGE_FILE_LIMIT);
- /* if faststart, update the offset of the atoms in the movie with the offset
- * that the movie headers before mdat will cause.
- * Also, send the ftyp */
- if (qtmux->fast_start_file) {
- GstFlowReturn flow_ret;
- offset = size = 0;
-
- flow_ret = gst_qt_mux_prepare_and_send_ftyp (qtmux);
- if (flow_ret != GST_FLOW_OK) {
- goto ftyp_error;
- }
- /* copy into NULL to obtain size */
- if (!atom_moov_copy_data (qtmux->moov, NULL, &size, &offset))
- goto serialize_error;
- GST_DEBUG_OBJECT (qtmux, "calculated moov atom size %" G_GUINT64_FORMAT,
- offset);
- offset += qtmux->header_size + (large_file ? 16 : 8);
-
- /* sum up with the extra atoms size */
- ret = gst_qt_mux_send_extra_atoms (qtmux, FALSE, &offset, FALSE);
- if (ret != GST_FLOW_OK)
- return ret;
- } else {
- offset = qtmux->header_size;
- }
- atom_moov_chunks_add_offset (qtmux->moov, offset);
-
- /* moov */
- /* note: as of this point, we no longer care about tracking written data size,
- * since there is no more use for it anyway */
- ret = gst_qt_mux_send_moov (qtmux, NULL, FALSE);
- if (ret != GST_FLOW_OK)
- return ret;
-
- /* extra atoms */
- ret = gst_qt_mux_send_extra_atoms (qtmux, TRUE, NULL, FALSE);
- if (ret != GST_FLOW_OK)
- return ret;
-
- /* if needed, send mdat atom and move buffered data into it */
- if (qtmux->fast_start_file) {
- /* mdat_size = accumulated (buffered data) */
- ret = gst_qt_mux_send_mdat_header (qtmux, NULL, qtmux->mdat_size,
- large_file);
- if (ret != GST_FLOW_OK)
- return ret;
- ret = gst_qt_mux_send_buffered_data (qtmux, NULL);
- if (ret != GST_FLOW_OK)
- return ret;
- } else {
- /* mdat needs update iff not using faststart */
- GST_DEBUG_OBJECT (qtmux, "updating mdat size");
- ret = gst_qt_mux_update_mdat_size (qtmux, qtmux->mdat_pos,
- qtmux->mdat_size, NULL);
- /* note; no seeking back to the end of file is done,
- * since we no longer write anything anyway */
- }
-
- return ret;
-
- /* ERRORS */
-serialize_error:
- {
- GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL),
- ("Failed to serialize moov"));
- return GST_FLOW_ERROR;
- }
-ftyp_error:
- {
- GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL), ("Failed to send ftyp"));
- return GST_FLOW_ERROR;
- }
-}
-
-static GstFlowReturn
-gst_qt_mux_pad_fragment_add_buffer (GstQTMux * qtmux, GstQTPad * pad,
- GstBuffer * buf, gboolean force, guint32 nsamples, gint64 dts,
- guint32 delta, guint32 size, gboolean sync, gint64 pts_offset)
-{
- GstFlowReturn ret = GST_FLOW_OK;
-
- /* setup if needed */
- if (G_UNLIKELY (!pad->traf || force))
- goto init;
-
-flush:
- /* flush pad fragment if threshold reached,
- * or at new keyframe if we should be minding those in the first place */
- if (G_UNLIKELY (force || (sync && pad->sync) ||
- pad->fragment_duration < (gint64) delta)) {
- AtomMOOF *moof;
- guint64 size = 0, offset = 0;
- guint8 *data = NULL;
- GstBuffer *buffer;
- guint i, total_size;
-
- /* now we know where moof ends up, update offset in tfra */
- if (pad->tfra)
- atom_tfra_update_offset (pad->tfra, qtmux->header_size);
-
- moof = atom_moof_new (qtmux->context, qtmux->fragment_sequence);
- /* takes ownership */
- atom_moof_add_traf (moof, pad->traf);
- pad->traf = NULL;
- atom_moof_copy_data (moof, &data, &size, &offset);
- buffer = _gst_buffer_new_take_data (data, offset);
- GST_LOG_OBJECT (qtmux, "writing moof size %d", GST_BUFFER_SIZE (buffer));
- ret = gst_qt_mux_send_buffer (qtmux, buffer, &qtmux->header_size, FALSE);
-
- /* and actual data */
- total_size = 0;
- for (i = 0; i < atom_array_get_len (&pad->fragment_buffers); i++) {
- total_size +=
- GST_BUFFER_SIZE (atom_array_index (&pad->fragment_buffers, i));
- }
-
- GST_LOG_OBJECT (qtmux, "writing %d buffers, total_size %d",
- atom_array_get_len (&pad->fragment_buffers), total_size);
- if (ret == GST_FLOW_OK)
- ret = gst_qt_mux_send_mdat_header (qtmux, &qtmux->header_size, total_size,
- FALSE);
- for (i = 0; i < atom_array_get_len (&pad->fragment_buffers); i++) {
- if (G_LIKELY (ret == GST_FLOW_OK))
- ret = gst_qt_mux_send_buffer (qtmux,
- atom_array_index (&pad->fragment_buffers, i), &qtmux->header_size,
- FALSE);
- else
- gst_buffer_unref (atom_array_index (&pad->fragment_buffers, i));
- }
-
- atom_array_clear (&pad->fragment_buffers);
- atom_moof_free (moof);
- qtmux->fragment_sequence++;
- force = FALSE;
- }
-
-init:
- if (G_UNLIKELY (!pad->traf)) {
- GST_LOG_OBJECT (qtmux, "setting up new fragment");
- pad->traf = atom_traf_new (qtmux->context, atom_trak_get_id (pad->trak));
- atom_array_init (&pad->fragment_buffers, 512);
- pad->fragment_duration = gst_util_uint64_scale (qtmux->fragment_duration,
- atom_trak_get_timescale (pad->trak), 1000);
-
- if (G_UNLIKELY (qtmux->mfra && !pad->tfra)) {
- pad->tfra = atom_tfra_new (qtmux->context, atom_trak_get_id (pad->trak));
- atom_mfra_add_tfra (qtmux->mfra, pad->tfra);
- }
- }
-
- /* add buffer and metadata */
- atom_traf_add_samples (pad->traf, delta, size, sync, pts_offset,
- pad->sync && sync);
- atom_array_append (&pad->fragment_buffers, buf, 256);
- pad->fragment_duration -= delta;
-
- if (pad->tfra) {
- guint32 sn = atom_traf_get_sample_num (pad->traf);
-
- if ((sync && pad->sync) || (sn == 1 && !pad->sync))
- atom_tfra_add_entry (pad->tfra, dts, sn);
- }
-
- if (G_UNLIKELY (force))
- goto flush;
-
- return ret;
-}
-
-/* sigh, tiny list helpers to re-order stuff */
-static void
-gst_qt_mux_push_ts (GstQTMux * qtmux, GstQTPad * pad, GstClockTime ts)
-{
- gint i;
-
- for (i = 0; (i < QTMUX_NO_OF_TS) && (i < pad->ts_n_entries); i++) {
- if (ts > pad->ts_entries[i])
- break;
- }
- memmove (&pad->ts_entries[i + 1], &pad->ts_entries[i],
- sizeof (GstClockTime) * (pad->ts_n_entries - i));
- pad->ts_entries[i] = ts;
- pad->ts_n_entries++;
-}
-
-/* takes ownership of @buf */
-static GstBuffer *
-gst_qt_mux_get_asc_buffer_ts (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf)
-{
- const gint wrap = G_N_ELEMENTS (pad->buf_entries);
- GstClockTime ts;
-
- /* store buffer and ts, latter ordered */
- if (buf) {
- pad->buf_entries[pad->buf_tail++] = buf;
- pad->buf_tail %= wrap;
- gst_qt_mux_push_ts (qtmux, pad, GST_BUFFER_TIMESTAMP (buf));
- }
-
- if (pad->ts_n_entries && (!buf || pad->ts_n_entries >= QTMUX_NO_OF_TS)) {
- ts = pad->ts_entries[--pad->ts_n_entries];
- buf = pad->buf_entries[pad->buf_head];
- pad->buf_entries[pad->buf_head++] = NULL;
- pad->buf_head %= wrap;
- buf = gst_buffer_make_metadata_writable (buf);
- /* track original ts (= pts ?) for later */
- GST_BUFFER_OFFSET_END (buf) = GST_BUFFER_TIMESTAMP (buf);
- GST_BUFFER_TIMESTAMP (buf) = ts;
- GST_DEBUG_OBJECT (qtmux, "next buffer uses reordered ts %" GST_TIME_FORMAT,
- GST_TIME_ARGS (ts));
- } else {
- buf = NULL;
- }
-
- return buf;
-}
-
-/*
- * Here we push the buffer and update the tables in the track atoms
- */
-static GstFlowReturn
-gst_qt_mux_add_buffer (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf)
-{
- GstBuffer *last_buf = NULL;
- GstClockTime duration;
- guint nsamples, sample_size;
- guint64 chunk_offset;
- gint64 last_dts, scaled_duration;
- gint64 pts_offset = 0;
- gboolean sync = FALSE, do_pts = FALSE;
- gboolean drain = (buf == NULL);
- GstFlowReturn ret;
-
- if (!pad->fourcc)
- goto not_negotiated;
-
- /* if this pad has a prepare function, call it */
- if (pad->prepare_buf_func != NULL) {
- buf = pad->prepare_buf_func (pad, buf, qtmux);
- }
-
-again:
- if (G_UNLIKELY (qtmux->dts_method == DTS_METHOD_REORDER)) {
- buf = gst_qt_mux_get_asc_buffer_ts (qtmux, pad, buf);
- if (!buf) {
- GST_DEBUG_OBJECT (qtmux, "no reordered buffer yet");
- return GST_FLOW_OK;
- }
- }
-
- last_buf = pad->last_buf;
- if (last_buf == NULL) {
-#ifndef GST_DISABLE_GST_DEBUG
- if (buf == NULL) {
- GST_DEBUG_OBJECT (qtmux, "Pad %s has no previous buffer stored and "
- "received NULL buffer, doing nothing",
- GST_PAD_NAME (pad->collect.pad));
- } else {
- GST_LOG_OBJECT (qtmux,
- "Pad %s has no previous buffer stored, storing now",
- GST_PAD_NAME (pad->collect.pad));
- }
-#endif
- pad->last_buf = buf;
- return GST_FLOW_OK;
- } else
- gst_buffer_ref (last_buf);
-
- /* nasty heuristic mess to guestimate dealing with DTS/PTS,
- * while also trying to stay close to input ts to preserve sync,
- * so in DTS_METHOD_DD:
- * - prefer using input ts where possible
- * - if those detected out-of-order (*), mark as out-of-order
- * - if in out-of-order, then
- * - if duration available, use that as delta
- * Also mind to preserve sync between streams, and adding
- * durations might drift, so try to resync when we expect
- * input ts == (sum of durations), which is at some keyframe input frame.
- * - if no duration available, we are actually in serious trouble and need
- * to hack around that, so we fail.
- * To remedy failure, alternatively, in DTS_METHOD_REORDER:
- * - collect some buffers and re-order timestamp,
- * then process the oldest buffer with smallest timestamps.
- * This should typically compensate for some codec's handywork with ts.
- * ... but in case this makes ts end up where not expected, in DTS_METHOD_ASC:
- * - keep each ts with its buffer and still keep a list of most recent X ts,
- * use the (ascending) minimum of those as DTS (and the difference as ts delta),
- * and use this DTS as a basis to obtain a (positive) CTS offset.
- * This should yield exact PTS == buffer ts, but it seems not all players
- * out there are aware of ctts pts ...
- *
- * 0.11 Phew, can we (pretty) please please sort out DTS/PTS on buffers ...
- */
- if (G_LIKELY (buf) && !pad->is_out_of_order) {
- if (G_LIKELY (GST_BUFFER_TIMESTAMP_IS_VALID (last_buf) &&
- GST_BUFFER_TIMESTAMP_IS_VALID (buf))) {
- if ((GST_BUFFER_TIMESTAMP (buf) < GST_BUFFER_TIMESTAMP (last_buf))) {
- GST_DEBUG_OBJECT (qtmux, "detected out-of-order input");
- pad->is_out_of_order = TRUE;
- }
- } else {
- /* this is pretty bad */
- GST_WARNING_OBJECT (qtmux, "missing input timestamp");
- /* fall back to durations */
- pad->is_out_of_order = TRUE;
- }
- }
-
- /* would have to be some unusual input, but not impossible */
- if (G_UNLIKELY (qtmux->dts_method == DTS_METHOD_REORDER &&
- pad->is_out_of_order)) {
- goto no_order;
- }
-
- /* fall back to duration if last buffer or
- * out-of-order (determined previously), otherwise use input ts */
- if (buf == NULL ||
- (pad->is_out_of_order && qtmux->dts_method == DTS_METHOD_DD)) {
- if (!GST_BUFFER_DURATION_IS_VALID (last_buf)) {
- /* be forgiving for some possibly last upstream flushed buffer */
- if (buf)
- goto no_time;
- GST_WARNING_OBJECT (qtmux, "no duration for last buffer");
- /* iso spec recommends some small value, try 0 */
- duration = 0;
- } else {
- duration = GST_BUFFER_DURATION (last_buf);
- /* avoid drift in sum timestamps,
- * so use input timestamp for suitable keyframe */
- if (buf && !GST_BUFFER_FLAG_IS_SET (buf, GST_BUFFER_FLAG_DELTA_UNIT) &&
- GST_BUFFER_TIMESTAMP (buf) >= pad->last_dts) {
- GST_DEBUG_OBJECT (qtmux, "resyncing out-of-order input to ts; "
- "replacing %" GST_TIME_FORMAT " by %" GST_TIME_FORMAT,
- GST_TIME_ARGS (pad->last_dts + duration),
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
- duration = GST_BUFFER_TIMESTAMP (buf) - pad->last_dts;
- }
- }
- } else if (qtmux->dts_method != DTS_METHOD_ASC) {
- duration = GST_BUFFER_TIMESTAMP (buf) - GST_BUFFER_TIMESTAMP (last_buf);
- } else {
- GstClockTime ts;
-
- g_assert (qtmux->dts_method == DTS_METHOD_ASC);
- if (!qtmux->guess_pts)
- goto need_pts;
-
- /* add timestamp to queue; keeps in descending order */
- gst_qt_mux_push_ts (qtmux, pad, GST_BUFFER_TIMESTAMP (last_buf));
- /* chuck out smallest/last one if we have enough */
- if (G_LIKELY (pad->ts_n_entries > QTMUX_NO_OF_TS))
- pad->ts_n_entries--;
- /* peek the now smallest timestamp */
- ts = pad->ts_entries[pad->ts_n_entries - 1];
- /* these tails are expected to be (strictly) ascending with
- * large enough history */
- GST_DEBUG_OBJECT (qtmux, "ASC method; base timestamp %" GST_TIME_FORMAT,
- GST_TIME_ARGS (ts));
- if (ts >= pad->last_dts) {
- duration = ts - pad->last_dts;
- } else {
- /* fallback to previous value, negative ct offset might handle */
- GST_WARNING_OBJECT (qtmux, "unexpected decrease in timestamp");
- duration = 0;
- }
- /* arrange for small non-zero duration/delta << expected frame time */
- ts = gst_util_uint64_scale (10, GST_SECOND,
- atom_trak_get_timescale (pad->trak));
- duration = MAX (duration, ts);
- }
-
- gst_buffer_replace (&pad->last_buf, buf);
-
- last_dts = gst_util_uint64_scale_round (pad->last_dts,
- atom_trak_get_timescale (pad->trak), GST_SECOND);
-
- /* fragments only deal with 1 buffer == 1 chunk (== 1 sample) */
- if (pad->sample_size && !qtmux->fragment_sequence) {
- /* Constant size packets: usually raw audio (with many samples per
- buffer (= chunk)), but can also be fixed-packet-size codecs like ADPCM
- */
- sample_size = pad->sample_size;
- if (GST_BUFFER_SIZE (last_buf) % sample_size != 0)
- goto fragmented_sample;
- /* note: qt raw audio storage warps it implicitly into a timewise
- * perfect stream, discarding buffer times */
- if (GST_BUFFER_DURATION (last_buf) != GST_CLOCK_TIME_NONE) {
- nsamples = gst_util_uint64_scale_round (GST_BUFFER_DURATION (last_buf),
- atom_trak_get_timescale (pad->trak), GST_SECOND);
- } else {
- nsamples = GST_BUFFER_SIZE (last_buf) / sample_size;
- }
- duration = GST_BUFFER_DURATION (last_buf) / nsamples;
-
- /* timescale = samplerate */
- scaled_duration = 1;
- pad->last_dts += duration * nsamples;
- } else {
- nsamples = 1;
- sample_size = GST_BUFFER_SIZE (last_buf);
- if (pad->have_dts) {
- gint64 scaled_dts;
- pad->last_dts = GST_BUFFER_OFFSET_END (last_buf);
- if ((gint64) (pad->last_dts) < 0) {
- scaled_dts = -gst_util_uint64_scale_round (-pad->last_dts,
- atom_trak_get_timescale (pad->trak), GST_SECOND);
- } else {
- scaled_dts = gst_util_uint64_scale_round (pad->last_dts,
- atom_trak_get_timescale (pad->trak), GST_SECOND);
- }
- scaled_duration = scaled_dts - last_dts;
- last_dts = scaled_dts;
- } else {
- /* first convert intended timestamp (in GstClockTime resolution) to
- * trak timescale, then derive delta;
- * this ensures sums of (scale)delta add up to converted timestamp,
- * which only deviates at most 1/scale from timestamp itself */
- scaled_duration = gst_util_uint64_scale_round (pad->last_dts + duration,
- atom_trak_get_timescale (pad->trak), GST_SECOND) - last_dts;
- pad->last_dts += duration;
- }
- }
- chunk_offset = qtmux->mdat_size;
-
- GST_LOG_OBJECT (qtmux,
- "Pad (%s) dts updated to %" GST_TIME_FORMAT,
- GST_PAD_NAME (pad->collect.pad), GST_TIME_ARGS (pad->last_dts));
- GST_LOG_OBJECT (qtmux,
- "Adding %d samples to track, duration: %" G_GUINT64_FORMAT
- " size: %" G_GUINT32_FORMAT " chunk offset: %" G_GUINT64_FORMAT,
- nsamples, scaled_duration, sample_size, chunk_offset);
-
- /* might be a sync sample */
- if (pad->sync &&
- !GST_BUFFER_FLAG_IS_SET (last_buf, GST_BUFFER_FLAG_DELTA_UNIT)) {
- GST_LOG_OBJECT (qtmux, "Adding new sync sample entry for track of pad %s",
- GST_PAD_NAME (pad->collect.pad));
- sync = TRUE;
- }
-
- /* optionally calculate ctts entry values
- * (if composition-time expected different from decoding-time) */
- /* really not recommended:
- * - decoder typically takes care of dts/pts issues
- * - in case of out-of-order, dts may only be determined as above
- * (e.g. sum of duration), which may be totally different from
- * buffer timestamps in case of multiple segment, non-perfect streams
- * (and just perhaps maybe with some luck segment_to_running_time
- * or segment_to_media_time might get near to it) */
- if ((pad->have_dts || qtmux->guess_pts)) {
- guint64 pts;
-
- pts = qtmux->dts_method == DTS_METHOD_REORDER ?
- GST_BUFFER_OFFSET_END (last_buf) : GST_BUFFER_TIMESTAMP (last_buf);
- pts = gst_util_uint64_scale_round (pts,
- atom_trak_get_timescale (pad->trak), GST_SECOND);
- pts_offset = (gint64) (pts - last_dts);
- do_pts = TRUE;
- GST_LOG_OBJECT (qtmux, "Adding ctts entry for pad %s: %" G_GINT64_FORMAT,
- GST_PAD_NAME (pad->collect.pad), pts_offset);
- }
-
- /*
- * Each buffer starts a new chunk, so we can assume the buffer
- * duration is the chunk duration
- */
- if (GST_CLOCK_TIME_IS_VALID (duration) && (duration > qtmux->longest_chunk ||
- !GST_CLOCK_TIME_IS_VALID (qtmux->longest_chunk))) {
- GST_DEBUG_OBJECT (qtmux, "New longest chunk found: %" GST_TIME_FORMAT
- ", pad %s", GST_TIME_ARGS (duration), GST_PAD_NAME (pad->collect.pad));
- qtmux->longest_chunk = duration;
- }
-
- /* if this is the first buffer, store the timestamp */
- if (G_UNLIKELY (pad->first_ts == GST_CLOCK_TIME_NONE) && last_buf) {
- if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_TIMESTAMP (last_buf))) {
- pad->first_ts = GST_BUFFER_TIMESTAMP (last_buf);
- } else {
- GST_DEBUG_OBJECT (qtmux, "First buffer for pad %s has no timestamp, "
- "using 0 as first timestamp", GST_PAD_NAME (pad->collect.pad));
- pad->first_ts = 0;
- }
- GST_DEBUG_OBJECT (qtmux, "Stored first timestamp for pad %s %"
- GST_TIME_FORMAT, GST_PAD_NAME (pad->collect.pad),
- GST_TIME_ARGS (pad->first_ts));
- }
-
- /* now we go and register this buffer/sample all over */
- /* note that a new chunk is started each time (not fancy but works) */
- if (qtmux->moov_recov_file) {
- if (!atoms_recov_write_trak_samples (qtmux->moov_recov_file, pad->trak,
- nsamples, (gint32) scaled_duration, sample_size, chunk_offset, sync,
- do_pts, pts_offset)) {
- GST_WARNING_OBJECT (qtmux, "Failed to write sample information to "
- "recovery file, disabling recovery");
- fclose (qtmux->moov_recov_file);
- qtmux->moov_recov_file = NULL;
- }
- }
-
- if (buf)
- gst_buffer_unref (buf);
-
- if (qtmux->fragment_sequence) {
- /* ensure that always sync samples are marked as such */
- ret = gst_qt_mux_pad_fragment_add_buffer (qtmux, pad, last_buf,
- buf == NULL, nsamples, last_dts, (gint32) scaled_duration, sample_size,
- !pad->sync || sync, pts_offset);
- } else {
- atom_trak_add_samples (pad->trak, nsamples, (gint32) scaled_duration,
- sample_size, chunk_offset, sync, pts_offset);
- ret = gst_qt_mux_send_buffer (qtmux, last_buf, &qtmux->mdat_size, TRUE);
- }
-
- if (G_UNLIKELY (drain && qtmux->dts_method == DTS_METHOD_REORDER &&
- ret == GST_FLOW_OK)) {
- buf = NULL;
- goto again;
- }
-
- return ret;
-
- /* ERRORS */
-bail:
- {
- if (buf)
- gst_buffer_unref (buf);
- gst_buffer_unref (last_buf);
- return GST_FLOW_ERROR;
- }
-no_time:
- {
- GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL),
- ("Received buffer without timestamp/duration. "
- "Using e.g. dts-method=reorder might help."));
- goto bail;
- }
-no_order:
- {
- GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL),
- ("DTS method failed to re-order timestamps."));
- goto bail;
- }
-need_pts:
- {
- GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL),
- ("Selected DTS method also needs PTS enabled."));
- goto bail;
- }
-fragmented_sample:
- {
- GST_ELEMENT_ERROR (qtmux, STREAM, MUX, (NULL),
- ("Audio buffer contains fragmented sample."));
- goto bail;
- }
-not_negotiated:
- {
- GST_ELEMENT_ERROR (qtmux, CORE, NEGOTIATION, (NULL),
- ("format wasn't negotiated before buffer flow on pad %s",
- GST_PAD_NAME (pad->collect.pad)));
- if (buf)
- gst_buffer_unref (buf);
- return GST_FLOW_NOT_NEGOTIATED;
- }
-}
-
-static GstFlowReturn
-gst_qt_mux_collected (GstCollectPads * pads, gpointer user_data)
-{
- GstFlowReturn ret = GST_FLOW_OK;
- GstQTMux *qtmux = GST_QT_MUX_CAST (user_data);
- GSList *walk;
- GstQTPad *best_pad = NULL;
- GstClockTime time, best_time = GST_CLOCK_TIME_NONE;
- GstBuffer *buf;
-
- if (G_UNLIKELY (qtmux->state == GST_QT_MUX_STATE_STARTED)) {
- if ((ret = gst_qt_mux_start_file (qtmux)) != GST_FLOW_OK)
- return ret;
- else
- qtmux->state = GST_QT_MUX_STATE_DATA;
- }
-
- if (G_UNLIKELY (qtmux->state == GST_QT_MUX_STATE_EOS))
- return GST_FLOW_UNEXPECTED;
-
- /* select the best buffer */
- walk = qtmux->collect->data;
- while (walk) {
- GstQTPad *pad;
- GstCollectData *data;
-
- data = (GstCollectData *) walk->data;
- pad = (GstQTPad *) data;
-
- walk = g_slist_next (walk);
-
- buf = gst_collect_pads_peek (pads, data);
- if (buf == NULL) {
- GST_LOG_OBJECT (qtmux, "Pad %s has no buffers",
- GST_PAD_NAME (pad->collect.pad));
- continue;
- }
- time = GST_BUFFER_TIMESTAMP (buf);
- gst_buffer_unref (buf);
-
- /* invalid should pass */
- if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (time))) {
- time =
- gst_segment_to_running_time (&data->segment, GST_FORMAT_TIME, time);
- if (G_UNLIKELY (!GST_CLOCK_TIME_IS_VALID (time))) {
- GST_DEBUG_OBJECT (qtmux, "clipping buffer on pad %s outside segment",
- GST_PAD_NAME (data->pad));
- buf = gst_collect_pads_pop (pads, data);
- gst_buffer_unref (buf);
- return GST_FLOW_OK;
- }
- }
-
- if (best_pad == NULL || !GST_CLOCK_TIME_IS_VALID (time) ||
- (GST_CLOCK_TIME_IS_VALID (best_time) && time < best_time)) {
- best_pad = pad;
- best_time = time;
- }
- }
-
- if (best_pad != NULL) {
- GST_LOG_OBJECT (qtmux, "selected pad %s with time %" GST_TIME_FORMAT,
- GST_PAD_NAME (best_pad->collect.pad), GST_TIME_ARGS (best_time));
- buf = gst_collect_pads_pop (pads, &best_pad->collect);
- buf = gst_buffer_make_metadata_writable (buf);
- GST_BUFFER_TIMESTAMP (buf) = best_time;
- ret = gst_qt_mux_add_buffer (qtmux, best_pad, buf);
- } else {
- ret = gst_qt_mux_stop_file (qtmux);
- if (ret == GST_FLOW_OK) {
- GST_DEBUG_OBJECT (qtmux, "Pushing eos");
- gst_pad_push_event (qtmux->srcpad, gst_event_new_eos ());
- ret = GST_FLOW_UNEXPECTED;
- } else {
- GST_WARNING_OBJECT (qtmux, "Failed to stop file: %s",
- gst_flow_get_name (ret));
- }
- qtmux->state = GST_QT_MUX_STATE_EOS;
- }
-
- return ret;
-}
-
-static gboolean
-check_field (GQuark field_id, const GValue * value, gpointer user_data)
-{
- GstStructure *structure = (GstStructure *) user_data;
- const GValue *other = gst_structure_id_get_value (structure, field_id);
- if (other == NULL)
- return FALSE;
- return gst_value_compare (value, other) == GST_VALUE_EQUAL;
-}
-
-static gboolean
-gst_qtmux_caps_is_subset_full (GstQTMux * qtmux, GstCaps * subset,
- GstCaps * superset)
-{
- GstStructure *sub_s = gst_caps_get_structure (subset, 0);
- GstStructure *sup_s = gst_caps_get_structure (superset, 0);
-
- return gst_structure_foreach (sub_s, check_field, sup_s);
-}
-
-static gboolean
-gst_qt_mux_audio_sink_set_caps (GstPad * pad, GstCaps * caps)
-{
- GstQTMux *qtmux = GST_QT_MUX_CAST (gst_pad_get_parent (pad));
- GstQTMuxClass *qtmux_klass = (GstQTMuxClass *) (G_OBJECT_GET_CLASS (qtmux));
- GstQTPad *qtpad = NULL;
- GstStructure *structure;
- const gchar *mimetype;
- gint rate, channels;
- const GValue *value = NULL;
- const GstBuffer *codec_data = NULL;
- GstQTMuxFormat format;
- AudioSampleEntry entry = { 0, };
- AtomInfo *ext_atom = NULL;
- gint constant_size = 0;
- const gchar *stream_format;
- GstCaps *current_caps = NULL;
-
- /* find stream data */
- qtpad = (GstQTPad *) gst_pad_get_element_private (pad);
- g_assert (qtpad);
-
- qtpad->prepare_buf_func = NULL;
-
- /* does not go well to renegotiate stream mid-way, unless
- * the old caps are a subset of the new one (this means upstream
- * added more info to the caps, as both should be 'fixed' caps) */
- if (qtpad->fourcc) {
- g_object_get (pad, "caps", &current_caps, NULL);
- g_assert (caps != NULL);
-
- if (!gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps)) {
- goto refuse_renegotiation;
- }
- GST_DEBUG_OBJECT (qtmux,
- "pad %s accepted renegotiation to %" GST_PTR_FORMAT " from %"
- GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, GST_PAD_CAPS (pad));
- }
-
- GST_DEBUG_OBJECT (qtmux, "%s:%s, caps=%" GST_PTR_FORMAT,
- GST_DEBUG_PAD_NAME (pad), caps);
-
- format = qtmux_klass->format;
- structure = gst_caps_get_structure (caps, 0);
- mimetype = gst_structure_get_name (structure);
-
- /* common info */
- if (!gst_structure_get_int (structure, "channels", &channels) ||
- !gst_structure_get_int (structure, "rate", &rate)) {
- goto refuse_caps;
- }
-
- /* optional */
- value = gst_structure_get_value (structure, "codec_data");
- if (value != NULL)
- codec_data = gst_value_get_buffer (value);
-
- qtpad->is_out_of_order = FALSE;
- qtpad->have_dts = FALSE;
-
- /* set common properties */
- entry.sample_rate = rate;
- entry.channels = channels;
- /* default */
- entry.sample_size = 16;
- /* this is the typical compressed case */
- if (format == GST_QT_MUX_FORMAT_QT) {
- entry.version = 1;
- entry.compression_id = -2;
- }
-
- /* now map onto a fourcc, and some extra properties */
- if (strcmp (mimetype, "audio/mpeg") == 0) {
- gint mpegversion = 0;
- gint layer = -1;
-
- gst_structure_get_int (structure, "mpegversion", &mpegversion);
- switch (mpegversion) {
- case 1:
- gst_structure_get_int (structure, "layer", &layer);
- switch (layer) {
- case 3:
- /* mp3 */
- /* note: QuickTime player does not like mp3 either way in iso/mp4 */
- if (format == GST_QT_MUX_FORMAT_QT)
- entry.fourcc = FOURCC__mp3;
- else {
- entry.fourcc = FOURCC_mp4a;
- ext_atom =
- build_esds_extension (qtpad->trak, ESDS_OBJECT_TYPE_MPEG1_P3,
- ESDS_STREAM_TYPE_AUDIO, codec_data, qtpad->avg_bitrate,
- qtpad->max_bitrate);
- }
- entry.samples_per_packet = 1152;
- entry.bytes_per_sample = 2;
- break;
- }
- break;
- case 4:
-
- /* check stream-format */
- stream_format = gst_structure_get_string (structure, "stream-format");
- if (stream_format) {
- if (strcmp (stream_format, "raw") != 0) {
- GST_WARNING_OBJECT (qtmux, "Unsupported AAC stream-format %s, "
- "please use 'raw'", stream_format);
- goto refuse_caps;
- }
- } else {
- GST_WARNING_OBJECT (qtmux, "No stream-format present in caps, "
- "assuming 'raw'");
- }
-
- if (!codec_data || GST_BUFFER_SIZE (codec_data) < 2)
- GST_WARNING_OBJECT (qtmux, "no (valid) codec_data for AAC audio");
- else {
- guint8 profile = GST_READ_UINT8 (GST_BUFFER_DATA (codec_data));
-
- /* warn if not Low Complexity profile */
- profile >>= 3;
- if (profile != 2)
- GST_WARNING_OBJECT (qtmux,
- "non-LC AAC may not run well on (Apple) QuickTime/iTunes");
- }
-
- /* AAC */
- entry.fourcc = FOURCC_mp4a;
-
- if (format == GST_QT_MUX_FORMAT_QT)
- ext_atom = build_mov_aac_extension (qtpad->trak, codec_data,
- qtpad->avg_bitrate, qtpad->max_bitrate);
- else
- ext_atom =
- build_esds_extension (qtpad->trak, ESDS_OBJECT_TYPE_MPEG4_P3,
- ESDS_STREAM_TYPE_AUDIO, codec_data, qtpad->avg_bitrate,
- qtpad->max_bitrate);
- break;
- default:
- break;
- }
- } else if (strcmp (mimetype, "audio/AMR") == 0) {
- entry.fourcc = FOURCC_samr;
- entry.sample_size = 16;
- entry.samples_per_packet = 160;
- entry.bytes_per_sample = 2;
- ext_atom = build_amr_extension ();
- } else if (strcmp (mimetype, "audio/AMR-WB") == 0) {
- entry.fourcc = FOURCC_sawb;
- entry.sample_size = 16;
- entry.samples_per_packet = 320;
- entry.bytes_per_sample = 2;
- ext_atom = build_amr_extension ();
- } else if (strcmp (mimetype, "audio/x-raw-int") == 0) {
- gint width;
- gint depth;
- gint endianness;
- gboolean sign;
-
- if (!gst_structure_get_int (structure, "width", &width) ||
- !gst_structure_get_int (structure, "depth", &depth) ||
- !gst_structure_get_boolean (structure, "signed", &sign)) {
- GST_DEBUG_OBJECT (qtmux, "broken caps, width/depth/signed field missing");
- goto refuse_caps;
- }
-
- if (depth <= 8) {
- endianness = G_BYTE_ORDER;
- } else if (!gst_structure_get_int (structure, "endianness", &endianness)) {
- GST_DEBUG_OBJECT (qtmux, "broken caps, endianness field missing");
- goto refuse_caps;
- }
-
- /* spec has no place for a distinction in these */
- if (width != depth) {
- GST_DEBUG_OBJECT (qtmux, "width must be same as depth!");
- goto refuse_caps;
- }
-
- if (sign) {
- if (endianness == G_LITTLE_ENDIAN)
- entry.fourcc = FOURCC_sowt;
- else if (endianness == G_BIG_ENDIAN)
- entry.fourcc = FOURCC_twos;
- /* maximum backward compatibility; only new version for > 16 bit */
- if (depth <= 16)
- entry.version = 0;
- /* not compressed in any case */
- entry.compression_id = 0;
- /* QT spec says: max at 16 bit even if sample size were actually larger,
- * however, most players (e.g. QuickTime!) seem to disagree, so ... */
- entry.sample_size = depth;
- entry.bytes_per_sample = depth / 8;
- entry.samples_per_packet = 1;
- entry.bytes_per_packet = depth / 8;
- entry.bytes_per_frame = entry.bytes_per_packet * channels;
- } else {
- if (width == 8 && depth == 8) {
- /* fall back to old 8-bit version */
- entry.fourcc = FOURCC_raw_;
- entry.version = 0;
- entry.compression_id = 0;
- entry.sample_size = 8;
- } else {
- GST_DEBUG_OBJECT (qtmux, "non 8-bit PCM must be signed");
- goto refuse_caps;
- }
- }
- constant_size = (depth / 8) * channels;
- } else if (strcmp (mimetype, "audio/x-alaw") == 0) {
- entry.fourcc = FOURCC_alaw;
- entry.samples_per_packet = 1023;
- entry.bytes_per_sample = 2;
- } else if (strcmp (mimetype, "audio/x-mulaw") == 0) {
- entry.fourcc = FOURCC_ulaw;
- entry.samples_per_packet = 1023;
- entry.bytes_per_sample = 2;
- } else if (strcmp (mimetype, "audio/x-adpcm") == 0) {
- gint blocksize;
- if (!gst_structure_get_int (structure, "block_align", &blocksize)) {
- GST_DEBUG_OBJECT (qtmux, "broken caps, block_align missing");
- goto refuse_caps;
- }
- /* Currently only supports WAV-style IMA ADPCM, for which the codec id is
- 0x11 */
- entry.fourcc = MS_WAVE_FOURCC (0x11);
- /* 4 byte header per channel (including one sample). 2 samples per byte
- remaining. Simplifying gives the following (samples per block per
- channel) */
- entry.samples_per_packet = 2 * blocksize / channels - 7;
- entry.bytes_per_sample = 2;
-
- entry.bytes_per_frame = blocksize;
- entry.bytes_per_packet = blocksize / channels;
- /* ADPCM has constant size packets */
- constant_size = 1;
- /* TODO: I don't really understand why this helps, but it does! Constant
- * size and compression_id of -2 seem to be incompatible, and other files
- * in the wild use this too. */
- entry.compression_id = -1;
-
- ext_atom = build_ima_adpcm_extension (channels, rate, blocksize);
- } else if (strcmp (mimetype, "audio/x-alac") == 0) {
- GstBuffer *codec_config;
- gint len;
-
- entry.fourcc = FOURCC_alac;
- /* let's check if codec data already comes with 'alac' atom prefix */
- if (!codec_data || (len = GST_BUFFER_SIZE (codec_data)) < 28) {
- GST_DEBUG_OBJECT (qtmux, "broken caps, codec data missing");
- goto refuse_caps;
- }
- if (GST_READ_UINT32_LE (GST_BUFFER_DATA (codec_data) + 4) == FOURCC_alac) {
- len -= 8;
- codec_config = gst_buffer_create_sub ((GstBuffer *) codec_data, 8, len);
- } else {
- codec_config = gst_buffer_ref ((GstBuffer *) codec_data);
- }
- if (len != 28) {
- /* does not look good, but perhaps some trailing unneeded stuff */
- GST_WARNING_OBJECT (qtmux, "unexpected codec-data size, possibly broken");
- }
- if (format == GST_QT_MUX_FORMAT_QT)
- ext_atom = build_mov_alac_extension (qtpad->trak, codec_config);
- else
- ext_atom = build_codec_data_extension (FOURCC_alac, codec_config);
- /* set some more info */
- entry.bytes_per_sample = 2;
- entry.samples_per_packet =
- GST_READ_UINT32_BE (GST_BUFFER_DATA (codec_config) + 4);
- gst_buffer_unref (codec_config);
- }
-
- if (!entry.fourcc)
- goto refuse_caps;
-
- /* ok, set the pad info accordingly */
- qtpad->fourcc = entry.fourcc;
- qtpad->sample_size = constant_size;
- atom_trak_set_audio_type (qtpad->trak, qtmux->context, &entry,
- qtmux->trak_timescale ? qtmux->trak_timescale : entry.sample_rate,
- ext_atom, constant_size);
-
- gst_object_unref (qtmux);
- return TRUE;
-
- /* ERRORS */
-refuse_caps:
- {
- GST_WARNING_OBJECT (qtmux, "pad %s refused caps %" GST_PTR_FORMAT,
- GST_PAD_NAME (pad), caps);
- gst_object_unref (qtmux);
- return FALSE;
- }
-refuse_renegotiation:
- {
- GST_WARNING_OBJECT (qtmux,
- "pad %s refused renegotiation to %" GST_PTR_FORMAT,
- GST_PAD_NAME (pad), caps);
- gst_object_unref (qtmux);
- return FALSE;
- }
-}
-
-/* scale rate up or down by factor of 10 to fit into [1000,10000] interval */
-static guint32
-adjust_rate (guint64 rate)
-{
- if (rate == 0)
- return 10000;
-
- while (rate >= 10000)
- rate /= 10;
-
- while (rate < 1000)
- rate *= 10;
-
- return (guint32) rate;
-}
-
-static gboolean
-gst_qt_mux_video_sink_set_caps (GstPad * pad, GstCaps * caps)
-{
- GstQTMux *qtmux = GST_QT_MUX_CAST (gst_pad_get_parent (pad));
- GstQTMuxClass *qtmux_klass = (GstQTMuxClass *) (G_OBJECT_GET_CLASS (qtmux));
- GstQTPad *qtpad = NULL;
- GstStructure *structure;
- const gchar *mimetype;
- gint width, height, depth = -1;
- gint framerate_num, framerate_den;
- guint32 rate;
- const GValue *value = NULL;
- const GstBuffer *codec_data = NULL;
- VisualSampleEntry entry = { 0, };
- GstQTMuxFormat format;
- AtomInfo *ext_atom = NULL;
- GList *ext_atom_list = NULL;
- gboolean sync = FALSE;
- int par_num, par_den;
- GstCaps *current_caps = NULL;
-
- /* find stream data */
- qtpad = (GstQTPad *) gst_pad_get_element_private (pad);
- g_assert (qtpad);
-
- qtpad->prepare_buf_func = NULL;
-
- /* does not go well to renegotiate stream mid-way, unless
- * the old caps are a subset of the new one (this means upstream
- * added more info to the caps, as both should be 'fixed' caps) */
- if (qtpad->fourcc) {
- g_object_get (pad, "caps", &current_caps, NULL);
- g_assert (caps != NULL);
-
- if (!gst_qtmux_caps_is_subset_full (qtmux, current_caps, caps)) {
- goto refuse_renegotiation;
- }
- GST_DEBUG_OBJECT (qtmux,
- "pad %s accepted renegotiation to %" GST_PTR_FORMAT " from %"
- GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, GST_PAD_CAPS (pad));
- }
-
- GST_DEBUG_OBJECT (qtmux, "%s:%s, caps=%" GST_PTR_FORMAT,
- GST_DEBUG_PAD_NAME (pad), caps);
-
- format = qtmux_klass->format;
- structure = gst_caps_get_structure (caps, 0);
- mimetype = gst_structure_get_name (structure);
-
- /* required parts */
- if (!gst_structure_get_int (structure, "width", &width) ||
- !gst_structure_get_int (structure, "height", &height))
- goto refuse_caps;
-
- /* optional */
- depth = -1;
- /* works as a default timebase */
- framerate_num = 10000;
- framerate_den = 1;
- gst_structure_get_fraction (structure, "framerate", &framerate_num,
- &framerate_den);
- gst_structure_get_int (structure, "depth", &depth);
- value = gst_structure_get_value (structure, "codec_data");
- if (value != NULL)
- codec_data = gst_value_get_buffer (value);
-
- par_num = 1;
- par_den = 1;
- gst_structure_get_fraction (structure, "pixel-aspect-ratio", &par_num,
- &par_den);
-
- qtpad->is_out_of_order = FALSE;
-
- /* bring frame numerator into a range that ensures both reasonable resolution
- * as well as a fair duration */
- rate = qtmux->trak_timescale ?
- qtmux->trak_timescale : adjust_rate (framerate_num);
- GST_DEBUG_OBJECT (qtmux, "Rate of video track selected: %" G_GUINT32_FORMAT,
- rate);
-
- /* set common properties */
- entry.width = width;
- entry.height = height;
- entry.par_n = par_num;
- entry.par_d = par_den;
- /* should be OK according to qt and iso spec, override if really needed */
- entry.color_table_id = -1;
- entry.frame_count = 1;
- entry.depth = 24;
-
- /* sync entries by default */
- sync = TRUE;
-
- /* now map onto a fourcc, and some extra properties */
- if (strcmp (mimetype, "video/x-raw-rgb") == 0) {
- gint bpp;
-
- entry.fourcc = FOURCC_raw_;
- gst_structure_get_int (structure, "bpp", &bpp);
- entry.depth = bpp;
- sync = FALSE;
- } else if (strcmp (mimetype, "video/x-raw-yuv") == 0) {
- guint32 format = 0;
-
- sync = FALSE;
- gst_structure_get_fourcc (structure, "format", &format);
- switch (format) {
- case GST_MAKE_FOURCC ('U', 'Y', 'V', 'Y'):
- if (depth == -1)
- depth = 24;
- entry.fourcc = FOURCC_2vuy;
- entry.depth = depth;
- break;
- }
- } else if (strcmp (mimetype, "video/x-h263") == 0) {
- ext_atom = NULL;
- if (format == GST_QT_MUX_FORMAT_QT)
- entry.fourcc = FOURCC_h263;
- else
- entry.fourcc = FOURCC_s263;
- ext_atom = build_h263_extension ();
- if (ext_atom != NULL)
- ext_atom_list = g_list_prepend (ext_atom_list, ext_atom);
- } else if (strcmp (mimetype, "video/x-divx") == 0 ||
- strcmp (mimetype, "video/mpeg") == 0) {
- gint version = 0;
-
- if (strcmp (mimetype, "video/x-divx") == 0) {
- gst_structure_get_int (structure, "divxversion", &version);
- version = version == 5 ? 1 : 0;
- } else {
- gst_structure_get_int (structure, "mpegversion", &version);
- version = version == 4 ? 1 : 0;
- }
- if (version) {
- entry.fourcc = FOURCC_mp4v;
- ext_atom =
- build_esds_extension (qtpad->trak, ESDS_OBJECT_TYPE_MPEG4_P2,
- ESDS_STREAM_TYPE_VISUAL, codec_data, qtpad->avg_bitrate,
- qtpad->max_bitrate);
- if (ext_atom != NULL)
- ext_atom_list = g_list_prepend (ext_atom_list, ext_atom);
- if (!codec_data)
- GST_WARNING_OBJECT (qtmux, "no codec_data for MPEG4 video; "
- "output might not play in Apple QuickTime (try global-headers?)");
- }
- } else if (strcmp (mimetype, "video/x-h264") == 0) {
- entry.fourcc = FOURCC_avc1;
- if (qtpad->avg_bitrate == 0) {
- gint avg_bitrate = 0;
- gst_structure_get_int (structure, "bitrate", &avg_bitrate);
- qtpad->avg_bitrate = avg_bitrate;
- }
- ext_atom = build_btrt_extension (0, qtpad->avg_bitrate, qtpad->max_bitrate);
- if (ext_atom != NULL)
- ext_atom_list = g_list_prepend (ext_atom_list, ext_atom);
- if (!codec_data)
- GST_WARNING_OBJECT (qtmux, "no codec_data in h264 caps");
- ext_atom = build_codec_data_extension (FOURCC_avcC, codec_data);
- if (ext_atom != NULL)
- ext_atom_list = g_list_prepend (ext_atom_list, ext_atom);
- } else if (strcmp (mimetype, "video/x-svq") == 0) {
- gint version = 0;
- const GstBuffer *seqh = NULL;
- const GValue *seqh_value;
- gdouble gamma = 0;
-
- gst_structure_get_int (structure, "svqversion", &version);
- if (version == 3) {
- entry.fourcc = FOURCC_SVQ3;
- entry.version = 3;
- entry.depth = 32;
-
- seqh_value = gst_structure_get_value (structure, "seqh");
- if (seqh_value) {
- seqh = gst_value_get_buffer (seqh_value);
- ext_atom = build_SMI_atom (seqh);
- if (ext_atom)
- ext_atom_list = g_list_prepend (ext_atom_list, ext_atom);
- }
-
- /* we need to add the gamma anyway because quicktime might crash
- * when it doesn't find it */
- if (!gst_structure_get_double (structure, "applied-gamma", &gamma)) {
- /* it seems that using 0 here makes it ignored */
- gamma = 0.0;
- }
- ext_atom = build_gama_atom (gamma);
- if (ext_atom)
- ext_atom_list = g_list_prepend (ext_atom_list, ext_atom);
- } else {
- GST_WARNING_OBJECT (qtmux, "SVQ version %d not supported. Please file "
- "a bug at http://bugzilla.gnome.org", version);
- }
- } else if (strcmp (mimetype, "video/x-dv") == 0) {
- gint version = 0;
- gboolean pal = TRUE;
-
- sync = FALSE;
- if (framerate_num != 25 || framerate_den != 1)
- pal = FALSE;
- gst_structure_get_int (structure, "dvversion", &version);
- /* fall back to typical one */
- if (!version)
- version = 25;
- switch (version) {
- case 25:
- if (pal)
- entry.fourcc = GST_MAKE_FOURCC ('d', 'v', 'c', 'p');
- else
- entry.fourcc = GST_MAKE_FOURCC ('d', 'v', 'c', ' ');
- break;
- case 50:
- if (pal)
- entry.fourcc = GST_MAKE_FOURCC ('d', 'v', '5', 'p');
- else
- entry.fourcc = GST_MAKE_FOURCC ('d', 'v', '5', 'n');
- break;
- default:
- GST_WARNING_OBJECT (qtmux, "unrecognized dv version");
- break;
- }
- } else if (strcmp (mimetype, "image/jpeg") == 0) {
- entry.fourcc = FOURCC_jpeg;
- sync = FALSE;
- } else if (strcmp (mimetype, "image/x-j2c") == 0 ||
- strcmp (mimetype, "image/x-jpc") == 0) {
- guint32 fourcc;
- const GValue *cmap_array;
- const GValue *cdef_array;
- gint ncomp = 0;
- gint fields = 1;
-
- if (strcmp (mimetype, "image/x-jpc") == 0) {
- qtpad->prepare_buf_func = gst_qt_mux_prepare_jpc_buffer;
- }
-
- gst_structure_get_int (structure, "num-components", &ncomp);
- gst_structure_get_int (structure, "fields", &fields);
- cmap_array = gst_structure_get_value (structure, "component-map");
- cdef_array = gst_structure_get_value (structure, "channel-definitions");
-
- ext_atom = NULL;
- entry.fourcc = FOURCC_mjp2;
- sync = FALSE;
- if (gst_structure_get_fourcc (structure, "fourcc", &fourcc) &&
- (ext_atom =
- build_jp2h_extension (qtpad->trak, width, height, fourcc, ncomp,
- cmap_array, cdef_array)) != NULL) {
- ext_atom_list = g_list_append (ext_atom_list, ext_atom);
-
- ext_atom = build_fiel_extension (fields);
- if (ext_atom)
- ext_atom_list = g_list_append (ext_atom_list, ext_atom);
-
- ext_atom = build_jp2x_extension (codec_data);
- if (ext_atom)
- ext_atom_list = g_list_append (ext_atom_list, ext_atom);
- } else {
- GST_DEBUG_OBJECT (qtmux, "missing or invalid fourcc in jp2 caps");
- goto refuse_caps;
- }
- } else if (strcmp (mimetype, "video/x-vp8") == 0) {
- entry.fourcc = FOURCC_VP80;
- sync = FALSE;
- } else if (strcmp (mimetype, "video/x-qt-part") == 0) {
- guint32 fourcc;
-
- gst_structure_get_fourcc (structure, "format", &fourcc);
- entry.fourcc = fourcc;
- qtpad->have_dts = TRUE;
- } else if (strcmp (mimetype, "video/x-mp4-part") == 0) {
- guint32 fourcc;
-
- gst_structure_get_fourcc (structure, "format", &fourcc);
- entry.fourcc = fourcc;
- qtpad->have_dts = TRUE;
- }
-
- if (!entry.fourcc)
- goto refuse_caps;
-
- /* ok, set the pad info accordingly */
- qtpad->fourcc = entry.fourcc;
- qtpad->sync = sync;
- atom_trak_set_video_type (qtpad->trak, qtmux->context, &entry, rate,
- ext_atom_list);
-
- gst_object_unref (qtmux);
- return TRUE;
-
- /* ERRORS */
-refuse_caps:
- {
- GST_WARNING_OBJECT (qtmux, "pad %s refused caps %" GST_PTR_FORMAT,
- GST_PAD_NAME (pad), caps);
- gst_object_unref (qtmux);
- return FALSE;
- }
-refuse_renegotiation:
- {
- GST_WARNING_OBJECT (qtmux,
- "pad %s refused renegotiation to %" GST_PTR_FORMAT " from %"
- GST_PTR_FORMAT, GST_PAD_NAME (pad), caps, GST_PAD_CAPS (pad));
- gst_object_unref (qtmux);
- return FALSE;
- }
-}
-
-static gboolean
-gst_qt_mux_sink_event (GstPad * pad, GstEvent * event)
-{
- gboolean ret;
- GstQTMux *qtmux;
- guint32 avg_bitrate = 0, max_bitrate = 0;
-
- qtmux = GST_QT_MUX_CAST (gst_pad_get_parent (pad));
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_TAG:{
- GstTagList *list;
- GstTagSetter *setter = GST_TAG_SETTER (qtmux);
- GstTagMergeMode mode;
-
- GST_OBJECT_LOCK (qtmux);
- mode = gst_tag_setter_get_tag_merge_mode (setter);
-
- GST_DEBUG_OBJECT (qtmux, "received tag event");
- gst_event_parse_tag (event, &list);
-
- gst_tag_setter_merge_tags (setter, list, mode);
- GST_OBJECT_UNLOCK (qtmux);
-
- if (gst_tag_list_get_uint (list, GST_TAG_BITRATE, &avg_bitrate) |
- gst_tag_list_get_uint (list, GST_TAG_MAXIMUM_BITRATE, &max_bitrate)) {
- GstQTPad *qtpad = gst_pad_get_element_private (pad);
- g_assert (qtpad);
-
- if (avg_bitrate > 0 && avg_bitrate < G_MAXUINT32)
- qtpad->avg_bitrate = avg_bitrate;
- if (max_bitrate > 0 && max_bitrate < G_MAXUINT32)
- qtpad->max_bitrate = max_bitrate;
- }
-
- break;
- }
- default:
- break;
- }
-
- ret = qtmux->collect_event (pad, event);
- gst_object_unref (qtmux);
-
- return ret;
-}
-
-static void
-gst_qt_mux_release_pad (GstElement * element, GstPad * pad)
-{
- GstQTMux *mux = GST_QT_MUX_CAST (element);
- GSList *walk;
-
- GST_DEBUG_OBJECT (element, "Releasing %s:%s", GST_DEBUG_PAD_NAME (pad));
-
- for (walk = mux->sinkpads; walk; walk = g_slist_next (walk)) {
- GstQTPad *qtpad = (GstQTPad *) walk->data;
- GST_DEBUG ("Checking %s:%s", GST_DEBUG_PAD_NAME (qtpad->collect.pad));
- if (qtpad->collect.pad == pad) {
- /* this is it, remove */
- mux->sinkpads = g_slist_delete_link (mux->sinkpads, walk);
- gst_element_remove_pad (element, pad);
- break;
- }
- }
-
- gst_collect_pads_remove_pad (mux->collect, pad);
-}
-
-static GstPad *
-gst_qt_mux_request_new_pad (GstElement * element,
- GstPadTemplate * templ, const gchar * req_name)
-{
- GstElementClass *klass = GST_ELEMENT_GET_CLASS (element);
- GstQTMux *qtmux = GST_QT_MUX_CAST (element);
- GstQTPad *collect_pad;
- GstPad *newpad;
- gboolean audio;
- gchar *name;
-
- if (templ->direction != GST_PAD_SINK)
- goto wrong_direction;
-
- if (qtmux->state > GST_QT_MUX_STATE_STARTED)
- goto too_late;
-
- if (templ == gst_element_class_get_pad_template (klass, "audio_%d")) {
- audio = TRUE;
- name = g_strdup_printf ("audio_%02d", qtmux->audio_pads++);
- } else if (templ == gst_element_class_get_pad_template (klass, "video_%d")) {
- audio = FALSE;
- name = g_strdup_printf ("video_%02d", qtmux->video_pads++);
- } else
- goto wrong_template;
-
- GST_DEBUG_OBJECT (qtmux, "Requested pad: %s", name);
-
- /* create pad and add to collections */
- newpad = gst_pad_new_from_template (templ, name);
- g_free (name);
- collect_pad = (GstQTPad *)
- gst_collect_pads_add_pad_full (qtmux->collect, newpad, sizeof (GstQTPad),
- (GstCollectDataDestroyNotify) (gst_qt_mux_pad_reset));
- /* set up pad */
- gst_qt_mux_pad_reset (collect_pad);
- collect_pad->trak = atom_trak_new (qtmux->context);
- atom_moov_add_trak (qtmux->moov, collect_pad->trak);
-
- qtmux->sinkpads = g_slist_append (qtmux->sinkpads, collect_pad);
-
- /* set up pad functions */
- if (audio)
- gst_pad_set_setcaps_function (newpad,
- GST_DEBUG_FUNCPTR (gst_qt_mux_audio_sink_set_caps));
- else
- gst_pad_set_setcaps_function (newpad,
- GST_DEBUG_FUNCPTR (gst_qt_mux_video_sink_set_caps));
-
- /* FIXME: hacked way to override/extend the event function of
- * GstCollectPads; because it sets its own event function giving the
- * element no access to events.
- */
- qtmux->collect_event = (GstPadEventFunction) GST_PAD_EVENTFUNC (newpad);
- gst_pad_set_event_function (newpad,
- GST_DEBUG_FUNCPTR (gst_qt_mux_sink_event));
-
- gst_pad_set_active (newpad, TRUE);
- gst_element_add_pad (element, newpad);
-
- return newpad;
-
- /* ERRORS */
-wrong_direction:
- {
- GST_WARNING_OBJECT (qtmux, "Request pad that is not a SINK pad.");
- return NULL;
- }
-too_late:
- {
- GST_WARNING_OBJECT (qtmux, "Not providing request pad after stream start.");
- return NULL;
- }
-wrong_template:
- {
- GST_WARNING_OBJECT (qtmux, "This is not our template!");
- return NULL;
- }
-}
-
-static void
-gst_qt_mux_get_property (GObject * object,
- guint prop_id, GValue * value, GParamSpec * pspec)
-{
- GstQTMux *qtmux = GST_QT_MUX_CAST (object);
-
- GST_OBJECT_LOCK (qtmux);
- switch (prop_id) {
- case PROP_MOVIE_TIMESCALE:
- g_value_set_uint (value, qtmux->timescale);
- break;
- case PROP_TRAK_TIMESCALE:
- g_value_set_uint (value, qtmux->trak_timescale);
- break;
- case PROP_DO_CTTS:
- g_value_set_boolean (value, qtmux->guess_pts);
- break;
- case PROP_DTS_METHOD:
- g_value_set_enum (value, qtmux->dts_method);
- break;
- case PROP_FAST_START:
- g_value_set_boolean (value, qtmux->fast_start);
- break;
- case PROP_FAST_START_TEMP_FILE:
- g_value_set_string (value, qtmux->fast_start_file_path);
- break;
- case PROP_MOOV_RECOV_FILE:
- g_value_set_string (value, qtmux->moov_recov_file_path);
- break;
- case PROP_FRAGMENT_DURATION:
- g_value_set_uint (value, qtmux->fragment_duration);
- break;
- case PROP_STREAMABLE:
- g_value_set_boolean (value, qtmux->streamable);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
- GST_OBJECT_UNLOCK (qtmux);
-}
-
-static void
-gst_qt_mux_generate_fast_start_file_path (GstQTMux * qtmux)
-{
- gchar *tmp;
-
- g_free (qtmux->fast_start_file_path);
- qtmux->fast_start_file_path = NULL;
-
- tmp = g_strdup_printf ("%s%d", "qtmux", g_random_int ());
- qtmux->fast_start_file_path = g_build_filename (g_get_tmp_dir (), tmp, NULL);
- g_free (tmp);
-}
-
-static void
-gst_qt_mux_set_property (GObject * object,
- guint prop_id, const GValue * value, GParamSpec * pspec)
-{
- GstQTMux *qtmux = GST_QT_MUX_CAST (object);
-
- GST_OBJECT_LOCK (qtmux);
- switch (prop_id) {
- case PROP_MOVIE_TIMESCALE:
- qtmux->timescale = g_value_get_uint (value);
- break;
- case PROP_TRAK_TIMESCALE:
- qtmux->trak_timescale = g_value_get_uint (value);
- break;
- case PROP_DO_CTTS:
- qtmux->guess_pts = g_value_get_boolean (value);
- break;
- case PROP_DTS_METHOD:
- qtmux->dts_method = g_value_get_enum (value);
- break;
- case PROP_FAST_START:
- qtmux->fast_start = g_value_get_boolean (value);
- break;
- case PROP_FAST_START_TEMP_FILE:
- g_free (qtmux->fast_start_file_path);
- qtmux->fast_start_file_path = g_value_dup_string (value);
- /* NULL means to generate a random one */
- if (!qtmux->fast_start_file_path) {
- gst_qt_mux_generate_fast_start_file_path (qtmux);
- }
- break;
- case PROP_MOOV_RECOV_FILE:
- g_free (qtmux->moov_recov_file_path);
- qtmux->moov_recov_file_path = g_value_dup_string (value);
- break;
- case PROP_FRAGMENT_DURATION:
- qtmux->fragment_duration = g_value_get_uint (value);
- break;
- case PROP_STREAMABLE:
- qtmux->streamable = g_value_get_boolean (value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
- break;
- }
- GST_OBJECT_UNLOCK (qtmux);
-}
-
-static GstStateChangeReturn
-gst_qt_mux_change_state (GstElement * element, GstStateChange transition)
-{
- GstStateChangeReturn ret;
- GstQTMux *qtmux = GST_QT_MUX_CAST (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- gst_collect_pads_start (qtmux->collect);
- qtmux->state = GST_QT_MUX_STATE_STARTED;
- break;
- case GST_STATE_CHANGE_PAUSED_TO_PLAYING:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_collect_pads_stop (qtmux->collect);
- break;
- default:
- break;
- }
-
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PLAYING_TO_PAUSED:
- break;
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_qt_mux_reset (qtmux, TRUE);
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- break;
- default:
- break;
- }
-
- return ret;
-}
-
-gboolean
-gst_qt_mux_register (GstPlugin * plugin)
-{
- GTypeInfo typeinfo = {
- sizeof (GstQTMuxClass),
- (GBaseInitFunc) gst_qt_mux_base_init,
- NULL,
- (GClassInitFunc) gst_qt_mux_class_init,
- NULL,
- NULL,
- sizeof (GstQTMux),
- 0,
- (GInstanceInitFunc) gst_qt_mux_init,
- };
- static const GInterfaceInfo tag_setter_info = {
- NULL, NULL, NULL
- };
- static const GInterfaceInfo tag_xmp_writer_info = {
- NULL, NULL, NULL
- };
- GType type;
- GstQTMuxFormat format;
- GstQTMuxClassParams *params;
- guint i = 0;
-
- GST_DEBUG_CATEGORY_INIT (gst_qt_mux_debug, "qtmux", 0, "QT Muxer");
-
- GST_LOG ("Registering muxers");
-
- while (TRUE) {
- GstQTMuxFormatProp *prop;
-
- prop = &gst_qt_mux_format_list[i];
- format = prop->format;
- if (format == GST_QT_MUX_FORMAT_NONE)
- break;
-
- /* create a cache for these properties */
- params = g_new0 (GstQTMuxClassParams, 1);
- params->prop = prop;
- params->src_caps = gst_static_caps_get (&prop->src_caps);
- params->video_sink_caps = gst_static_caps_get (&prop->video_sink_caps);
- params->audio_sink_caps = gst_static_caps_get (&prop->audio_sink_caps);
-
- /* create the type now */
- type = g_type_register_static (GST_TYPE_ELEMENT, prop->type_name, &typeinfo,
- 0);
- g_type_set_qdata (type, GST_QT_MUX_PARAMS_QDATA, (gpointer) params);
- g_type_add_interface_static (type, GST_TYPE_TAG_SETTER, &tag_setter_info);
- g_type_add_interface_static (type, GST_TYPE_TAG_XMP_WRITER,
- &tag_xmp_writer_info);
-
- if (!gst_element_register (plugin, prop->name, GST_RANK_PRIMARY, type))
- return FALSE;
-
- i++;
- }
-
- GST_LOG ("Finished registering muxers");
-
- /* FIXME: ideally classification tag should be added and
- registered in gstreamer core gsttaglist
- */
-
- GST_LOG ("Registering tags");
-
- gst_tag_register (GST_TAG_3GP_CLASSIFICATION, GST_TAG_FLAG_META,
- G_TYPE_STRING, GST_TAG_3GP_CLASSIFICATION, "content classification",
- gst_tag_merge_use_first);
-
- GST_LOG ("Finished registering tags");
-
- return TRUE;
-}
diff --git a/gst/qtmux/gstqtmux.h b/gst/qtmux/gstqtmux.h
deleted file mode 100644
index 3a2cb492f..000000000
--- a/gst/qtmux/gstqtmux.h
+++ /dev/null
@@ -1,228 +0,0 @@
-/* Quicktime muxer plugin for GStreamer
- * Copyright (C) 2008-2010 Thiago Santos <thiagoss@embedded.ufcg.edu.br>
- *
- * 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.
- */
-/*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __GST_QT_MUX_H__
-#define __GST_QT_MUX_H__
-
-#include <gst/gst.h>
-#include <gst/base/gstcollectpads.h>
-
-#include "fourcc.h"
-#include "atoms.h"
-#include "atomsrecovery.h"
-#include "gstqtmuxmap.h"
-
-G_BEGIN_DECLS
-
-#define GST_TYPE_QT_MUX (gst_qt_mux_get_type())
-#define GST_QT_MUX(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_QT_MUX, GstQTMux))
-#define GST_QT_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_QT_MUX, GstQTMux))
-#define GST_IS_QT_MUX(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_QT_MUX))
-#define GST_IS_QT_MUX_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_QT_MUX))
-#define GST_QT_MUX_CAST(obj) ((GstQTMux*)(obj))
-
-
-typedef struct _GstQTMux GstQTMux;
-typedef struct _GstQTMuxClass GstQTMuxClass;
-typedef struct _GstQTPad GstQTPad;
-
-/*
- * GstQTPadPrepareBufferFunc
- *
- * Receives a buffer (takes ref) and returns a new buffer that should
- * replace the passed one.
- *
- * Useful for when the pad/datatype needs some manipulation before
- * being muxed. (Originally added for image/x-jpc support, for which buffers
- * need to be wrapped into a isom box)
- */
-typedef GstBuffer * (*GstQTPadPrepareBufferFunc) (GstQTPad * pad,
- GstBuffer * buf, GstQTMux * qtmux);
-
-#define QTMUX_NO_OF_TS 10
-
-struct _GstQTPad
-{
- GstCollectData collect; /* we extend the CollectData */
-
- /* fourcc id of stream */
- guint32 fourcc;
- /* whether using format that have out of order buffers */
- gboolean is_out_of_order;
- /* whether upstream provides valid PTS data */
- gboolean have_dts;
- /* if not 0, track with constant sized samples, e.g. raw audio */
- guint sample_size;
- /* make sync table entry */
- gboolean sync;
- /* bitrates */
- guint32 avg_bitrate, max_bitrate;
-
- GstBuffer *last_buf;
- /* dts of last_buf */
- GstClockTime last_dts;
-
- /* store the first timestamp for comparing with other streams and
- * know if there are late streams */
- GstClockTime first_ts;
- GstClockTime ts_entries[QTMUX_NO_OF_TS + 2];
- guint ts_n_entries;
- GstBuffer *buf_entries[QTMUX_NO_OF_TS + 2];
- guint buf_head;
- guint buf_tail;
-
- /* all the atom and chunk book-keeping is delegated here
- * unowned/uncounted reference, parent MOOV owns */
- AtomTRAK *trak;
- /* fragmented support */
- /* meta data book-keeping delegated here */
- AtomTRAF *traf;
- /* fragment buffers */
- ATOM_ARRAY (GstBuffer *) fragment_buffers;
- /* running fragment duration */
- gint64 fragment_duration;
- /* optional fragment index book-keeping */
- AtomTFRA *tfra;
-
- /* if nothing is set, it won't be called */
- GstQTPadPrepareBufferFunc prepare_buf_func;
-};
-
-typedef enum _GstQTMuxState
-{
- GST_QT_MUX_STATE_NONE,
- GST_QT_MUX_STATE_STARTED,
- GST_QT_MUX_STATE_DATA,
- GST_QT_MUX_STATE_EOS
-} GstQTMuxState;
-
-struct _GstQTMux
-{
- GstElement element;
-
- GstPad *srcpad;
- GstCollectPads *collect;
- GSList *sinkpads;
-
- /* state */
- GstQTMuxState state;
-
- /* size of header (prefix, atoms (ftyp, mdat)) */
- guint64 header_size;
- /* accumulated size of raw media data (a priori not including mdat header) */
- guint64 mdat_size;
- /* position of mdat atom (for later updating) */
- guint64 mdat_pos;
-
- /* keep track of the largest chunk to fine-tune brands */
- GstClockTime longest_chunk;
-
- /* atom helper objects */
- AtomsContext *context;
- AtomFTYP *ftyp;
- AtomMOOV *moov;
- GSList *extra_atoms; /* list of extra top-level atoms (e.g. UUID for xmp)
- * Stored as AtomInfo structs */
-
- /* fragmented file index */
- AtomMFRA *mfra;
-
- /* fast start */
- FILE *fast_start_file;
-
- /* moov recovery */
- FILE *moov_recov_file;
-
- /* fragment sequence */
- guint32 fragment_sequence;
-
- /* properties */
- guint32 timescale;
- guint32 trak_timescale;
- AtomsTreeFlavor flavor;
- gboolean fast_start;
- gboolean guess_pts;
- gint dts_method;
- gchar *fast_start_file_path;
- gchar *moov_recov_file_path;
- guint32 fragment_duration;
- gboolean streamable;
-
- /* for collect pads event handling function */
- GstPadEventFunction collect_event;
-
- /* for request pad naming */
- guint video_pads, audio_pads;
-};
-
-struct _GstQTMuxClass
-{
- GstElementClass parent_class;
-
- GstQTMuxFormat format;
-};
-
-/* type register helper struct */
-typedef struct _GstQTMuxClassParams
-{
- GstQTMuxFormatProp *prop;
- GstCaps *src_caps;
- GstCaps *video_sink_caps;
- GstCaps *audio_sink_caps;
-} GstQTMuxClassParams;
-
-#define GST_QT_MUX_PARAMS_QDATA g_quark_from_static_string("qt-mux-params")
-
-GType gst_qt_mux_get_type (void);
-gboolean gst_qt_mux_register (GstPlugin * plugin);
-
-/* FIXME: ideally classification tag should be added and
- * registered in gstreamer core gsttaglist
- *
- * this tag is a string in the format: entityfourcc://table_num/content
- * FIXME Shouldn't we add a field for 'language'?
- */
-#define GST_TAG_3GP_CLASSIFICATION "classification"
-
-G_END_DECLS
-
-#endif /* __GST_QT_MUX_H__ */
diff --git a/gst/qtmux/gstqtmuxmap.c b/gst/qtmux/gstqtmuxmap.c
deleted file mode 100644
index b8859b46b..000000000
--- a/gst/qtmux/gstqtmuxmap.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/* Quicktime muxer plugin for GStreamer
- * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
- * Copyright (C) 2008 Mark Nauwelaerts <mnauw@users.sf.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.
- */
-/*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "gstqtmuxmap.h"
-#include "fourcc.h"
-#include "ftypcc.h"
-
-/* static info related to various format */
-
-#define COMMON_VIDEO_CAPS \
- "width = (int) [ 16, 4096 ], " \
- "height = (int) [ 16, 4096 ], " \
- "framerate = (fraction) [ 0, MAX ]"
-
-#define COMMON_VIDEO_CAPS_NO_FRAMERATE \
- "width = (int) [ 16, 4096 ], " \
- "height = (int) [ 16, 4096 ] "
-
-#define H263_CAPS \
- "video/x-h263, " \
- COMMON_VIDEO_CAPS
-
-#define H264_CAPS \
- "video/x-h264, " \
- "stream-format = (string) avc, " \
- COMMON_VIDEO_CAPS
-
-#define MPEG4V_CAPS \
- "video/mpeg, " \
- "mpegversion = (int) 4, "\
- "systemstream = (boolean) false, " \
- COMMON_VIDEO_CAPS "; " \
- "video/x-divx, " \
- "divxversion = (int) 5, "\
- COMMON_VIDEO_CAPS
-
-#define SVQ_CAPS \
- "video/x-svq, " \
- "svqversion = (int) 3, " \
- COMMON_VIDEO_CAPS
-
-#define COMMON_AUDIO_CAPS(c, r) \
- "channels = (int) [ 1, " G_STRINGIFY (c) " ], " \
- "rate = (int) [ 1, " G_STRINGIFY (r) " ]"
-
-#define PCM_CAPS \
- "audio/x-raw-int, " \
- "width = (int) 8, " \
- "depth = (int) 8, " \
- COMMON_AUDIO_CAPS (2, MAX) ", " \
- "signed = (boolean) { true, false }; " \
- "audio/x-raw-int, " \
- "width = (int) 16, " \
- "depth = (int) 16, " \
- "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }, " \
- COMMON_AUDIO_CAPS (2, MAX) ", " \
- "signed = (boolean) true " \
-
-#define PCM_CAPS_FULL \
- PCM_CAPS "; " \
- "audio/x-raw-int, " \
- "width = (int) 24, " \
- "depth = (int) 24, " \
- "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }, " \
- COMMON_AUDIO_CAPS (2, MAX) ", " \
- "signed = (boolean) true; " \
- "audio/x-raw-int, " \
- "width = (int) 32, " \
- "depth = (int) 32, " \
- "endianness = (int) { BIG_ENDIAN, LITTLE_ENDIAN }, " \
- COMMON_AUDIO_CAPS (2, MAX) ", " \
- "signed = (boolean) true "
-
-#define MP3_CAPS \
- "audio/mpeg, " \
- "mpegversion = (int) 1, " \
- "layer = (int) 3, " \
- COMMON_AUDIO_CAPS (2, MAX)
-
-#define AAC_CAPS \
- "audio/mpeg, " \
- "mpegversion = (int) 4, " \
- "stream-format = (string) raw, " \
- COMMON_AUDIO_CAPS (8, MAX)
-
-#define AMR_CAPS \
- "audio/AMR, " \
- "rate = (int) 8000, " \
- "channels = [ 1, 2 ]; " \
- "audio/AMR-WB, " \
- "rate = (int) 16000, " \
- "channels = [ 1, 2 ] "
-
-#define ADPCM_CAPS \
- "audio/x-adpcm, " \
- "layout = (string)dvi, " \
- "block_align = (int)[64, 8096], " \
- COMMON_AUDIO_CAPS(2, MAX)
-
-#define ALAC_CAPS \
- "audio/x-alac, " \
- COMMON_AUDIO_CAPS(2, MAX)
-
-/* FIXME 0.11 - take a look at bugs #580005 and #340375 */
-GstQTMuxFormatProp gst_qt_mux_format_list[] = {
- /* original QuickTime format; see Apple site (e.g. qtff.pdf) */
- {
- GST_QT_MUX_FORMAT_QT,
- "qtmux",
- "QuickTime",
- "GstQTMux",
- GST_STATIC_CAPS ("video/quicktime, variant = (string) apple"),
- GST_STATIC_CAPS ("video/x-raw-rgb, "
- COMMON_VIDEO_CAPS "; "
- "video/x-raw-yuv, "
- "format = (fourcc) UYVY, "
- COMMON_VIDEO_CAPS "; "
- MPEG4V_CAPS "; "
- H263_CAPS "; "
- H264_CAPS "; "
- SVQ_CAPS "; "
- "video/x-dv, "
- "systemstream = (boolean) false, "
- COMMON_VIDEO_CAPS "; "
- "image/jpeg, "
- COMMON_VIDEO_CAPS_NO_FRAMERATE "; "
- "video/x-vp8, "
- COMMON_VIDEO_CAPS "; " "video/x-qt-part, " COMMON_VIDEO_CAPS),
- GST_STATIC_CAPS (PCM_CAPS_FULL "; "
- MP3_CAPS " ; "
- AAC_CAPS " ; "
- ADPCM_CAPS " ; "
- "audio/x-alaw, " COMMON_AUDIO_CAPS (2, MAX) "; "
- AMR_CAPS " ; " ALAC_CAPS)
- }
- ,
- /* ISO 14496-14: mp42 as ISO base media extension
- * (supersedes original ISO 144996-1 mp41) */
- {
- GST_QT_MUX_FORMAT_MP4,
- "mp4mux",
- "MP4",
- "GstMP4Mux",
- GST_STATIC_CAPS ("video/quicktime, variant = (string) iso"),
- GST_STATIC_CAPS (MPEG4V_CAPS "; " H264_CAPS ";"
- "video/x-mp4-part," COMMON_VIDEO_CAPS),
- GST_STATIC_CAPS (MP3_CAPS "; " AAC_CAPS " ; " ALAC_CAPS)
- }
- ,
- /* Microsoft Smooth Streaming fmp4/isml */
- /* TODO add WMV/WMA support */
- {
- GST_QT_MUX_FORMAT_ISML,
- "ismlmux",
- "ISML",
- "GstISMLMux",
- GST_STATIC_CAPS ("video/quicktime, variant = (string) iso"),
- GST_STATIC_CAPS (MPEG4V_CAPS "; " H264_CAPS),
- GST_STATIC_CAPS (MP3_CAPS "; " AAC_CAPS)
- }
- ,
- /* 3GPP Technical Specification 26.244 V7.3.0
- * (extended in 3GPP2 File Formats for Multimedia Services) */
- {
- GST_QT_MUX_FORMAT_3GP,
- "gppmux",
- "3GPP",
- "GstGPPMux",
- GST_STATIC_CAPS ("video/quicktime, variant = (string) 3gpp"),
- GST_STATIC_CAPS (H263_CAPS "; " MPEG4V_CAPS "; " H264_CAPS),
- GST_STATIC_CAPS (AMR_CAPS "; " MP3_CAPS "; " AAC_CAPS)
- }
- ,
- /* ISO 15444-3: Motion-JPEG-2000 (also ISO base media extension) */
- {
- GST_QT_MUX_FORMAT_MJ2,
- "mj2mux",
- "MJ2",
- "GstMJ2Mux",
- GST_STATIC_CAPS ("video/mj2"),
- GST_STATIC_CAPS ("image/x-j2c, " COMMON_VIDEO_CAPS "; "
- "image/x-jpc, " COMMON_VIDEO_CAPS),
- GST_STATIC_CAPS (PCM_CAPS)
- }
- ,
- {
- GST_QT_MUX_FORMAT_NONE,
- }
- ,
-};
-
-/* pretty static, but may turn out needed a few times */
-AtomsTreeFlavor
-gst_qt_mux_map_format_to_flavor (GstQTMuxFormat format)
-{
- if (format == GST_QT_MUX_FORMAT_QT)
- return ATOMS_TREE_FLAVOR_MOV;
- else if (format == GST_QT_MUX_FORMAT_3GP)
- return ATOMS_TREE_FLAVOR_3GP;
- else if (format == GST_QT_MUX_FORMAT_ISML)
- return ATOMS_TREE_FLAVOR_ISML;
- else
- return ATOMS_TREE_FLAVOR_ISOM;
-}
-
-static void
-gst_qt_mux_map_check_tracks (AtomMOOV * moov, gint * _video, gint * _audio,
- gboolean * _has_h264)
-{
- GList *it;
- gint video = 0, audio = 0;
- gboolean has_h264 = FALSE;
-
- for (it = moov->traks; it != NULL; it = g_list_next (it)) {
- AtomTRAK *track = it->data;
-
- if (track->is_video) {
- video++;
- if (track->is_h264)
- has_h264 = TRUE;
- } else
- audio++;
- }
-
- if (_video)
- *_video = video;
- if (_audio)
- *_audio = audio;
- if (_has_h264)
- *_has_h264 = has_h264;
-}
-
-/* pretty static, but possibly dynamic format info */
-
-/* notes:
- * - avc1 brand is not used, since the specific extensions indicated by it
- * are not used (e.g. sample groupings, etc)
- * - TODO: maybe even more 3GPP brand fine-tuning ??
- * (but that might need ftyp rewriting at the end) */
-void
-gst_qt_mux_map_format_to_header (GstQTMuxFormat format, GstBuffer ** _prefix,
- guint32 * _major, guint32 * _version, GList ** _compatible, AtomMOOV * moov,
- GstClockTime longest_chunk, gboolean faststart)
-{
- static guint32 qt_brands[] = { 0 };
- static guint32 mp4_brands[] = { FOURCC_mp41, FOURCC_isom, FOURCC_iso2, 0 };
- static guint32 isml_brands[] = { FOURCC_iso2, 0 };
- static guint32 gpp_brands[] = { FOURCC_isom, FOURCC_iso2, 0 };
- static guint32 mjp2_brands[] = { FOURCC_isom, FOURCC_iso2, 0 };
- static guint8 mjp2_prefix[] =
- { 0, 0, 0, 12, 'j', 'P', ' ', ' ', 0x0D, 0x0A, 0x87, 0x0A };
- guint32 *comp = NULL;
- guint32 major = 0, version = 0;
- GstBuffer *prefix = NULL;
- GList *result = NULL;
-
- g_return_if_fail (_prefix != NULL);
- g_return_if_fail (_major != NULL);
- g_return_if_fail (_version != NULL);
- g_return_if_fail (_compatible != NULL);
-
- switch (format) {
- case GST_QT_MUX_FORMAT_QT:
- major = FOURCC_qt__;
- comp = qt_brands;
- version = 0x20050300;
- break;
- case GST_QT_MUX_FORMAT_MP4:
- major = FOURCC_mp42;
- comp = mp4_brands;
- break;
- case GST_QT_MUX_FORMAT_ISML:
- major = FOURCC_isml;
- comp = isml_brands;
- break;
- case GST_QT_MUX_FORMAT_3GP:
- {
- gint video, audio;
- gboolean has_h264;
-
- gst_qt_mux_map_check_tracks (moov, &video, &audio, &has_h264);
- /* only track restriction really matters for Basic Profile */
- if (video <= 1 && audio <= 1) {
- /* it seems only newer spec knows about H264 */
- major = has_h264 ? FOURCC_3gp6 : FOURCC_3gp4;
- version = has_h264 ? 0x100 : 0x200;
- } else {
- major = FOURCC_3gg6;
- version = 0x100;
- }
- comp = gpp_brands;
-
- /*
- * We assume that we have chunks in dts order
- */
- if (faststart && longest_chunk <= GST_SECOND) {
- /* add progressive download profile */
- result = g_list_append (result, GUINT_TO_POINTER (FOURCC_3gr6));
- }
- break;
- }
- case GST_QT_MUX_FORMAT_MJ2:
- major = FOURCC_mjp2;
- comp = mjp2_brands;
- version = 0;
- prefix = gst_buffer_new_and_alloc (sizeof (mjp2_prefix));
- memcpy (GST_BUFFER_DATA (prefix), mjp2_prefix, GST_BUFFER_SIZE (prefix));
- break;
- default:
- g_assert_not_reached ();
- break;
- }
-
- /* convert list to list, hm */
- while (comp && *comp != 0) {
- /* order matters over efficiency */
- result = g_list_append (result, GUINT_TO_POINTER (*comp));
- comp++;
- }
-
- *_major = major;
- *_version = version;
- *_prefix = prefix;
- *_compatible = result;
-
- /* TODO 3GPP may include mp42 as compatible if applicable */
- /* TODO 3GPP major brand 3gp7 if at most 1 video and audio track */
-}
diff --git a/gst/qtmux/gstqtmuxmap.h b/gst/qtmux/gstqtmuxmap.h
deleted file mode 100644
index 767d62a4a..000000000
--- a/gst/qtmux/gstqtmuxmap.h
+++ /dev/null
@@ -1,83 +0,0 @@
-/* Quicktime muxer plugin for GStreamer
- * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
- * Copyright (C) 2008 Mark Nauwelaerts <mnauw@users.sf.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.
- */
-/*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __GST_QT_MUX_MAP_H__
-#define __GST_QT_MUX_MAP_H__
-
-#include "atoms.h"
-
-#include <glib.h>
-#include <gst/gst.h>
-
-typedef enum _GstQTMuxFormat
-{
- GST_QT_MUX_FORMAT_NONE = 0,
- GST_QT_MUX_FORMAT_QT,
- GST_QT_MUX_FORMAT_MP4,
- GST_QT_MUX_FORMAT_3GP,
- GST_QT_MUX_FORMAT_MJ2,
- GST_QT_MUX_FORMAT_ISML
-} GstQTMuxFormat;
-
-typedef struct _GstQTMuxFormatProp
-{
- GstQTMuxFormat format;
- const gchar *name;
- const gchar *long_name;
- const gchar *type_name;
- GstStaticCaps src_caps;
- GstStaticCaps video_sink_caps;
- GstStaticCaps audio_sink_caps;
-} GstQTMuxFormatProp;
-
-extern GstQTMuxFormatProp gst_qt_mux_format_list[];
-
-void gst_qt_mux_map_format_to_header (GstQTMuxFormat format, GstBuffer ** _prefix,
- guint32 * _major, guint32 * verson,
- GList ** _compatible, AtomMOOV * moov,
- GstClockTime longest_chunk,
- gboolean faststart);
-
-AtomsTreeFlavor gst_qt_mux_map_format_to_flavor (GstQTMuxFormat format);
-
-#endif /* __GST_QT_MUX_MAP_H__ */
diff --git a/gst/qtmux/gstqtmuxplugin.c b/gst/qtmux/gstqtmuxplugin.c
deleted file mode 100644
index 440b9808a..000000000
--- a/gst/qtmux/gstqtmuxplugin.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Quicktime muxer plugin for GStreamer
- * Copyright (C) 2008-2010 Thiago Santos <thiagoss@embedded.ufcg.edu.br>
- * Copyright (C) 2008 Mark Nauwelaerts <mnauw@users.sf.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.
- */
-/*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifdef HAVE_CONFIG_H
-#include "config.h"
-#endif
-
-#include "gstqtmux.h"
-#include "gstqtmoovrecover.h"
-
-static gboolean
-gst_qt_mux_plugin_init (GstPlugin * plugin)
-{
- if (!gst_qt_mux_register (plugin))
- return FALSE;
- if (!gst_qt_moov_recover_register (plugin))
- return FALSE;
-
- return TRUE;
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "qtmux",
- "Quicktime Muxer plugin",
- gst_qt_mux_plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME,
- GST_PACKAGE_ORIGIN);
diff --git a/gst/qtmux/properties.c b/gst/qtmux/properties.c
deleted file mode 100644
index 8dafb2e21..000000000
--- a/gst/qtmux/properties.c
+++ /dev/null
@@ -1,210 +0,0 @@
-/* Quicktime muxer plugin for GStreamer
- * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
- *
- * 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.
- */
-/*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#include "properties.h"
-
-/* if needed, re-allocate buffer to ensure size bytes can be written into it
- * at offset */
-void
-prop_copy_ensure_buffer (guint8 ** buffer, guint64 * bsize, guint64 * offset,
- guint64 size)
-{
- if (buffer && *bsize - *offset < size) {
- *bsize += size + 10 * 1024;
- *buffer = g_realloc (*buffer, *bsize);
- }
-}
-
-static guint64
-copy_func (void *prop, guint size, guint8 ** buffer, guint64 * bsize,
- guint64 * offset)
-{
- if (buffer) {
- prop_copy_ensure_buffer (buffer, bsize, offset, size);
- memcpy (*buffer + *offset, prop, size);
- }
- *offset += size;
- return size;
-}
-
-#define INT_ARRAY_COPY_FUNC_FAST(name, datatype) \
-guint64 prop_copy_ ## name ## _array (datatype *prop, guint size, \
- guint8 ** buffer, guint64 * bsize, guint64 * offset) { \
- return copy_func (prop, sizeof (datatype) * size, buffer, bsize, offset);\
-}
-
-#define INT_ARRAY_COPY_FUNC(name, datatype) \
-guint64 prop_copy_ ## name ## _array (datatype *prop, guint size, \
- guint8 ** buffer, guint64 * bsize, guint64 * offset) { \
- guint i; \
- \
- for (i = 0; i < size; i++) { \
- prop_copy_ ## name (prop[i], buffer, bsize, offset); \
- } \
- return sizeof (datatype) * size; \
-}
-
-/* INTEGERS */
-guint64
-prop_copy_uint8 (guint8 prop, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- return copy_func (&prop, sizeof (guint8), buffer, size, offset);
-}
-
-guint64
-prop_copy_uint16 (guint16 prop, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- prop = GUINT16_TO_BE (prop);
- return copy_func (&prop, sizeof (guint16), buffer, size, offset);
-}
-
-guint64
-prop_copy_uint32 (guint32 prop, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- prop = GUINT32_TO_BE (prop);
- return copy_func (&prop, sizeof (guint32), buffer, size, offset);
-}
-
-guint64
-prop_copy_uint64 (guint64 prop, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- prop = GUINT64_TO_BE (prop);
- return copy_func (&prop, sizeof (guint64), buffer, size, offset);
-}
-
-guint64
-prop_copy_int32 (gint32 prop, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- prop = GINT32_TO_BE (prop);
- return copy_func (&prop, sizeof (guint32), buffer, size, offset);
-}
-
-/* uint8 can use direct copy in any case, and may be used for large quantity */
-INT_ARRAY_COPY_FUNC_FAST (uint8, guint8);
-/* not used in large quantity anyway */
-INT_ARRAY_COPY_FUNC (uint16, guint16);
-INT_ARRAY_COPY_FUNC (uint32, guint32);
-INT_ARRAY_COPY_FUNC (uint64, guint64);
-
-/* FOURCC */
-guint64
-prop_copy_fourcc (guint32 prop, guint8 ** buffer, guint64 * size,
- guint64 * offset)
-{
- prop = GINT32_TO_LE (prop);
- return copy_func (&prop, sizeof (guint32), buffer, size, offset);
-}
-
-INT_ARRAY_COPY_FUNC (fourcc, guint32);
-
-/**
- * prop_copy_fixed_size_string:
- * @string: the string to be copied
- * @str_size: size of the string
- * @buffer: the array to copy the string to
- * @offset: the position in the buffer array.
- * This value is updated to the point right after the copied string.
- *
- * Copies a string of bytes without placing its size at the beginning.
- *
- * Returns: the number of bytes copied
- */
-guint64
-prop_copy_fixed_size_string (guint8 * string, guint str_size, guint8 ** buffer,
- guint64 * size, guint64 * offset)
-{
- return copy_func (string, str_size * sizeof (guint8), buffer, size, offset);
-}
-
-/**
- * prop_copy_size_string:
- *
- * @string: the string to be copied
- * @str_size: size of the string
- * @buffer: the array to copy the string to
- * @offset: the position in the buffer array.
- * This value is updated to the point right after the copied string.
- *
- * Copies a string and its size to an array. Example:
- * string = 'abc\0'
- * result in the array: [3][a][b][c] (each [x] represents a position)
- *
- * Returns: the number of bytes copied
- */
-guint64
-prop_copy_size_string (guint8 * string, guint str_size, guint8 ** buffer,
- guint64 * size, guint64 * offset)
-{
- guint64 original_offset = *offset;
-
- prop_copy_uint8 (str_size, buffer, size, offset);
- prop_copy_fixed_size_string (string, str_size, buffer, size, offset);
- return *offset - original_offset;
-}
-
-/**
- * prop_copy_null_terminated_string:
- * @string: the string to be copied
- * @buffer: the array to copy the string to
- * @offset: the position in the buffer array.
- * This value is updated to the point right after the copied string.
- *
- * Copies a string including its null terminating char to an array.
- *
- * Returns: the number of bytes copied
- */
-guint64
-prop_copy_null_terminated_string (gchar * string, guint8 ** buffer,
- guint64 * size, guint64 * offset)
-{
- guint64 original_offset = *offset;
- guint len = strlen (string);
-
- prop_copy_fixed_size_string ((guint8 *) string, len, buffer, size, offset);
- prop_copy_uint8 ('\0', buffer, size, offset);
- return *offset - original_offset;
-}
diff --git a/gst/qtmux/properties.h b/gst/qtmux/properties.h
deleted file mode 100644
index ad67e0da0..000000000
--- a/gst/qtmux/properties.h
+++ /dev/null
@@ -1,87 +0,0 @@
-/* Quicktime muxer plugin for GStreamer
- * Copyright (C) 2008 Thiago Sousa Santos <thiagoss@embedded.ufcg.edu.br>
- *
- * 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.
- */
-/*
- * Unless otherwise indicated, Source Code is licensed under MIT license.
- * See further explanation attached in License Statement (distributed in the file
- * LICENSE).
- *
- * Permission is hereby granted, free of charge, to any person obtaining a copy of
- * this software and associated documentation files (the "Software"), to deal in
- * the Software without restriction, including without limitation the rights to
- * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
- * of the Software, and to permit persons to whom the Software is furnished to do
- * so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in all
- * copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
- * SOFTWARE.
- */
-
-#ifndef __PROPERTIES_H__
-#define __PROPERTIES_H__
-
-#include <glib.h>
-#include <string.h>
-
-/**
- * Functions for copying atoms properties.
- *
- * All of them receive, as the input, the property to be copied, the destination
- * buffer, and a pointer to an offset in the destination buffer to copy to the right place.
- * This offset will be updated to the new value (offset + copied_size)
- * The functions return the size of the property that has been copied or 0
- * if it couldn't copy.
- */
-
-void prop_copy_ensure_buffer (guint8 ** buffer, guint64 * bsize, guint64 * offset, guint64 size);
-
-guint64 prop_copy_uint8 (guint8 prop, guint8 **buffer, guint64 *size, guint64 *offset);
-guint64 prop_copy_uint16 (guint16 prop, guint8 **buffer, guint64 *size, guint64 *offset);
-guint64 prop_copy_uint32 (guint32 prop, guint8 **buffer, guint64 *size, guint64 *offset);
-guint64 prop_copy_uint64 (guint64 prop, guint8 **buffer, guint64 *size, guint64 *offset);
-
-guint64 prop_copy_int32 (gint32 prop, guint8 **buffer, guint64 *size, guint64 *offset);
-
-guint64 prop_copy_uint8_array (guint8 *prop, guint size,
- guint8 **buffer, guint64 *bsize, guint64 *offset);
-guint64 prop_copy_uint16_array (guint16 *prop, guint size,
- guint8 **buffer, guint64 *bsize, guint64 *offset);
-guint64 prop_copy_uint32_array (guint32 *prop, guint size,
- guint8 **buffer, guint64 *bsize, guint64 *offset);
-guint64 prop_copy_uint64_array (guint64 *prop, guint size,
- guint8 **buffer, guint64 *bsize, guint64 *offset);
-
-guint64 prop_copy_fourcc (guint32 prop, guint8 **buffer, guint64 *size, guint64 *offset);
-guint64 prop_copy_fourcc_array (guint32 *prop, guint size,
- guint8 **buffer, guint64 *bsize, guint64 *offset);
-guint64 prop_copy_fixed_size_string (guint8 *string, guint str_size,
- guint8 **buffer, guint64 *size, guint64 *offset);
-guint64 prop_copy_size_string (guint8 *string, guint str_size,
- guint8 **buffer, guint64 *size, guint64 *offset);
-guint64 prop_copy_null_terminated_string (gchar *string,
- guint8 **buffer, guint64 *size, guint64 *offset);
-
-#endif /* __PROPERTIES_H__ */
diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am
index 2f8207a8f..433b94f28 100644
--- a/tests/check/Makefile.am
+++ b/tests/check/Makefile.am
@@ -163,7 +163,6 @@ check_PROGRAMS = \
$(check_jifmux) \
elements/jpegparse \
$(check_logoinsert) \
- elements/qtmux \
elements/mxfdemux \
elements/mxfmux \
elements/id3mux \
@@ -174,7 +173,6 @@ check_PROGRAMS = \
$(check_vp8) \
$(check_zbar) \
$(check_orc) \
- pipelines/tagschecking \
$(EXPERIMENTAL_CHECKS)
noinst_HEADERS = elements/mxfdemux.h
diff --git a/tests/check/elements/.gitignore b/tests/check/elements/.gitignore
index df8ab1761..b68288dbe 100644
--- a/tests/check/elements/.gitignore
+++ b/tests/check/elements/.gitignore
@@ -25,7 +25,6 @@ mxfdemux
mxfmux
neonhttpsrc
ofa
-qtmux
rganalysis
rglimiter
rgvolume
diff --git a/tests/check/elements/qtmux.c b/tests/check/elements/qtmux.c
deleted file mode 100644
index 1db618cec..000000000
--- a/tests/check/elements/qtmux.c
+++ /dev/null
@@ -1,422 +0,0 @@
-/* GStreamer
- *
- * unit test for qtmux
- *
- * Copyright (C) <2008> Mark Nauwelaerts <mnauw@users.sf.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.
- */
-
-#include <unistd.h>
-
-#include <gst/check/gstcheck.h>
-
-/* For ease of programming we use globals to keep refs for our floating
- * src and sink pads we create; otherwise we always have to do get_pad,
- * get_peer, and then remove references in every test function */
-static GstPad *mysrcpad, *mysinkpad;
-
-#define AUDIO_CAPS_STRING "audio/mpeg, " \
- "mpegversion = (int) 1, " \
- "layer = (int) 3, " \
- "channels = (int) 2, " \
- "rate = (int) 48000"
-#define VIDEO_CAPS_STRING "video/mpeg, " \
- "mpegversion = (int) 4, " \
- "width = (int) 384, " \
- "height = (int) 288, " \
- "framerate = (fraction) 25/1"
-
-static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
- GST_PAD_SINK,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/quicktime"));
-static GstStaticPadTemplate srcvideotemplate = GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS (VIDEO_CAPS_STRING));
-
-static GstStaticPadTemplate srcaudiotemplate = GST_STATIC_PAD_TEMPLATE ("src",
- GST_PAD_SRC,
- GST_PAD_ALWAYS,
- GST_STATIC_CAPS (AUDIO_CAPS_STRING));
-
-
-/* setup and teardown needs some special handling for muxer */
-static GstPad *
-setup_src_pad (GstElement * element,
- GstStaticPadTemplate * template, GstCaps * caps, const gchar * sinkname)
-{
- GstPad *srcpad, *sinkpad;
-
- GST_DEBUG_OBJECT (element, "setting up sending pad");
- /* sending pad */
- srcpad = gst_pad_new_from_static_template (template, "src");
- fail_if (srcpad == NULL, "Could not create a srcpad");
- ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1);
-
- if (!(sinkpad = gst_element_get_static_pad (element, sinkname)))
- sinkpad = gst_element_get_request_pad (element, sinkname);
- fail_if (sinkpad == NULL, "Could not get sink pad from %s",
- GST_ELEMENT_NAME (element));
- /* references are owned by: 1) us, 2) qtmux, 3) collect pads */
- ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
- if (caps)
- fail_unless (gst_pad_set_caps (srcpad, caps));
- fail_unless (gst_pad_link (srcpad, sinkpad) == GST_PAD_LINK_OK,
- "Could not link source and %s sink pads", GST_ELEMENT_NAME (element));
- gst_object_unref (sinkpad); /* because we got it higher up */
-
- /* references are owned by: 1) qtmux, 2) collect pads */
- ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 2);
-
- return srcpad;
-}
-
-static void
-teardown_src_pad (GstPad * srcpad)
-{
- GstPad *sinkpad;
-
- /* clean up floating src pad */
- sinkpad = gst_pad_get_peer (srcpad);
- fail_if (sinkpad == NULL);
- /* pad refs held by 1) qtmux 2) collectpads and 3) us (through _get_peer) */
- ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
-
- gst_pad_unlink (srcpad, sinkpad);
-
- /* after unlinking, pad refs still held by
- * 1) qtmux and 2) collectpads and 3) us (through _get_peer) */
- ASSERT_OBJECT_REFCOUNT (sinkpad, "sinkpad", 3);
- gst_object_unref (sinkpad);
- /* one more ref is held by element itself */
-
- /* pad refs held by creator */
- ASSERT_OBJECT_REFCOUNT (srcpad, "srcpad", 1);
- gst_object_unref (srcpad);
-}
-
-static GstElement *
-setup_qtmux (GstStaticPadTemplate * srctemplate, const gchar * sinkname)
-{
- GstElement *qtmux;
-
- GST_DEBUG ("setup_qtmux");
- qtmux = gst_check_setup_element ("qtmux");
- mysrcpad = setup_src_pad (qtmux, srctemplate, NULL, sinkname);
- mysinkpad = gst_check_setup_sink_pad (qtmux, &sinktemplate, NULL);
- gst_pad_set_active (mysrcpad, TRUE);
- gst_pad_set_active (mysinkpad, TRUE);
-
- return qtmux;
-}
-
-static void
-cleanup_qtmux (GstElement * qtmux, const gchar * sinkname)
-{
- GST_DEBUG ("cleanup_qtmux");
- gst_element_set_state (qtmux, GST_STATE_NULL);
-
- gst_pad_set_active (mysrcpad, FALSE);
- gst_pad_set_active (mysinkpad, FALSE);
- teardown_src_pad (mysrcpad);
- gst_check_teardown_sink_pad (qtmux);
- gst_check_teardown_element (qtmux);
-}
-
-static void
-check_qtmux_pad (GstStaticPadTemplate * srctemplate, const gchar * sinkname)
-{
- GstElement *qtmux;
- GstBuffer *inbuffer, *outbuffer;
- GstCaps *caps;
- int num_buffers;
- int i;
- guint8 data0[12] = "\000\000\000\024ftypqt ";
- guint8 data1[8] = "\000\000\000\001mdat";
- guint8 data2[4] = "moov";
-
- qtmux = setup_qtmux (srctemplate, sinkname);
- fail_unless (gst_element_set_state (qtmux,
- GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
- "could not set to playing");
-
- inbuffer = gst_buffer_new_and_alloc (1);
- caps = gst_caps_copy (gst_pad_get_pad_template_caps (mysrcpad));
- gst_buffer_set_caps (inbuffer, caps);
- gst_caps_unref (caps);
- GST_BUFFER_TIMESTAMP (inbuffer) = 0;
- GST_BUFFER_DURATION (inbuffer) = 40 * GST_MSECOND;
- ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
- fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
-
- /* send eos to have moov written */
- fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
-
- num_buffers = g_list_length (buffers);
- /* at least expect ftyp, mdat header, buffer chunk and moov */
- fail_unless (num_buffers >= 4);
-
- for (i = 0; i < num_buffers; ++i) {
- outbuffer = GST_BUFFER (buffers->data);
- fail_if (outbuffer == NULL);
- buffers = g_list_remove (buffers, outbuffer);
-
- switch (i) {
- case 0:
- {
- /* ftyp header */
- guint8 *data = GST_BUFFER_DATA (outbuffer);
-
- fail_unless (GST_BUFFER_SIZE (outbuffer) >= 20);
- fail_unless (memcmp (data, data0, sizeof (data0)) == 0);
- fail_unless (memcmp (data + 16, data0 + 8, 4) == 0);
- break;
- }
- case 1: /* mdat header */
- fail_unless (GST_BUFFER_SIZE (outbuffer) == 16);
- fail_unless (memcmp (GST_BUFFER_DATA (outbuffer), data1, sizeof (data1))
- == 0);
- break;
- case 2: /* buffer we put in */
- fail_unless (GST_BUFFER_SIZE (outbuffer) == 1);
- break;
- case 3: /* moov */
- fail_unless (GST_BUFFER_SIZE (outbuffer) > 8);
- fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data2,
- sizeof (data2)) == 0);
- break;
- default:
- break;
- }
-
- ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
- gst_buffer_unref (outbuffer);
- outbuffer = NULL;
- }
-
- g_list_free (buffers);
- buffers = NULL;
-
- cleanup_qtmux (qtmux, sinkname);
-}
-
-static void
-check_qtmux_pad_fragmented (GstStaticPadTemplate * srctemplate,
- const gchar * sinkname, gboolean streamable)
-{
- GstElement *qtmux;
- GstBuffer *inbuffer, *outbuffer;
- GstCaps *caps;
- int num_buffers;
- int i;
- guint8 data0[12] = "\000\000\000\024ftypqt ";
- guint8 data1[4] = "mdat";
- guint8 data2[4] = "moov";
- guint8 data3[4] = "moof";
- guint8 data4[4] = "mfra";
-
- qtmux = setup_qtmux (srctemplate, sinkname);
- g_object_set (qtmux, "fragment-duration", 2000, NULL);
- g_object_set (qtmux, "streamable", streamable, NULL);
- fail_unless (gst_element_set_state (qtmux,
- GST_STATE_PLAYING) == GST_STATE_CHANGE_SUCCESS,
- "could not set to playing");
-
- inbuffer = gst_buffer_new_and_alloc (1);
- caps = gst_caps_copy (gst_pad_get_pad_template_caps (mysrcpad));
- gst_buffer_set_caps (inbuffer, caps);
- gst_caps_unref (caps);
- GST_BUFFER_TIMESTAMP (inbuffer) = 0;
- GST_BUFFER_DURATION (inbuffer) = 40 * GST_MSECOND;
- ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
- fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
-
- /* send eos to have all written */
- fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
-
- num_buffers = g_list_length (buffers);
- /* at least expect ftyp, moov, moof, mdat header, buffer chunk
- * and optionally mfra */
- fail_unless (num_buffers >= 5);
-
- for (i = 0; i < num_buffers; ++i) {
- outbuffer = GST_BUFFER (buffers->data);
- fail_if (outbuffer == NULL);
- buffers = g_list_remove (buffers, outbuffer);
-
- switch (i) {
- case 0:
- {
- /* ftyp header */
- guint8 *data = GST_BUFFER_DATA (outbuffer);
-
- fail_unless (GST_BUFFER_SIZE (outbuffer) >= 20);
- fail_unless (memcmp (data, data0, sizeof (data0)) == 0);
- fail_unless (memcmp (data + 16, data0 + 8, 4) == 0);
- break;
- }
- case 1: /* moov */
- fail_unless (GST_BUFFER_SIZE (outbuffer) > 8);
- fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data2,
- sizeof (data2)) == 0);
- break;
- case 2: /* moof */
- fail_unless (GST_BUFFER_SIZE (outbuffer) > 8);
- fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data3,
- sizeof (data3)) == 0);
- break;
- case 3: /* mdat header */
- fail_unless (GST_BUFFER_SIZE (outbuffer) == 8);
- fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data1,
- sizeof (data1)) == 0);
- break;
- case 4: /* buffer we put in */
- fail_unless (GST_BUFFER_SIZE (outbuffer) == 1);
- break;
- case 5: /* mfra */
- fail_unless (GST_BUFFER_SIZE (outbuffer) > 8);
- fail_unless (memcmp (GST_BUFFER_DATA (outbuffer) + 4, data4,
- sizeof (data4)) == 0);
- break;
- default:
- break;
- }
-
- ASSERT_BUFFER_REFCOUNT (outbuffer, "outbuffer", 1);
- gst_buffer_unref (outbuffer);
- outbuffer = NULL;
- }
-
- g_list_free (buffers);
- buffers = NULL;
-
- cleanup_qtmux (qtmux, sinkname);
-}
-
-
-GST_START_TEST (test_video_pad)
-{
- check_qtmux_pad (&srcvideotemplate, "video_%d");
-}
-
-GST_END_TEST;
-
-GST_START_TEST (test_audio_pad)
-{
- check_qtmux_pad (&srcaudiotemplate, "audio_%d");
-}
-
-GST_END_TEST;
-
-
-GST_START_TEST (test_video_pad_frag)
-{
- check_qtmux_pad_fragmented (&srcvideotemplate, "video_%d", FALSE);
-}
-
-GST_END_TEST;
-
-GST_START_TEST (test_audio_pad_frag)
-{
- check_qtmux_pad_fragmented (&srcaudiotemplate, "audio_%d", FALSE);
-}
-
-GST_END_TEST;
-
-
-GST_START_TEST (test_video_pad_frag_streamable)
-{
- check_qtmux_pad_fragmented (&srcvideotemplate, "video_%d", TRUE);
-}
-
-GST_END_TEST;
-
-
-GST_START_TEST (test_audio_pad_frag_streamable)
-{
- check_qtmux_pad_fragmented (&srcaudiotemplate, "audio_%d", TRUE);
-}
-
-GST_END_TEST;
-
-
-GST_START_TEST (test_reuse)
-{
- GstElement *qtmux = setup_qtmux (&srcvideotemplate, "video_%d");
- GstBuffer *inbuffer;
- GstCaps *caps;
-
- gst_element_set_state (qtmux, GST_STATE_PLAYING);
- gst_element_set_state (qtmux, GST_STATE_NULL);
- gst_element_set_state (qtmux, GST_STATE_PLAYING);
- gst_pad_set_active (mysrcpad, TRUE);
- gst_pad_set_active (mysinkpad, TRUE);
-
- inbuffer = gst_buffer_new_and_alloc (1);
- fail_unless (inbuffer != NULL);
- caps = gst_caps_copy (gst_pad_get_pad_template_caps (mysrcpad));
- gst_buffer_set_caps (inbuffer, caps);
- gst_caps_unref (caps);
- GST_BUFFER_TIMESTAMP (inbuffer) = 0;
- GST_BUFFER_DURATION (inbuffer) = 40 * GST_MSECOND;
- ASSERT_BUFFER_REFCOUNT (inbuffer, "inbuffer", 1);
- fail_unless (gst_pad_push (mysrcpad, inbuffer) == GST_FLOW_OK);
-
- /* send eos to have all written */
- fail_unless (gst_pad_push_event (mysrcpad, gst_event_new_eos ()) == TRUE);
-
- cleanup_qtmux (qtmux, "video_%d");
-}
-
-GST_END_TEST;
-
-static Suite *
-qtmux_suite (void)
-{
- Suite *s = suite_create ("qtmux");
- TCase *tc_chain = tcase_create ("general");
-
- suite_add_tcase (s, tc_chain);
- tcase_add_test (tc_chain, test_video_pad);
- tcase_add_test (tc_chain, test_audio_pad);
- tcase_add_test (tc_chain, test_video_pad_frag);
- tcase_add_test (tc_chain, test_audio_pad_frag);
- tcase_add_test (tc_chain, test_video_pad_frag_streamable);
- tcase_add_test (tc_chain, test_audio_pad_frag_streamable);
-
- tcase_add_test (tc_chain, test_reuse);
-
- return s;
-}
-
-int
-main (int argc, char **argv)
-{
- int nf;
-
- Suite *s = qtmux_suite ();
- SRunner *sr = srunner_create (s);
-
- gst_check_init (&argc, &argv);
-
- srunner_run_all (sr, CK_NORMAL);
- nf = srunner_ntests_failed (sr);
- srunner_free (sr);
-
- return nf;
-}
diff --git a/tests/check/pipelines/tagschecking.c b/tests/check/pipelines/tagschecking.c
deleted file mode 100644
index 91a556c52..000000000
--- a/tests/check/pipelines/tagschecking.c
+++ /dev/null
@@ -1,350 +0,0 @@
-/* GStreamer
- * Copyright (C) 2008 Nokia Corporation. (contact <stefan.kost@nokia.com>)
- * Copyright (C) 2010 Thiago Santos <thiago.sousa.santos@collabora.co.uk>
- *
- * 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>
-
-static GstTagList *received_tags = NULL;
-
-static gboolean
-bus_handler (GstBus * bus, GstMessage * message, gpointer data)
-{
- GMainLoop *loop = (GMainLoop *) data;
-
- switch (message->type) {
- case GST_MESSAGE_EOS:
- g_main_loop_quit (loop);
- break;
- case GST_MESSAGE_WARNING:
- case GST_MESSAGE_ERROR:{
- GError *gerror;
-
- gchar *debug;
-
- gst_message_parse_error (message, &gerror, &debug);
- gst_object_default_error (GST_MESSAGE_SRC (message), gerror, debug);
- g_error_free (gerror);
- g_free (debug);
- g_main_loop_quit (loop);
- break;
- }
- case GST_MESSAGE_TAG:{
- if (received_tags == NULL) {
- gst_message_parse_tag (message, &received_tags);
- } else {
- GstTagList *tl = NULL, *ntl = NULL;
-
- gst_message_parse_tag (message, &tl);
- if (tl) {
- ntl = gst_tag_list_merge (received_tags, tl, GST_TAG_MERGE_PREPEND);
- if (ntl) {
- GST_LOG ("taglists merged: %" GST_PTR_FORMAT, ntl);
- gst_tag_list_free (received_tags);
- received_tags = ntl;
- }
- gst_tag_list_free (tl);
- }
- }
- break;
- }
- default:
- break;
- }
-
- return TRUE;
-}
-
-/*
- * Creates a pipeline in the form:
- * fakesrc num-buffers=1 ! caps ! muxer ! filesink location=file
- *
- * And sets the tags in tag_str into the muxer via tagsetter.
- */
-static void
-test_mux_tags (const gchar * tag_str, const gchar * caps,
- const gchar * muxer, const gchar * file)
-{
- GstElement *pipeline;
- GstBus *bus;
- GMainLoop *loop;
- GstTagList *sent_tags;
- GstElement *mux;
- GstTagSetter *setter;
- gchar *launch_str;
-
- GST_DEBUG ("testing xmp muxing on : %s", muxer);
-
- launch_str = g_strdup_printf ("fakesrc num-buffers=1 ! %s ! %s name=mux ! "
- "filesink location=%s name=sink", caps, muxer, file);
- pipeline = gst_parse_launch (launch_str, NULL);
- g_free (launch_str);
- fail_unless (pipeline != NULL);
-
- mux = gst_bin_get_by_name (GST_BIN (pipeline), "mux");
- fail_unless (mux != NULL);
-
- loop = g_main_loop_new (NULL, TRUE);
- fail_unless (loop != NULL);
-
- bus = gst_element_get_bus (pipeline);
- fail_unless (bus != NULL);
- gst_bus_add_watch (bus, bus_handler, loop);
- gst_object_unref (bus);
-
- gst_element_set_state (pipeline, GST_STATE_READY);
-
- setter = GST_TAG_SETTER (mux);
- fail_unless (setter != NULL);
- sent_tags = gst_structure_from_string (tag_str, NULL);
- fail_unless (sent_tags != NULL);
- gst_tag_setter_merge_tags (setter, sent_tags, GST_TAG_MERGE_REPLACE);
- gst_tag_list_free (sent_tags);
-
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
- g_main_loop_run (loop);
-
- gst_element_set_state (pipeline, GST_STATE_NULL);
-
- g_main_loop_unref (loop);
- g_object_unref (mux);
- g_object_unref (pipeline);
-}
-
-/*
- * Makes a pipeline in the form:
- * filesrc location=file ! demuxer ! fakesink
- *
- * And gets the tags that are posted on the bus to compare
- * with the tags in 'tag_str'
- */
-static void
-test_demux_tags (const gchar * tag_str, const gchar * demuxer,
- const gchar * file)
-{
- GstElement *pipeline;
- GstBus *bus;
- GMainLoop *loop;
- GstTagList *sent_tags;
- gint i, j, n_recv, n_sent;
- const gchar *name_sent, *name_recv;
- const GValue *value_sent, *value_recv;
- gboolean found;
- gint comparison;
- GstElement *demux;
- gchar *launch_str;
-
- GST_DEBUG ("testing tags : %s", tag_str);
-
- if (received_tags) {
- gst_tag_list_free (received_tags);
- received_tags = NULL;
- }
-
- launch_str = g_strdup_printf ("filesrc location=%s ! %s name=demux ! "
- "fakesink", file, demuxer);
- pipeline = gst_parse_launch (launch_str, NULL);
- g_free (launch_str);
- fail_unless (pipeline != NULL);
-
- demux = gst_bin_get_by_name (GST_BIN (pipeline), "demux");
- fail_unless (demux != NULL);
-
- loop = g_main_loop_new (NULL, TRUE);
- fail_unless (loop != NULL);
-
- bus = gst_element_get_bus (pipeline);
- fail_unless (bus != NULL);
- gst_bus_add_watch (bus, bus_handler, loop);
- gst_object_unref (bus);
-
- sent_tags = gst_structure_from_string (tag_str, NULL);
- fail_unless (sent_tags != NULL);
-
- gst_element_set_state (pipeline, GST_STATE_PLAYING);
- g_main_loop_run (loop);
-
- GST_DEBUG ("mainloop done : %p", received_tags);
-
- /* verify tags */
- fail_unless (received_tags != NULL);
- n_recv = gst_structure_n_fields (received_tags);
- n_sent = gst_structure_n_fields (sent_tags);
- fail_unless (n_recv >= n_sent);
- /* FIXME: compare taglits values */
- for (i = 0; i < n_sent; i++) {
- name_sent = gst_structure_nth_field_name (sent_tags, i);
- value_sent = gst_structure_get_value (sent_tags, name_sent);
- found = FALSE;
- for (j = 0; j < n_recv; j++) {
- name_recv = gst_structure_nth_field_name (received_tags, j);
- if (!strcmp (name_sent, name_recv)) {
- value_recv = gst_structure_get_value (received_tags, name_recv);
- comparison = gst_value_compare (value_sent, value_recv);
- if (comparison != GST_VALUE_EQUAL) {
- gchar *vs = g_strdup_value_contents (value_sent);
- gchar *vr = g_strdup_value_contents (value_recv);
- GST_DEBUG ("sent = %s:'%s', recv = %s:'%s'",
- G_VALUE_TYPE_NAME (value_sent), vs,
- G_VALUE_TYPE_NAME (value_recv), vr);
- g_free (vs);
- g_free (vr);
- }
- fail_unless (comparison == GST_VALUE_EQUAL,
- "tag item %s has been received with different type or value",
- name_sent);
- found = TRUE;
- break;
- }
- }
- fail_unless (found, "tag item %s is lost", name_sent);
- }
-
- gst_tag_list_free (received_tags);
- received_tags = NULL;
- gst_tag_list_free (sent_tags);
-
- gst_element_set_state (pipeline, GST_STATE_NULL);
-
- g_main_loop_unref (loop);
- g_object_unref (demux);
- g_object_unref (pipeline);
-}
-
-/*
- * Tests if the muxer/demuxer pair can serialize the tags in 'tag_str'
- * to a file and recover them correctly.
- *
- * 'caps' are used to assure the muxer accepts the fake buffer fakesrc
- * will send to it.
- */
-static void
-test_tags (const gchar * tag_str, const gchar * caps, const gchar * muxer,
- const gchar * demuxer)
-{
- gchar *tmpfile;
- gchar *tmp;
-
- tmp = g_strdup_printf ("%s%d", "gst-check-xmp-test-", g_random_int ());
- tmpfile = g_build_filename (g_get_tmp_dir (), tmp, NULL);
- g_free (tmp);
-
- GST_DEBUG ("testing tags : %s", tag_str);
- test_mux_tags (tag_str, caps, muxer, tmpfile);
- test_demux_tags (tag_str, demuxer, tmpfile);
- g_free (tmpfile);
-}
-
-#define H264_CAPS "video/x-h264, width=(int)320, height=(int)240," \
- " framerate=(fraction)30/1, codec_data=(buffer)" \
- "01401592ffe10017674d401592540a0fd8088000000300" \
- "8000001e478b175001000468ee3c80, stream-format=(string)avc"
-
-#define COMMON_TAGS \
- "taglist,title=test_title," \
- "artist=test_artist," \
- "keywords=\"key1,key2\"," \
- "description=test_desc"
-
-GST_START_TEST (test_common_tags)
-{
- if (!gst_default_registry_check_feature_version ("qtdemux", 0, 10, 23)) {
- GST_INFO ("Skipping test, qtdemux either not available or too old");
- return;
- }
- test_tags (COMMON_TAGS, H264_CAPS, "qtmux", "qtdemux");
- test_tags (COMMON_TAGS, H264_CAPS, "mp4mux", "qtdemux");
- test_tags (COMMON_TAGS, H264_CAPS, "gppmux", "qtdemux");
-}
-
-GST_END_TEST;
-
-#define GEO_LOCATION_TAGS \
- "taglist,geo-location-country=Brazil," \
- "geo-location-city=\"Campina Grande\"," \
- "geo-location-sublocation=Bodocongo," \
- "geo-location-latitude=-12.125," \
- "geo-location-longitude=56.75," \
- "geo-location-elevation=327.5"
-
-GST_START_TEST (test_geo_location_tags)
-{
- if (!gst_default_registry_check_feature_version ("qtdemux", 0, 10, 23)) {
- GST_INFO ("Skipping test, qtdemux either not available or too old");
- return;
- }
- test_tags (GEO_LOCATION_TAGS, H264_CAPS, "qtmux", "qtdemux");
- test_tags (GEO_LOCATION_TAGS, H264_CAPS, "mp4mux", "qtdemux");
- test_tags (GEO_LOCATION_TAGS, H264_CAPS, "gppmux", "qtdemux");
-}
-
-GST_END_TEST;
-
-
-#define USER_TAGS \
- "taglist,user-rating=(uint)85"
-
-GST_START_TEST (test_user_tags)
-{
- if (!gst_default_registry_check_feature_version ("qtdemux", 0, 10, 23)) {
- GST_INFO ("Skipping test, qtdemux either not available or too old");
- return;
- }
-
- test_tags (USER_TAGS, H264_CAPS, "qtmux", "qtdemux");
- test_tags (USER_TAGS, H264_CAPS, "mp4mux", "qtdemux");
- test_tags (USER_TAGS, H264_CAPS, "gppmux", "qtdemux");
-}
-
-GST_END_TEST;
-
-static Suite *
-metadata_suite (void)
-{
- Suite *s = suite_create ("tagschecking");
-
- TCase *tc_chain = tcase_create ("general");
-
- /* time out after 60s, not the default 3 */
- tcase_set_timeout (tc_chain, 60);
-
- suite_add_tcase (s, tc_chain);
- tcase_add_test (tc_chain, test_common_tags);
- tcase_add_test (tc_chain, test_geo_location_tags);
- tcase_add_test (tc_chain, test_user_tags);
-
- return s;
-}
-
-int
-main (int argc, char **argv)
-{
- int nf;
-
- Suite *s = metadata_suite ();
-
- SRunner *sr = srunner_create (s);
-
- gst_check_init (&argc, &argv);
-
- srunner_run_all (sr, CK_NORMAL);
- nf = srunner_ntests_failed (sr);
- srunner_free (sr);
-
- return nf;
-}