summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWim Taymans <wim.taymans@collabora.co.uk>2011-09-26 22:31:17 +0200
committerWim Taymans <wim.taymans@collabora.co.uk>2011-09-26 22:31:17 +0200
commit7f4cf50496ef6797aaba819d0924bb5c4baf09a4 (patch)
tree44154878bf094cb393c31af479377b98df192ff3
parent6a44e54b09dcc7a9d0f4499375810892a8582403 (diff)
parentf4e744ff4921bef432b40128bdd0b33786e44732 (diff)
Merge branch 'master' into 0.11
m---------common0
-rw-r--r--configure.ac13
-rw-r--r--docs/libs/.gitignore28
-rw-r--r--docs/libs/Makefile.am52
-rw-r--r--docs/libs/gst-plugins-bad-libs-docs.sgml1
-rw-r--r--docs/libs/gst-plugins-bad-libs-sections.txt34
-rw-r--r--docs/plugins/Makefile.am43
-rw-r--r--docs/plugins/gst-plugins-bad-plugins-sections.txt12
-rw-r--r--ext/Makefile.am8
-rw-r--r--ext/celt/gstceltdec.c9
-rw-r--r--ext/celt/gstceltenc.c37
-rw-r--r--ext/celt/gstceltenc.h1
-rw-r--r--ext/faac/Makefile.am3
-rw-r--r--ext/faac/gstfaac.c568
-rw-r--r--ext/faac/gstfaac.h40
-rw-r--r--ext/faad/Makefile.am3
-rw-r--r--ext/faad/gstfaad.c761
-rw-r--r--ext/faad/gstfaad.h28
-rw-r--r--ext/kate/gstkateparse.h2
-rw-r--r--ext/kate/gstkatetiger.c9
-rw-r--r--ext/rtmp/gstrtmpsink.c29
-rw-r--r--ext/spandsp/Makefile.am9
-rw-r--r--ext/spandsp/gstspandsp.c40
-rw-r--r--ext/spandsp/gstspanplc.c300
-rw-r--r--ext/spandsp/gstspanplc.h60
-rw-r--r--gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c6
-rw-r--r--gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c5
-rw-r--r--gst-libs/gst/codecparsers/Makefile.am20
-rw-r--r--gst-libs/gst/codecparsers/gsth264parser.c158
-rw-r--r--gst-libs/gst/codecparsers/gsth264parser.h40
-rw-r--r--gst-libs/gst/codecparsers/gstmpegvideoparser.c89
-rw-r--r--gst-libs/gst/codecparsers/gstmpegvideoparser.h126
-rw-r--r--gst-libs/gst/codecparsers/gstvc1parser.c1442
-rw-r--r--gst-libs/gst/codecparsers/gstvc1parser.h468
-rw-r--r--gst-plugins-bad.spec.in9
-rw-r--r--gst/camerabin2/gstcamerabin2.c52
-rw-r--r--gst/hls/gsthlsdemux.c24
-rw-r--r--gst/hls/gsthlsdemux.h1
-rw-r--r--gst/hls/m3u8.c30
-rw-r--r--gst/hls/m3u8.h2
-rw-r--r--gst/mpegdemux/gstmpegtsdemux.c2
-rw-r--r--gst/mpegpsmux/psmux.c2
-rw-r--r--gst/mpegtsdemux/mpegtsbase.c6
-rw-r--r--gst/mpegtsdemux/mpegtsbase.h3
-rw-r--r--gst/mpegtsdemux/tsdemux.c4
-rw-r--r--gst/mpegvideoparse/mpegvideoparse.c2
-rw-r--r--gst/pcapparse/Makefile.am4
-rw-r--r--gst/pcapparse/gstirtspparse.c255
-rw-r--r--gst/pcapparse/gstirtspparse.h70
-rw-r--r--gst/pcapparse/gstpcapparse.c14
-rw-r--r--gst/pcapparse/plugin.c44
-rw-r--r--gst/rtpvp8/Makefile.am6
-rw-r--r--gst/rtpvp8/dboolhuff.LICENSE30
-rw-r--r--gst/rtpvp8/dboolhuff.c68
-rw-r--r--gst/rtpvp8/dboolhuff.h151
-rw-r--r--gst/rtpvp8/gstrtpvp8pay.c110
-rw-r--r--gst/videoparsers/Makefile.am1
-rw-r--r--gst/videoparsers/dirac_parse.c4
-rw-r--r--gst/videoparsers/gstdiracparse.c9
-rw-r--r--gst/videoparsers/gsth263parse.c16
-rw-r--r--gst/videoparsers/gsth264parse.c66
-rw-r--r--gst/videoparsers/gstmpegvideoparse.c56
-rw-r--r--gst/videoparsers/gstmpegvideoparse.h1
-rw-r--r--gst/videoparsers/plugin.c6
-rw-r--r--tests/check/Makefile.am13
-rw-r--r--tests/check/libs/h264parser.c2
-rw-r--r--tests/check/libs/vc1parser.c1230
67 files changed, 5188 insertions, 1549 deletions
diff --git a/common b/common
-Subproject a39eb835fb3be2a4c5a6a89b5ca5cc064e79b2e
+Subproject 11f0cd5a3fba36f85cf3e434150bfe66b1bf08d
diff --git a/configure.ac b/configure.ac
index dda50d4c9..a82ddb72d 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1735,6 +1735,17 @@ AG_GST_CHECK_FEATURE(RTMP, [rtmp library], rtmp, [
AG_GST_PKG_CHECK_MODULES(RTMP, librtmp)
])
+dnl *** spandsp ***
+translit(dnm, m, l) AM_CONDITIONAL(USE_SPANDSP, true)
+AG_GST_CHECK_FEATURE(SPANDSP, [Spandsp], spandsp, [
+ PKG_CHECK_MODULES(SPANDSP, spandsp >= 0.0.6, [
+ HAVE_SPANDSP="yes" ], [
+ HAVE_SPANDSP="no"
+ ])
+])
+AC_SUBST(SPANDSP_CFLAGS)
+AC_SUBST(SPANDSP_LIBS)
+
dnl *** GSettings ***
translit(dnm, m, l) AM_CONDITIONAL(USE_GSETTINGS, true)
AG_GST_CHECK_FEATURE(GSETTINGS, [GSettings plugin], gsettings, [
@@ -1797,6 +1808,7 @@ AM_CONDITIONAL(USE_WILDMIDI, false)
AM_CONDITIONAL(USE_SDL, false)
AM_CONDITIONAL(USE_SNDFILE, false)
AM_CONDITIONAL(USE_SOUNDTOUCH, false)
+AM_CONDITIONAL(USE_SPANDSP, false)
AM_CONDITIONAL(USE_SPC, false)
AM_CONDITIONAL(USE_GME, false)
AM_CONDITIONAL(USE_GSETTINGS, false)
@@ -2046,6 +2058,7 @@ ext/schroedinger/Makefile
ext/sdl/Makefile
ext/sndfile/Makefile
ext/soundtouch/Makefile
+ext/spandsp/Makefile
ext/teletextdec/Makefile
ext/gme/Makefile
ext/gsettings/Makefile
diff --git a/docs/libs/.gitignore b/docs/libs/.gitignore
new file mode 100644
index 000000000..83bf78579
--- /dev/null
+++ b/docs/libs/.gitignore
@@ -0,0 +1,28 @@
+Makefile
+Makefile.in
+
+*-decl.txt
+*-decl-list.txt
+*-undocumented.txt
+*-undeclared.txt
+*-unused.txt
+*.bak
+*.args
+*.hierarchy
+*.interfaces
+*.prerequisites
+*.signals
+
+gst-plugins-bad-libs.args.new
+gst-plugins-bad-libs.signals.new
+
+tmpl
+xml
+html
+
+gst-plugins-bad-libs-scan
+gst-plugins-bad-libs-scan.c
+*-registry.*
+
+*.stamp
+
diff --git a/docs/libs/Makefile.am b/docs/libs/Makefile.am
index e93bbda17..aaa35658d 100644
--- a/docs/libs/Makefile.am
+++ b/docs/libs/Makefile.am
@@ -13,43 +13,17 @@ FORMATS=html
html: html-build.stamp
include $(top_srcdir)/common/upload-doc.mak
-# generated basefiles
-#basefiles = \
-## $(DOC_MODULE).types \
-# $(DOC_MODULE)-sections.txt \
-# $(DOC_MODULE)-docs.sgml
-
-# ugly hack to make -unused.sgml work
-#unused-build.stamp:
-# BUILDDIR=`pwd` && \
-# cd $(srcdir)/tmpl && \
-# ln -sf gstreamer-libs-unused.sgml \
-# $$BUILDDIR/tmpl/gstreamer-libs-@GST_MAJORMINOR@-unused.sgml
-# touch unused-build.stamp
-
-# these rules are added to create parallel docs using GST_MAJORMINOR
-#$(basefiles): gstreamer-libs-@GST_MAJORMINOR@%: gstreamer-libs%
-# cp $< $@
-
-#CLEANFILES = $(basefiles)
-
# The top-level SGML file. Change it if you want.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
-# The directory containing the source code. Relative to $(top_srcdir).
+# The directory containing the source code.
# gtk-doc will search all .c & .h files beneath here for inline comments
# documenting functions and macros.
DOC_SOURCE_DIR=$(top_srcdir)/gst-libs/gst
-DOC_BUILD_DIR=$(top_builddir)/gst-libs/gst
# Extra options to supply to gtkdoc-scan.
SCAN_OPTIONS=--deprecated-guards="GST_DISABLE_DEPRECATED"
-# FIXME :
-# there's something wrong with gstreamer-sections.txt not being in the dist
-# maybe it doesn't resolve; we're adding it below for now
-#EXTRA_DIST = gstreamer.types.in gstreamer.hierarchy $(DOC_MODULE)-sections.txt gstreamer-sections.txt $(DOC_MAIN_SGML_FILE)
-
# Extra options to supply to gtkdoc-mkdb.
MKDB_OPTIONS=--sgml-mode --output-format=xml
@@ -58,20 +32,8 @@ FIXXREF_OPTIONS=--extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \
--extra-dir=$(GST_PREFIX)/share/gtk-doc/html
# Used for dependencies.
-HFILE_GLOB=$(DOC_SOURCE_DIR)/*/*.h
-CFILE_GLOB=$(DOC_SOURCE_DIR)/*/*.c
-
-# this is a wingo addition
-# thomasvs: another nice wingo addition would be an explanation on why
-# this is useful ;)
-
-SCANOBJ_DEPS = \
- $(top_builddir)/gst-libs/gst/codecparsers/libgstcodecparsers-@GST_MAJORMINOR@.la \
- $(top_builddir)/gst-libs/gst/basecamerabinsrc/libgstbasecamerabinsrc-@GST_MAJORMINOR@.la \
- $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \
- $(top_builddir)/gst-libs/gst/signalprocessor/libgstsignalprocessor-@GST_MAJORMINOR@.la \
- $(top_builddir)/gst-libs/gst/video/libgstbasevideo-@GST_MAJORMINOR@.la
-
+HFILE_GLOB=$(top_srcdir)/gst-libs/gst/*/*.h
+CFILE_GLOB=$(top_srcdir)/gst-libs/gst/*/*.c
# Header files to ignore when scanning.
IGNORE_HFILES =
@@ -88,7 +50,13 @@ extra_files =
# CFLAGS and LDFLAGS for compiling scan program. Only needed if your app/lib
# contains GtkObjects/GObjects and you want to document signals and properties.
GTKDOC_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS)
-GTKDOC_LIBS = $(SCANOBJ_DEPS) $(GST_BASE_LIBS) $(GST_BAD_LIBS)
+GTKDOC_LIBS = \
+ $(top_builddir)/gst-libs/gst/codecparsers/libgstcodecparsers-@GST_MAJORMINOR@.la \
+ $(top_builddir)/gst-libs/gst/basecamerabinsrc/libgstbasecamerabinsrc-@GST_MAJORMINOR@.la \
+ $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \
+ $(top_builddir)/gst-libs/gst/signalprocessor/libgstsignalprocessor-@GST_MAJORMINOR@.la \
+ $(top_builddir)/gst-libs/gst/video/libgstbasevideo-@GST_MAJORMINOR@.la \
+ $(GST_BASE_LIBS) $(GST_BAD_LIBS)
GTKDOC_CC=$(LIBTOOL) --tag=CC --mode=compile $(CC)
GTKDOC_LD=$(LIBTOOL) --tag=CC --mode=link $(CC)
diff --git a/docs/libs/gst-plugins-bad-libs-docs.sgml b/docs/libs/gst-plugins-bad-libs-docs.sgml
index f137ca3c2..bc648842e 100644
--- a/docs/libs/gst-plugins-bad-libs-docs.sgml
+++ b/docs/libs/gst-plugins-bad-libs-docs.sgml
@@ -30,6 +30,7 @@
</para>
<xi:include href="xml/gsth264parser.xml" />
<xi:include href="xml/gstmpegvideoparser.xml" />
+ <xi:include href="xml/gstvc1parser.xml" />
</chapter>
<chapter id="video">
diff --git a/docs/libs/gst-plugins-bad-libs-sections.txt b/docs/libs/gst-plugins-bad-libs-sections.txt
index 73cc72019..cd515e6af 100644
--- a/docs/libs/gst-plugins-bad-libs-sections.txt
+++ b/docs/libs/gst-plugins-bad-libs-sections.txt
@@ -45,6 +45,40 @@ gst_h264_parse_pps
</SECTION>
<SECTION>
+<FILE>gstvc1parser</FILE>
+<TITLE>vc1parser</TITLE>
+<INCLUDE>gst/codecparsers/gstvc1parser.h</INCLUDE>
+MAX_HRD_NUM_LEAKY_BUCKETS
+GST_VC1_BFRACTION_BASIS
+GstVC1StartCode
+GstVC1Profile
+GstVC1ParseResult
+GstVC1PictureType
+GstVC1Level
+GstVC1QuantizerSpec
+GstVC1DQProfile
+GstVC1Condover
+GstVC1MvMode
+GstVC1SeqHdr
+GstVC1AdvancedSeqHdr
+GstVC1SimpleMainSeqHdr
+GstVC1HrdParam
+GstVC1EntryPointHdr
+GstVC1FrameHdr
+GstVC1PicAdvanced
+GstVC1PicSimpleMain
+GstVC1Picture
+GstVC1VopDquant
+GstVC1BDU
+gst_vc1_identify_next_bdu
+gst_vc1_parse_sequence_header
+gst_vc1_parse_entry_point_header
+gst_vc1_parse_frame_header
+<SUBSECTION Standard>
+<SUBSECTION Private>
+</SECTION>
+
+<SECTION>
<FILE>gstmpegvideoparser</FILE>
<TITLE>mpegvideoparser</TITLE>
<INCLUDE>gst/codecparsers/gstmpegvideoparser.h</INCLUDE>
diff --git a/docs/plugins/Makefile.am b/docs/plugins/Makefile.am
index 4f8f0cfcd..a948927df 100644
--- a/docs/plugins/Makefile.am
+++ b/docs/plugins/Makefile.am
@@ -13,33 +13,13 @@ FORMATS=html
html: html-build.stamp
include $(top_srcdir)/common/upload-doc.mak
-# generated basefiles
-#basefiles = \
-## $(DOC_MODULE).types \
-# $(DOC_MODULE)-sections.txt \
-# $(DOC_MODULE)-docs.sgml
-
-# ugly hack to make -unused.sgml work
-#unused-build.stamp:
-# BUILDDIR=`pwd` && \
-# cd $(srcdir)/tmpl && \
-# ln -sf gstreamer-libs-unused.sgml \
-# $$BUILDDIR/tmpl/gstreamer-libs-@GST_MAJORMINOR@-unused.sgml
-# touch unused-build.stamp
-
-# these rules are added to create parallel docs using GST_MAJORMINOR
-#$(basefiles): gstreamer-libs-@GST_MAJORMINOR@%: gstreamer-libs%
-# cp $< $@
-
-#CLEANFILES = $(basefiles)
-
# The top-level SGML file. Change it if you want.
DOC_MAIN_SGML_FILE=$(DOC_MODULE)-docs.sgml
-# The directory containing the source code. Relative to $(top_srcdir).
+# The directory containing the source code.
# gtk-doc will search all .c & .h files beneath here for inline comments
# documenting functions and macros.
-DOC_SOURCE_DIR = $(top_srcdir)
+DOC_SOURCE_DIR = $(top_srcdir)/gst $(top_srcdir)/ext $(top_srcdir)/sys
# Extra options to supply to gtkdoc-scan.
SCAN_OPTIONS=
@@ -53,15 +33,12 @@ FIXXREF_OPTIONS=--extra-dir=$(GLIB_PREFIX)/share/gtk-doc/html \
--extra-dir=$(GSTPB_PREFIX)/share/gtk-doc/html
# Used for dependencies.
-HFILE_GLOB=$(DOC_SOURCE_DIR)/*/*/*.h $(DOC_SOURCE_DIR)/*/*/*.hh
-CFILE_GLOB=$(DOC_SOURCE_DIR)/*/*/*.c $(DOC_SOURCE_DIR)/*/*/*.cc
-
-# this is a wingo addition
-# thomasvs: another nice wingo addition would be an explanation on why
-# this is useful ;)
-
-SCANOBJ_DEPS = \
- $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la
+HFILE_GLOB= \
+ $(top_srcdir)/gst/*/*.h $(top_srcdir)/ext/*/*.h $(top_srcdir)/sys/*/*.h \
+ $(top_srcdir)/ext/*/*.hh
+CFILE_GLOB= \
+ $(top_srcdir)/gst/*/*.c $(top_srcdir)/ext/*/*.c $(top_srcdir)/sys/*/*.c \
+ $(top_srcdir)/ext/*/*.cc $(top_srcdir)/sys/*/*.m
# Header files to ignore when scanning.
IGNORE_HFILES =
@@ -214,7 +191,9 @@ extra_files =
# CFLAGS and LDFLAGS for compiling scan program. Only needed if your app/lib
# contains GtkObjects/GObjects and you want to document signals and properties.
GTKDOC_CFLAGS = -DGST_USE_UNSTABLE_API $(GST_PLUGINS_BAD_CFLAGS) $(GST_BASE_CFLAGS) -I$(top_builddir)
-GTKDOC_LIBS = $(SCANOBJ_DEPS) $(GST_BASE_LIBS)
+GTKDOC_LIBS = \
+ $(top_builddir)/gst-libs/gst/interfaces/libgstphotography-@GST_MAJORMINOR@.la \
+ $(GST_BASE_LIBS)
GTKDOC_CC=$(LIBTOOL) --tag=CC --mode=compile $(CC)
GTKDOC_LD=$(LIBTOOL) --tag=CC --mode=link $(CC)
diff --git a/docs/plugins/gst-plugins-bad-plugins-sections.txt b/docs/plugins/gst-plugins-bad-plugins-sections.txt
index 29315d4af..d7fc96e95 100644
--- a/docs/plugins/gst-plugins-bad-plugins-sections.txt
+++ b/docs/plugins/gst-plugins-bad-plugins-sections.txt
@@ -121,12 +121,12 @@ gst_camerabin_get_type
GstCameraBin2
<SUBSECTION Standard>
GstCameraBin2Class
-GST_CAMERABIN2
-GST_IS_CAMERABIN2
-GST_TYPE_CAMERABIN2
-GST_CAMERABIN2_CLASS
-GST_IS_CAMERABIN2_CLASS
-gst_camerabin2_get_type
+GST_CAMERA_BIN2
+GST_IS_CAMERA_BIN2
+GST_TYPE_CAMERA_BIN2
+GST_CAMERA_BIN2_CLASS
+GST_IS_CAMERA_BIN2_CLASS
+gst_camera_bin2_get_type
</SECTION>
<SECTION>
diff --git a/ext/Makefile.am b/ext/Makefile.am
index 2a6f8ec76..95ba3da75 100644
--- a/ext/Makefile.am
+++ b/ext/Makefile.am
@@ -324,6 +324,12 @@ else
SOUNDTOUCH_DIR=
endif
+if USE_SPANDSP
+SPANDSP_DIR = spandsp
+else
+SPANDSP_DIR =
+endif
+
if USE_SPC
SPC_DIR=spc
else
@@ -433,6 +439,7 @@ SUBDIRS=\
$(SMOOTHWAVE_DIR) \
$(SNDFILE_DIR) \
$(SOUNDTOUCH_DIR) \
+ $(SPANDSP_DIR) \
$(GME_DIR) \
$(SPC_DIR) \
$(SWFDEC_DIR) \
@@ -485,6 +492,7 @@ DIST_SUBDIRS = \
sdl \
sndfile \
soundtouch \
+ spandsp \
spc \
gme \
swfdec \
diff --git a/ext/celt/gstceltdec.c b/ext/celt/gstceltdec.c
index f80e5cdb1..6d3d9433c 100644
--- a/ext/celt/gstceltdec.c
+++ b/ext/celt/gstceltdec.c
@@ -560,8 +560,11 @@ celt_dec_chain_parse_header (GstCeltDec * dec, GstBuffer * buf)
gint error = CELT_OK;
/* get the header */
- celt_header_from_packet ((const unsigned char *) GST_BUFFER_DATA (buf),
+ error =
+ celt_header_from_packet ((const unsigned char *) GST_BUFFER_DATA (buf),
GST_BUFFER_SIZE (buf), &dec->header);
+ if (error < 0)
+ goto invalid_header;
if (memcmp (dec->header.codec_id, "CELT ", 8) != 0)
goto invalid_header;
@@ -760,7 +763,11 @@ celt_dec_chain_parse_data (GstCeltDec * dec, GstBuffer * buf,
#else
error = celt_decode (dec->state, data, size, out_data);
#endif
+#ifdef HAVE_CELT_0_11
+ if (error < 0) {
+#else
if (error != CELT_OK) {
+#endif
GST_WARNING_OBJECT (dec, "Decoding error: %d", error);
return GST_FLOW_ERROR;
}
diff --git a/ext/celt/gstceltenc.c b/ext/celt/gstceltenc.c
index 74815798e..9e6944df0 100644
--- a/ext/celt/gstceltenc.c
+++ b/ext/celt/gstceltenc.c
@@ -253,6 +253,9 @@ gst_celt_enc_sink_setcaps (GstPad * pad, GstCaps * caps)
gst_caps_unref (otherpadcaps);
}
+ if (enc->requested_frame_size > 0)
+ enc->frame_size = enc->requested_frame_size;
+
GST_DEBUG_OBJECT (pad, "channels=%d rate=%d frame-size=%d",
enc->channels, enc->rate, enc->frame_size);
@@ -573,6 +576,7 @@ gst_celt_enc_init (GstCeltEnc * enc, GstCeltEncClass * klass)
enc->bitrate = DEFAULT_BITRATE;
enc->frame_size = DEFAULT_FRAMESIZE;
+ enc->requested_frame_size = -1;
enc->cbr = DEFAULT_CBR;
enc->complexity = DEFAULT_COMPLEXITY;
enc->max_bitrate = DEFAULT_MAX_BITRATE;
@@ -695,16 +699,18 @@ encoder_creation_failed:
/* prepare a buffer for transmission */
static GstBuffer *
gst_celt_enc_buffer_from_data (GstCeltEnc * enc, guchar * data,
- gint data_len, guint64 granulepos)
+ guint data_len, gint64 granulepos)
{
GstBuffer *outbuf;
- outbuf = gst_buffer_new_and_alloc (data_len);
- memcpy (GST_BUFFER_DATA (outbuf), data, data_len);
+ outbuf = gst_buffer_new ();
+ GST_BUFFER_DATA (outbuf) = data;
+ GST_BUFFER_MALLOCDATA (outbuf) = data;
+ GST_BUFFER_SIZE (outbuf) = data_len;
GST_BUFFER_OFFSET (outbuf) = enc->bytes_out;
GST_BUFFER_OFFSET_END (outbuf) = granulepos;
- GST_LOG_OBJECT (enc, "encoded buffer of %d bytes", GST_BUFFER_SIZE (outbuf));
+ GST_LOG_OBJECT (enc, "encoded buffer of %u bytes", GST_BUFFER_SIZE (outbuf));
return outbuf;
}
@@ -903,11 +909,17 @@ gst_celt_enc_chain (GstPad * pad, GstBuffer * buf)
constraints */
GstBuffer *buf1, *buf2;
GstCaps *caps;
- guchar data[100];
+ /* libcelt has a bug which underestimates header size by 4... */
+ unsigned int header_size = enc->header.header_size + 4;
+ unsigned char *data = g_malloc (header_size);
/* create header buffer */
- celt_header_to_packet (&enc->header, data, 100);
- buf1 = gst_celt_enc_buffer_from_data (enc, data, 100, 0);
+ int error = celt_header_to_packet (&enc->header, data, header_size);
+ if (error < 0) {
+ g_free (data);
+ goto no_header;
+ }
+ buf1 = gst_celt_enc_buffer_from_data (enc, data, header_size, 0);
/* create comment buffer */
buf2 = gst_celt_enc_create_metadata_buffer (enc);
@@ -966,6 +978,7 @@ gst_celt_enc_chain (GstPad * pad, GstBuffer * buf)
/* Check if we have a continous stream, if not drop some samples or the buffer or
* insert some silence samples */
if (enc->next_ts != GST_CLOCK_TIME_NONE &&
+ GST_BUFFER_TIMESTAMP_IS_VALID (buf) &&
GST_BUFFER_TIMESTAMP (buf) < enc->next_ts) {
guint64 diff = enc->next_ts - GST_BUFFER_TIMESTAMP (buf);
guint64 diff_bytes;
@@ -1038,6 +1051,13 @@ not_setup:
goto done;
}
+no_header:
+ {
+ GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL),
+ ("Failed to encode header"));
+ ret = GST_FLOW_ERROR;
+ goto done;
+ }
}
@@ -1090,7 +1110,8 @@ gst_celt_enc_set_property (GObject * object, guint prop_id,
enc->bitrate = g_value_get_int (value);
break;
case PROP_FRAMESIZE:
- enc->frame_size = g_value_get_int (value);
+ enc->requested_frame_size = g_value_get_int (value);
+ enc->frame_size = enc->requested_frame_size;
break;
case PROP_CBR:
enc->cbr = g_value_get_boolean (value);
diff --git a/ext/celt/gstceltenc.h b/ext/celt/gstceltenc.h
index ec8a283c0..86fbc36f3 100644
--- a/ext/celt/gstceltenc.h
+++ b/ext/celt/gstceltenc.h
@@ -62,6 +62,7 @@ struct _GstCeltEnc {
gint bitrate;
gint frame_size;
+ gint requested_frame_size;
gboolean cbr;
gint complexity;
gint max_bitrate;
diff --git a/ext/faac/Makefile.am b/ext/faac/Makefile.am
index 13918ed3e..2aafa0229 100644
--- a/ext/faac/Makefile.am
+++ b/ext/faac/Makefile.am
@@ -1,7 +1,8 @@
plugin_LTLIBRARIES = libgstfaac.la
libgstfaac_la_SOURCES = gstfaac.c
-libgstfaac_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) \
+libgstfaac_la_CFLAGS = -DGST_USE_UNSTABLE_API \
+ $(GST_PLUGINS_BASE_CFLAGS) $(GST_BASE_CFLAGS) \
$(GST_CFLAGS) $(FAAC_CFLAGS)
libgstfaac_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \
-lgstaudio-@GST_MAJORMINOR@ -lgstpbutils-@GST_MAJORMINOR@ \
diff --git a/ext/faac/gstfaac.c b/ext/faac/gstfaac.c
index c0db878d5..eb132d3b4 100644
--- a/ext/faac/gstfaac.c
+++ b/ext/faac/gstfaac.c
@@ -91,12 +91,6 @@
"rate = (int) {" SAMPLE_RATES "}, " \
"stream-format = (string) { adts, raw }, " \
"profile = (string) { main, lc }"
- enum
-{
- VBR = 1,
- ABR
-};
-
static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
@@ -119,74 +113,41 @@ enum
PROP_SHORTCTL
};
-static void gst_faac_base_init (GstFaacClass * klass);
-static void gst_faac_class_init (GstFaacClass * klass);
-static void gst_faac_init (GstFaac * faac);
-static void gst_faac_finalize (GObject * object);
-static void gst_faac_reset (GstFaac * faac);
+enum
+{
+ VBR = 1,
+ ABR
+};
static void gst_faac_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec);
static void gst_faac_get_property (GObject * object,
guint prop_id, GValue * value, GParamSpec * pspec);
-static gboolean gst_faac_sink_event (GstPad * pad, GstEvent * event);
static gboolean gst_faac_configure_source_pad (GstFaac * faac);
-static gboolean gst_faac_sink_setcaps (GstPad * pad, GstCaps * caps);
-static GstCaps *gst_faac_sink_getcaps (GstPad * pad);
-static GstFlowReturn gst_faac_push_buffers (GstFaac * faac, gboolean force);
-static GstFlowReturn gst_faac_chain (GstPad * pad, GstBuffer * data);
-static GstStateChangeReturn gst_faac_change_state (GstElement * element,
- GstStateChange transition);
+static GstCaps *gst_faac_getcaps (GstAudioEncoder * enc);
-static GstElementClass *parent_class = NULL;
+static gboolean gst_faac_start (GstAudioEncoder * enc);
+static gboolean gst_faac_stop (GstAudioEncoder * enc);
+static gboolean gst_faac_set_format (GstAudioEncoder * enc,
+ GstAudioInfo * info);
+static GstFlowReturn gst_faac_handle_frame (GstAudioEncoder * enc,
+ GstBuffer * in_buf);
GST_DEBUG_CATEGORY_STATIC (faac_debug);
#define GST_CAT_DEFAULT faac_debug
-#define FAAC_DEFAULT_OUTPUTFORMAT 0 /* RAW */
#define FAAC_DEFAULT_QUALITY 100
#define FAAC_DEFAULT_BITRATE 128 * 1000
-#define FAAC_DEFAULT_RATE_CONTROL VBR
+#define FAAC_DEFAULT_RATE_CONTROL VBR
#define FAAC_DEFAULT_TNS FALSE
#define FAAC_DEFAULT_MIDSIDE TRUE
#define FAAC_DEFAULT_SHORTCTL SHORTCTL_NORMAL
-GType
-gst_faac_get_type (void)
-{
- static GType gst_faac_type = 0;
-
- if (!gst_faac_type) {
- static const GTypeInfo gst_faac_info = {
- sizeof (GstFaacClass),
- (GBaseInitFunc) gst_faac_base_init,
- NULL,
- (GClassInitFunc) gst_faac_class_init,
- NULL,
- NULL,
- sizeof (GstFaac),
- 0,
- (GInstanceInitFunc) gst_faac_init,
- };
- const GInterfaceInfo preset_interface_info = {
- NULL, /* interface_init */
- NULL, /* interface_finalize */
- NULL /* interface_data */
- };
-
- gst_faac_type = g_type_register_static (GST_TYPE_ELEMENT,
- "GstFaac", &gst_faac_info, 0);
-
- g_type_add_interface_static (gst_faac_type, GST_TYPE_PRESET,
- &preset_interface_info);
- }
-
- return gst_faac_type;
-}
+GST_BOILERPLATE (GstFaac, gst_faac, GstAudioEncoder, GST_TYPE_AUDIO_ENCODER);
static void
-gst_faac_base_init (GstFaacClass * klass)
+gst_faac_base_init (gpointer klass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
@@ -248,106 +209,80 @@ static void
gst_faac_class_init (GstFaacClass * klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
+ GstAudioEncoderClass *base_class = GST_AUDIO_ENCODER_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
gobject_class->set_property = gst_faac_set_property;
gobject_class->get_property = gst_faac_get_property;
- gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_faac_finalize);
+
+ base_class->start = GST_DEBUG_FUNCPTR (gst_faac_start);
+ base_class->stop = GST_DEBUG_FUNCPTR (gst_faac_stop);
+ base_class->set_format = GST_DEBUG_FUNCPTR (gst_faac_set_format);
+ base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_faac_handle_frame);
+ base_class->getcaps = GST_DEBUG_FUNCPTR (gst_faac_getcaps);
/* properties */
g_object_class_install_property (gobject_class, PROP_QUALITY,
g_param_spec_int ("quality", "Quality (%)",
"Variable bitrate (VBR) quantizer quality in %", 1, 1000,
- FAAC_DEFAULT_QUALITY, G_PARAM_READWRITE));
+ FAAC_DEFAULT_QUALITY,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_BITRATE,
g_param_spec_int ("bitrate", "Bitrate (bps)",
- "Average bitrate (ABR) in bits/sec", 8 * 1000, 320 * 1000,
- FAAC_DEFAULT_BITRATE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ "Average Bitrate (ABR) in bits/sec", 8 * 1000, 320 * 1000,
+ FAAC_DEFAULT_BITRATE,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_RATE_CONTROL,
g_param_spec_enum ("rate-control", "Rate Control (ABR/VBR)",
"Encoding bitrate type (VBR/ABR)", GST_TYPE_FAAC_RATE_CONTROL,
- FAAC_DEFAULT_RATE_CONTROL, G_PARAM_READWRITE));
+ FAAC_DEFAULT_RATE_CONTROL,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_TNS,
g_param_spec_boolean ("tns", "TNS", "Use temporal noise shaping",
- FAAC_DEFAULT_TNS, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ FAAC_DEFAULT_TNS,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_MIDSIDE,
g_param_spec_boolean ("midside", "Midside", "Allow mid/side encoding",
- FAAC_DEFAULT_MIDSIDE, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ FAAC_DEFAULT_MIDSIDE,
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (gobject_class, PROP_SHORTCTL,
g_param_spec_enum ("shortctl", "Block type",
"Block type encorcing",
GST_TYPE_FAAC_SHORTCTL, FAAC_DEFAULT_SHORTCTL,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
-
- /* virtual functions */
- gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_faac_change_state);
+ G_PARAM_CONSTRUCT | G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
}
static void
-gst_faac_init (GstFaac * faac)
+gst_faac_init (GstFaac * faac, GstFaacClass * klass)
{
- faac->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
- gst_pad_set_chain_function (faac->sinkpad,
- GST_DEBUG_FUNCPTR (gst_faac_chain));
- gst_pad_set_setcaps_function (faac->sinkpad,
- GST_DEBUG_FUNCPTR (gst_faac_sink_setcaps));
- gst_pad_set_getcaps_function (faac->sinkpad,
- GST_DEBUG_FUNCPTR (gst_faac_sink_getcaps));
- gst_pad_set_event_function (faac->sinkpad,
- GST_DEBUG_FUNCPTR (gst_faac_sink_event));
- gst_element_add_pad (GST_ELEMENT (faac), faac->sinkpad);
-
- faac->srcpad = gst_pad_new_from_static_template (&src_template, "src");
- gst_pad_use_fixed_caps (faac->srcpad);
- gst_element_add_pad (GST_ELEMENT (faac), faac->srcpad);
-
- faac->adapter = gst_adapter_new ();
-
- faac->profile = LOW;
- faac->mpegversion = 4;
-
- /* default properties */
- faac->quality = FAAC_DEFAULT_QUALITY;
- faac->bitrate = FAAC_DEFAULT_BITRATE;
- faac->brtype = FAAC_DEFAULT_RATE_CONTROL;
- faac->shortctl = FAAC_DEFAULT_SHORTCTL;
- faac->outputformat = FAAC_DEFAULT_OUTPUTFORMAT;
- faac->tns = FAAC_DEFAULT_TNS;
- faac->midside = FAAC_DEFAULT_MIDSIDE;
-
- gst_faac_reset (faac);
}
static void
-gst_faac_reset (GstFaac * faac)
+gst_faac_close_encoder (GstFaac * faac)
{
+ if (faac->handle)
+ faacEncClose (faac->handle);
faac->handle = NULL;
- faac->samplerate = -1;
- faac->channels = -1;
- faac->offset = 0;
- gst_adapter_clear (faac->adapter);
}
-static void
-gst_faac_finalize (GObject * object)
+static gboolean
+gst_faac_start (GstAudioEncoder * enc)
{
- GstFaac *faac = (GstFaac *) object;
+ GstFaac *faac = GST_FAAC (enc);
- g_object_unref (faac->adapter);
-
- G_OBJECT_CLASS (parent_class)->finalize (object);
+ GST_DEBUG_OBJECT (faac, "start");
+ return TRUE;
}
-static void
-gst_faac_close_encoder (GstFaac * faac)
+static gboolean
+gst_faac_stop (GstAudioEncoder * enc)
{
- if (faac->handle)
- faacEncClose (faac->handle);
- faac->handle = NULL;
- gst_adapter_clear (faac->adapter);
- faac->offset = 0;
+ GstFaac *faac = GST_FAAC (enc);
+
+ GST_DEBUG_OBJECT (faac, "stop");
+ gst_faac_close_encoder (faac);
+ return TRUE;
}
static const GstAudioChannelPosition aac_channel_positions[][8] = {
@@ -380,7 +315,7 @@ static const GstAudioChannelPosition aac_channel_positions[][8] = {
};
static GstCaps *
-gst_faac_sink_getcaps (GstPad * pad)
+gst_faac_getcaps (GstAudioEncoder * enc)
{
static volatile gsize sinkcaps = 0;
@@ -433,87 +368,29 @@ gst_faac_sink_getcaps (GstPad * pad)
gst_structure_free (s);
g_value_unset (&rates_arr);
- GST_DEBUG_OBJECT (pad, "Generated sinkcaps: %" GST_PTR_FORMAT, tmp);
+ GST_DEBUG_OBJECT (enc, "Generated sinkcaps: %" GST_PTR_FORMAT, tmp);
g_once_init_leave (&sinkcaps, (gsize) tmp);
}
- return gst_caps_ref ((GstCaps *) sinkcaps);
-}
-
-/* check downstream caps to configure format */
-static void
-gst_faac_negotiate (GstFaac * faac)
-{
- GstCaps *caps;
-
- caps = gst_pad_get_allowed_caps (faac->srcpad);
-
- GST_DEBUG_OBJECT (faac, "allowed caps: %" GST_PTR_FORMAT, caps);
-
- if (caps && gst_caps_get_size (caps) > 0) {
- GstStructure *s = gst_caps_get_structure (caps, 0);
- const gchar *str = NULL;
- gint i = 4;
-
- if ((str = gst_structure_get_string (s, "stream-format"))) {
- if (strcmp (str, "adts") == 0) {
- GST_DEBUG_OBJECT (faac, "use ADTS format for output");
- faac->outputformat = 1;
- } else if (strcmp (str, "raw") == 0) {
- GST_DEBUG_OBJECT (faac, "use RAW format for output");
- faac->outputformat = 0;
- } else {
- GST_DEBUG_OBJECT (faac, "unknown stream-format: %s", str);
- faac->outputformat = 0;
- }
- }
-
- if ((str = gst_structure_get_string (s, "profile"))) {
- if (strcmp (str, "main") == 0) {
- faac->profile = MAIN;
- } else if (strcmp (str, "lc") == 0) {
- faac->profile = LOW;
- } else if (strcmp (str, "ssr") == 0) {
- faac->profile = SSR;
- } else if (strcmp (str, "ltp") == 0) {
- faac->profile = LTP;
- } else {
- faac->profile = LOW;
- }
- }
-
- if (!gst_structure_get_int (s, "mpegversion", &i) || i == 4) {
- faac->mpegversion = 4;
- } else {
- faac->mpegversion = 2;
- }
- }
-
- if (caps)
- gst_caps_unref (caps);
+ return gst_audio_encoder_proxy_getcaps (enc, (GstCaps *) sinkcaps);
}
static gboolean
-gst_faac_sink_setcaps (GstPad * pad, GstCaps * caps)
+gst_faac_set_format (GstAudioEncoder * enc, GstAudioInfo * info)
{
- GstFaac *faac = GST_FAAC (gst_pad_get_parent (pad));
- GstStructure *structure = gst_caps_get_structure (caps, 0);
+ GstFaac *faac = GST_FAAC (enc);
faacEncHandle *handle;
gint channels, samplerate, width;
gulong samples, bytes, fmt = 0, bps = 0;
gboolean result = FALSE;
- if (!gst_caps_is_fixed (caps))
- goto refuse_caps;
-
- if (!gst_structure_get_int (structure, "channels", &channels) ||
- !gst_structure_get_int (structure, "rate", &samplerate)) {
- goto refuse_caps;
- }
+ /* base class takes care */
+ channels = GST_AUDIO_INFO_CHANNELS (info);
+ samplerate = GST_AUDIO_INFO_RATE (info);
+ width = GST_AUDIO_INFO_WIDTH (info);
- if (gst_structure_has_name (structure, "audio/x-raw-int")) {
- gst_structure_get_int (structure, "width", &width);
+ if (GST_AUDIO_INFO_IS_INTEGER (info)) {
switch (width) {
case 16:
fmt = FAAC_INPUT_16BIT;
@@ -527,30 +404,20 @@ gst_faac_sink_setcaps (GstPad * pad, GstCaps * caps)
default:
g_return_val_if_reached (FALSE);
}
- } else if (gst_structure_has_name (structure, "audio/x-raw-float")) {
+ } else {
fmt = FAAC_INPUT_FLOAT;
bps = 4;
}
- if (!fmt)
- goto refuse_caps;
-
- /* If the encoder is initialized, do not
- reinitialize it again if not necessary */
- if (faac->handle) {
- if (samplerate == faac->samplerate && channels == faac->channels &&
- fmt == faac->format)
- return TRUE;
-
- /* clear out pending frames */
- gst_faac_push_buffers (faac, TRUE);
-
- gst_faac_close_encoder (faac);
- }
+ /* clean up in case of re-configure */
+ gst_faac_close_encoder (faac);
if (!(handle = faacEncOpen (samplerate, channels, &samples, &bytes)))
goto setup_failed;
+ /* mind channel count */
+ samples /= channels;
+
/* ok, record and set up */
faac->format = fmt;
faac->bps = bps;
@@ -560,13 +427,15 @@ gst_faac_sink_setcaps (GstPad * pad, GstCaps * caps)
faac->channels = channels;
faac->samplerate = samplerate;
- gst_faac_negotiate (faac);
-
/* finish up */
result = gst_faac_configure_source_pad (faac);
+ /* report needs to base class */
+ gst_audio_encoder_set_frame_samples_min (enc, samples);
+ gst_audio_encoder_set_frame_samples_max (enc, samples);
+ gst_audio_encoder_set_frame_max (enc, 1);
+
done:
- gst_object_unref (faac);
return result;
/* ERRORS */
@@ -575,11 +444,64 @@ setup_failed:
GST_ELEMENT_ERROR (faac, LIBRARY, SETTINGS, (NULL), (NULL));
goto done;
}
-refuse_caps:
- {
- GST_WARNING_OBJECT (faac, "refused caps %" GST_PTR_FORMAT, caps);
- goto done;
+}
+
+/* check downstream caps to configure format */
+static void
+gst_faac_negotiate (GstFaac * faac)
+{
+ GstCaps *caps;
+
+ /* default setup */
+ faac->profile = LOW;
+ faac->mpegversion = 4;
+ faac->outputformat = 0;
+
+ caps = gst_pad_get_allowed_caps (GST_AUDIO_ENCODER_SRC_PAD (faac));
+
+ GST_DEBUG_OBJECT (faac, "allowed caps: %" GST_PTR_FORMAT, caps);
+
+ if (caps && gst_caps_get_size (caps) > 0) {
+ GstStructure *s = gst_caps_get_structure (caps, 0);
+ const gchar *str = NULL;
+ gint i = 4;
+
+ if ((str = gst_structure_get_string (s, "stream-format"))) {
+ if (strcmp (str, "adts") == 0) {
+ GST_DEBUG_OBJECT (faac, "use ADTS format for output");
+ faac->outputformat = 1;
+ } else if (strcmp (str, "raw") == 0) {
+ GST_DEBUG_OBJECT (faac, "use RAW format for output");
+ faac->outputformat = 0;
+ } else {
+ GST_DEBUG_OBJECT (faac, "unknown stream-format: %s", str);
+ faac->outputformat = 0;
+ }
+ }
+
+ if ((str = gst_structure_get_string (s, "profile"))) {
+ if (strcmp (str, "main") == 0) {
+ faac->profile = MAIN;
+ } else if (strcmp (str, "lc") == 0) {
+ faac->profile = LOW;
+ } else if (strcmp (str, "ssr") == 0) {
+ faac->profile = SSR;
+ } else if (strcmp (str, "ltp") == 0) {
+ faac->profile = LTP;
+ } else {
+ faac->profile = LOW;
+ }
+ }
+
+ if (!gst_structure_get_int (s, "mpegversion", &i) || i == 4) {
+ faac->mpegversion = 4;
+ } else {
+ faac->mpegversion = 2;
+ }
}
+
+ if (caps)
+ gst_caps_unref (caps);
}
static gboolean
@@ -590,6 +512,9 @@ gst_faac_configure_source_pad (GstFaac * faac)
faacEncConfiguration *conf;
guint maxbitrate;
+ /* negotiate stream format */
+ gst_faac_negotiate (faac);
+
/* we negotiated caps update current configuration */
conf = faacEncGetCurrentConfiguration (faac->handle);
conf->mpegVersion = (faac->mpegversion == 4) ? MPEG4 : MPEG2;
@@ -698,7 +623,7 @@ gst_faac_configure_source_pad (GstFaac * faac)
GST_DEBUG_OBJECT (faac, "src pad caps: %" GST_PTR_FORMAT, srccaps);
- ret = gst_pad_set_caps (faac->srcpad, srccaps);
+ ret = gst_pad_set_caps (GST_AUDIO_ENCODER_SRC_PAD (faac), srccaps);
gst_caps_unref (srccaps);
return ret;
@@ -717,127 +642,33 @@ invalid_codec_data:
}
static GstFlowReturn
-gst_faac_push_buffers (GstFaac * faac, gboolean force)
+gst_faac_handle_frame (GstAudioEncoder * enc, GstBuffer * in_buf)
{
+ GstFaac *faac = GST_FAAC (enc);
GstFlowReturn ret = GST_FLOW_OK;
- gint av, frame_size, size, ret_size;
- GstBuffer *outbuf;
- guint64 timestamp, distance;
+ GstBuffer *out_buf;
+ gint size, ret_size;
const guint8 *data;
- /* samples already considers channel count */
- frame_size = faac->samples * faac->bps;
-
- while (G_LIKELY (ret == GST_FLOW_OK)) {
-
- av = gst_adapter_available (faac->adapter);
-
- GST_LOG_OBJECT (faac, "pushing: force: %d, frame_size: %d, av: %d, "
- "offset: %d", force, frame_size, av, faac->offset);
-
- /* idea:
- * - start of adapter corresponds with what has already been encoded
- * (i.e. really returned by faac)
- * - start + offset is what needs to be fed to faac next
- * That way we can timestamp the output based
- * on adapter provided timestamp (and duration is a fixed frame duration) */
+ out_buf = gst_buffer_new_and_alloc (faac->bytes);
- /* not enough data for one frame and no flush forcing */
- if (!force && (av < frame_size + faac->offset))
- break;
-
- if (G_LIKELY (av - faac->offset >= frame_size)) {
- GST_LOG_OBJECT (faac, "encoding a frame");
- data = gst_adapter_peek (faac->adapter, faac->offset + frame_size);
- data += faac->offset;
- size = frame_size;
- } else if (av - faac->offset > 0) {
- GST_LOG_OBJECT (faac, "encoding leftover");
- data = gst_adapter_peek (faac->adapter, av);
- data += faac->offset;
- size = av - faac->offset;
- } else {
- GST_LOG_OBJECT (faac, "emptying encoder");
- data = NULL;
- size = 0;
- }
-
- outbuf = gst_buffer_new_and_alloc (faac->bytes);
-
- if (G_UNLIKELY ((ret_size = faacEncEncode (faac->handle, (gint32 *) data,
- size / faac->bps, GST_BUFFER_DATA (outbuf),
- faac->bytes)) < 0)) {
- gst_buffer_unref (outbuf);
- goto encode_failed;
- }
-
- GST_LOG_OBJECT (faac, "encoder return: %d", ret_size);
-
- /* consumed, advanced view */
- faac->offset += size;
- g_assert (faac->offset <= av);
-
- if (G_UNLIKELY (!ret_size)) {
- gst_buffer_unref (outbuf);
- if (size)
- continue;
- else
- break;
- }
-
- /* deal with encoder lead-out */
- if (G_UNLIKELY (av == 0 && faac->offset == 0)) {
- GST_DEBUG_OBJECT (faac, "encoder returned additional data");
- /* continuous with previous output, ok to have 0 duration */
- timestamp = faac->next_ts;
- } else {
- /* after some caching, finally some data */
- /* adapter gives time */
- timestamp = gst_adapter_prev_timestamp (faac->adapter, &distance);
- }
-
- if (G_LIKELY ((av = gst_adapter_available (faac->adapter)) >= frame_size)) {
- /* must have then come from a complete frame */
- gst_adapter_flush (faac->adapter, frame_size);
- faac->offset -= frame_size;
- size = frame_size;
- } else {
- /* otherwise leftover */
- gst_adapter_clear (faac->adapter);
- faac->offset = 0;
- size = av;
- }
-
- GST_BUFFER_SIZE (outbuf) = ret_size;
- if (G_LIKELY (GST_CLOCK_TIME_IS_VALID (timestamp)))
- GST_BUFFER_TIMESTAMP (outbuf) = timestamp +
- GST_FRAMES_TO_CLOCK_TIME (distance / faac->channels / faac->bps,
- faac->samplerate);
- GST_BUFFER_DURATION (outbuf) =
- GST_FRAMES_TO_CLOCK_TIME (size / faac->channels / faac->bps,
- faac->samplerate);
- faac->next_ts =
- GST_BUFFER_TIMESTAMP (outbuf) + GST_BUFFER_DURATION (outbuf);
-
- /* perhaps check/set DISCONT based on timestamps ? */
-
- GST_LOG_OBJECT (faac, "Pushing out buffer time: %" GST_TIME_FORMAT
- " duration: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
- GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
-
- gst_buffer_set_caps (outbuf, GST_PAD_CAPS (faac->srcpad));
- ret = gst_pad_push (faac->srcpad, outbuf);
+ if (G_LIKELY (in_buf)) {
+ data = GST_BUFFER_DATA (in_buf);
+ size = GST_BUFFER_SIZE (in_buf);
+ } else {
+ data = NULL;
+ size = 0;
}
- /* in case encoder returns less than expected, clear our view as well */
- if (G_UNLIKELY (force)) {
-#ifndef GST_DISABLE_GST_DEBUG
- if ((av = gst_adapter_available (faac->adapter)))
- GST_WARNING_OBJECT (faac, "encoder left %d bytes; discarding", av);
-#endif
- gst_adapter_clear (faac->adapter);
- faac->offset = 0;
+ if (G_UNLIKELY ((ret_size = faacEncEncode (faac->handle, (gint32 *) data,
+ size / faac->bps, GST_BUFFER_DATA (out_buf),
+ GST_BUFFER_SIZE (out_buf))) < 0))
+ goto encode_failed;
+
+ GST_LOG_OBJECT (faac, "encoder return: %d", ret_size);
+ if (ret_size > 0) {
+ GST_BUFFER_SIZE (out_buf) = ret_size;
+ ret = gst_audio_encoder_finish_frame (enc, out_buf, faac->samples);
}
return ret;
@@ -850,72 +681,6 @@ encode_failed:
}
}
-static gboolean
-gst_faac_sink_event (GstPad * pad, GstEvent * event)
-{
- GstFaac *faac;
- gboolean ret;
-
- faac = GST_FAAC (gst_pad_get_parent (pad));
-
- GST_LOG_OBJECT (faac, "received %s", GST_EVENT_TYPE_NAME (event));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_EOS:
- {
- if (faac->handle) {
- /* flush first */
- GST_DEBUG_OBJECT (faac, "Pushing out remaining buffers because of EOS");
- gst_faac_push_buffers (faac, TRUE);
- }
-
- ret = gst_pad_event_default (pad, event);
- break;
- }
- default:
- ret = gst_pad_event_default (pad, event);
- break;
-
- }
- gst_object_unref (faac);
- return ret;
-}
-
-static GstFlowReturn
-gst_faac_chain (GstPad * pad, GstBuffer * inbuf)
-{
- GstFlowReturn result = GST_FLOW_OK;
- GstFaac *faac;
-
- faac = GST_FAAC (gst_pad_get_parent (pad));
-
- if (!faac->handle)
- goto no_handle;
-
- GST_LOG_OBJECT (faac, "Got buffer time: %" GST_TIME_FORMAT " duration: %"
- GST_TIME_FORMAT, GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (inbuf)),
- GST_TIME_ARGS (GST_BUFFER_DURATION (inbuf)));
-
- gst_adapter_push (faac->adapter, inbuf);
-
- result = gst_faac_push_buffers (faac, FALSE);
-
-done:
- gst_object_unref (faac);
-
- return result;
-
- /* ERRORS */
-no_handle:
- {
- GST_ELEMENT_ERROR (faac, CORE, NEGOTIATION, (NULL),
- ("format wasn't negotiated before chain function"));
- gst_buffer_unref (inbuf);
- result = GST_FLOW_ERROR;
- goto done;
- }
-}
-
static void
gst_faac_set_property (GObject * object,
guint prop_id, const GValue * value, GParamSpec * pspec)
@@ -986,35 +751,6 @@ gst_faac_get_property (GObject * object,
GST_OBJECT_UNLOCK (faac);
}
-static GstStateChangeReturn
-gst_faac_change_state (GstElement * element, GstStateChange transition)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
- GstFaac *faac = GST_FAAC (element);
-
- /* upwards state changes */
- switch (transition) {
- default:
- break;
- }
-
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- /* downwards state changes */
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- {
- gst_faac_close_encoder (faac);
- gst_faac_reset (faac);
- break;
- }
- default:
- break;
- }
-
- return ret;
-}
-
static gboolean
plugin_init (GstPlugin * plugin)
{
diff --git a/ext/faac/gstfaac.h b/ext/faac/gstfaac.h
index f5ab5ab4f..5bd057493 100644
--- a/ext/faac/gstfaac.h
+++ b/ext/faac/gstfaac.h
@@ -21,8 +21,8 @@
#define __GST_FAAC_H__
#include <gst/gst.h>
-#include <gst/base/gstadapter.h>
-#include <gst/audio/audio.h>
+#include <gst/audio/gstaudioencoder.h>
+
#include <faac.h>
G_BEGIN_DECLS
@@ -42,41 +42,37 @@ typedef struct _GstFaac GstFaac;
typedef struct _GstFaacClass GstFaacClass;
struct _GstFaac {
- GstElement element;
-
- /* pads */
- GstPad *srcpad, *sinkpad;
+ GstAudioEncoder element;
/* stream properties */
gint samplerate,
channels,
format,
- bps,
+ bps;
+
+ /* input frame size */
+ gulong samples;
+ /* required output buffer size */
+ gulong bytes;
+
+ /* negotiated */
+ gint mpegversion, outputformat;
+
+ /* properties */
+ gint bitrate,
+ profile,
quality,
- bitrate,
brtype,
- profile,
- mpegversion,
- shortctl,
- outputformat;
+ shortctl;
gboolean tns,
midside;
- gulong bytes,
- samples;
/* FAAC object */
faacEncHandle handle;
-
- /* cache of the input */
- GstAdapter *adapter;
- /* offset of data to be encoded next */
- guint offset;
- /* ts for last buffer */
- GstClockTime next_ts;
};
struct _GstFaacClass {
- GstElementClass parent_class;
+ GstAudioEncoderClass parent_class;
};
GType gst_faac_get_type (void);
diff --git a/ext/faad/Makefile.am b/ext/faad/Makefile.am
index 957ad7849..cc7636dca 100644
--- a/ext/faad/Makefile.am
+++ b/ext/faad/Makefile.am
@@ -1,7 +1,8 @@
plugin_LTLIBRARIES = libgstfaad.la
libgstfaad_la_SOURCES = gstfaad.c
-libgstfaad_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \
+libgstfaad_la_CFLAGS = -DGST_USE_UNSTABLE_API \
+ $(GST_PLUGINS_BASE_CFLAGS) \
$(GST_BASE_CFLAGS) $(GST_CFLAGS) $(FAAD_CFLAGS)
libgstfaad_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) -lgstaudio-@GST_MAJORMINOR@ \
$(GST_BASE_LIBS) $(GST_LIBS) $(FAAD_LIBS)
diff --git a/ext/faad/gstfaad.c b/ext/faad/gstfaad.c
index 1f9c3d228..252e9529d 100644
--- a/ext/faad/gstfaad.c
+++ b/ext/faad/gstfaad.c
@@ -140,55 +140,24 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
GST_STATIC_CAPS (STATIC_CAPS)
);
-static void gst_faad_base_init (GstFaadClass * klass);
-static void gst_faad_class_init (GstFaadClass * klass);
-static void gst_faad_init (GstFaad * faad);
static void gst_faad_reset (GstFaad * faad);
-static void gst_faad_finalize (GObject * object);
-
-static void clear_queued (GstFaad * faad);
-
-static gboolean gst_faad_setcaps (GstPad * pad, GstCaps * caps);
-static gboolean gst_faad_src_event (GstPad * pad, GstEvent * event);
-static gboolean gst_faad_sink_event (GstPad * pad, GstEvent * event);
-static gboolean gst_faad_src_query (GstPad * pad, GstQuery * query);
-static GstFlowReturn gst_faad_chain (GstPad * pad, GstBuffer * buffer);
-static GstStateChangeReturn gst_faad_change_state (GstElement * element,
- GstStateChange transition);
-static gboolean gst_faad_src_convert (GstFaad * faad, GstFormat src_format,
- gint64 src_val, GstFormat dest_format, gint64 * dest_val);
-static gboolean gst_faad_open_decoder (GstFaad * faad);
-static void gst_faad_close_decoder (GstFaad * faad);
-static GstElementClass *parent_class; /* NULL */
+static gboolean gst_faad_start (GstAudioDecoder * dec);
+static gboolean gst_faad_stop (GstAudioDecoder * dec);
+static gboolean gst_faad_set_format (GstAudioDecoder * dec, GstCaps * caps);
+static gboolean gst_faad_parse (GstAudioDecoder * dec, GstAdapter * adapter,
+ gint * offset, gint * length);
+static GstFlowReturn gst_faad_handle_frame (GstAudioDecoder * dec,
+ GstBuffer * buffer);
+static void gst_faad_flush (GstAudioDecoder * dec, gboolean hard);
-GType
-gst_faad_get_type (void)
-{
- static GType gst_faad_type = 0;
-
- if (!gst_faad_type) {
- static const GTypeInfo gst_faad_info = {
- sizeof (GstFaadClass),
- (GBaseInitFunc) gst_faad_base_init,
- NULL,
- (GClassInitFunc) gst_faad_class_init,
- NULL,
- NULL,
- sizeof (GstFaad),
- 0,
- (GInstanceInitFunc) gst_faad_init,
- };
-
- gst_faad_type = g_type_register_static (GST_TYPE_ELEMENT,
- "GstFaad", &gst_faad_info, 0);
- }
+static gboolean gst_faad_open_decoder (GstFaad * faad);
+static void gst_faad_close_decoder (GstFaad * faad);
- return gst_faad_type;
-}
+GST_BOILERPLATE (GstFaad, gst_faad, GstAudioDecoder, GST_TYPE_AUDIO_DECODER);
static void
-gst_faad_base_init (GstFaadClass * klass)
+gst_faad_base_init (gpointer klass)
{
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
@@ -208,47 +177,27 @@ gst_faad_base_init (GstFaadClass * klass)
static void
gst_faad_class_init (GstFaadClass * klass)
{
- GstElementClass *gstelement_class = GST_ELEMENT_CLASS (klass);
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+ GstAudioDecoderClass *base_class = GST_AUDIO_DECODER_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
- gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_faad_finalize);
-
- gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_faad_change_state);
+ base_class->start = GST_DEBUG_FUNCPTR (gst_faad_start);
+ base_class->stop = GST_DEBUG_FUNCPTR (gst_faad_stop);
+ base_class->set_format = GST_DEBUG_FUNCPTR (gst_faad_set_format);
+ base_class->parse = GST_DEBUG_FUNCPTR (gst_faad_parse);
+ base_class->handle_frame = GST_DEBUG_FUNCPTR (gst_faad_handle_frame);
+ base_class->flush = GST_DEBUG_FUNCPTR (gst_faad_flush);
}
static void
-gst_faad_init (GstFaad * faad)
+gst_faad_init (GstFaad * faad, GstFaadClass * klass)
{
- faad->sinkpad = gst_pad_new_from_static_template (&sink_template, "sink");
- gst_element_add_pad (GST_ELEMENT (faad), faad->sinkpad);
- gst_pad_set_event_function (faad->sinkpad,
- GST_DEBUG_FUNCPTR (gst_faad_sink_event));
- gst_pad_set_setcaps_function (faad->sinkpad,
- GST_DEBUG_FUNCPTR (gst_faad_setcaps));
- gst_pad_set_chain_function (faad->sinkpad,
- GST_DEBUG_FUNCPTR (gst_faad_chain));
-
- faad->srcpad = gst_pad_new_from_static_template (&src_template, "src");
- gst_pad_use_fixed_caps (faad->srcpad);
- gst_pad_set_query_function (faad->srcpad,
- GST_DEBUG_FUNCPTR (gst_faad_src_query));
- gst_pad_set_event_function (faad->srcpad,
- GST_DEBUG_FUNCPTR (gst_faad_src_event));
- gst_element_add_pad (GST_ELEMENT (faad), faad->srcpad);
-
- faad->adapter = gst_adapter_new ();
-
gst_faad_reset (faad);
}
static void
gst_faad_reset_stream_state (GstFaad * faad)
{
- faad->sync_flush = 0;
- gst_adapter_clear (faad->adapter);
- clear_queued (faad);
if (faad->handle)
faacDecPostSeekReset (faad->handle, 0);
}
@@ -256,45 +205,43 @@ gst_faad_reset_stream_state (GstFaad * faad)
static void
gst_faad_reset (GstFaad * faad)
{
- gst_segment_init (&faad->segment, GST_FORMAT_TIME);
faad->samplerate = -1;
faad->channels = -1;
faad->init = FALSE;
faad->packetised = FALSE;
g_free (faad->channel_positions);
faad->channel_positions = NULL;
- faad->next_ts = GST_CLOCK_TIME_NONE;
- faad->prev_ts = 0;
- faad->bytes_in = 0;
- faad->sum_dur_out = 0;
- faad->error_count = 0;
faad->last_header = 0;
gst_faad_reset_stream_state (faad);
}
-
-static void
-gst_faad_finalize (GObject * object)
+static gboolean
+gst_faad_start (GstAudioDecoder * dec)
{
- GstFaad *faad = GST_FAAD (object);
+ GstFaad *faad = GST_FAAD (dec);
- g_object_unref (faad->adapter);
+ GST_DEBUG_OBJECT (dec, "start");
+ gst_faad_reset (faad);
+
+ /* call upon legacy upstream byte support (e.g. seeking) */
+ gst_audio_decoder_set_byte_time (dec, TRUE);
+ /* never mind a few errors */
+ gst_audio_decoder_set_max_errors (dec, 10);
- G_OBJECT_CLASS (parent_class)->finalize (object);
+ return TRUE;
}
-static void
-gst_faad_send_tags (GstFaad * faad)
+static gboolean
+gst_faad_stop (GstAudioDecoder * dec)
{
- GstTagList *tags;
+ GstFaad *faad = GST_FAAD (dec);
- tags = gst_tag_list_new ();
-
- gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE,
- GST_TAG_AUDIO_CODEC, "MPEG-4 AAC audio", NULL);
+ GST_DEBUG_OBJECT (dec, "stop");
+ gst_faad_reset (faad);
+ gst_faad_close_decoder (faad);
- gst_element_found_tags (GST_ELEMENT (faad), tags);
+ return TRUE;
}
static gint
@@ -327,9 +274,9 @@ aac_rate_idx (gint rate)
}
static gboolean
-gst_faad_setcaps (GstPad * pad, GstCaps * caps)
+gst_faad_set_format (GstAudioDecoder * dec, GstCaps * caps)
{
- GstFaad *faad = GST_FAAD (gst_pad_get_parent (pad));
+ GstFaad *faad = GST_FAAD (dec);
GstStructure *str = gst_caps_get_structure (caps, 0);
GstBuffer *buf;
const GValue *value;
@@ -352,8 +299,8 @@ gst_faad_setcaps (GstPad * pad, GstCaps * caps)
/* We have codec data, means packetised stream */
faad->packetised = TRUE;
- buf = gst_value_get_buffer (value);
+ buf = gst_value_get_buffer (value);
g_return_val_if_fail (buf != NULL, FALSE);
cdata = GST_BUFFER_DATA (buf);
@@ -391,9 +338,6 @@ gst_faad_setcaps (GstPad * pad, GstCaps * caps)
faad->channels = 0;
faad->init = TRUE;
- gst_faad_send_tags (faad);
-
- gst_adapter_clear (faad->adapter);
} else if ((value = gst_structure_get_value (str, "framed")) &&
g_value_get_boolean (value) == TRUE) {
faad->packetised = TRUE;
@@ -424,7 +368,6 @@ gst_faad_setcaps (GstPad * pad, GstCaps * caps)
}
}
- gst_object_unref (faad);
return TRUE;
/* ERRORS */
@@ -535,349 +478,6 @@ gst_faad_chanpos_to_gst (GstFaad * faad, guchar * fpos, guint num,
return pos;
}
-static void
-clear_queued (GstFaad * faad)
-{
- g_list_foreach (faad->queued, (GFunc) gst_mini_object_unref, NULL);
- g_list_free (faad->queued);
- faad->queued = NULL;
- g_list_foreach (faad->gather, (GFunc) gst_mini_object_unref, NULL);
- g_list_free (faad->gather);
- faad->gather = NULL;
- g_list_foreach (faad->decode, (GFunc) gst_mini_object_unref, NULL);
- g_list_free (faad->decode);
- faad->decode = NULL;
-}
-
-static GstFlowReturn
-flush_queued (GstFaad * faad)
-{
- GstFlowReturn ret = GST_FLOW_OK;
-
- while (faad->queued) {
- GstBuffer *buf = GST_BUFFER_CAST (faad->queued->data);
-
- GST_LOG_OBJECT (faad, "pushing buffer %p, timestamp %"
- GST_TIME_FORMAT ", duration %" GST_TIME_FORMAT, buf,
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)),
- GST_TIME_ARGS (GST_BUFFER_DURATION (buf)));
-
- /* iterate ouput queue an push downstream */
- ret = gst_pad_push (faad->srcpad, buf);
-
- faad->queued = g_list_delete_link (faad->queued, faad->queued);
- }
- return ret;
-}
-
-static GstFlowReturn
-gst_faad_drain (GstFaad * faad)
-{
- GstFlowReturn ret = GST_FLOW_OK;
-
- GST_DEBUG_OBJECT (faad, "draining");
-
- if (faad->segment.rate < 0.0) {
- /* also decode tail = head of previous fragment to fill this one */
- while (faad->decode) {
- GstBuffer *buf = GST_BUFFER_CAST (faad->decode->data);
-
- GST_DEBUG_OBJECT (faad, "processing delayed decode buffer");
- gst_faad_chain (faad->sinkpad, buf);
- faad->decode = g_list_delete_link (faad->decode, faad->decode);
- }
- /* if we have some queued frames for reverse playback, flush
- * them now */
- ret = flush_queued (faad);
- /* move non-decoded leading buffers gathered in previous run
- * to decode queue for this run */
- faad->decode = g_list_reverse (faad->gather);
- faad->gather = NULL;
- } else {
- /* squeeze any possible remaining frames that are pending sync */
- gst_faad_chain (faad->sinkpad, NULL);
- }
- return ret;
-}
-
-static gboolean
-gst_faad_do_raw_seek (GstFaad * faad, GstEvent * event)
-{
- GstSeekFlags flags;
- GstSeekType start_type, end_type;
- GstFormat format;
- gdouble rate;
- gint64 start, start_time;
-
- gst_event_parse_seek (event, &rate, &format, &flags, &start_type,
- &start_time, &end_type, NULL);
-
- if (rate != 1.0 ||
- format != GST_FORMAT_TIME ||
- start_type != GST_SEEK_TYPE_SET || end_type != GST_SEEK_TYPE_NONE) {
- return FALSE;
- }
-
- if (!gst_faad_src_convert (faad, GST_FORMAT_TIME, start_time,
- GST_FORMAT_BYTES, &start)) {
- return FALSE;
- }
-
- event = gst_event_new_seek (1.0, GST_FORMAT_BYTES, flags,
- GST_SEEK_TYPE_SET, start, GST_SEEK_TYPE_NONE, -1);
-
- GST_DEBUG_OBJECT (faad, "seeking to %" GST_TIME_FORMAT " at byte offset %"
- G_GINT64_FORMAT, GST_TIME_ARGS (start_time), start);
-
- return gst_pad_push_event (faad->sinkpad, event);
-}
-
-static gboolean
-gst_faad_src_event (GstPad * pad, GstEvent * event)
-{
- GstFaad *faad;
- gboolean res;
-
- faad = GST_FAAD (gst_pad_get_parent (pad));
-
- GST_LOG_OBJECT (faad, "Handling %s event", GST_EVENT_TYPE_NAME (event));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_SEEK:{
- /* try upstream first, there might be a demuxer */
- gst_event_ref (event);
- if (!(res = gst_pad_push_event (faad->sinkpad, event))) {
- res = gst_faad_do_raw_seek (faad, event);
- }
- gst_event_unref (event);
- break;
- }
- default:
- res = gst_pad_push_event (faad->sinkpad, event);
- break;
- }
-
- gst_object_unref (faad);
- return res;
-}
-
-static gboolean
-gst_faad_sink_event (GstPad * pad, GstEvent * event)
-{
- GstFaad *faad;
- gboolean res = TRUE;
-
- faad = GST_FAAD (gst_pad_get_parent (pad));
-
- GST_LOG_OBJECT (faad, "Handling %s event", GST_EVENT_TYPE_NAME (event));
-
- switch (GST_EVENT_TYPE (event)) {
- case GST_EVENT_FLUSH_STOP:
- gst_faad_reset_stream_state (faad);
- res = gst_pad_push_event (faad->srcpad, event);
- break;
- case GST_EVENT_EOS:
- gst_faad_drain (faad);
- gst_faad_reset_stream_state (faad);
- res = gst_pad_push_event (faad->srcpad, event);
- break;
- case GST_EVENT_NEWSEGMENT:
- {
- GstFormat fmt;
- gboolean is_update;
- gint64 start, end, base;
- gdouble rate;
-
- gst_event_parse_new_segment (event, &is_update, &rate, &fmt, &start,
- &end, &base);
-
- /* drain queued buffers before we activate the new segment */
- gst_faad_drain (faad);
-
- if (fmt == GST_FORMAT_TIME) {
- GST_DEBUG_OBJECT (faad,
- "Got NEWSEGMENT event in GST_FORMAT_TIME, passing on (%"
- GST_TIME_FORMAT " - %" GST_TIME_FORMAT ")", GST_TIME_ARGS (start),
- GST_TIME_ARGS (end));
- gst_segment_set_newsegment (&faad->segment, is_update, rate, fmt, start,
- end, base);
- } else if (fmt == GST_FORMAT_BYTES) {
- gint64 new_start = 0;
- gint64 new_end = -1;
-
- GST_DEBUG_OBJECT (faad, "Got NEWSEGMENT event in GST_FORMAT_BYTES (%"
- G_GUINT64_FORMAT " - %" G_GUINT64_FORMAT ")", start, end);
-
- if (gst_faad_src_convert (faad, GST_FORMAT_BYTES, start,
- GST_FORMAT_TIME, &new_start)) {
- if (end != -1) {
- gst_faad_src_convert (faad, GST_FORMAT_BYTES, end,
- GST_FORMAT_TIME, &new_end);
- }
- } else {
- GST_DEBUG_OBJECT (faad,
- "no average bitrate yet, sending newsegment with start at 0");
- }
- gst_event_unref (event);
-
- event = gst_event_new_new_segment (is_update, rate,
- GST_FORMAT_TIME, new_start, new_end, new_start);
-
- gst_segment_set_newsegment (&faad->segment, is_update, rate,
- GST_FORMAT_TIME, new_start, new_end, new_start);
-
- GST_DEBUG_OBJECT (faad,
- "Sending new NEWSEGMENT event, time %" GST_TIME_FORMAT
- " - %" GST_TIME_FORMAT, GST_TIME_ARGS (new_start),
- GST_TIME_ARGS (new_end));
-
- faad->next_ts = GST_CLOCK_TIME_NONE;
- faad->prev_ts = new_start;
- }
-
- res = gst_pad_push_event (faad->srcpad, event);
- break;
- }
- default:
- res = gst_pad_event_default (pad, event);
- break;
- }
-
- gst_object_unref (faad);
- return res;
-}
-
-static gboolean
-gst_faad_src_convert (GstFaad * faad, GstFormat src_format, gint64 src_val,
- GstFormat dest_format, gint64 * dest_val)
-{
- guint64 bytes_in, time_out, val;
-
- if (src_format == dest_format) {
- if (dest_val)
- *dest_val = src_val;
- return TRUE;
- }
-
- GST_OBJECT_LOCK (faad);
- bytes_in = faad->bytes_in;
- time_out = faad->sum_dur_out;
- GST_OBJECT_UNLOCK (faad);
-
- if (bytes_in == 0 || time_out == 0)
- return FALSE;
-
- /* convert based on the average bitrate so far */
- if (src_format == GST_FORMAT_BYTES && dest_format == GST_FORMAT_TIME) {
- val = gst_util_uint64_scale (src_val, time_out, bytes_in);
- } else if (src_format == GST_FORMAT_TIME && dest_format == GST_FORMAT_BYTES) {
- val = gst_util_uint64_scale (src_val, bytes_in, time_out);
- } else {
- return FALSE;
- }
-
- if (dest_val)
- *dest_val = (gint64) val;
-
- return TRUE;
-}
-
-static gboolean
-gst_faad_src_query (GstPad * pad, GstQuery * query)
-{
- gboolean res = FALSE;
- GstFaad *faad;
- GstPad *peer = NULL;
-
- faad = GST_FAAD (gst_pad_get_parent (pad));
-
- GST_LOG_OBJECT (faad, "processing %s query", GST_QUERY_TYPE_NAME (query));
-
- switch (GST_QUERY_TYPE (query)) {
- case GST_QUERY_DURATION:{
- GstFormat format;
- gint64 len_bytes, duration;
-
- /* try upstream first, in case there's a demuxer */
- if ((res = gst_pad_query_default (pad, query)))
- break;
-
- gst_query_parse_duration (query, &format, NULL);
- if (format != GST_FORMAT_TIME) {
- GST_DEBUG_OBJECT (faad, "query failed: can't handle format %s",
- gst_format_get_name (format));
- break;
- }
-
- peer = gst_pad_get_peer (faad->sinkpad);
- if (peer == NULL)
- break;
-
- format = GST_FORMAT_BYTES;
- if (!gst_pad_query_duration (peer, &format, &len_bytes)) {
- GST_DEBUG_OBJECT (faad, "query failed: failed to get upstream length");
- break;
- }
-
- res = gst_faad_src_convert (faad, GST_FORMAT_BYTES, len_bytes,
- GST_FORMAT_TIME, &duration);
-
- if (res) {
- gst_query_set_duration (query, GST_FORMAT_TIME, duration);
-
- GST_LOG_OBJECT (faad, "duration estimate: %" GST_TIME_FORMAT,
- GST_TIME_ARGS (duration));
- }
- break;
- }
- case GST_QUERY_POSITION:{
- GstFormat format;
- gint64 pos_bytes, pos;
-
- /* try upstream first, in case there's a demuxer */
- if ((res = gst_pad_query_default (pad, query)))
- break;
-
- gst_query_parse_position (query, &format, NULL);
- if (format != GST_FORMAT_TIME) {
- GST_DEBUG_OBJECT (faad, "query failed: can't handle format %s",
- gst_format_get_name (format));
- break;
- }
-
- peer = gst_pad_get_peer (faad->sinkpad);
- if (peer == NULL)
- break;
-
- format = GST_FORMAT_BYTES;
- if (!gst_pad_query_position (peer, &format, &pos_bytes)) {
- GST_OBJECT_LOCK (faad);
- pos = faad->next_ts;
- GST_OBJECT_UNLOCK (faad);
- res = TRUE;
- } else {
- res = gst_faad_src_convert (faad, GST_FORMAT_BYTES, pos_bytes,
- GST_FORMAT_TIME, &pos);
- }
-
- if (res) {
- gst_query_set_position (query, GST_FORMAT_TIME, pos);
- }
- break;
- }
- default:
- res = gst_pad_query_default (pad, query);
- break;
- }
-
- if (peer)
- gst_object_unref (peer);
-
- gst_object_unref (faad);
- return res;
-}
-
-
static gboolean
gst_faad_update_caps (GstFaad * faad, faacDecFrameInfo * info)
{
@@ -935,7 +535,7 @@ gst_faad_update_caps (GstFaad * faad, faacDecFrameInfo * info)
GST_DEBUG_OBJECT (faad, "New output caps: %" GST_PTR_FORMAT, caps);
- ret = gst_pad_set_caps (faad->srcpad, caps);
+ ret = gst_pad_set_caps (GST_AUDIO_DECODER_SRC_PAD (faad), caps);
gst_caps_unref (caps);
return ret;
@@ -950,12 +550,13 @@ gst_faad_update_caps (GstFaad * faad, faacDecFrameInfo * info)
* gst/typefind/) for ADTS because 12 bits isn't very reliable.
*/
static gboolean
-gst_faad_sync (GstFaad * faad, guint8 * data, guint size, gboolean next,
- guint * off)
+gst_faad_sync (GstFaad * faad, const guint8 * data, guint size, gboolean next,
+ gint * off, gint * length)
{
guint n = 0;
gint snc;
gboolean ret = FALSE;
+ guint len = 0;
GST_LOG_OBJECT (faad, "Finding syncpoint");
@@ -968,8 +569,6 @@ gst_faad_sync (GstFaad * faad, guint8 * data, guint size, gboolean next,
if ((snc & 0xfff6) == 0xfff0) {
/* we have an ADTS syncpoint. Parse length and find
* next syncpoint. */
- guint len;
-
GST_LOG_OBJECT (faad,
"Found one ADTS syncpoint at offset 0x%x, tracing next...", n);
@@ -1012,10 +611,14 @@ gst_faad_sync (GstFaad * faad, guint8 * data, guint size, gboolean next,
}
exit:
+
*off = n;
- if (!ret)
+ if (ret) {
+ *length = len;
+ } else {
GST_LOG_OBJECT (faad, "Found no syncpoint");
+ }
return ret;
}
@@ -1038,78 +641,52 @@ looks_like_valid_header (guint8 * input_data, guint input_size)
return FALSE;
}
-#define FAAD_MAX_ERROR 10
-#define FAAD_MAX_SYNC 10 * 8 * 1024
+static GstFlowReturn
+gst_faad_parse (GstAudioDecoder * dec, GstAdapter * adapter,
+ gint * offset, gint * length)
+{
+ GstFaad *faad;
+ const guint8 *data;
+ guint size;
+ gboolean sync, eos;
+
+ faad = GST_FAAD (dec);
+
+ size = gst_adapter_available (adapter);
+ g_return_val_if_fail (size > 0, GST_FLOW_ERROR);
+
+ gst_audio_decoder_get_parse_state (dec, &sync, &eos);
+
+ if (faad->packetised) {
+ *offset = 0;
+ *length = size;
+ return GST_FLOW_OK;
+ } else {
+ data = gst_adapter_peek (adapter, size);
+ return gst_faad_sync (faad, data, size, !eos, offset, length) ?
+ GST_FLOW_OK : GST_FLOW_UNEXPECTED;
+ }
+}
static GstFlowReturn
-gst_faad_chain (GstPad * pad, GstBuffer * buffer)
+gst_faad_handle_frame (GstAudioDecoder * dec, GstBuffer * buffer)
{
+ GstFaad *faad;
GstFlowReturn ret = GST_FLOW_OK;
guint input_size;
- guint available;
guchar *input_data;
- GstFaad *faad;
GstBuffer *outbuf;
faacDecFrameInfo info;
void *out;
- gboolean run_loop = TRUE;
- guint sync_off;
- GstClockTime ts;
- gboolean next;
-
- faad = GST_FAAD (gst_pad_get_parent (pad));
-
- if (G_LIKELY (buffer)) {
- GST_LOG_OBJECT (faad, "buffer of size %d with ts: %" GST_TIME_FORMAT
- ", duration %" GST_TIME_FORMAT, GST_BUFFER_SIZE (buffer),
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)),
- GST_TIME_ARGS (GST_BUFFER_DURATION (buffer)));
-
- if (GST_BUFFER_IS_DISCONT (buffer)) {
- gst_faad_drain (faad);
- gst_faad_reset_stream_state (faad);
- faad->discont = TRUE;
- }
-
- gst_adapter_push (faad->adapter, buffer);
- buffer = NULL;
- next = TRUE;
- } else {
- next = FALSE;
- }
- available = gst_adapter_available (faad->adapter);
- input_size = available;
- if (G_UNLIKELY (!available))
- goto out;
+ faad = GST_FAAD (dec);
- ts = gst_adapter_prev_timestamp (faad->adapter, NULL);
- if (GST_CLOCK_TIME_IS_VALID (ts) && (ts != faad->prev_ts)) {
- faad->prev_ts = ts;
- } else {
- /* nothing new */
- ts = GST_CLOCK_TIME_NONE;
- }
+ /* no fancy draining */
+ if (G_UNLIKELY (!buffer))
+ return GST_FLOW_OK;
- if (!GST_CLOCK_TIME_IS_VALID (faad->next_ts))
- faad->next_ts = faad->prev_ts;
-
- input_data = (guchar *) gst_adapter_peek (faad->adapter, available);
-
- if (!faad->packetised) {
- if (!gst_faad_sync (faad, input_data, input_size, next, &sync_off)) {
- faad->sync_flush += sync_off;
- input_size -= sync_off;
- if (faad->sync_flush > FAAD_MAX_SYNC)
- goto parse_failed;
- else
- goto out;
- } else {
- faad->sync_flush = 0;
- input_data += sync_off;
- input_size -= sync_off;
- }
- }
+ input_data = GST_BUFFER_DATA (buffer);
+ input_size = GST_BUFFER_SIZE (buffer);
init:
/* init if not already done during capsnego */
@@ -1143,7 +720,6 @@ init:
}
faad->init = TRUE;
- gst_faad_send_tags (faad);
/* make sure we create new caps below */
faad->samplerate = 0;
@@ -1151,18 +727,11 @@ init:
}
/* decode cycle */
- info.bytesconsumed = input_size;
info.error = 0;
- while ((input_size > 0) && run_loop) {
+ do {
- if (faad->packetised) {
- /* Only one packet per buffer, no matter how much is really consumed */
- run_loop = FALSE;
- } else {
- if (input_size < FAAD_MIN_STREAMSIZE || info.bytesconsumed <= 0) {
- break;
- }
+ if (!faad->packetised) {
/* faad only really parses ADTS header at Init time, not when decoding,
* so monitor for changes and kick faad when needed */
if (GST_READ_UINT32_BE (input_data) >> 4 != faad->last_header >> 4) {
@@ -1178,33 +747,14 @@ init:
out = faacDecDecode (faad->handle, &info, input_data, input_size);
if (info.error > 0) {
- /* mark discont for the next buffer */
- faad->discont = TRUE;
- /* flush a bit, arranges for resync next time */
- input_size--;
- faad->error_count++;
- /* do not bail out at once, but know when to stop */
- if (faad->error_count > FAAD_MAX_ERROR)
- goto decode_failed;
- else {
- GST_WARNING_OBJECT (faad, "decoding error: %s",
- faacDecGetErrorMessage (info.error));
- goto out;
- }
+ /* give up on frame and bail out */
+ gst_audio_decoder_finish_frame (dec, NULL, 1);
+ goto decode_failed;
}
- /* ok again */
- faad->error_count = 0;
-
GST_LOG_OBJECT (faad, "%d bytes consumed, %d samples decoded",
(guint) info.bytesconsumed, (guint) info.samples);
- if (info.bytesconsumed > input_size)
- info.bytesconsumed = input_size;
-
- input_size -= info.bytesconsumed;
- input_data += info.bytesconsumed;
-
if (out && info.samples > 0) {
if (!gst_faad_update_caps (faad, &info))
goto negotiation_failed;
@@ -1213,82 +763,21 @@ init:
if (info.samples > G_MAXUINT / faad->bps)
goto sample_overflow;
- /* play decoded data */
- if (info.samples > 0) {
- guint bufsize = info.samples * faad->bps;
- guint num_samples = info.samples / faad->channels;
-
- /* note: info.samples is total samples, not per channel */
- ret =
- gst_pad_alloc_buffer_and_set_caps (faad->srcpad, 0, bufsize,
- GST_PAD_CAPS (faad->srcpad), &outbuf);
- if (ret != GST_FLOW_OK)
- goto out;
-
- memcpy (GST_BUFFER_DATA (outbuf), out, GST_BUFFER_SIZE (outbuf));
- GST_BUFFER_OFFSET (outbuf) =
- GST_CLOCK_TIME_TO_FRAMES (faad->next_ts, faad->samplerate);
- GST_BUFFER_TIMESTAMP (outbuf) = faad->next_ts;
- GST_BUFFER_DURATION (outbuf) =
- GST_FRAMES_TO_CLOCK_TIME (num_samples, faad->samplerate);
-
- GST_OBJECT_LOCK (faad);
- faad->next_ts += GST_BUFFER_DURATION (outbuf);
- faad->sum_dur_out += GST_BUFFER_DURATION (outbuf);
- faad->bytes_in += info.bytesconsumed;
- GST_OBJECT_UNLOCK (faad);
-
- if ((outbuf = gst_audio_buffer_clip (outbuf, &faad->segment,
- faad->samplerate, faad->bps * faad->channels))) {
- GST_LOG_OBJECT (faad,
- "pushing buffer, off=%" G_GUINT64_FORMAT ", ts=%" GST_TIME_FORMAT,
- GST_BUFFER_OFFSET (outbuf),
- GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)));
-
- if (faad->discont) {
- GST_BUFFER_FLAG_SET (outbuf, GST_BUFFER_FLAG_DISCONT);
- faad->discont = FALSE;
- }
-
- if (faad->segment.rate > 0.0) {
- ret = gst_pad_push (faad->srcpad, outbuf);
- } else {
- /* reverse playback, queue frame till later when we get a discont. */
- GST_LOG_OBJECT (faad, "queued frame");
- faad->queued = g_list_prepend (faad->queued, outbuf);
- ret = GST_FLOW_OK;
- }
- if (ret != GST_FLOW_OK)
- goto out;
- }
- }
- } else {
- if (faad->packetised && faad->segment.rate < 0.0) {
- /* leading non-decoded frames used as tail
- * for next preceding fragment */
- outbuf = gst_adapter_take_buffer (faad->adapter, available);
- available = 0;
- outbuf = gst_buffer_make_metadata_writable (outbuf);
- GST_BUFFER_FLAG_UNSET (outbuf, GST_BUFFER_FLAG_DISCONT);
- faad->gather = g_list_prepend (faad->gather, outbuf);
- }
- }
+ /* note: info.samples is total samples, not per channel */
+ ret =
+ gst_pad_alloc_buffer_and_set_caps (GST_AUDIO_DECODER_SRC_PAD
+ (faad), 0, info.samples * faad->bps,
+ GST_PAD_CAPS (GST_AUDIO_DECODER_SRC_PAD (faad)), &outbuf);
+ if (ret != GST_FLOW_OK)
+ goto out;
+
+ memcpy (GST_BUFFER_DATA (outbuf), out, GST_BUFFER_SIZE (outbuf));
- /* adjust to incoming new timestamp, if any, after decoder delay */
- if (GST_CLOCK_TIME_IS_VALID (ts)) {
- faad->next_ts = ts;
- ts = GST_CLOCK_TIME_NONE;
+ ret = gst_audio_decoder_finish_frame (dec, outbuf, 1);
}
- }
+ } while (FALSE);
out:
- /* in raw case: (pretend) all consumed */
- if (faad->packetised)
- input_size = 0;
- gst_adapter_flush (faad->adapter, available - input_size);
-
- gst_object_unref (faad);
-
return ret;
/* ERRORS */
@@ -1315,9 +804,8 @@ init2_failed:
}
decode_failed:
{
- GST_ELEMENT_ERROR (faad, STREAM, DECODE, (NULL),
- ("decoding error: %s", faacDecGetErrorMessage (info.error)));
- ret = GST_FLOW_ERROR;
+ GST_AUDIO_DECODER_ERROR (faad, 1, STREAM, DECODE, (NULL),
+ ("decoding error: %s", faacDecGetErrorMessage (info.error)), ret);
goto out;
}
negotiation_failed:
@@ -1334,13 +822,12 @@ sample_overflow:
ret = GST_FLOW_ERROR;
goto out;
}
-parse_failed:
- {
- GST_ELEMENT_ERROR (faad, STREAM, DECODE, (NULL),
- ("failed to parse non-packetized stream"));
- ret = GST_FLOW_ERROR;
- goto out;
- }
+}
+
+static void
+gst_faad_flush (GstAudioDecoder * dec, gboolean hard)
+{
+ gst_faad_reset_stream_state (GST_FAAD (dec));
}
static gboolean
@@ -1377,38 +864,6 @@ gst_faad_close_decoder (GstFaad * faad)
}
}
-static GstStateChangeReturn
-gst_faad_change_state (GstElement * element, GstStateChange transition)
-{
- GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
- GstFaad *faad = GST_FAAD (element);
-
- switch (transition) {
- case GST_STATE_CHANGE_NULL_TO_READY:
- break;
- case GST_STATE_CHANGE_READY_TO_PAUSED:
- break;
- default:
- break;
- }
-
- if (GST_ELEMENT_CLASS (parent_class)->change_state)
- ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
-
- switch (transition) {
- case GST_STATE_CHANGE_PAUSED_TO_READY:
- gst_faad_reset (faad);
- gst_faad_close_decoder (faad);
- break;
- case GST_STATE_CHANGE_READY_TO_NULL:
- break;
- default:
- break;
- }
-
- return ret;
-}
-
static gboolean
plugin_init (GstPlugin * plugin)
{
diff --git a/ext/faad/gstfaad.h b/ext/faad/gstfaad.h
index 455225047..deb98b831 100644
--- a/ext/faad/gstfaad.h
+++ b/ext/faad/gstfaad.h
@@ -21,7 +21,8 @@
#define __GST_FAAD_H__
#include <gst/gst.h>
-#include <gst/base/gstadapter.h>
+#include <gst/audio/gstaudiodecoder.h>
+
#ifdef FAAD_IS_NEAAC
#include <neaacdec.h>
#else
@@ -42,10 +43,7 @@ G_BEGIN_DECLS
(G_TYPE_CHECK_CLASS_TYPE ((klass), GST_TYPE_FAAD))
typedef struct _GstFaad {
- GstElement element;
-
- GstPad *srcpad;
- GstPad *sinkpad;
+ GstAudioDecoder element;
guint samplerate; /* sample rate of the last MPEG frame */
guint channels; /* number of channels of the last frame */
@@ -55,34 +53,16 @@ typedef struct _GstFaad {
guint8 fake_codec_data[2];
guint32 last_header;
- GstAdapter *adapter;
-
/* FAAD object */
faacDecHandle handle;
gboolean init;
gboolean packetised; /* We must differentiate between raw and packetised streams */
- gint64 prev_ts; /* timestamp of previous buffer */
- gint64 next_ts; /* timestamp of next buffer */
- guint64 bytes_in; /* bytes received */
- guint64 sum_dur_out; /* sum of durations of decoded buffers we sent out */
- gint error_count;
- gboolean discont;
- gint sync_flush;
-
- /* segment handling */
- GstSegment segment;
-
- /* list of raw output buffers for reverse playback */
- GList *queued;
- /* gather/decode queues for reverse playback */
- GList *gather;
- GList *decode;
} GstFaad;
typedef struct _GstFaadClass {
- GstElementClass parent_class;
+ GstAudioDecoderClass parent_class;
} GstFaadClass;
GType gst_faad_get_type (void);
diff --git a/ext/kate/gstkateparse.h b/ext/kate/gstkateparse.h
index 509f6c498..f9dd041cd 100644
--- a/ext/kate/gstkateparse.h
+++ b/ext/kate/gstkateparse.h
@@ -36,7 +36,7 @@ G_BEGIN_DECLS
(G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_KATE_PARSE,GstKateParseClass))
#define GST_IS_KATE_PARSE(obj) \
(G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_KATE_PARSE))
-#define GST_IS_KATKATEE_CLASS(klass) \
+#define GST_IS_KATE_PARSE_CLASS(klass) \
(G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_KATE_PARSE))
typedef struct _GstKateParse GstKateParse;
typedef struct _GstKateParseClass GstKateParseClass;
diff --git a/ext/kate/gstkatetiger.c b/ext/kate/gstkatetiger.c
index 81ac6f755..41da4db15 100644
--- a/ext/kate/gstkatetiger.c
+++ b/ext/kate/gstkatetiger.c
@@ -677,6 +677,7 @@ gst_kate_tiger_video_set_caps (GstPad * pad, GstCaps * caps)
GstKateTiger *tiger = GST_KATE_TIGER (gst_pad_get_parent (pad));
GstVideoFormat format;
gint w, h;
+ gboolean ret;
GST_KATE_TIGER_MUTEX_LOCK (tiger);
@@ -692,10 +693,10 @@ gst_kate_tiger_video_set_caps (GstPad * pad, GstCaps * caps)
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
- gst_pad_set_caps (tiger->srcpad, caps);
+ ret = gst_pad_set_caps (tiger->srcpad, caps);
gst_object_unref (tiger);
- return TRUE;
+ return ret;
}
static gdouble
@@ -858,9 +859,13 @@ gst_kate_tiger_seek (GstKateTiger * tiger, GstPad * pad, GstEvent * event)
gst_event_parse_seek (event, &rate, &format, &flags, &cur_type, &cur,
&stop_type, &stop);
+ if (flags & GST_SEEK_FLAG_FLUSH)
+ gst_pad_push_event (tiger->srcpad, gst_event_new_flush_start ());
+
GST_KATE_TIGER_MUTEX_LOCK (tiger);
tiger->video_flushing = TRUE;
gst_kate_util_decoder_base_set_flushing (&tiger->decoder, TRUE);
+ g_cond_broadcast (tiger->cond);
GST_KATE_TIGER_MUTEX_UNLOCK (tiger);
if (format == GST_FORMAT_TIME) {
diff --git a/ext/rtmp/gstrtmpsink.c b/ext/rtmp/gstrtmpsink.c
index e3933b150..90a1a79ec 100644
--- a/ext/rtmp/gstrtmpsink.c
+++ b/ext/rtmp/gstrtmpsink.c
@@ -164,20 +164,6 @@ gst_rtmp_sink_start (GstBaseSink * basesink)
/* Mark this as an output connection */
RTMP_EnableWrite (sink->rtmp);
- /* open the connection */
- if (!RTMP_IsConnected (sink->rtmp)) {
- if (!RTMP_Connect (sink->rtmp, NULL) || !RTMP_ConnectStream (sink->rtmp, 0)) {
- GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
- ("Could not connect to RTMP stream \"%s\" for writing", sink->uri));
- RTMP_Free (sink->rtmp);
- sink->rtmp = NULL;
- g_free (sink->rtmp_uri);
- sink->rtmp_uri = NULL;
- return FALSE;
- }
- GST_DEBUG_OBJECT (sink, "Opened connection to %s", sink->rtmp_uri);
- }
-
sink->first = TRUE;
return TRUE;
@@ -210,6 +196,21 @@ gst_rtmp_sink_render (GstBaseSink * bsink, GstBuffer * buf)
GstBuffer *reffed_buf = NULL;
if (sink->first) {
+ /* open the connection */
+ if (!RTMP_IsConnected (sink->rtmp)) {
+ if (!RTMP_Connect (sink->rtmp, NULL)
+ || !RTMP_ConnectStream (sink->rtmp, 0)) {
+ GST_ELEMENT_ERROR (sink, RESOURCE, OPEN_WRITE, (NULL),
+ ("Could not connect to RTMP stream \"%s\" for writing", sink->uri));
+ RTMP_Free (sink->rtmp);
+ sink->rtmp = NULL;
+ g_free (sink->rtmp_uri);
+ sink->rtmp_uri = NULL;
+ return GST_FLOW_ERROR;
+ }
+ GST_DEBUG_OBJECT (sink, "Opened connection to %s", sink->rtmp_uri);
+ }
+
/* FIXME: Parse the first buffer and see if it contains a header plus a packet instead
* of just assuming it's only the header */
GST_LOG_OBJECT (sink, "Caching first buffer of size %d for concatenation",
diff --git a/ext/spandsp/Makefile.am b/ext/spandsp/Makefile.am
new file mode 100644
index 000000000..46585958a
--- /dev/null
+++ b/ext/spandsp/Makefile.am
@@ -0,0 +1,9 @@
+plugin_LTLIBRARIES = libgstspandsp.la
+
+libgstspandsp_la_SOURCES = gstspandsp.c gstspanplc.c
+libgstspandsp_la_CFLAGS = $(GST_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) $(SPANDSP_CFLAGS)
+libgstspandsp_la_LIBADD = $(SPANDSP_LIBS) $(GST_PLUGINS_BASE_LIBS) $(GST_LIBS)
+libgstspandsp_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS)
+libgstspandsp_la_LIBTOOLFLAGS = --tag=disable-static
+
+noinst_HEADERS = gstspanplc.h
diff --git a/ext/spandsp/gstspandsp.c b/ext/spandsp/gstspandsp.c
new file mode 100644
index 000000000..ad1c3a817
--- /dev/null
+++ b/ext/spandsp/gstspandsp.c
@@ -0,0 +1,40 @@
+/*
+ * (C) 2011 Collabora Ltd.
+ * Contact: Youness Alaoui <youness.alaoui@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.
+ */
+
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gstspanplc.h"
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ return gst_element_register (plugin, "spanplc",
+ GST_RANK_PRIMARY, GST_TYPE_SPAN_PLC);
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "spandsp",
+ "libspandsp plugin",
+ plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN)
diff --git a/ext/spandsp/gstspanplc.c b/ext/spandsp/gstspanplc.c
new file mode 100644
index 000000000..58edce9f4
--- /dev/null
+++ b/ext/spandsp/gstspanplc.c
@@ -0,0 +1,300 @@
+/*
+ * (C) 2011 Collabora Ltd.
+ * Contact: Youness Alaoui <youness.alaoui@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.
+ */
+
+/**
+ * SECTION:element-spanplc
+ *
+ * The spanplc (Packet Loss Concealment) element provides a synthetic
+ * fill-in signal, to minimise the audible effect of lost packets in
+ * VoIP applications
+ *
+ */
+
+
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+#include "gstspanplc.h"
+
+GST_BOILERPLATE (GstSpanPlc, gst_span_plc, GstElement, GST_TYPE_ELEMENT);
+
+GST_DEBUG_CATEGORY_STATIC (gst_span_plc_debug);
+#define GST_CAT_DEFAULT gst_span_plc_debug
+
+
+static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-raw-int, "
+ "endianness = (int) BYTE_ORDER, signed = (bool) TRUE, "
+ "width = (int) 16, depth = (int) 16, "
+ "rate = (int) [ 1, MAX ], channels = (int) 1")
+ );
+
+static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("audio/x-raw-int, "
+ "endianness = (int) BYTE_ORDER, signed = (bool) TRUE, "
+ "width = (int) 16, depth = (int) 16, "
+ "rate = (int) [ 1, MAX ], channels = (int) 1")
+ );
+
+static void gst_span_plc_dispose (GObject * object);
+
+static GstStateChangeReturn gst_span_plc_change_state (GstElement * element,
+ GstStateChange transition);
+static gboolean gst_span_plc_setcaps_sink (GstPad * pad, GstCaps * caps);
+static GstFlowReturn gst_span_plc_chain (GstPad * pad, GstBuffer * buf);
+static gboolean gst_span_plc_event_sink (GstPad * pad, GstEvent * event);
+
+static void
+gst_span_plc_base_init (gpointer gclass)
+{
+ GstElementClass *element_class = (GstElementClass *) gclass;
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&src_factory));
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&sink_factory));
+
+ gst_element_class_set_details_simple (element_class, "SpanDSP PLC",
+ "Filter/Effect/Audio",
+ "Adds packet loss concealment to audio",
+ "Youness Alaoui <youness.alaoui@collabora.co.uk>");
+}
+
+/* initialize the plugin's class */
+static void
+gst_span_plc_class_init (GstSpanPlcClass * klass)
+{
+ GObjectClass *gobject_class = (GObjectClass *) klass;
+ GstElementClass *gstelement_class = (GstElementClass *) klass;
+
+ gobject_class->dispose = gst_span_plc_dispose;
+
+ gstelement_class->change_state =
+ GST_DEBUG_FUNCPTR (gst_span_plc_change_state);
+
+ GST_DEBUG_CATEGORY_INIT (gst_span_plc_debug, "spanplc",
+ 0, "spanDSP's packet loss concealment");
+}
+
+static void
+gst_span_plc_init (GstSpanPlc * plc, GstSpanPlcClass * gclass)
+{
+ GST_DEBUG_OBJECT (plc, "init");
+
+ plc->srcpad = gst_pad_new_from_static_template (&src_factory, "src");
+ plc->sinkpad = gst_pad_new_from_static_template (&sink_factory, "sink");
+
+ gst_pad_set_setcaps_function (plc->sinkpad,
+ GST_DEBUG_FUNCPTR (gst_span_plc_setcaps_sink));
+
+ gst_pad_set_getcaps_function (plc->srcpad,
+ GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
+ gst_pad_set_getcaps_function (plc->sinkpad,
+ GST_DEBUG_FUNCPTR (gst_pad_proxy_getcaps));
+
+ gst_pad_set_chain_function (plc->sinkpad,
+ GST_DEBUG_FUNCPTR (gst_span_plc_chain));
+
+ gst_pad_set_event_function (plc->sinkpad,
+ GST_DEBUG_FUNCPTR (gst_span_plc_event_sink));
+
+ gst_element_add_pad (GST_ELEMENT (plc), plc->srcpad);
+ gst_element_add_pad (GST_ELEMENT (plc), plc->sinkpad);
+
+ plc->plc_state = NULL;
+ plc->last_stop = GST_CLOCK_TIME_NONE;
+
+ GST_DEBUG_OBJECT (plc, "init complete");
+}
+
+static void
+gst_span_plc_dispose (GObject * object)
+{
+ GstSpanPlc *plc = GST_SPAN_PLC (object);
+
+ if (plc->plc_state)
+ plc_free (plc->plc_state);
+ plc->plc_state = NULL;
+
+ G_OBJECT_CLASS (parent_class)->dispose (object);
+}
+
+static void
+gst_span_plc_flush (GstSpanPlc * plc, gboolean renew)
+{
+ if (plc->plc_state)
+ plc_free (plc->plc_state);
+ if (renew)
+ plc->plc_state = plc_init (NULL);
+ else
+ plc->plc_state = NULL;
+ plc->last_stop = GST_CLOCK_TIME_NONE;
+}
+
+static GstStateChangeReturn
+gst_span_plc_change_state (GstElement * element, GstStateChange transition)
+{
+ GstSpanPlc *plc = GST_SPAN_PLC (element);
+ GstStateChangeReturn ret;
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ gst_span_plc_flush (plc, TRUE);
+ break;
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ gst_span_plc_flush (plc, FALSE);
+ default:
+ break;
+ }
+
+ return ret;
+}
+
+static gboolean
+gst_span_plc_setcaps_sink (GstPad * pad, GstCaps * caps)
+{
+ GstSpanPlc *plc = GST_SPAN_PLC (gst_pad_get_parent (pad));
+ GstStructure *s = NULL;
+ gboolean ret = FALSE;
+
+ ret = gst_pad_set_caps (plc->srcpad, caps);
+ s = gst_caps_get_structure (caps, 0);
+ if (s) {
+ gst_structure_get_int (s, "rate", &plc->sample_rate);
+ GST_DEBUG_OBJECT (plc, "setcaps: got sample rate : %d", plc->sample_rate);
+ }
+
+ gst_span_plc_flush (plc, TRUE);
+ gst_object_unref (plc);
+
+ return ret;
+}
+
+static GstFlowReturn
+gst_span_plc_chain (GstPad * pad, GstBuffer * buffer)
+{
+ GstSpanPlc *plc = GST_SPAN_PLC (GST_PAD_PARENT (pad));
+ GstClockTime buffer_duration;
+
+ if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer))
+ plc->last_stop = GST_BUFFER_TIMESTAMP (buffer);
+ else
+ GST_WARNING_OBJECT (plc, "Buffer has no timestamp!");
+
+ if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
+ buffer_duration = GST_BUFFER_DURATION (buffer);
+ } else {
+ GST_WARNING_OBJECT (plc, "Buffer has no duration!");
+ buffer_duration = (GST_BUFFER_SIZE (buffer) /
+ (plc->sample_rate * sizeof (guint16))) * GST_SECOND;
+ GST_DEBUG_OBJECT (plc, "Buffer duration : %" GST_TIME_FORMAT,
+ GST_TIME_ARGS (buffer_duration));
+ }
+
+ plc->last_stop += buffer_duration;
+
+ if (plc->plc_state->missing_samples != 0)
+ buffer = gst_buffer_make_writable (buffer);
+ plc_rx (plc->plc_state, (int16_t *) GST_BUFFER_DATA (buffer),
+ GST_BUFFER_SIZE (buffer) / 2);
+
+ return gst_pad_push (plc->srcpad, buffer);
+}
+
+static void
+gst_span_plc_send_fillin (GstSpanPlc * plc, GstClockTime duration)
+{
+ guint buf_size;
+ GstBuffer *buffer = NULL;
+
+ buf_size = ((float) duration / GST_SECOND) * plc->sample_rate;
+ buf_size *= sizeof (guint16);
+ buffer = gst_buffer_new_and_alloc (buf_size);
+ GST_DEBUG_OBJECT (plc, "Missing packet of %" GST_TIME_FORMAT
+ " == %d bytes", GST_TIME_ARGS (duration), buf_size);
+ plc_fillin (plc->plc_state, (int16_t *) GST_BUFFER_DATA (buffer),
+ GST_BUFFER_SIZE (buffer) / 2);
+ GST_BUFFER_TIMESTAMP (buffer) = plc->last_stop;
+ GST_BUFFER_DURATION (buffer) = duration;
+ gst_buffer_set_caps (buffer, GST_PAD_CAPS (plc->srcpad));
+ gst_pad_push (plc->srcpad, buffer);
+}
+
+static gboolean
+gst_span_plc_event_sink (GstPad * pad, GstEvent * event)
+{
+ gboolean ret = FALSE;
+ GstSpanPlc *plc = GST_SPAN_PLC (gst_pad_get_parent (pad));
+
+ GST_DEBUG_OBJECT (plc, "received event %s", GST_EVENT_TYPE_NAME (event));
+
+ switch (GST_EVENT_TYPE (event)) {
+ case GST_EVENT_NEWSEGMENT:
+ {
+ GstFormat format;
+ gdouble rate;
+ gint64 start, stop, time;
+ gboolean update;
+
+ gst_event_parse_new_segment (event, &update, &rate, &format, &start,
+ &stop, &time);
+
+ if (format != GST_FORMAT_TIME)
+ goto newseg_wrong_format;
+
+ if (update) {
+ /* time progressed without data, see if we can fill the gap with
+ * some concealment data */
+ if (plc->last_stop < start)
+ gst_span_plc_send_fillin (plc, start - plc->last_stop);
+ }
+ plc->last_stop = start;
+ break;
+ }
+ case GST_EVENT_FLUSH_START:
+ gst_span_plc_flush (plc, TRUE);
+ break;
+ default:
+ break;
+ }
+ ret = gst_pad_push_event (plc->srcpad, event);
+
+ gst_object_unref (plc);
+
+ return ret;
+newseg_wrong_format:
+ {
+ GST_DEBUG_OBJECT (plc, "received non TIME newsegment");
+ gst_object_unref (plc);
+ return FALSE;
+ }
+}
diff --git a/ext/spandsp/gstspanplc.h b/ext/spandsp/gstspanplc.h
new file mode 100644
index 000000000..86c10ac23
--- /dev/null
+++ b/ext/spandsp/gstspanplc.h
@@ -0,0 +1,60 @@
+/*
+ * (C) 2011 Collabora Ltd.
+ * Contact: Youness Alaoui <youness.alaoui@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.
+ */
+
+#ifndef __GST_SPANDSP_H__
+#define __GST_SPANDSP_H__
+
+#include <gst/gst.h>
+
+#include <spandsp.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_SPAN_PLC (gst_span_plc_get_type())
+#define GST_SPAN_PLC(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),GST_TYPE_SPAN_PLC,GstSpanPlc))
+#define GST_SPAN_PLC_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),GST_TYPE_SPAN_PLC,GstSpanPlcClass))
+#define GST_IS_SPAN_PLC(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),GST_TYPE_SPAN_PLC))
+#define GST_IS_SPAN_PLC_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),GST_TYPE_SPAN_PLC))
+
+typedef struct _GstSpanPlc GstSpanPlc;
+typedef struct _GstSpanPlcClass GstSpanPlcClass;
+
+struct _GstSpanPlc
+{
+ GstElement element;
+
+ GstPad *sinkpad;
+ GstPad *srcpad;
+
+ /* <private> */
+ plc_state_t *plc_state;
+ GstClockTime last_stop;
+ gint sample_rate;
+};
+
+struct _GstSpanPlcClass
+{
+ GstElementClass parent_class;
+};
+
+GType gst_span_plc_get_type (void);
+
+G_END_DECLS
+
+#endif
diff --git a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c
index 56bdc6cf6..d5b8ed772 100644
--- a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c
+++ b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c
@@ -445,7 +445,11 @@ gst_base_camera_src_change_state (GstElement * element,
gst_camerabin_create_preview_pipeline (GST_ELEMENT_CAST (self),
self->preview_filter);
- g_assert (self->preview_pipeline != NULL);
+ if (self->preview_pipeline == NULL) {
+ /* failed to create preview pipeline, fail state change */
+ return GST_STATE_CHANGE_FAILURE;
+ }
+
self->preview_filter_changed = FALSE;
if (self->preview_caps) {
GST_DEBUG_OBJECT (self,
diff --git a/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c b/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c
index b916d7f6b..be42c98dc 100644
--- a/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c
+++ b/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c
@@ -146,7 +146,8 @@ gst_camerabin_create_preview_pipeline (GstElement * element,
}
g_object_set (data->appsrc, "emit-signals", FALSE, NULL);
- g_object_set (data->appsink, "sync", FALSE, NULL);
+ g_object_set (data->appsink, "sync", FALSE, "enable-last-buffer",
+ FALSE, NULL);
gst_bin_add_many (GST_BIN (data->pipeline), data->appsrc, data->capsfilter,
data->appsink, csp, vscale, NULL);
@@ -230,6 +231,8 @@ void
gst_camerabin_destroy_preview_pipeline (GstCameraBinPreviewPipelineData *
preview)
{
+ g_return_if_fail (preview != NULL);
+
if (preview->processing_lock) {
g_mutex_free (preview->processing_lock);
preview->processing_lock = NULL;
diff --git a/gst-libs/gst/codecparsers/Makefile.am b/gst-libs/gst/codecparsers/Makefile.am
index 7fa44f158..c3dfe9307 100644
--- a/gst-libs/gst/codecparsers/Makefile.am
+++ b/gst-libs/gst/codecparsers/Makefile.am
@@ -1,17 +1,27 @@
lib_LTLIBRARIES = libgstcodecparsers-@GST_MAJORMINOR@.la
libgstcodecparsers_@GST_MAJORMINOR@_la_SOURCES = \
- gstmpegvideoparser.c gsth264parser.c
+ gstmpegvideoparser.c gsth264parser.c gstvc1parser.c
libgstcodecparsers_@GST_MAJORMINOR@includedir = \
$(includedir)/gstreamer-@GST_MAJORMINOR@/gst/codecparsers
libgstcodecparsers_@GST_MAJORMINOR@include_HEADERS = \
- gstmpegvideoparser.h gsth264parser.h
+ gstmpegvideoparser.h gsth264parser.h gstvc1parser.h
-libgstcodecparsers_@GST_MAJORMINOR@_la_CFLAGS = $(GST_PLUGINS_BAD_CFLAGS) $(GST_CFLAGS)
-libgstcodecparsers_@GST_MAJORMINOR@_la_LIBADD = $(GST_BASE_LIBS) $(GST_LIBS)
-libgstcodecparsers_@GST_MAJORMINOR@_la_LDFLAGS = $(GST_LIB_LDFLAGS) $(GST_ALL_LDFLAGS) $(GST_LT_LDFLAGS)
+libgstcodecparsers_@GST_MAJORMINOR@_la_CFLAGS = \
+ $(GST_PLUGINS_BAD_CFLAGS) \
+ -DGST_USE_UNSTABLE_API \
+ $(GST_CFLAGS)
+
+libgstcodecparsers_@GST_MAJORMINOR@_la_LIBADD = \
+ $(GST_BASE_LIBS) \
+ $(GST_LIBS)
+
+libgstcodecparsers_@GST_MAJORMINOR@_la_LDFLAGS = \
+ $(GST_LIB_LDFLAGS) \
+ $(GST_ALL_LDFLAGS) \
+ $(GST_LT_LDFLAGS)
Android.mk: $(BUILT_SOURCES) Makefile.am
androgenizer -:PROJECT libgstcodecparsers -:STATIC libgstcodecparsers-@GST_MAJORMINOR@ \
diff --git a/gst-libs/gst/codecparsers/gsth264parser.c b/gst-libs/gst/codecparsers/gsth264parser.c
index 869aa6122..b496c0fef 100644
--- a/gst-libs/gst/codecparsers/gsth264parser.c
+++ b/gst-libs/gst/codecparsers/gsth264parser.c
@@ -32,25 +32,52 @@
* @short_description: Convenience library for h264 video
* bitstream parsing.
*
- * It offers you basic parsing in AVC mode or not. Tp identify Nals in a bitstream and
- * parse its basic headers, you should call:
+ * It offers you bitstream parsing in AVC mode or not. To identify Nals in a bitstream and
+ * parse its headers, you should call:
* <itemizedlist>
* <listitem>
- * gst_h264_parser_identify_nalu to identify the following nalu in not AVC bitstreams
+ * #gst_h264_parser_identify_nalu to identify the following nalu in not AVC bitstreams
* </listitem>
* <listitem>
- * gst_h264_parser_identify_nalu_avc to identify the following nalu in AVC bitstreams
+ * #gst_h264_parser_identify_nalu_avc to identify the nalu in AVC bitstreams
* </listitem>
* </itemizedlist>
*
* Then, depending on the #GstH264NalUnitType of the newly parsed #GstH264NalUnit, you should
- * call the differents functions to parse the struct.
+ * call the differents functions to parse the structure:
+ * <itemizedlist>
+ * <listitem>
+ * From #GST_H264_NAL_SLICE to #GST_H264_NAL_SLICE_IDR: #gst_h264_parser_parse_slice_hdr
+ * </listitem>
+ * <listitem>
+ * #GST_H264_NAL_SEI: #gst_h264_parser_parse_sei
+ * </listitem>
+ * <listitem>
+ * #GST_H264_NAL_SPS: #gst_h264_parser_parse_sps
+ * </listitem>
+ * <listitem>
+ * #GST_H264_NAL_PPS: #gst_h264_parser_parse_pps
+ * </listitem>
+ * <listitem>
+ * Any other: #gst_h264_parser_parse_nal
+ * </listitem>
+ * </itemizedlist>
*
* Note: You should always call gst_h264_parser_parse_nal if you don't actually need
- * #GstH264NalUnitType to be parsed for your personnal use. This, to guarantee that the
+ * #GstH264NalUnitType to be parsed for your personnal use, in order to guarantee that the
* #GstH264NalParser is always up to date.
*
- * For more details about the structures, look at the ISO specifications.
+ * For more details about the structures, look at the ITU-T H.264 and ISO/IEC 14496-10 – MPEG-4
+ * Part 10 specifications, you can download them from:
+ *
+ * <itemizedlist>
+ * <listitem>
+ * ITU-T H.264: http://www.itu.int/rec/T-REC-H.264
+ * </listitem>
+ * <listitem>
+ * ISO/IEC 14496-10: http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=56538
+ * </listitem>
+ * </itemizedlist>
*/
#ifdef HAVE_CONFIG_H
@@ -1064,7 +1091,7 @@ gst_h264_parser_parse_pic_timing (GstH264NalParser * nalparser,
guint i;
READ_UINT8 (nr, tim->pic_struct, 4);
- CHECK_ALLOWED (tim->pic_struct, 0, 8);
+ CHECK_ALLOWED ((gint8) tim->pic_struct, 0, 8);
num_clock_num_ts = num_clock_ts_table[tim->pic_struct];
for (i = 0; i < num_clock_num_ts; i++) {
@@ -1090,7 +1117,8 @@ error:
/**
* gst_h264_nal_parser_new:
*
- * Creates a nez #GstH264NalParser
+ * Creates a new #GstH264NalParser. It should be freed with
+ * gst_h264_nal_parser_free after use.
*
* Returns: a new #GstH264NalParser
*/
@@ -1099,7 +1127,7 @@ gst_h264_nal_parser_new (void)
{
GstH264NalParser *nalparser;
- nalparser = g_malloc0 (sizeof (GstH264NalParser));
+ nalparser = g_slice_new0 (GstH264NalParser);
GST_DEBUG_CATEGORY_INIT (h264_parser_debug, "codecparsers_h264", 0,
"h264 parser library");
@@ -1107,14 +1135,28 @@ gst_h264_nal_parser_new (void)
}
/**
+ * gst_h264_nal_parser_free:
+ * @nalparser: the #GstH264NalParser to free
+ *
+ * Frees @nalparser and sets it to %NULL
+ */
+void
+gst_h264_nal_parser_free (GstH264NalParser * nalparser)
+{
+ g_slice_free (GstH264NalParser, nalparser);
+
+ nalparser = NULL;
+}
+
+/**
* gst_h264_parser_identify_nalu:
* @nalparser: a #GstH264NalParser
* @data: The data to parse
- * @offset: the offset from which to parse @data
+ * @offset: the offset from which to parse @data
* @size: the size of @data
* @nalu: The #GstH264NalUnit where to store parsed nal headers
*
- * Parses the buffer and set @nalu from the next nalu data from @data
+ * Parses @data and fills @nalu from the next nalu data from @data
*
* Returns: a #GstH264ParserResult
*/
@@ -1125,8 +1167,8 @@ gst_h264_parser_identify_nalu (GstH264NalParser * nalparser,
gint off1, off2;
if (size - offset < 4) {
- GST_DEBUG ("Can't parse, buffer has too small size %u, offset %u", size,
- offset);
+ GST_DEBUG ("Can't parse, buffer has too small size %" G_GSSIZE_FORMAT
+ ", offset %u", size, offset);
return GST_H264_PARSER_ERROR;
}
@@ -1180,12 +1222,14 @@ gst_h264_parser_identify_nalu (GstH264NalParser * nalparser,
/**
* gst_h264_parser_identify_nalu_avc:
+ * @nalparser: a #GstH264NalParser
* @data: The data to parse, must be the beging of the Nal unit
+ * @offset: the offset from which to parse @data
* @size: the size of @data
* @nal_length_size: the size in bytes of the AVC nal length prefix.
* @nalu: The #GstH264NalUnit where to store parsed nal headers
*
- * Parses the data and sets @nalu from @data.
+ * Parses @data and sets @nalu.
*
* Returns: a #GstH264ParserResult
*/
@@ -1221,6 +1265,17 @@ gst_h264_parser_identify_nalu_avc (GstH264NalParser * nalparser,
return GST_H264_PARSER_OK;
}
+/**
+ * gst_h264_parser_parse_nal:
+ * @nalparser: a #GstH264NalParser
+ * @nalu: The #GstH264NalUnit to parse
+ *
+ * This function should be called in the case one doesn't need to
+ * parse a specific structure. It is necessary to do so to make
+ * sure @nalparser is up to date.
+ *
+ * Returns: a #GstH264ParserResult
+ */
GstH264ParserResult
gst_h264_parser_parse_nal (GstH264NalParser * nalparser, GstH264NalUnit * nalu)
{
@@ -1241,11 +1296,11 @@ gst_h264_parser_parse_nal (GstH264NalParser * nalparser, GstH264NalUnit * nalu)
/**
* gst_h264_parser_parse_sps:
* @nalparser: a #GstH264NalParser
- * @nalu: The #GST_H264_NAL_SPS #GstH264NalUnit you want to parse
- * @slice: The #GstH264SPS to set.
+ * @nalu: The #GST_H264_NAL_SPS #GstH264NalUnit to parse
+ * @sps: The #GstH264SPS to fill.
* @parse_vui_params: Whether to parse the vui_params or not
*
- * Parses the @data, and sets the @sps.
+ * Parses @data, and fills the @sps structure.
*
* Returns: a #GstH264ParserResult
*/
@@ -1269,11 +1324,11 @@ gst_h264_parser_parse_sps (GstH264NalParser * nalparser, GstH264NalUnit * nalu,
/**
* gst_h264_parse_sps:
- * @nalu: The #GST_H264_NAL_SPS #GstH264NalUnit you want to parse
- * @slice: The #GstH264SPS to set.
+ * @nalu: The #GST_H264_NAL_SPS #GstH264NalUnit to parse
+ * @sps: The #GstH264SPS to fill.
* @parse_vui_params: Whether to parse the vui_params or not
*
- * Parses the @data, and sets the @sps.
+ * Parses @data, and fills the @sps structure.
*
* Returns: a #GstH264ParserResult
*/
@@ -1413,19 +1468,25 @@ gst_h264_parse_sps (GstH264NalUnit * nalu, GstH264SPS * sps,
sps->width = width;
sps->height = height;
- /* derive framerate */
- /* FIXME verify / also handle other cases */
- GST_LOG ("Framerate: %u %u %u %u", parse_vui_params,
- vui->fixed_frame_rate_flag, sps->frame_mbs_only_flag,
- vui->pic_struct_present_flag);
-
- if (parse_vui_params && vui->fixed_frame_rate_flag &&
- sps->frame_mbs_only_flag && !vui->pic_struct_present_flag) {
- sps->fps_num = vui->time_scale;
- sps->fps_den = vui->num_units_in_tick;
- /* picture is a frame = 2 fields */
- sps->fps_den *= 2;
- GST_LOG ("framerate %d/%d", sps->fps_num, sps->fps_den);
+ if (vui) {
+ /* derive framerate */
+ /* FIXME verify / also handle other cases */
+ GST_LOG ("Framerate: %u %u %u %u", parse_vui_params,
+ vui->fixed_frame_rate_flag, sps->frame_mbs_only_flag,
+ vui->pic_struct_present_flag);
+
+ if (parse_vui_params && vui->fixed_frame_rate_flag &&
+ sps->frame_mbs_only_flag && !vui->pic_struct_present_flag) {
+ sps->fps_num = vui->time_scale;
+ sps->fps_den = vui->num_units_in_tick;
+ /* picture is a frame = 2 fields */
+ sps->fps_den *= 2;
+ GST_LOG ("framerate %d/%d", sps->fps_num, sps->fps_den);
+ }
+ } else {
+ sps->fps_num = 0;
+ sps->fps_den = 1;
+ GST_LOG ("No VUI, unknown framerate");
}
sps->valid = TRUE;
@@ -1441,12 +1502,10 @@ error:
/**
* gst_h264_parse_pps:
* @nalparser: a #GstH264NalParser
- * @data: the data to parse
- * @size: the size of @data
- * @nalu: The #GST_H264_NAL_PPS #GstH264NalUnit you want to parse
- * @slice: The #GstH264PPS to set.
+ * @nalu: The #GST_H264_NAL_PPS #GstH264NalUnit to parse
+ * @pps: The #GstH264PPS to fill.
*
- * Parses the @data, and sets the @pps.
+ * Parses @data, and fills the @pps structure.
*
* Returns: a #GstH264ParserResult
*/
@@ -1572,12 +1631,10 @@ error:
/**
* gst_h264_parser_parse_pps:
* @nalparser: a #GstH264NalParser
- * @data: the data to parse
- * @size: the size of @data
- * @nalu: The #GST_H264_NAL_PPS #GstH264NalUnit you want to parse
- * @slice: The #GstH264PPS to set.
+ * @nalu: The #GST_H264_NAL_PPS #GstH264NalUnit to parse
+ * @pps: The #GstH264PPS to fill.
*
- * Parses the @data, and sets the @pps.
+ * Parses @data, and fills the @pps structure.
*
* Returns: a #GstH264ParserResult
*/
@@ -1599,12 +1656,13 @@ gst_h264_parser_parse_pps (GstH264NalParser * nalparser,
/**
* gst_h264_parser_parse_slice_hdr:
- * @nalu: The #GST_H264_NAL_SLICE #GstH264NalUnit you want to parse
- * @slice: The #GstH264SliceHdr to set.
+ * @nalparser: a #GstH264NalParser
+ * @nalu: The #GST_H264_NAL_SLICE #GstH264NalUnit to parse
+ * @slice: The #GstH264SliceHdr to fill.
* @parse_pred_weight_table: Whether to parse the pred_weight_table or not
* @parse_dec_ref_pic_marking: Whether to parse the dec_ref_pic_marking or not
*
- * Parses the @data, and sets the @slice.
+ * Parses @data, and fills the @slice structure.
*
* Returns: a #GstH264ParserResult
*/
@@ -1776,10 +1834,10 @@ error:
/**
* gst_h264_parser_parse_sei:
* @nalparser: a #GstH264NalParser
- * @nalu: The #GST_H264_NAL_SEI #GstH264NalUnit you want to parse
- * @slice: The #GstH264SEIMessage to set.
+ * @nalu: The #GST_H264_NAL_SEI #GstH264NalUnit to parse
+ * @sei: The #GstH264SEIMessage to fill.
*
- * Parses the @data, and sets the @pps.
+ * Parses @data, and fills the @sei structures.
*
* Returns: a #GstH264ParserResult
*/
diff --git a/gst-libs/gst/codecparsers/gsth264parser.h b/gst-libs/gst/codecparsers/gsth264parser.h
index 84577f686..2dfe2d7b6 100644
--- a/gst-libs/gst/codecparsers/gsth264parser.h
+++ b/gst-libs/gst/codecparsers/gsth264parser.h
@@ -30,6 +30,11 @@
#ifndef __GST_H264_PARSER_H__
#define __GST_H264_PARSER_H__
+#ifndef GST_USE_UNSTABLE_API
+#warning "The H.264 parsing library is unstable API and may change in future."
+#warning "You can define GST_USE_UNSTABLE_API to avoid this warning."
+#endif
+
#include <gst/gst.h>
G_BEGIN_DECLS
@@ -45,19 +50,19 @@ G_BEGIN_DECLS
/**
* GstH264NalUnitType:
- * @GST_H264_NAL_UNKNOWN: Unkonw nal type
+ * @GST_H264_NAL_UNKNOWN: Unknown nal type
* @GST_H264_NAL_SLICE: Slice nal
* @GST_H264_NAL_SLICE_DPA: DPA slice nal
* @GST_H264_NAL_SLICE_DPB: DPB slice nal
* @GST_H264_NAL_SLICE_DPC: DPC slice nal
* @GST_H264_NAL_SLICE_IDR: DPR slice nal
- * @GST_H264_NAL_SEI: Supplemental enhancement information nal unit
- * @GST_H264_NAL_SPS: Sequence parameter set nal unit
- * @GST_H264_NAL_PPS: Picture parameter set nal unit
- * @GST_H264_NAL_AU_DELIMITER: Access unit delimiter nal unit
+ * @GST_H264_NAL_SEI: Supplemental enhancement information (SEI) nal unit
+ * @GST_H264_NAL_SPS: Sequence parameter set (SPS) nal unit
+ * @GST_H264_NAL_PPS: Picture parameter set (PPS) nal unit
+ * @GST_H264_NAL_AU_DELIMITER: Access unit (AU) delimiter nal unit
* @GST_H264_NAL_SEQ_END: End of sequence nal unit
* @GST_H264_NAL_STREAM_END: End of stream nal unit
- * @GST_H264_NAL_FILLER_DATA: Filler data na lunit
+ * @GST_H264_NAL_FILLER_DATA: Filler data nal lunit
*
* Indicates the type of H264 Nal Units
*/
@@ -81,13 +86,13 @@ typedef enum
/**
* GstH264ParserResult:
* @GST_H264_PARSER_OK: The parsing succeded
- * @GST_H264_PARSER_BROKEN_DATA: The data we parsed where broken
- * @GST_H264_PARSER_BROKEN_LINK: The link to a needed struct for the parsing couldn't be found
+ * @GST_H264_PARSER_BROKEN_DATA: The data to parse is broken
+ * @GST_H264_PARSER_BROKEN_LINK: The link to structure needed for the parsing couldn't be found
* @GST_H264_PARSER_ERROR: An error accured when parsing
* @GST_H264_PARSER_NO_NAL: No nal found during the parsing
- * @GST_H264_PARSER_NO_NAL_END: Start of the nal found, not the end.
+ * @GST_H264_PARSER_NO_NAL_END: Start of the nal found, but not the end.
*
- * Information about how the parsing of a H264 elements went.
+ * The result of parsing H264 data.
*/
typedef enum
{
@@ -101,11 +106,11 @@ typedef enum
/**
* GstH264SEIPayloadType:
- * @GST_H264_SEI_BUF_PERIOD: The Sei Message contains a buffering period message
- * @GST_H264_SEI_PIC_TIMING: The Sei Message contains a picture timing message
+ * @GST_H264_SEI_BUF_PERIOD: Buffering Period SEI Message
+ * @GST_H264_SEI_PIC_TIMING: Picture Timing SEI Message
* ...
*
- * The type of the SEI message information
+ * The type of SEI message.
*/
typedef enum
{
@@ -294,7 +299,7 @@ struct _GstH264HRDParams
* samples outside picture boundaries may be used in inter prediction
* @max_bytes_per_pic_denom: indicates a number of bytes not exceeded by the sum of the sizes of
* the VCL NAL units associated with any coded picture in the coded video sequence.
- * @max_bits_per_mb_denom: indicates the maximum number of coded bits of macroblock_layer()
+ * @max_bits_per_mb_denom: indicates the maximum number of coded bits of macroblock_layer
* @log2_max_mv_length_horizontal: indicate the maximum absolute value of a decoded horizontal
* motion vector component
* @log2_max_mv_length_vertical: indicate the maximum absolute value of a decoded vertical
@@ -363,7 +368,7 @@ struct _GstH264VUIParams
* @id: The ID of the sequence parameter set
* @profile_idc: indicate the profile to which the coded video sequence conforms
*
- *
+ * H264 Sequence Parameter Set (SPS)
*/
struct _GstH264SPS
{
@@ -429,6 +434,11 @@ struct _GstH264SPS
gboolean valid;
};
+/**
+ * GstH264PPS:
+ *
+ * H264 Picture Parameter Set
+ */
struct _GstH264PPS
{
gint id;
diff --git a/gst-libs/gst/codecparsers/gstmpegvideoparser.c b/gst-libs/gst/codecparsers/gstmpegvideoparser.c
index 44df76ad5..e871017fa 100644
--- a/gst-libs/gst/codecparsers/gstmpegvideoparser.c
+++ b/gst-libs/gst/codecparsers/gstmpegvideoparser.c
@@ -309,12 +309,12 @@ scan_for_start_codes (const GstByteReader * reader, guint offset, guint size)
/**
* gst_mpeg_video_parse:
- * @data: The datas from which to parse
+ * @data: The data to parse
* @size: The size of @data
- * @offset: The offset from which to start the parsing
+ * @offset: The offset from which to start parsing
*
- * Parses @data, and detects the different packets types, offset,
- * and size, starting from @offset
+ * Parses the MPEG 1/2 video bitstream contained in @data , and returns the
+ * detect packets as a list of #GstMpegVideoTypeOffsetSize.
*
* Returns: a #GList of #GstMpegVideoTypeOffsetSize
*/
@@ -324,7 +324,8 @@ gst_mpeg_video_parse (guint8 * data, gsize size, guint offset)
gint off, rsize;
GstByteReader br;
GList *ret = NULL;
- size = size - offset;
+
+ size -= offset;
if (!initialized) {
GST_DEBUG_CATEGORY_INIT (mpegvideo_parser_debug, "codecparsers_mpegvideo",
@@ -373,12 +374,12 @@ gst_mpeg_video_parse (guint8 * data, gsize size, guint offset)
/**
* gst_mpeg_video_parse_sequence_header:
- * @seqhdr: The #GstMpegVideoSequenceHdr to set
- * @data: The datas from which to parse the seqhdr
+ * @seqhdr: (out): The #GstMpegVideoSequenceHdr structure to fill
+ * @data: The data from which to parse the sequence header
* @size: The size of @data
* @offset: The offset in byte from which to start parsing @data
*
- * Sets the @seqhdr Mpeg Video Sequence Header structure members from @data
+ * Parses the @seqhdr Mpeg Video Sequence Header structure members from @data
*
* Returns: %TRUE if the seqhdr could be parsed correctly, %FALSE otherwize.
*/
@@ -388,9 +389,11 @@ gst_mpeg_video_parse_sequence_header (GstMpegVideoSequenceHdr * seqhdr,
{
GstBitReader br;
- size = size - offset;
+ g_return_val_if_fail (seqhdr != NULL, FALSE);
- if (size - offset < 4)
+ size -= offset;
+
+ if (size < 4)
return FALSE;
gst_bit_reader_init (&br, &data[offset], size);
@@ -400,12 +403,12 @@ gst_mpeg_video_parse_sequence_header (GstMpegVideoSequenceHdr * seqhdr,
/**
* gst_mpeg_video_parse_sequence_extension:
- * @seqhdr: The #GstMpegVideoSequenceExt to set
- * @data: The datas from which to parse the seqext
+ * @seqext: (out): The #GstMpegVideoSequenceExt structure to fill
+ * @data: The data from which to parse the sequence extension
* @size: The size of @data
* @offset: The offset in byte from which to start parsing @data
*
- * Sets the @seqext Mpeg Video Sequence Extension structure members from @data
+ * Parses the @seqext Mpeg Video Sequence Extension structure members from @data
*
* Returns: %TRUE if the seqext could be parsed correctly, %FALSE otherwize.
*/
@@ -415,7 +418,9 @@ gst_mpeg_video_parse_sequence_extension (GstMpegVideoSequenceExt * seqext,
{
GstBitReader br;
- size = size - offset;
+ g_return_val_if_fail (seqext != NULL, FALSE);
+
+ size -= offset;
if (size < 6) {
GST_DEBUG ("not enough bytes to parse the extension");
@@ -464,12 +469,12 @@ gst_mpeg_video_parse_sequence_extension (GstMpegVideoSequenceExt * seqext,
/**
* gst_mpeg_video_parse_quant_matrix_extension:
- * @ext: The #GstMpegVideoQuantMatrixExt to set
- * @data: The datas from which to parse @quant
+ * @quant: (out): The #GstMpegVideoQuantMatrixExt structure to fill
+ * @data: The data from which to parse the Quantization Matrix extension
* @size: The size of @data
* @offset: The offset in byte from which to start the parsing
*
- * Sets the @quant Mpeg Video Quant Matrix Extension structure members from
+ * Parses the @quant Mpeg Video Quant Matrix Extension structure members from
* @data
*
* Returns: %TRUE if the quant matrix extension could be parsed correctly,
@@ -482,7 +487,9 @@ gst_mpeg_video_parse_quant_matrix_extension (GstMpegVideoQuantMatrixExt * quant,
guint8 i;
GstBitReader br;
- size = size - offset;
+ g_return_val_if_fail (quant != NULL, FALSE);
+
+ size -= offset;
if (size < 1) {
GST_DEBUG ("not enough bytes to parse the extension");
@@ -537,12 +544,12 @@ failed:
/**
* gst_mpeg_video_parse_picture_extension:
- * @ext: The #GstMpegVideoPictureExt to set
- * @data: The datas from which to parse the ext
+ * @ext: (out): The #GstMpegVideoPictureExt structure to fill
+ * @data: The data from which to parse the picture extension
* @size: The size of @data
* @offset: The offset in byte from which to start the parsing
*
- * Sets the @ext Mpeg Video Picture Extension structure members from @data
+ * Parse the @ext Mpeg Video Picture Extension structure members from @data
*
* Returns: %TRUE if the picture extension could be parsed correctly,
* %FALSE otherwize.
@@ -553,7 +560,9 @@ gst_mpeg_video_parse_picture_extension (GstMpegVideoPictureExt * ext,
{
GstBitReader br;
- size = size - offset;
+ g_return_val_if_fail (ext != NULL, FALSE);
+
+ size -= offset;
if (size < 4)
return FALSE;
@@ -636,14 +645,15 @@ failed:
/**
* gst_mpeg_video_parse_picture_header:
- * @hdr: The #GstMpegVideoPictureHdr to set
- * @data: The datas from which to parse the hdr
+ * @hdr: (out): The #GstMpegVideoPictureHdr structure to fill
+ * @data: The data from which to parse the picture header
* @size: The size of @data
* @offset: The offset in byte from which to start the parsing
*
- * Sets the @hdr Mpeg Video Picture Header structure members from @data
+ * Parsers the @hdr Mpeg Video Picture Header structure members from @data
*
- * Returns: %TRUE if the picture sequence could be parsed correctly, %FALSE otherwize.
+ * Returns: %TRUE if the picture sequence could be parsed correctly, %FALSE
+ * otherwize.
*/
gboolean
gst_mpeg_video_parse_picture_header (GstMpegVideoPictureHdr * hdr,
@@ -654,24 +664,26 @@ gst_mpeg_video_parse_picture_header (GstMpegVideoPictureHdr * hdr,
size = size - offset;
if (size < 4)
- return FALSE;
+ goto failed;
gst_bit_reader_init (&br, &data[offset], size);
/* temperal sequence number */
if (!gst_bit_reader_get_bits_uint16 (&br, &hdr->tsn, 10))
- return FALSE;
+ goto failed;
+
/* frame type */
if (!gst_bit_reader_get_bits_uint8 (&br, (guint8 *) & hdr->pic_type, 3))
- return FALSE;
+ goto failed;
+
if (hdr->pic_type == 0 || hdr->pic_type > 4)
- return FALSE; /* Corrupted picture packet */
+ goto failed; /* Corrupted picture packet */
/* skype VBV delay */
if (!gst_bit_reader_skip (&br, 8))
- return FALSE;
+ goto failed;
if (hdr->pic_type == GST_MPEG_VIDEO_PICTURE_TYPE_P
|| hdr->pic_type == GST_MPEG_VIDEO_PICTURE_TYPE_B) {
@@ -699,20 +711,19 @@ gst_mpeg_video_parse_picture_header (GstMpegVideoPictureHdr * hdr,
failed:
{
- GST_WARNING ("Failed to parse sequence extension");
+ GST_WARNING ("Failed to parse picture header");
return FALSE;
}
}
/**
* gst_mpeg_video_parse_gop:
- * @gop: The #GstMpegVideoGop to set
- * @data: The datas from which to parse the gop
+ * @gop: (out): The #GstMpegVideoGop structure to fill
+ * @data: The data from which to parse the gop
* @size: The size of @data
* @offset: The offset in byte from which to start the parsing
*
- *
- * Sets the @gop Mpeg Video Group of Picture structure members from @data
+ * Parses the @gop Mpeg Video Group of Picture structure members from @data
*
* Returns: %TRUE if the gop could be parsed correctly, %FALSE otherwize.
*/
@@ -722,7 +733,9 @@ gst_mpeg_video_parse_gop (GstMpegVideoGop * gop, guint8 * data,
{
GstBitReader br;
- size = size - offset;
+ g_return_val_if_fail (gop != NULL, FALSE);
+
+ size -= offset;
if (size < 4)
return FALSE;
@@ -745,7 +758,7 @@ gst_mpeg_video_parse_gop (GstMpegVideoGop * gop, guint8 * data,
READ_UINT8 (&br, gop->closed_gop, 1);
- READ_UINT8 (&br, gop->broken_gop, 1);
+ READ_UINT8 (&br, gop->broken_link, 1);
return TRUE;
diff --git a/gst-libs/gst/codecparsers/gstmpegvideoparser.h b/gst-libs/gst/codecparsers/gstmpegvideoparser.h
index a42792b81..a212a9444 100644
--- a/gst-libs/gst/codecparsers/gstmpegvideoparser.h
+++ b/gst-libs/gst/codecparsers/gstmpegvideoparser.h
@@ -26,6 +26,11 @@
#ifndef __GST_MPEG_VIDEO_UTILS_H__
#define __GST_MPEG_VIDEO_UTILS_H__
+#ifndef GST_USE_UNSTABLE_API
+#warning "The Mpeg video parsing library is unstable API and may change in future."
+#warning "You can define GST_USE_UNSTABLE_API to avoid this warning."
+#endif
+
#include <gst/gst.h>
G_BEGIN_DECLS
@@ -57,32 +62,43 @@ typedef enum {
} GstMpegVideoPacketTypeCode;
/**
+ * GST_MPEG_VIDEO_PACKET_IS_SLICE:
+ * @typecode: The MPEG video packet type code
+ *
+ * Checks whether a packet type code is a slice.
+ *
+ * Returns: %TRUE if the packet type code corresponds to a slice,
+ * else %FALSE.
+ */
+#define GST_MPEG_VIDEO_PACKET_IS_SLICE(typecode) ((typecode) >= GST_MPEG_VIDEO_PACKET_SLICE_MIN && \
+ (typecode) <= GST_MPEG_VIDEO_PACKET_SLICE_MAX)
+
+/**
* GstMpegVideoPacketExtensionCode:
* @GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE: Sequence extension code
- * @GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY: Display extension code
- * @GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX: Quantizer extension code
- * @GST_MPEG_VIDEO_PACKET_EXT_GOP: Group Of Picture extension code
+ * @GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY: Sequence Display extension code
+ * @GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX: Quantization Matrix extension code
+ * @GST_MPEG_VIDEO_PACKET_EXT_PICTURE: Picture coding extension
*
- * Indicates what type of packets are in this
- * block, some are mutually * exclusive though - ie, sequence packs are
- * accumulated separately. GOP & Picture may occur together or separately
+ * Indicates what type of packets are in this block, some are mutually
+ * exclusive though - ie, sequence packs are accumulated separately. GOP &
+ * Picture may occur together or separately.
*/
typedef enum {
GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE = 0x01,
GST_MPEG_VIDEO_PACKET_EXT_SEQUENCE_DISPLAY = 0x02,
GST_MPEG_VIDEO_PACKET_EXT_QUANT_MATRIX = 0x03,
- GST_MPEG_VIDEO_PACKET_EXT_GOP = 0x04,
GST_MPEG_VIDEO_PACKET_EXT_PICTURE = 0x08
} GstMpegVideoPacketExtensionCode;
/**
* GstMpegVideoLevel:
- * @GST_MPEG_VIDEO_LEVEL_LOW: Level Low
- * @GST_MPEG_VIDEO_LEVEL_MAIN: Level Main
- * @GST_MPEG_VIDEO_LEVEL_HIGH_1440: Level High 1440
- * @GST_MPEG_VIDEO_LEVEL_HIGH: Level High
+ * @GST_MPEG_VIDEO_LEVEL_LOW: Low level (LL)
+ * @GST_MPEG_VIDEO_LEVEL_MAIN: Main level (ML)
+ * @GST_MPEG_VIDEO_LEVEL_HIGH_1440: High 1440 level (H-14)
+ * @GST_MPEG_VIDEO_LEVEL_HIGH: High level (HL)
*
- * Indicates the level in use
+ * Mpeg-2 Levels.
**/
typedef enum {
GST_MPEG_VIDEO_LEVEL_HIGH = 0x04,
@@ -93,14 +109,14 @@ typedef enum {
/**
* GstMpegVideoProfile:
- * @GST_MPEG_VIDEO_PROFILE_422,
- * @GST_MPEG_VIDEO_PROFILE_HIGH,
- * @GST_MPEG_VIDEO_PROFILE_SPATIALLY_SCALABLE,
- * @GST_MPEG_VIDEO_PROFILE_SNR_SCALABLE,
- * @GST_MPEG_VIDEO_PROFILE_MAIN,
- * @GST_MPEG_VIDEO_PROFILE_SIMPLE,
+ * @GST_MPEG_VIDEO_PROFILE_422: 4:2:2 profile (422)
+ * @GST_MPEG_VIDEO_PROFILE_HIGH: High profile (HP)
+ * @GST_MPEG_VIDEO_PROFILE_SPATIALLY_SCALABLE: Spatially Scalable profile (Spatial)
+ * @GST_MPEG_VIDEO_PROFILE_SNR_SCALABLE: SNR Scalable profile (SNR)
+ * @GST_MPEG_VIDEO_PROFILE_MAIN: Main profile (MP)
+ * @GST_MPEG_VIDEO_PROFILE_SIMPLE: Simple profile (SP)
*
- * Indicates the profile type in use
+ * Mpeg-2 Profiles.
**/
typedef enum {
GST_MPEG_VIDEO_PROFILE_422 = 0x00,
@@ -112,13 +128,29 @@ typedef enum {
} GstMpegVideoProfile;
/**
+ * GstMpegVideoChromaFormat:
+ * @GST_MPEG_VIDEO_CHROMA_RES: Invalid (reserved for future use)
+ * @GST_MPEG_VIDEO_CHROMA_420: 4:2:0 subsampling
+ * @GST_MPEG_VIDEO_CHROMA_422: 4:2:2 subsampling
+ * @GST_MPEG_VIDEO_CHROMA_444: 4:4:4 (non-subsampled)
+ *
+ * Chroma subsampling type.
+ */
+typedef enum {
+ GST_MPEG_VIDEO_CHROMA_RES = 0x00,
+ GST_MPEG_VIDEO_CHROMA_420 = 0x01,
+ GST_MPEG_VIDEO_CHROMA_422 = 0x02,
+ GST_MPEG_VIDEO_CHROMA_444 = 0x03,
+} GstMpegVideoChromaFormat;
+
+/**
* GstMpegVideoPictureType:
- * @GST_MPEG_VIDEO_PICTURE_TYPE_I: Type I
- * @GST_MPEG_VIDEO_PICTURE_TYPE_P: Type P
- * @GST_MPEG_VIDEO_PICTURE_TYPE_B: Type B
- * @GST_MPEG_VIDEO_PICTURE_TYPE_D: Type D
+ * @GST_MPEG_VIDEO_PICTURE_TYPE_I: Intra-coded (I) frame
+ * @GST_MPEG_VIDEO_PICTURE_TYPE_P: Predictive-codec (P) frame
+ * @GST_MPEG_VIDEO_PICTURE_TYPE_B: Bidirectionally predictive-coded (B) frame
+ * @GST_MPEG_VIDEO_PICTURE_TYPE_D: D frame
*
- * Indicates the type of picture
+ * Picture type.
*/
typedef enum {
GST_MPEG_VIDEO_PICTURE_TYPE_I = 0x01,
@@ -131,9 +163,9 @@ typedef enum {
* GstMpegVideoPictureStructure:
* @GST_MPEG_VIDEO_PICTURE_STRUCTURE_TOP_FIELD: Top field
* @GST_MPEG_VIDEO_PICTURE_STRUCTURE_BOTTOM_FIELD: Bottom field
- * @GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME: Frame
+ * @GST_MPEG_VIDEO_PICTURE_STRUCTURE_FRAME: Frame picture
*
- * Indicates the structure of picture
+ * Picture structure type.
*/
typedef enum {
GST_MPEG_VIDEO_PICTURE_STRUCTURE_TOP_FIELD = 0x01,
@@ -168,20 +200,20 @@ typedef struct _GstMpegVideoTypeOffsetSize GstMpegVideoTypeOffsetSize;
struct _GstMpegVideoSequenceHdr
{
guint16 width, height;
- guint8 aspect_ratio_info;
- guint8 frame_rate_code;
+ guint8 aspect_ratio_info;
+ guint8 frame_rate_code;
guint32 bitrate_value;
guint16 vbv_buffer_size_value;
- guint8 constrained_parameters_flag;
+ guint8 constrained_parameters_flag;
- guint8 intra_quantizer_matrix[64];
- guint8 non_intra_quantizer_matrix[64];
+ guint8 intra_quantizer_matrix[64];
+ guint8 non_intra_quantizer_matrix[64];
/* Calculated values */
- guint par_w, par_h;
- guint fps_n, fps_d;
- guint bitrate;
+ guint par_w, par_h;
+ guint fps_n, fps_d;
+ guint bitrate;
};
/**
@@ -194,7 +226,7 @@ struct _GstMpegVideoSequenceHdr
* @vert_size_ext: Vertical size
* @bitrate_ext: The bitrate
* @vbv_buffer_size_extension: Vbv vuffer size
- * @low_delay: %TRUE if the sequence doesn't contain any B-pitcture, %FALSE
+ * @low_delay: %TRUE if the sequence doesn't contain any B-pictures, %FALSE
* otherwize
* @fps_n_ext: Framerate nominator code
* @fps_d_ext: Framerate denominator code
@@ -222,14 +254,14 @@ struct _GstMpegVideoSequenceExt
/**
* GstMpegVideoQuantMatrixExt:
- * @load_intra_quantiser_matrix
- * @intra_quantiser_matrix
- * @load_non_intra_quantiser_matrix
+ * @load_intra_quantiser_matrix:
+ * @intra_quantiser_matrix:
+ * @load_non_intra_quantiser_matrix:
* @non_intra_quantiser_matrix:
- * @load_chroma_intra_quantiser_matrix
- * @chroma_intra_quantiser_matrix
- * @load_chroma_non_intra_quantiser_matrix
- * @chroma_non_intra_quantiser_matrix
+ * @load_chroma_intra_quantiser_matrix:
+ * @chroma_intra_quantiser_matrix:
+ * @load_chroma_non_intra_quantiser_matrix:
+ * @chroma_non_intra_quantiser_matrix:
*
* The Quant Matrix Extension structure
*/
@@ -314,7 +346,7 @@ struct _GstMpegVideoPictureExt
* @second: Second (0-59)
* @frame: Frame (0-59)
* @closed_gop: Closed Gop
- * @broken_gop: Broken Gop
+ * @broken_link: Broken link
*
* The Mpeg Video Group of Picture structure.
*/
@@ -325,7 +357,7 @@ struct _GstMpegVideoGop
guint8 hour, minute, second, frame;
guint8 closed_gop;
- guint8 broken_gop;
+ guint8 broken_link;
};
/**
@@ -339,11 +371,11 @@ struct _GstMpegVideoGop
struct _GstMpegVideoTypeOffsetSize
{
guint8 type;
- guint offset;
- gint size;
+ guint offset;
+ gint size;
};
-GList * gst_mpeg_video_parse (guint8 * data, gsize size, guint offset);
+GList *gst_mpeg_video_parse (guint8 * data, gsize size, guint offset);
gboolean gst_mpeg_video_parse_sequence_header (GstMpegVideoSequenceHdr * params,
guint8 * data, gsize size, guint offset);
diff --git a/gst-libs/gst/codecparsers/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c
new file mode 100644
index 000000000..8b0b78567
--- /dev/null
+++ b/gst-libs/gst/codecparsers/gstvc1parser.c
@@ -0,0 +1,1442 @@
+/* Gstreamer
+ * Copyright (C) <2011> Intel
+ * Copyright (C) <2011> Collabora Ltd.
+ * Copyright (C) <2011> Thibault Saunier <thibault.saunier@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+/**
+ * SECTION:gstvc1parser
+ * @short_description: Convenience library for parsing vc1 video
+ * bitstream.
+ *
+ * For more details about the structures, look at the
+ * smpte specifications (S421m-2006.pdf).
+ *
+ */
+
+#ifdef HAVE_CONFIG_H
+# include "config.h"
+#endif
+
+#include "gstvc1parser.h"
+#include <gst/base/gstbytereader.h>
+#include <gst/base/gstbitreader.h>
+#include <string.h>
+
+#ifndef GST_DISABLE_GST_DEBUG
+
+#define GST_CAT_DEFAULT ensure_debug_category()
+
+static GstDebugCategory *
+ensure_debug_category (void)
+{
+ static gsize cat_gonce = 0;
+
+ if (g_once_init_enter (&cat_gonce)) {
+ gsize cat_done;
+
+ cat_done = (gsize) _gst_debug_category_new ("codecparsers_vc1", 0,
+ "VC1 codec parsing library");
+
+ g_once_init_leave (&cat_gonce, cat_done);
+ }
+
+ return (GstDebugCategory *) cat_gonce;
+}
+
+#else
+
+#define ensure_debug_category() /* NOOP */
+
+#endif /* GST_DISABLE_GST_DEBUG */
+
+/* ------------------------------------------------------------------------- */
+
+#define GET_BITS(b, num, bits) G_STMT_START { \
+ if (!gst_bit_reader_get_bits_uint32(b, bits, num)) \
+ goto failed; \
+ GST_TRACE ("parsed %d bits: %d", num, *(bits)); \
+} G_STMT_END
+
+#define READ_UINT8(br, val, nbits) G_STMT_START { \
+ if (!gst_bit_reader_get_bits_uint8 (br, &val, nbits)) { \
+ GST_WARNING ("failed to read uint8, nbits: %d", nbits); \
+ goto failed; \
+ } \
+} G_STMT_END
+
+#define READ_UINT16(br, val, nbits) G_STMT_START { \
+ if (!gst_bit_reader_get_bits_uint16 (br, &val, nbits)) { \
+ GST_WARNING ("failed to read uint16, nbits: %d", nbits); \
+ goto failed; \
+ } \
+} G_STMT_END
+
+#define READ_UINT32(br, val, nbits) G_STMT_START { \
+ if (!gst_bit_reader_get_bits_uint32 (br, &val, nbits)) { \
+ GST_WARNING ("failed to read uint32, nbits: %d", nbits); \
+ goto failed; \
+ } \
+} G_STMT_END
+
+#define SKIP(br, nbits) G_STMT_START { \
+ if (!gst_bit_reader_skip (br, nbits)) { \
+ GST_WARNING ("Failed to skip nbits: %d", nbits); \
+ goto failed; \
+ } \
+} G_STMT_END
+
+const guint8 vc1_pquant_table[3][32] = {
+ { /* Implicit quantizer */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 6, 7, 8, 9, 10, 11, 12,
+ 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 27, 29, 31},
+ { /* Explicit quantizer, pquantizer uniform */
+ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15,
+ 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31},
+ { /* Explicit quantizer, pquantizer non-uniform */
+ 0, 1, 1, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13,
+ 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 29, 31}
+};
+
+const guint8 mvmode_table[2][5] = {
+ {
+ GST_VC1_MVMODE_1MV_HPEL_BILINEAR,
+ GST_VC1_MVMODE_1MV,
+ GST_VC1_MVMODE_1MV_HPEL,
+ GST_VC1_MVMODE_MIXED_MV,
+ GST_VC1_MVMODE_INTENSITY_COMP},
+ {
+ GST_VC1_MVMODE_1MV,
+ GST_VC1_MVMODE_MIXED_MV,
+ GST_VC1_MVMODE_1MV_HPEL,
+ GST_VC1_MVMODE_INTENSITY_COMP,
+ GST_VC1_MVMODE_1MV_HPEL_BILINEAR}
+};
+
+const guint8 mvmode2_table[2][4] = {
+ {
+ GST_VC1_MVMODE_1MV_HPEL_BILINEAR,
+ GST_VC1_MVMODE_1MV,
+ GST_VC1_MVMODE_1MV_HPEL,
+ GST_VC1_MVMODE_MIXED_MV},
+ {
+ GST_VC1_MVMODE_1MV,
+ GST_VC1_MVMODE_MIXED_MV,
+ GST_VC1_MVMODE_1MV_HPEL,
+ GST_VC1_MVMODE_1MV_HPEL_BILINEAR}
+};
+
+static const guint bfraction_vlc_table[] = {
+ 0x00, 3, 128,
+ 0x01, 3, 85,
+ 0x02, 3, 170,
+ 0x03, 3, 64,
+ 0x04, 3, 192,
+ 0x05, 3, 51,
+ 0x06, 3, 102,
+ 0x70, 3, 153,
+ 0x71, 7, 204,
+ 0x72, 7, 43,
+ 0x73, 7, 215,
+ 0x74, 7, 37,
+ 0x75, 7, 74,
+ 0x76, 7, 111,
+ 0x77, 7, 148,
+ 0x78, 7, 185,
+ 0x79, 7, 222,
+ 0x7a, 7, 32,
+ 0x7b, 7, 96,
+ 0x7c, 7, 160,
+ 0x7d, 7, 224,
+ 0x7e, 7, 0, /* Indicate sthat it is smtpe reserved */
+ 0x7f, 7, GST_VC1_PICTURE_TYPE_BI
+};
+
+/* Imode types */
+enum
+{
+ IMODE_RAW,
+ IMODE_NORM2,
+ IMODE_DIFF2,
+ IMODE_NORM6,
+ IMODE_DIFF6,
+ IMODE_ROWSKIP,
+ IMODE_COLSKIP
+};
+
+static const guint imode_vlc_table[] = {
+ 0x02, 2, IMODE_NORM2, /* 10 */
+ 0x03, 2, IMODE_NORM6, /* 11 */
+ 0x02, 3, IMODE_ROWSKIP, /* 010 */
+ 0x03, 3, IMODE_COLSKIP, /* 011 */
+ 0x01, 3, IMODE_DIFF2, /* 001 */
+ 0x01, 4, IMODE_DIFF6, /* 0001 */
+ 0x00, 4, IMODE_RAW /* 0000 */
+};
+
+const guint vc1_norm2_codes_vlc_table[] = {
+ 0x00, 1, 1,
+ 0x03, 2, 3,
+ 0x04, 3, 3,
+ 0x05, 3, 2
+};
+
+const guint norm6_vlc_table[256] = {
+ 0x001, 1, 0,
+ 0x002, 4, 0,
+ 0x003, 4, 0,
+ 0x004, 4, 0,
+ 0x005, 4, 0,
+ 0x006, 4, 0,
+ 0x007, 4, 0,
+ 0x007, 6, 0,
+ 0x000, 8, 0,
+ 0x001, 8, 0,
+ 0x002, 8, 0,
+ 0x003, 8, 0,
+ 0x004, 8, 0,
+ 0x005, 8, 0,
+ 0x006, 8, 0,
+ 0x007, 8, 0,
+ 0x008, 8, 0,
+ 0x009, 8, 0,
+ 0x00A, 8, 0,
+ 0x00B, 8, 0,
+ 0x00C, 8, 0,
+ 0x00D, 8, 0,
+ 0x00E, 8, 0,
+ 0x037, 9, 0,
+ 0x036, 9, 0,
+ 0x035, 9, 0,
+ 0x034, 9, 0,
+ 0x033, 9, 0,
+ 0x032, 9, 0,
+ 0x047, 10, 0,
+ 0x04B, 10, 0,
+ 0x04D, 10, 0,
+ 0x04E, 10, 0,
+ 0x30E, 13, 0,
+ 0x053, 10, 0,
+ 0x055, 10, 0,
+ 0x056, 10, 0,
+ 0x30D, 13, 0,
+ 0x059, 10, 0,
+ 0x05A, 10, 0,
+ 0x30C, 13, 0,
+ 0x05C, 10, 0,
+ 0x30B, 13, 0,
+ 0x30A, 13, 0,
+ 0x043, 10, 0,
+ 0x045, 10, 0,
+ 0x046, 10, 0,
+ 0x309, 13, 0,
+ 0x049, 10, 0,
+ 0x04A, 10, 0,
+ 0x308, 13, 0,
+ 0x04C, 10, 0,
+ 0x307, 13, 0,
+ 0x306, 13, 0,
+ 0x051, 10, 0,
+ 0x052, 10, 0,
+ 0x305, 13, 0,
+ 0x054, 10, 0,
+ 0x304, 13, 0,
+ 0x303, 13, 0,
+ 0x058, 10, 0,
+ 0x302, 13, 0,
+ 0x301, 13, 0,
+ 0x300, 13, 0
+};
+
+static inline guint8
+decode_colskip (GstBitReader * br, guint width, guint height)
+{
+ guint i;
+ guint8 colskip;
+
+ GST_DEBUG ("Colskip rowskip");
+
+ for (i = 0; i < height; i++) {
+ READ_UINT8 (br, colskip, 1);
+
+ if (colskip)
+ SKIP (br, width);
+ }
+
+ return 1;
+
+failed:
+ GST_WARNING ("Failed to parse colskip");
+
+ return 0;
+}
+
+static inline guint8
+decode_rowskip (GstBitReader * br, guint width, guint height)
+{
+ guint i;
+ guint8 rowskip;
+
+ GST_DEBUG ("Parsing rowskip");
+
+ for (i = 0; i < height; i++) {
+ READ_UINT8 (br, rowskip, 1);
+
+ if (rowskip)
+ SKIP (br, width);
+ }
+ return 1;
+
+failed:
+ GST_WARNING ("Failed to parse rowskip");
+
+ return 0;
+}
+
+static inline gint8
+decode012 (GstBitReader * br)
+{
+ guint8 n;
+
+ READ_UINT8 (br, n, 1);
+
+ if (n == 0)
+ return 0;
+
+ READ_UINT8 (br, n, 1);
+
+ return n + 1;
+
+failed:
+ GST_WARNING ("Could not decode 0 1 2 returning -1");
+
+ return -1;
+}
+
+static inline guint
+calculate_nb_pan_scan_win (GstVC1AdvancedSeqHdr * advseqhdr,
+ GstVC1PicAdvanced * pic)
+{
+ if (advseqhdr->interlace && !advseqhdr->psf) {
+ if (advseqhdr->pulldown)
+ return pic->rff + 2;
+
+ return 2;
+
+ } else {
+ if (advseqhdr->pulldown)
+ return pic->rptfrm + 1;
+
+ return 1;
+ }
+}
+
+
+/**
+ * table should look like:
+ * {Value, nbBits, Meaning,
+ * ...
+ * } nbBits must be increasing
+ */
+static gboolean
+decode_vlc (GstBitReader * br, guint * res, const guint * table, guint length)
+{
+ guint8 i;
+ guint cbits = 0;
+ guint32 value = 0;
+
+ for (i = 0; i < length; i += 3) {
+ if (cbits != table[i + 1]) {
+ cbits = table[i + 1];
+ if (!gst_bit_reader_peek_bits_uint32 (br, &value, cbits)) {
+ goto failed;
+ }
+ }
+
+ if (value == table[i]) {
+ SKIP (br, cbits);
+ if (res)
+ *res = table[i + 2];
+
+ return TRUE;
+ }
+ }
+
+failed:
+ {
+ GST_DEBUG ("Could not decode VLC returning -1");
+
+ return FALSE;
+ }
+}
+
+/*** bitplane decoding ***/
+static gint
+bitplane_decoding (GstBitReader * br, guint height,
+ guint width, guint8 * is_raw)
+{
+ guint imode;
+ guint i, j, offset = 0;
+
+ SKIP (br, 1);
+ if (!decode_vlc (br, &imode, imode_vlc_table, G_N_ELEMENTS (imode_vlc_table)))
+ goto failed;
+
+ switch (imode) {
+ case IMODE_RAW:
+
+ GST_DEBUG ("Parsing IMODE_RAW");
+
+ *is_raw = TRUE;
+ return TRUE;
+
+ case IMODE_DIFF2:
+ case IMODE_NORM2:
+
+ GST_DEBUG ("Parsing IMODE_DIFF2 or IMODE_NORM2 biplane");
+
+ if ((height * width) & 1) {
+ SKIP (br, 1);
+ }
+
+ for (i = offset; i < height * width; i += 2) {
+ /*guint x; */
+ if (!decode_vlc (br, NULL, vc1_norm2_codes_vlc_table,
+ G_N_ELEMENTS (vc1_norm2_codes_vlc_table))) {
+ goto failed;
+ }
+ }
+ break;
+
+ case IMODE_DIFF6:
+ case IMODE_NORM6:
+
+ GST_DEBUG ("Parsing IMODE_DIFF6 or IMODE_NORM6 biplane");
+
+ if (!(height % 3) && (width % 3)) { // use 2x3 decoding
+
+ for (i = 0; i < height; i += 3) {
+ for (j = width & 1; j < width; j += 2) {
+ if (!decode_vlc (br, NULL, norm6_vlc_table,
+ G_N_ELEMENTS (norm6_vlc_table))) {
+ goto failed;
+ }
+ }
+ }
+ } else {
+ for (i = height & 1; i < height; i += 2) {
+ for (j = width % 3; j < width; j += 3) {
+ if (!decode_vlc (br, NULL, norm6_vlc_table,
+ G_N_ELEMENTS (norm6_vlc_table))) {
+ goto failed;
+ }
+ }
+ }
+
+ j = width % 3;
+ if (j)
+ decode_colskip (br, height, width);
+
+ if (height & 1)
+ decode_rowskip (br, height, width);
+ }
+ break;
+ case IMODE_ROWSKIP:
+
+ GST_DEBUG ("Parsing IMODE_ROWSKIP biplane");
+
+ if (!decode_rowskip (br, width, height))
+ goto failed;
+ break;
+ case IMODE_COLSKIP:
+
+ GST_DEBUG ("Parsing IMODE_COLSKIP biplane");
+
+ if (decode_colskip (br, width, height))
+ goto failed;
+ break;
+ }
+
+ return TRUE;
+
+failed:
+ GST_WARNING ("Failed to decode bitplane");
+
+ return FALSE;
+}
+
+static gboolean
+parse_vopdquant (GstBitReader * br, GstVC1FrameHdr * framehdr, guint8 dquant)
+{
+ GstVC1VopDquant *vopdquant = &framehdr->vopdquant;
+
+ GST_DEBUG ("Parsing vopdquant");
+
+ vopdquant->dqbilevel = 0;
+
+ if (dquant == 2) {
+ READ_UINT8 (br, vopdquant->dquantfrm, 1);
+
+ READ_UINT8 (br, vopdquant->pqdiff, 3);
+
+ if (vopdquant->pqdiff == 7)
+ READ_UINT8 (br, vopdquant->abspq, 5);
+ else
+ vopdquant->abspq = framehdr->pquant + vopdquant->pqdiff + 1;
+
+ } else {
+ READ_UINT8 (br, vopdquant->dquantfrm, 1);
+ GST_DEBUG (" %u DquantFrm %u", gst_bit_reader_get_pos (br),
+ vopdquant->dquantfrm);
+
+ if (vopdquant->dquantfrm) {
+ READ_UINT8 (br, vopdquant->dqprofile, 1);
+
+ switch (vopdquant->dqprofile) {
+ case GST_VC1_DQPROFILE_SINGLE_EDGE:
+ case GST_VC1_DQPROFILE_DOUBLE_EDGES:
+ READ_UINT8 (br, vopdquant->dqsbedge, 2);
+ break;
+
+ case GST_VC1_DQPROFILE_ALL_MBS:
+ READ_UINT8 (br, vopdquant->dqbilevel, 1);
+ break;
+ }
+
+ if (vopdquant->dqbilevel
+ || vopdquant->dqprofile != GST_VC1_DQPROFILE_ALL_MBS) {
+ {
+ READ_UINT8 (br, vopdquant->pqdiff, 3);
+
+ if (vopdquant->pqdiff == 7)
+ READ_UINT8 (br, vopdquant->abspq, 5);
+ }
+ }
+ }
+ }
+
+ return TRUE;
+
+failed:
+ GST_WARNING ("Failed to parse vopdquant");
+
+ return FALSE;
+}
+
+static inline gint
+scan_for_start_codes (const guint8 * data, guint size)
+{
+ GstByteReader br;
+ gst_byte_reader_init (&br, data, size);
+
+ /* NALU not empty, so we can at least expect 1 (even 2) bytes following sc */
+ return gst_byte_reader_masked_scan_uint32 (&br, 0xffffff00, 0x00000100,
+ 0, size);
+}
+
+static inline gint
+get_unary (GstBitReader * br, gint stop, gint len)
+{
+ int i;
+ guint8 current = 0xff;
+
+ for (i = 0; i < len; i++) {
+ gst_bit_reader_get_bits_uint8 (br, &current, 1);
+ if (current == stop)
+ return i;
+ }
+
+ return i;
+}
+
+static GstVC1ParseResult
+parse_hrd_param_flag (GstBitReader * br, GstVC1HrdParam * hrd_param)
+{
+ guint i;
+
+ GST_DEBUG ("Parsing Hrd param flag");
+
+
+ if (gst_bit_reader_get_remaining (br) < 13)
+ goto failed;
+
+ hrd_param->hrd_num_leaky_buckets =
+ gst_bit_reader_get_bits_uint8_unchecked (br, 5);
+ hrd_param->bit_rate_exponent =
+ gst_bit_reader_get_bits_uint8_unchecked (br, 4);
+ hrd_param->buffer_size_exponent =
+ gst_bit_reader_get_bits_uint8_unchecked (br, 4);
+
+ if (gst_bit_reader_get_remaining (br) <
+ (32 * hrd_param->hrd_num_leaky_buckets))
+ goto failed;
+
+ for (i = 0; i < hrd_param->hrd_num_leaky_buckets; i++) {
+ hrd_param->hrd_rate[i] = gst_bit_reader_get_bits_uint16_unchecked (br, 16);
+ hrd_param->hrd_buffer[i] =
+ gst_bit_reader_get_bits_uint16_unchecked (br, 16);
+ }
+
+ return GST_VC1_PARSER_OK;
+
+failed:
+ GST_WARNING ("Failed to parse hrd param flag");
+
+ return GST_VC1_PARSER_ERROR;
+}
+
+static GstVC1ParseResult
+parse_sequence_header_advanced (GstVC1SeqHdr * seqhdr, GstBitReader * br)
+{
+ GstVC1AdvancedSeqHdr *advanced = &seqhdr->profile.advanced;
+
+ GST_DEBUG ("Parsing sequence header in advanced mode");
+
+ READ_UINT8 (br, advanced->level, 3);
+
+ READ_UINT8 (br, seqhdr->colordiff_format, 2);
+ READ_UINT8 (br, seqhdr->frmrtq_postproc, 3);
+ READ_UINT8 (br, seqhdr->bitrtq_postproc, 5);
+
+ GST_DEBUG ("level %u, colordiff_format %u , frmrtq_postproc %u,"
+ " bitrtq_postproc %u", advanced->level, seqhdr->colordiff_format,
+ seqhdr->frmrtq_postproc, seqhdr->bitrtq_postproc);
+
+ /* Calulate bitrate and framerate */
+ if (seqhdr->frmrtq_postproc == 0 && seqhdr->bitrtq_postproc == 30) {
+ seqhdr->framerate = 0;
+ seqhdr->bitrate = 0;
+ } else if (seqhdr->frmrtq_postproc == 0 && seqhdr->bitrtq_postproc == 30) {
+ seqhdr->framerate = 2;
+ seqhdr->bitrate = 1952;
+ } else if (seqhdr->frmrtq_postproc == 0 && seqhdr->bitrtq_postproc == 31) {
+ seqhdr->framerate = 6;
+ seqhdr->bitrate = 2016;
+ } else {
+ if (seqhdr->frmrtq_postproc == 7) {
+ seqhdr->framerate = 30;
+ } else {
+ seqhdr->framerate = 2 + (seqhdr->frmrtq_postproc * 4);
+ }
+ if (seqhdr->bitrtq_postproc == 31) {
+ seqhdr->bitrate = 2016;
+ } else {
+ seqhdr->bitrate = 32 + (seqhdr->bitrtq_postproc * 64);
+ }
+ }
+
+ if (gst_bit_reader_get_remaining (br) < 32)
+ goto failed;
+
+ advanced->postprocflag = gst_bit_reader_get_bits_uint8_unchecked (br, 1);
+ advanced->max_coded_width = gst_bit_reader_get_bits_uint16_unchecked (br, 12);
+ advanced->max_coded_height =
+ gst_bit_reader_get_bits_uint16_unchecked (br, 12);
+ advanced->max_coded_width = (advanced->max_coded_width + 1) << 1;
+ advanced->max_coded_height = (advanced->max_coded_height + 1) << 1;
+ advanced->pulldown = gst_bit_reader_get_bits_uint8_unchecked (br, 1);
+ advanced->interlace = gst_bit_reader_get_bits_uint8_unchecked (br, 1);
+ advanced->tfcntrflag = gst_bit_reader_get_bits_uint8_unchecked (br, 1);
+ seqhdr->finterpflag = gst_bit_reader_get_bits_uint8_unchecked (br, 1);
+
+ GST_DEBUG ("postprocflag %u, max_coded_width %u, max_coded_height %u,"
+ "pulldown %u, interlace %u, tfcntrflag %u, finterpflag %u",
+ advanced->postprocflag, advanced->max_coded_width,
+ advanced->max_coded_height, advanced->pulldown,
+ advanced->interlace, advanced->tfcntrflag, seqhdr->finterpflag);
+
+ /* Skipping reserved bit */
+ gst_bit_reader_skip_unchecked (br, 1);
+
+ advanced->psf = gst_bit_reader_get_bits_uint8_unchecked (br, 1);
+ advanced->display_ext = gst_bit_reader_get_bits_uint8_unchecked (br, 1);
+ if (advanced->display_ext) {
+ READ_UINT16 (br, advanced->disp_horiz_size, 14);
+ READ_UINT16 (br, advanced->disp_vert_size, 14);
+
+ advanced->disp_horiz_size++;
+ advanced->disp_vert_size++;
+
+ READ_UINT8 (br, advanced->aspect_ratio_flag, 1);
+
+ if (advanced->aspect_ratio_flag) {
+ READ_UINT8 (br, advanced->aspect_ratio, 4);
+
+ if (advanced->aspect_ratio == 15) {
+ READ_UINT8 (br, advanced->aspect_horiz_size, 8);
+ READ_UINT8 (br, advanced->aspect_vert_size, 8);
+ }
+ }
+ READ_UINT8 (br, advanced->framerate_flag, 1);
+ if (advanced->framerate_flag) {
+ READ_UINT8 (br, advanced->framerateind, 1);
+
+ if (!advanced->framerateind) {
+ READ_UINT8 (br, advanced->frameratenr, 8);
+ READ_UINT8 (br, advanced->frameratedr, 4);
+ } else {
+ READ_UINT16 (br, advanced->framerateexp, 16);
+ }
+ }
+ READ_UINT8 (br, advanced->color_format_flag, 1);
+
+ if (advanced->color_format_flag) {
+ if (gst_bit_reader_get_remaining (br) < 24)
+ goto failed;
+
+ advanced->color_prim = gst_bit_reader_get_bits_uint8_unchecked (br, 8);
+ advanced->transfer_char = gst_bit_reader_get_bits_uint8_unchecked (br, 8);
+ advanced->matrix_coef = gst_bit_reader_get_bits_uint8_unchecked (br, 8);
+ }
+ }
+ READ_UINT8 (br, advanced->hrd_param_flag, 1);
+ if (advanced->hrd_param_flag)
+ return parse_hrd_param_flag (br, &advanced->hrd_param);
+
+ return GST_VC1_PARSER_OK;
+
+failed:
+ GST_WARNING ("Failed to parse advanced headers");
+
+ return GST_VC1_PARSER_ERROR;
+}
+
+static GstVC1ParseResult
+parse_frame_header_advanced (GstBitReader * br, GstVC1FrameHdr * framehdr,
+ GstVC1SeqHdr * seqhdr)
+{
+ GstVC1AdvancedSeqHdr *advhdr = &seqhdr->profile.advanced;
+ GstVC1PicAdvanced *pic = &framehdr->pic.advanced;
+ GstVC1EntryPointHdr *entrypthdr = &advhdr->entrypoint;
+ guint8 mvmodeidx;
+ guint width = (entrypthdr->coded_width + 15) >> 4;
+ guint height = (entrypthdr->coded_height + 15) >> 4;
+
+ GST_DEBUG ("Parsing Frame header advanced %u", advhdr->interlace);
+
+ /* Set the conveninence fields */
+ framehdr->profile = seqhdr->profiletype;
+ framehdr->dquant = entrypthdr->dquant;
+
+ if (advhdr->interlace) {
+ gint8 fcm = decode012 (br);
+
+ if (fcm < 0)
+ goto failed;
+
+ pic->fcm = (guint8) fcm;
+ }
+
+ framehdr->ptype = get_unary (br, 0, 4);
+
+ if (framehdr->ptype == GST_VC1_PICTURE_TYPE_SKIPPED)
+ goto failed;
+
+ if (advhdr->tfcntrflag) {
+ READ_UINT8 (br, pic->tfcntr, 8);
+ GST_DEBUG ("tfcntr %u", pic->tfcntr);
+ }
+
+ if (advhdr->pulldown) {
+ if (!advhdr->interlace || advhdr->psf) {
+
+ READ_UINT8 (br, pic->rptfrm, 2);
+ GST_DEBUG ("rptfrm %u", pic->rptfrm);
+
+ } else {
+
+ READ_UINT8 (br, pic->tff, 1);
+ READ_UINT8 (br, pic->rff, 1);
+ GST_DEBUG ("tff %u, rff %u", pic->tff, pic->rff);
+ }
+ }
+
+ if (entrypthdr->panscan_flag) {
+ READ_UINT8 (br, pic->ps_present, 1);
+
+ if (pic->ps_present) {
+ guint i, nb_pan_scan_win = calculate_nb_pan_scan_win (advhdr, pic);
+
+ if (gst_bit_reader_get_remaining (br) < 64 * nb_pan_scan_win)
+ goto failed;
+
+ for (i = 0; i < nb_pan_scan_win; i++) {
+ pic->ps_hoffset = gst_bit_reader_get_bits_uint32_unchecked (br, 18);
+ pic->ps_voffset = gst_bit_reader_get_bits_uint32_unchecked (br, 18);
+ pic->ps_width = gst_bit_reader_get_bits_uint16_unchecked (br, 14);
+ pic->ps_height = gst_bit_reader_get_bits_uint16_unchecked (br, 14);
+ }
+ }
+ }
+
+ READ_UINT8 (br, pic->rndctrl, 1);
+
+ if (advhdr->interlace) {
+ READ_UINT8 (br, pic->uvsamp, 1);
+ GST_DEBUG ("uvsamp %u", pic->uvsamp);
+ }
+
+ if (seqhdr->finterpflag) {
+ READ_UINT8 (br, framehdr->interpfrm, 1);
+ GST_DEBUG ("interpfrm %u", framehdr->interpfrm);
+ }
+
+ if (framehdr->ptype == GST_VC1_PICTURE_TYPE_B) {
+ if (!decode_vlc (br, (guint *) & pic->bfraction, bfraction_vlc_table,
+ G_N_ELEMENTS (bfraction_vlc_table)))
+ goto failed;
+
+ GST_DEBUG ("bfraction %u", pic->bfraction);
+
+ if (pic->bfraction == GST_VC1_PICTURE_TYPE_BI) {
+ framehdr->ptype = GST_VC1_PICTURE_TYPE_BI;
+ }
+
+ }
+
+ READ_UINT8 (br, framehdr->pqindex, 5);
+ if (!framehdr->pqindex)
+ goto failed;
+
+ /* compute pquant */
+ if (entrypthdr->quantizer == GST_VC1_QUANTIZER_IMPLICITLY)
+ framehdr->pquant = vc1_pquant_table[0][framehdr->pqindex];
+ else
+ framehdr->pquant = vc1_pquant_table[1][framehdr->pqindex];
+
+ framehdr->pquantizer = 1;
+ if (entrypthdr->quantizer == GST_VC1_QUANTIZER_IMPLICITLY)
+ framehdr->pquantizer = framehdr->pqindex < 9;
+ if (entrypthdr->quantizer == GST_VC1_QUANTIZER_NON_UNIFORM)
+ framehdr->pquantizer = 0;
+
+ if (framehdr->pqindex <= 8)
+ READ_UINT8 (br, framehdr->halfqp, 1);
+ else
+ framehdr->halfqp = 0;
+
+ if (entrypthdr->quantizer == GST_VC1_QUANTIZER_EXPLICITLY) {
+ READ_UINT8 (br, framehdr->pquantizer, 1);
+ }
+
+ if (advhdr->postprocflag)
+ READ_UINT8 (br, pic->postproc, 2);
+
+ GST_DEBUG ("Parsing %u picture, pqindex %u, pquant %u pquantizer %u"
+ "halfqp %u", framehdr->ptype, framehdr->pqindex, framehdr->pquant,
+ framehdr->pquantizer, framehdr->halfqp);
+
+ switch (framehdr->ptype) {
+ case GST_VC1_PICTURE_TYPE_I:
+ case GST_VC1_PICTURE_TYPE_BI:
+ if (!bitplane_decoding (br, height, width, &pic->acpred))
+ goto failed;
+
+ if (entrypthdr->overlap && framehdr->pquant <= 8) {
+ pic->condover = decode012 (br);
+
+ if (pic->condover == (guint8) - 1)
+ goto failed;
+
+ else if (pic->condover == GST_VC1_CONDOVER_SELECT) {
+
+ if (!bitplane_decoding (br, height, width, &pic->overflags))
+ goto failed;
+ GST_DEBUG ("overflags %u", pic->overflags);
+ }
+ }
+
+ framehdr->transacfrm = get_unary (br, 0, 2);
+ pic->transacfrm2 = get_unary (br, 0, 2);
+ READ_UINT8 (br, framehdr->transdctab, 1);
+
+ if (framehdr->dquant)
+ parse_vopdquant (br, framehdr, framehdr->dquant);
+
+ GST_DEBUG ("acpred %u, condover %u transacfrm %u transacfrm2 %u,",
+ pic->acpred, pic->condover, framehdr->transacfrm, pic->transacfrm2);
+ break;
+
+ case GST_VC1_PICTURE_TYPE_B:
+ if (entrypthdr->extended_mv)
+ pic->mvrange = get_unary (br, 0, 3);
+ else
+ pic->mvrange = 0;
+
+ READ_UINT8 (br, pic->mvmode, 1);
+
+ if (!bitplane_decoding (br, height, width, &pic->directmb))
+ goto failed;
+
+ if (!bitplane_decoding (br, height, width, &pic->skipmb))
+ goto failed;
+
+ READ_UINT8 (br, pic->mvtab, 2);
+ READ_UINT8 (br, pic->cbptab, 2);
+
+ if (framehdr->dquant) {
+ parse_vopdquant (br, framehdr, framehdr->dquant);
+ }
+
+ if (entrypthdr->vstransform) {
+ READ_UINT8 (br, pic->ttmbf, 1);
+
+ if (pic->ttmbf) {
+ READ_UINT8 (br, pic->ttfrm, 2);
+ }
+ }
+
+ framehdr->transacfrm = get_unary (br, 0, 2);
+ READ_UINT8 (br, framehdr->transdctab, 1);
+
+ GST_DEBUG ("transacfrm %u transdctab %u mvmode %u mvtab %u,"
+ "cbptab %u directmb %u skipmb %u", framehdr->transacfrm,
+ framehdr->transdctab, pic->mvmode, pic->mvtab, pic->cbptab,
+ pic->directmb, pic->skipmb);
+
+ break;
+ case GST_VC1_PICTURE_TYPE_P:
+ if (entrypthdr->extended_mv)
+ pic->mvrange = get_unary (br, 0, 3);
+ else
+ pic->mvrange = 0;
+
+ mvmodeidx = framehdr->pquant > 12 ? 0 : 1;
+ pic->mvmode = mvmode_table[mvmodeidx][get_unary (br, 1, 4)];
+
+ if (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP) {
+
+ pic->mvmode2 = mvmode2_table[mvmodeidx][get_unary (br, 1, 4)];
+ READ_UINT8 (br, pic->lumscale, 6);
+ READ_UINT8 (br, pic->lumshift, 6);
+
+ GST_DEBUG ("lumscale %u lumshift %u", pic->lumscale, pic->lumshift);
+ }
+
+ if (pic->mvmode == GST_VC1_MVMODE_MIXED_MV ||
+ (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP &&
+ pic->mvmode2 == GST_VC1_MVMODE_MIXED_MV)) {
+ if (!bitplane_decoding (br, height, width, &pic->mvtypemb))
+ goto failed;
+ GST_DEBUG ("mvtypemb %u", pic->mvtypemb);
+ }
+
+ if (!bitplane_decoding (br, height, width, &pic->skipmb) ||
+ gst_bit_reader_get_remaining (br) < 4)
+ goto failed;
+
+ pic->mvtab = gst_bit_reader_get_bits_uint8_unchecked (br, 2);
+ pic->cbptab = gst_bit_reader_get_bits_uint8_unchecked (br, 2);
+
+ if (framehdr->dquant) {
+ parse_vopdquant (br, framehdr, framehdr->dquant);
+ }
+
+ if (entrypthdr->vstransform) {
+ READ_UINT8 (br, pic->ttmbf, 1);
+
+ if (pic->ttmbf) {
+ READ_UINT8 (br, pic->ttfrm, 2);
+ }
+ }
+
+ framehdr->transacfrm = get_unary (br, 0, 2);
+ READ_UINT8 (br, framehdr->transdctab, 1);
+
+ GST_DEBUG ("transacfrm %u transdctab %u mvmode %u mvtab %u,"
+ "cbptab %u skipmb %u", framehdr->transacfrm, framehdr->transdctab,
+ pic->mvmode, pic->mvtab, pic->cbptab, pic->skipmb);
+
+ break;
+ }
+
+ return GST_VC1_PARSER_OK;
+
+failed:
+ GST_WARNING ("Failed to parse frame header");
+
+ return GST_VC1_PARSER_ERROR;
+}
+
+static GstVC1ParseResult
+parse_frame_header (GstBitReader * br, GstVC1FrameHdr * framehdr,
+ GstVC1SeqHdr * seqhdr)
+{
+ guint8 mvmodeidx;
+ GstVC1PicSimpleMain *pic = &framehdr->pic.simple;
+ GstVC1SimpleMainSeqHdr *simplehdr = &seqhdr->profile.simplemain;
+ guint width = (simplehdr->coded_width + 15) >> 4;
+ guint height = (simplehdr->coded_height + 15) >> 4;
+
+
+ GST_DEBUG ("Parsing frame header in simple or main mode");
+
+ /* Set the conveninence fields */
+ framehdr->profile = seqhdr->profiletype;
+ framehdr->dquant = simplehdr->dquant;
+
+ framehdr->interpfrm = 0;
+ if (seqhdr->finterpflag)
+ READ_UINT8 (br, framehdr->interpfrm, 1);
+
+ READ_UINT8 (br, pic->frmcnt, 2);
+
+ pic->rangeredfrm = 0;
+ if (simplehdr->rangered) {
+ READ_UINT8 (br, pic->rangeredfrm, 2);
+ }
+
+ /* Figuring out the picture type */
+ READ_UINT8 (br, framehdr->ptype, 1);
+ if (simplehdr->maxbframes) {
+ if (!framehdr->ptype) {
+ READ_UINT8 (br, framehdr->ptype, 1);
+
+ if (framehdr->ptype)
+ framehdr->ptype = GST_VC1_PICTURE_TYPE_I;
+ else
+ framehdr->ptype = GST_VC1_PICTURE_TYPE_B;
+
+ } else
+ framehdr->ptype = GST_VC1_PICTURE_TYPE_P;
+
+ } else {
+ if (framehdr->ptype)
+ framehdr->ptype = GST_VC1_PICTURE_TYPE_P;
+ else
+ framehdr->ptype = GST_VC1_PICTURE_TYPE_I;
+ }
+
+
+ if (framehdr->ptype == GST_VC1_PICTURE_TYPE_B) {
+
+ if (!decode_vlc (br, (guint *) & pic->bfraction, bfraction_vlc_table,
+ G_N_ELEMENTS (bfraction_vlc_table)))
+ goto failed;
+
+ if (pic->bfraction == GST_VC1_PICTURE_TYPE_BI) {
+ framehdr->ptype = GST_VC1_PICTURE_TYPE_BI;
+ }
+ GST_DEBUG ("bfraction= %d", pic->bfraction);
+ }
+
+ if (framehdr->ptype == GST_VC1_PICTURE_TYPE_I ||
+ framehdr->ptype == GST_VC1_PICTURE_TYPE_BI)
+ READ_UINT8 (br, pic->bf, 7);
+
+ READ_UINT8 (br, framehdr->pqindex, 5);
+ if (!framehdr->pqindex)
+ return GST_VC1_PARSER_ERROR;
+
+ GST_DEBUG ("pqindex %u", framehdr->pqindex);
+
+ /* compute pquant */
+ if (simplehdr->quantizer == GST_VC1_QUANTIZER_IMPLICITLY)
+ framehdr->pquant = vc1_pquant_table[0][framehdr->pqindex];
+ else
+ framehdr->pquant = vc1_pquant_table[1][framehdr->pqindex];
+
+ GST_DEBUG ("pquant %u", framehdr->pquant);
+
+ if (framehdr->pqindex <= 8)
+ READ_UINT8 (br, framehdr->halfqp, 1);
+ else
+ framehdr->halfqp = 0;
+
+ /* Set pquantizer */
+ framehdr->pquantizer = 1;
+ if (simplehdr->quantizer == GST_VC1_QUANTIZER_IMPLICITLY)
+ framehdr->pquantizer = framehdr->pqindex < 9;
+ else if (simplehdr->quantizer == GST_VC1_QUANTIZER_NON_UNIFORM)
+ framehdr->pquantizer = 0;
+
+ if (simplehdr->quantizer == GST_VC1_QUANTIZER_EXPLICITLY)
+ READ_UINT8 (br, framehdr->pquantizer, 1);
+
+ if (simplehdr->extended_mv == 1) {
+ pic->mvrange = get_unary (br, 0, 3);
+ GST_DEBUG ("mvrange %u", pic->mvrange);
+ }
+
+ if (simplehdr->multires && (framehdr->ptype == GST_VC1_PICTURE_TYPE_P ||
+ framehdr->ptype == GST_VC1_PICTURE_TYPE_I)) {
+ READ_UINT8 (br, pic->respic, 2);
+ GST_DEBUG ("Respic %u", pic->respic);
+ }
+
+ GST_DEBUG ("Parsing %u Frame, pquantizer %u, halfqp %u, rangeredfrm %u, "
+ "interpfrm %u", framehdr->ptype, framehdr->pquantizer, framehdr->halfqp,
+ pic->rangeredfrm, framehdr->interpfrm);
+
+ switch (framehdr->ptype) {
+ case GST_VC1_PICTURE_TYPE_I:
+ case GST_VC1_PICTURE_TYPE_BI:
+ framehdr->transacfrm = get_unary (br, 0, 2);
+ pic->transacfrm2 = get_unary (br, 0, 2);
+ READ_UINT8 (br, framehdr->transdctab, 1);
+
+ GST_DEBUG ("transacfrm %u, transacfrm2 %u, transdctab %u",
+ framehdr->transacfrm, pic->transacfrm2, framehdr->transdctab);
+ break;
+
+ case GST_VC1_PICTURE_TYPE_P:
+ mvmodeidx = framehdr->pquant > 12;
+
+ pic->mvmode = mvmode_table[mvmodeidx][get_unary (br, 1, 4)];
+
+ if (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP) {
+ pic->mvmode2 = mvmode2_table[mvmodeidx][get_unary (br, 1, 4)];
+ READ_UINT8 (br, pic->lumscale, 6);
+ READ_UINT8 (br, pic->lumshift, 6);
+ GST_DEBUG ("lumscale %u lumshift %u", pic->lumscale, pic->lumshift);
+ }
+
+ if (pic->mvmode == GST_VC1_MVMODE_MIXED_MV ||
+ (pic->mvmode == GST_VC1_MVMODE_INTENSITY_COMP &&
+ pic->mvmode2 == GST_VC1_MVMODE_MIXED_MV)) {
+ if (!bitplane_decoding (br, height, width, &pic->mvtypemb))
+ goto failed;
+ GST_DEBUG ("mvtypemb %u", pic->mvtypemb);
+ }
+ if (!bitplane_decoding (br, height, width, &pic->skipmb))
+ goto failed;
+
+ READ_UINT8 (br, pic->mvtab, 2);
+ READ_UINT8 (br, pic->cbptab, 2);
+
+ if (framehdr->dquant) {
+ parse_vopdquant (br, framehdr, framehdr->dquant);
+ }
+
+ if (simplehdr->vstransform) {
+ READ_UINT8 (br, pic->ttmbf, 1);
+ GST_DEBUG ("ttmbf %u", pic->ttmbf);
+
+ if (pic->ttmbf) {
+ READ_UINT8 (br, pic->ttfrm, 2);
+ GST_DEBUG ("ttfrm %u", pic->ttfrm);
+ }
+ }
+
+ framehdr->transacfrm = get_unary (br, 0, 2);
+ READ_UINT8 (br, framehdr->transdctab, 1);
+
+ GST_DEBUG ("transacfrm %u transdctab %u mvmode %u mvtab %u,"
+ "cbptab %u skipmb %u", framehdr->transacfrm, framehdr->transdctab,
+ pic->mvmode, pic->mvtab, pic->cbptab, pic->skipmb);
+ break;
+
+ case GST_VC1_PICTURE_TYPE_B:
+ READ_UINT8 (br, pic->mvmode, 1);
+ if (!bitplane_decoding (br, height, width, &pic->directmb))
+ goto failed;
+ if (!bitplane_decoding (br, height, width, &pic->skipmb) == -1)
+ goto failed;
+
+ READ_UINT8 (br, pic->mvtab, 2);
+ READ_UINT8 (br, pic->cbptab, 2);
+
+ if (framehdr->dquant)
+ parse_vopdquant (br, framehdr, framehdr->dquant);
+
+ if (simplehdr->vstransform) {
+ READ_UINT8 (br, pic->ttmbf, 1);
+
+ if (pic->ttmbf) {
+ READ_UINT8 (br, pic->ttfrm, 2);
+ }
+ }
+
+ framehdr->transacfrm = get_unary (br, 0, 2);
+ READ_UINT8 (br, framehdr->transdctab, 1);
+
+ GST_DEBUG ("transacfrm %u transdctab %u mvmode %u mvtab %u,"
+ "cbptab %u directmb %u skipmb %u", framehdr->transacfrm,
+ framehdr->transdctab, pic->mvmode, pic->mvtab, pic->cbptab,
+ pic->directmb, pic->skipmb);
+
+ break;
+ }
+
+ return GST_VC1_PARSER_OK;
+
+failed:
+ GST_WARNING ("Failed to parse Simple picture header");
+
+ return GST_VC1_PARSER_ERROR;
+}
+
+/**** API ****/
+/**
+ * gst_vc1_identify_next_bdu:
+ * @data: The data to parse
+ * @size: the size of @data
+ * @bdu: (out): The #GstVC1BDU where to store parsed bdu headers
+ *
+ * Parses @data and fills @bdu fields
+ *
+ * Returns: a #GstVC1ParseResult
+ */
+GstVC1ParseResult
+gst_vc1_identify_next_bdu (const guint8 * data, gsize size, GstVC1BDU * bdu)
+{
+ gint off1, off2;
+
+ g_return_val_if_fail (bdu != NULL, GST_VC1_PARSER_ERROR);
+
+ ensure_debug_category ();
+
+ if (size <= 4) {
+ GST_DEBUG ("Can't parse, buffer is to small size %" G_GSSIZE_FORMAT, size);
+ return GST_VC1_PARSER_ERROR;
+ }
+
+ off1 = scan_for_start_codes (data, size);
+
+ if (off1 < 0) {
+ GST_DEBUG ("No start code prefix in this buffer");
+ return GST_VC1_PARSER_NO_BDU;
+ }
+
+ bdu->sc_offset = off1;
+
+ bdu->offset = off1 + 4;
+ bdu->data = (guint8 *) data;
+ bdu->type = (GstVC1StartCode) (data[bdu->offset - 1]);
+
+ off2 = scan_for_start_codes (data + bdu->offset, size - bdu->offset);
+ if (off2 < 0) {
+ GST_DEBUG ("Bdu start %d, No end found", bdu->offset);
+
+ return GST_VC1_PARSER_NO_BDU_END;
+ }
+
+ if (off2 > 0 && data[bdu->offset + off2 - 1] == 00)
+ off2--;
+
+ bdu->size = off2;
+
+ GST_DEBUG ("Complete bdu found. Off: %d, Size: %d", bdu->offset, bdu->size);
+ return GST_VC1_PARSER_OK;
+}
+
+/**
+ * gst_vc1_parse_sequence_header:
+ * @data: The data to parse
+ * @size: the size of @data
+ * @seqhdr: The #GstVC1SeqHdr to set.
+ *
+ * Parses @data, and fills @seqhdr fields.
+ *
+ * Returns: a #GstVC1ParseResult
+ */
+GstVC1ParseResult
+gst_vc1_parse_sequence_header (const guint8 * data, gsize size,
+ GstVC1SeqHdr * seqhdr)
+{
+ GstBitReader br;
+ guint8 old_interlaced_mode;
+ GstVC1SimpleMainSeqHdr *simplehdr = &seqhdr->profile.simplemain;
+
+ g_return_val_if_fail (seqhdr != NULL, GST_VC1_PARSER_ERROR);
+
+ ensure_debug_category ();
+
+ gst_bit_reader_init (&br, data, size);
+
+ READ_UINT8 (&br, seqhdr->profiletype, 2);
+
+ if (seqhdr->profiletype == GST_VC1_PROFILE_ADVANCED) {
+ return parse_sequence_header_advanced (seqhdr, &br);
+ }
+
+ GST_DEBUG ("Parsing sequence header in simple or main mode");
+
+ if (gst_bit_reader_get_remaining (&br) < 29)
+ goto failed;
+
+ /* Reserved bits */
+ old_interlaced_mode = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+ if (old_interlaced_mode)
+ GST_WARNING ("Old interlaced mode used");
+
+ simplehdr->wmvp = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+ if (simplehdr->wmvp)
+ GST_DEBUG ("WMVP mode");
+
+ seqhdr->frmrtq_postproc = gst_bit_reader_get_bits_uint8_unchecked (&br, 3);
+ seqhdr->bitrtq_postproc = gst_bit_reader_get_bits_uint8_unchecked (&br, 5);
+ simplehdr->loop_filter = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+
+ /* Skipping reserved3 bit */
+ gst_bit_reader_skip_unchecked (&br, 1);
+
+ simplehdr->multires = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+
+ /* Skipping reserved4 bit */
+ gst_bit_reader_skip_unchecked (&br, 1);
+
+ simplehdr->fastuvmc = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+ simplehdr->extended_mv = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+ simplehdr->dquant = gst_bit_reader_get_bits_uint8_unchecked (&br, 2);
+ simplehdr->vstransform = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+
+ /* Skipping reserved5 bit */
+ gst_bit_reader_skip_unchecked (&br, 1);
+
+ simplehdr->overlap = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+ simplehdr->syncmarker = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+ simplehdr->rangered = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+ simplehdr->maxbframes = gst_bit_reader_get_bits_uint8_unchecked (&br, 3);
+ simplehdr->quantizer = gst_bit_reader_get_bits_uint8_unchecked (&br, 2);
+ seqhdr->finterpflag = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+
+ GST_DEBUG ("frmrtq_postproc %u, bitrtq_postproc %u, loop_filter %u, "
+ "multires %u, fastuvmc %u, extended_mv %u, dquant %u, vstransform %u, "
+ "overlap %u, syncmarker %u, rangered %u, maxbframes %u, quantizer %u, "
+ "finterpflag %u", seqhdr->frmrtq_postproc, seqhdr->bitrtq_postproc,
+ simplehdr->loop_filter, simplehdr->multires, simplehdr->fastuvmc,
+ simplehdr->extended_mv, simplehdr->dquant, simplehdr->vstransform,
+ simplehdr->overlap, simplehdr->syncmarker, simplehdr->rangered,
+ simplehdr->maxbframes, simplehdr->quantizer, seqhdr->finterpflag);
+
+ if (simplehdr->wmvp) {
+ if (gst_bit_reader_get_remaining (&br) < 29)
+ goto failed;
+
+ simplehdr->coded_width = gst_bit_reader_get_bits_uint16_unchecked (&br, 11);
+ simplehdr->coded_height =
+ gst_bit_reader_get_bits_uint16_unchecked (&br, 11);
+ simplehdr->framerate = gst_bit_reader_get_bits_uint8_unchecked (&br, 5);
+ gst_bit_reader_skip_unchecked (&br, 1);
+ simplehdr->slice_code = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+
+ GST_DEBUG ("coded_width %u, coded_height %u, framerate %u slice_code %u",
+ simplehdr->coded_width, simplehdr->coded_height, simplehdr->framerate,
+ simplehdr->slice_code);
+ }
+
+ return GST_VC1_PARSER_OK;
+
+failed:
+ GST_WARNING ("Failed to parse sequence header");
+
+ return GST_VC1_PARSER_ERROR;
+}
+
+/**
+ * gst_vc1_parse_entry_point_header:
+ * @data: The data to parse
+ * @size: the size of @data
+ * @entrypoint: (out): The #GstVC1EntryPointHdr to set.
+ * @seqhdr: The #GstVC1SeqHdr currently being parsed
+ *
+ * Parses @data, and sets @entrypoint fields.
+ *
+ * Returns: a #GstVC1EntryPointHdr
+ */
+GstVC1ParseResult
+gst_vc1_parse_entry_point_header (const guint8 * data, gsize size,
+ GstVC1EntryPointHdr * entrypoint, GstVC1SeqHdr * seqhdr)
+{
+ GstBitReader br;
+ guint8 i;
+ GstVC1AdvancedSeqHdr *advanced = &seqhdr->profile.advanced;
+
+ g_return_val_if_fail (entrypoint != NULL, GST_VC1_PARSER_ERROR);
+
+ ensure_debug_category ();
+
+ gst_bit_reader_init (&br, data, size);
+
+ if (gst_bit_reader_get_remaining (&br) < 13)
+ goto failed;
+
+ entrypoint->broken_link = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+ entrypoint->closed_entry = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+ entrypoint->panscan_flag = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+ entrypoint->refdist_flag = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+ entrypoint->loopfilter = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+ entrypoint->fastuvmc = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+ entrypoint->extended_mv = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+ entrypoint->dquant = gst_bit_reader_get_bits_uint8_unchecked (&br, 2);
+ entrypoint->vstransform = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+ entrypoint->overlap = gst_bit_reader_get_bits_uint8_unchecked (&br, 1);
+ entrypoint->quantizer = gst_bit_reader_get_bits_uint8_unchecked (&br, 2);
+
+ if (advanced->hrd_param_flag) {
+ for (i = 0; i < seqhdr->profile.advanced.hrd_param.hrd_num_leaky_buckets;
+ i++)
+ READ_UINT8 (&br, entrypoint->hrd_full[MAX_HRD_NUM_LEAKY_BUCKETS], 8);
+ }
+
+ READ_UINT8 (&br, entrypoint->coded_size_flag, 1);
+ if (entrypoint->coded_size_flag) {
+ READ_UINT16 (&br, entrypoint->coded_width, 12);
+ READ_UINT16 (&br, entrypoint->coded_height, 12);
+ entrypoint->coded_height = (entrypoint->coded_height + 1) << 1;
+ entrypoint->coded_width = (entrypoint->coded_width + 1) << 1;
+ }
+
+ if (entrypoint->extended_mv)
+ READ_UINT8 (&br, entrypoint->extended_dmv, 1);
+
+ READ_UINT8 (&br, entrypoint->range_mapy_flag, 1);
+ if (entrypoint->range_mapy_flag)
+ READ_UINT8 (&br, entrypoint->range_mapy, 3);
+
+ READ_UINT8 (&br, entrypoint->range_mapuv_flag, 1);
+ if (entrypoint->range_mapy_flag)
+ READ_UINT8 (&br, entrypoint->range_mapuv, 3);
+
+ advanced->entrypoint = *entrypoint;
+
+ return GST_VC1_PARSER_OK;
+
+failed:
+ GST_WARNING ("Failed to parse entry point header");
+
+ return GST_VC1_PARSER_ERROR;
+}
+
+/**
+ * gst_vc1_parse_frame_header:
+ * @data: The data to parse
+ * @size: the size of @data
+ * @entrypoint: The #GstVC1EntryPointHdr to set.
+ * @seqhdr: The #GstVC1SeqHdr currently being parsed
+ *
+ * Parses @data, and fills @entrypoint fields.
+ *
+ * Returns: a #GstVC1EntryPointHdr
+ */
+GstVC1ParseResult
+gst_vc1_parse_frame_header (const guint8 * data, gsize size,
+ GstVC1FrameHdr * framehdr, GstVC1SeqHdr * seqhdr)
+{
+ GstBitReader br;
+
+ ensure_debug_category ();
+
+ gst_bit_reader_init (&br, data, size);
+
+ if (seqhdr->profiletype == GST_VC1_PROFILE_ADVANCED)
+ return parse_frame_header_advanced (&br, framehdr, seqhdr);
+ else
+ return parse_frame_header (&br, framehdr, seqhdr);
+
+}
diff --git a/gst-libs/gst/codecparsers/gstvc1parser.h b/gst-libs/gst/codecparsers/gstvc1parser.h
new file mode 100644
index 000000000..511df6417
--- /dev/null
+++ b/gst-libs/gst/codecparsers/gstvc1parser.h
@@ -0,0 +1,468 @@
+/* Gstreamer
+ * Copyright (C) <2011> Intel
+ * Copyright (C) <2011> Collabora Ltd.
+ * Copyright (C) <2011> Thibault Saunier <thibault.saunier@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_VC1_PARSER_H__
+#define __GST_VC1_PARSER_H__
+
+#ifndef GST_USE_UNSTABLE_API
+#warning "The VC1 parsing library is unstable API and may change in future."
+#warning "You can define GST_USE_UNSTABLE_API to avoid this warning."
+#endif
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define MAX_HRD_NUM_LEAKY_BUCKETS 31
+
+/**
+ * @GST_VC1_BFRACTION_BASIS: The @bfraction variable should be divided
+ * by this constant to have the actual value.
+ */
+#define GST_VC1_BFRACTION_BASIS 256
+
+typedef enum {
+ GST_VC1_END_OF_SEQ = 0x0A,
+ GST_VC1_SLICE = 0x0B,
+ GST_VC1_FIELD = 0x0C,
+ GST_VC1_FRAME = 0x0D,
+ GST_VC1_ENTRYPOINT = 0x0E,
+ GST_VC1_SEQUENCE = 0x0F,
+ GST_VC1_SLICE_USER = 0x1B,
+ GST_VC1_FIELD_USER = 0x1C,
+ GST_VC1_FRAME_USER = 0x1D,
+ GST_VC1_ENTRY_POINT_USER = 0x1E,
+ GST_VC1_SEQUENCE_USER = 0x1F
+} GstVC1StartCode;
+
+typedef enum {
+ GST_VC1_PROFILE_SIMPLE,
+ GST_VC1_PROFILE_MAIN,
+ GST_VC1_PROFILE_RESERVED,
+ GST_VC1_PROFILE_ADVANCED
+} GstVC1Profile;
+
+typedef enum {
+ GST_VC1_PARSER_OK,
+ GST_VC1_PARSER_BROKEN_DATA,
+ GST_VC1_PARSER_NO_BDU,
+ GST_VC1_PARSER_NO_BDU_END,
+ GST_VC1_PARSER_ERROR,
+} GstVC1ParseResult;
+
+typedef enum
+{
+ GST_VC1_PICTURE_TYPE_P,
+ GST_VC1_PICTURE_TYPE_B,
+ GST_VC1_PICTURE_TYPE_I,
+ GST_VC1_PICTURE_TYPE_BI,
+ GST_VC1_PICTURE_TYPE_SKIPPED
+} GstVC1PictureType;
+
+typedef enum
+{
+ GST_VC1_LEVEL_LOW = 0, /* Simple/Main profile low level */
+ GST_VC1_LEVELMEDIUM = 1, /* Simple/Main profile medium level */
+ GST_VC1_LEVELHIGH = 2, /* Main profile high level */
+
+ GST_VC1_LEVEL_L0 = 0, /* Advanced profile level 0 */
+ GST_VC1_LEVEL_L1 = 1, /* Advanced profile level 1 */
+ GST_VC1_LEVEL_L2 = 2, /* Advanced profile level 2 */
+ GST_VC1_LEVEL_L3 = 3, /* Advanced profile level 3 */
+ GST_VC1_LEVEL_L4 = 4, /* Advanced profile level 4 */
+
+ /* 5 to 7 reserved */
+ GST_VC1_LEVEL_UNKNOWN = 255 /* Unknown profile */
+} GstVC1Level;
+
+typedef enum
+{
+ GST_VC1_QUANTIZER_IMPLICITLY,
+ GST_VC1_QUANTIZER_EXPLICITLY,
+ GST_VC1_QUANTIZER_NON_UNIFORM,
+ GST_VC1_QUANTIZER_UNIFORM
+} GstVC1QuantizerSpec;
+
+typedef enum {
+ GST_VC1_DQPROFILE_FOUR_EDGES,
+ GST_VC1_DQPROFILE_DOUBLE_EDGES,
+ GST_VC1_DQPROFILE_SINGLE_EDGE,
+ GST_VC1_DQPROFILE_ALL_MBS
+} GstVC1DQProfile;
+
+typedef enum {
+ GST_VC1_CONDOVER_NONE,
+ GST_VC1_CONDOVER_ALL,
+ GST_VC1_CONDOVER_SELECT
+} GstVC1Condover;
+
+/**
+ * GstVC1MvMode:
+ *
+ */
+typedef enum
+{
+ GST_VC1_MVMODE_1MV_HPEL_BILINEAR,
+ GST_VC1_MVMODE_1MV,
+ GST_VC1_MVMODE_1MV_HPEL,
+ GST_VC1_MVMODE_MIXED_MV,
+ GST_VC1_MVMODE_INTENSITY_COMP
+} GstVC1MvMode;
+
+typedef struct _GstVC1SeqHdr GstVC1SeqHdr;
+typedef struct _GstVC1AdvancedSeqHdr GstVC1AdvancedSeqHdr;
+typedef struct _GstVC1SimpleMainSeqHdr GstVC1SimpleMainSeqHdr;
+typedef struct _GstVC1HrdParam GstVC1HrdParam;
+typedef struct _GstVC1EntryPointHdr GstVC1EntryPointHdr;
+
+/* Pictures Structures */
+typedef struct _GstVC1FrameHdr GstVC1FrameHdr;
+typedef struct _GstVC1PicAdvanced GstVC1PicAdvanced;
+typedef struct _GstVC1PicSimpleMain GstVC1PicSimpleMain;
+typedef struct _GstVC1Picture GstVC1Picture;
+
+typedef struct _GstVC1VopDquant GstVC1VopDquant;
+
+typedef struct _GstVC1BDU GstVC1BDU;
+
+struct _GstVC1HrdParam
+{
+ guint8 hrd_num_leaky_buckets;
+ guint8 bit_rate_exponent;
+ guint8 buffer_size_exponent;
+ guint16 hrd_rate[MAX_HRD_NUM_LEAKY_BUCKETS];
+ guint16 hrd_buffer[MAX_HRD_NUM_LEAKY_BUCKETS];
+};
+
+/**
+ * GstVC1SimpleMainSeqHdr:
+ *
+ * Structure for simple and main profile sequence headers specific parameters.
+ */
+struct _GstVC1SimpleMainSeqHdr
+{
+ guint8 res_sprite;
+ guint8 loop_filter;
+ guint8 multires;
+ guint8 fastuvmc;
+ guint8 extended_mv;
+ guint8 dquant;
+ guint8 vstransform;
+ guint8 overlap;
+ guint8 syncmarker;
+ guint8 rangered;
+ guint8 maxbframes;
+ guint8 quantizer;
+
+ /* This should be filled by user if previously known */
+ guint16 coded_width;
+ /* This should be filled by user if previously known */
+ guint16 coded_height;
+
+ /* Wmvp specific */
+ guint8 wmvp; /* Specify if the stream is wmp or not */
+ guint8 framerate;
+ guint8 slice_code;
+};
+
+/**
+ * GstVC1EntryPointHdr:
+ *
+ * Structure for entrypoint header, this will be used only in advanced profiles
+ */
+struct _GstVC1EntryPointHdr
+{
+ guint8 broken_link;
+ guint8 closed_entry;
+ guint8 panscan_flag;
+ guint8 refdist_flag;
+ guint8 loopfilter;
+ guint8 fastuvmc;
+ guint8 extended_mv;
+ guint8 dquant;
+ guint8 vstransform;
+ guint8 overlap;
+ guint8 quantizer;
+ guint8 coded_size_flag;
+ guint16 coded_width;
+ guint16 coded_height;
+ guint8 extended_dmv;
+ guint8 range_mapy_flag;
+ guint8 range_mapy;
+ guint8 range_mapuv_flag;
+ guint8 range_mapuv;
+
+ guint8 hrd_full[MAX_HRD_NUM_LEAKY_BUCKETS];
+};
+
+/**
+ * GstVC1AdvancedSeqHdr:
+ *
+ * Structure for the advanced profile sequence headers specific parameters.
+ */
+struct _GstVC1AdvancedSeqHdr
+{
+ guint8 level;
+ guint8 postprocflag;
+ guint16 max_coded_width;
+ guint16 max_coded_height;
+ guint8 pulldown;
+ guint8 interlace;
+ guint8 tfcntrflag;
+ guint8 psf;
+ guint8 display_ext;
+ guint16 disp_horiz_size;
+ guint16 disp_vert_size;
+ guint8 aspect_ratio_flag;
+ guint8 aspect_ratio;
+ guint8 aspect_horiz_size;
+ guint8 aspect_vert_size;
+ guint8 framerate_flag;
+ guint8 framerateind;
+ guint8 frameratenr;
+ guint8 frameratedr;
+ guint16 framerateexp;
+ guint8 color_format_flag;
+ guint8 color_prim;
+ guint8 transfer_char;
+ guint8 matrix_coef;
+ guint8 hrd_param_flag;
+
+ GstVC1HrdParam hrd_param;
+
+ /* The last parsed entry point */
+ GstVC1EntryPointHdr entrypoint;
+};
+
+/**
+ * GstVC1SeqHdr:
+ *
+ * Structure for sequence headers in any profile.
+ */
+struct _GstVC1SeqHdr
+{
+ guint8 profiletype;
+ guint8 colordiff_format;
+ guint8 frmrtq_postproc;
+ guint8 bitrtq_postproc;
+ guint8 finterpflag;
+
+ /* calculated */
+ guint framerate; /* Around in fps, 0 if unknown*/
+ guint bitrate; /* Around in kpbs, 0 if unknown*/
+
+ union {
+ GstVC1AdvancedSeqHdr advanced;
+ GstVC1SimpleMainSeqHdr simplemain;
+ } profile;
+
+};
+
+/**
+ * GstVC1PicSimpleMain:
+ * @bfaction: Should be divided by #GST_VC1_BFRACTION_BASIS
+ * to get the real value.
+ */
+struct _GstVC1PicSimpleMain
+{
+ guint8 frmcnt;
+ guint8 mvrange;
+ guint8 rangeredfrm;
+
+ /* I and P pic simple and main profiles only */
+ guint8 respic;
+
+ /* I and BI pic simple and main profiles only */
+ guint8 transacfrm2;
+ guint8 bf;
+
+ /* B and P pic simple and main profiles only */
+ guint8 mvmode;
+ guint8 mvtab;
+ guint8 ttmbf;
+
+ /* P pic simple and main profiles only */
+ guint8 mvmode2;
+ guint8 lumscale;
+ guint8 lumshift;
+
+ guint8 cbptab;
+ guint8 ttfrm;
+
+ /* B and BI picture only
+ * Should be divided by #GST_VC1_BFRACTION_BASIS
+ * to get the real value. */
+ guint8 bfraction;
+
+ /* Biplane value, those fields only mention the fact
+ * that the bitplane is in raw mode or not */
+ guint8 mvtypemb;
+ guint8 skipmb;
+ guint8 directmb; /* B pic main profile only */
+};
+
+/**
+ * GstVC1PicAdvanced:
+ * @bfaction: Should be divided by #GST_VC1_BFRACTION_BASIS
+ * to get the real value.
+ */
+struct _GstVC1PicAdvanced
+{
+ guint8 fcm;
+ guint8 tfcntr;
+
+ guint8 rptfrm;
+ guint8 tff;
+ guint8 rff;
+ guint8 ps_present;
+ guint32 ps_hoffset;
+ guint32 ps_voffset;
+ guint16 ps_width;
+ guint16 ps_height;
+ guint8 rndctrl;
+ guint8 uvsamp;
+ guint8 postproc;
+
+ /* B and P picture specific */
+ guint8 mvrange;
+ guint8 mvmode;
+ guint8 mvtab;
+ guint8 cbptab;
+ guint8 ttmbf;
+ guint8 ttfrm;
+
+ /* B and BI picture only
+ * Should be divided by #GST_VC1_BFRACTION_BASIS
+ * to get the real value. */
+ guint8 bfraction;
+
+ /* ppic */
+ guint8 mvmode2;
+ guint8 lumscale;
+ guint8 lumshift;
+
+ /* bipic */
+ guint8 bf;
+ guint8 condover;
+ guint8 transacfrm2;
+
+ /* Biplane value, those fields only mention the fact
+ * that the bitplane is in raw mode or not */
+ guint8 acpred;
+ guint8 overflags;
+ guint8 mvtypemb;
+ guint8 skipmb;
+ guint8 directmb;
+};
+
+
+struct _GstVC1VopDquant
+{
+ guint8 pqdiff;
+ guint8 abspq;
+
+
+ /* if dqant != 2*/
+ guint8 dquantfrm;
+ guint8 dqprofile;
+
+ /* if dqprofile == GST_VC1_DQPROFILE_SINGLE_EDGE
+ * or GST_VC1_DQPROFILE_DOUBLE_EDGE:*/
+ guint8 dqsbedge;
+
+ /* if dqprofile == GST_VC1_DQPROFILE_SINGLE_EDGE
+ * or GST_VC1_DQPROFILE_DOUBLE_EDGE:*/
+ guint8 dqbedge;
+
+ /* if dqprofile == GST_VC1_DQPROFILE_ALL_MBS */
+ guint8 dqbilevel;
+
+};
+
+/**
+ * GstVC1FrameHdr:
+ *
+ * Structure that represent picture in any profile or mode.
+ * You should look at @ptype and @profile to know what is currently
+ * in use.
+ */
+struct _GstVC1FrameHdr
+{
+ /* common fields */
+ guint8 ptype;
+ guint8 interpfrm;
+ guint8 halfqp;
+ guint8 transacfrm;
+ guint8 transdctab;
+ guint8 pqindex;
+ guint8 pquantizer;
+
+ /* Computed */
+ guint8 pquant;
+
+ /* Convenience fields */
+ guint8 profile;
+ guint8 dquant;
+
+ /* If dquant */
+ GstVC1VopDquant vopdquant;
+
+ union {
+ GstVC1PicSimpleMain simple;
+ GstVC1PicAdvanced advanced;
+ } pic;
+};
+
+/**
+ * GstVC1BDU:
+ *
+ * Structure that represents a Bitstream Data Unit.
+ */
+struct _GstVC1BDU
+{
+ GstVC1StartCode type;
+ guint size;
+ guint sc_offset;
+ guint offset;
+ guint8 * data;
+};
+
+GstVC1ParseResult gst_vc1_identify_next_bdu (const guint8 *data,
+ gsize size,
+ GstVC1BDU *bdu);
+
+
+GstVC1ParseResult gst_vc1_parse_sequence_header (const guint8 *data,
+ gsize size,
+ GstVC1SeqHdr * seqhdr);
+
+GstVC1ParseResult gst_vc1_parse_entry_point_header (const guint8 *data,
+ gsize size,
+ GstVC1EntryPointHdr * entrypoint,
+ GstVC1SeqHdr *seqhdr);
+
+GstVC1ParseResult gst_vc1_parse_frame_header (const guint8 *data,
+ gsize size,
+ GstVC1FrameHdr * framehdr,
+ GstVC1SeqHdr *seqhdr);
+
+G_END_DECLS
+#endif
diff --git a/gst-plugins-bad.spec.in b/gst-plugins-bad.spec.in
index adbd33df6..eac41e081 100644
--- a/gst-plugins-bad.spec.in
+++ b/gst-plugins-bad.spec.in
@@ -227,7 +227,6 @@ make ERROR_CFLAGS='' ERROR_CXXFLAGS=''
%{_libdir}/gstreamer-%{majorminor}/libgsth264parse.so
%{_libdir}/gstreamer-%{majorminor}/libgsthdvparse.so
%{_libdir}/gstreamer-%{majorminor}/libgstid3tag.so
-%{_libdir}/gstreamer-%{majorminor}/libgstinvtelecine.so
%{_libdir}/gstreamer-%{majorminor}/libgstivfparse.so
%{_libdir}/gstreamer-%{majorminor}/libgstjpegformat.so
%{_libdir}/gstreamer-%{majorminor}/libgstlegacyresample.so
@@ -274,9 +273,13 @@ make ERROR_CFLAGS='' ERROR_CXXFLAGS=''
%{_libdir}/gstreamer-%{majorminor}/libgstvideofiltersbad.so
%{_libdir}/gstreamer-%{majorminor}/libgstvideoparsersbad.so
%{_libdir}/gstreamer-%{majorminor}/libgsty4mdec.so
-%{_libdir}/gstreamer-%{majorminor}//libgstopenal.so
+%{_libdir}/gstreamer-%{majorminor}/libgstopenal.so
%{_libdir}/libgstbasecamerabinsrc-%{majorminor}.so.0
%{_libdir}/libgstbasecamerabinsrc-%{majorminor}.so.0.0.0
+%{_libdir}/gstreamer-%{majorminor}/libgstaudiovisualizers.so
+%{_libdir}/gstreamer-%{majorminor}/libgstfaceoverlay.so
+%{_libdir}/gstreamer-%{majorminor}/libgstinter.so
+%{_libdir}/gstreamer-%{majorminor}/libgstremovesilence.so
# System (Linux) specific plugins
%{_libdir}/gstreamer-%{majorminor}/libgstdvb.so
@@ -343,10 +346,12 @@ make ERROR_CFLAGS='' ERROR_CXXFLAGS=''
# pkg-config files
%{_libdir}/pkgconfig/gstreamer-plugins-bad-%{majorminor}.pc
+%{_libdir}/pkgconfig/gstreamer-codecparsers-0.10.pc
%files devel-docs
%defattr(-,root,root,-)
%doc %{_datadir}/gtk-doc/html/gst-plugins-bad-plugins-%{majorminor}
+%doc %{_datadir}/gtk-doc/html/gst-plugins-bad-libs-%{majorminor}
%changelog
* Thu May 19 2011 Christian Schaller <christian.schaller@collabora.co.uk>
diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c
index 1caa16404..5a227138e 100644
--- a/gst/camerabin2/gstcamerabin2.c
+++ b/gst/camerabin2/gstcamerabin2.c
@@ -166,9 +166,15 @@
#include <gst/gst-i18n-plugin.h>
#include <gst/pbutils/pbutils.h>
+#if GLIB_CHECK_VERSION(2,29,6)
+#define gst_camerabin2_atomic_int_add g_atomic_int_add
+#else
+#define gst_camerabin2_atomic_int_add g_atomic_int_exchange_and_add
+#endif
+
#define GST_CAMERA_BIN2_PROCESSING_INC(c) \
{ \
- gint bef = g_atomic_int_exchange_and_add (&c->processing_counter, 1); \
+ gint bef = gst_camerabin2_atomic_int_add (&c->processing_counter, 1); \
if (bef == 0) \
g_object_notify (G_OBJECT (c), "idle"); \
GST_DEBUG_OBJECT ((c), "Processing counter incremented to: %d", \
@@ -374,11 +380,6 @@ gst_camera_bin_start_capture (GstCameraBin2 * camerabin)
if (camerabin->audio_src) {
GstClock *clock = gst_pipeline_get_clock (GST_PIPELINE_CAST (camerabin));
- /* FIXME We need to set audiosrc to null to make it resync the ringbuffer
- * while bug https://bugzilla.gnome.org/show_bug.cgi?id=648359 isn't
- * fixed */
- gst_element_set_state (camerabin->audio_src, GST_STATE_NULL);
-
/* need to reset eos status (pads could be flushing) */
gst_element_set_state (camerabin->audio_capsfilter, GST_STATE_READY);
gst_element_set_state (camerabin->audio_volume, GST_STATE_READY);
@@ -446,6 +447,14 @@ gst_camera_bin_stop_capture (GstCameraBin2 * camerabin)
if (camerabin->mode == MODE_VIDEO && camerabin->audio_src) {
camerabin->audio_drop_eos = FALSE;
gst_element_send_event (camerabin->audio_src, gst_event_new_eos ());
+
+ /* FIXME We need to set audiosrc to null to make it resync the ringbuffer
+ * while bug https://bugzilla.gnome.org/show_bug.cgi?id=648359 isn't
+ * fixed.
+ *
+ * Also, we set to NULL here to stop capturing audio through to the next
+ * video mode start capture. */
+ gst_element_set_state (camerabin->audio_src, GST_STATE_NULL);
}
}
@@ -485,7 +494,12 @@ gst_camera_bin_src_notify_readyforcapture (GObject * obj, GParamSpec * pspec,
GST_DEBUG_OBJECT (camera, "Switching videobin location to %s", location);
g_object_set (camera->videosink, "location", location, NULL);
g_free (location);
- gst_element_set_state (camera->videosink, GST_STATE_PLAYING);
+ if (gst_element_set_state (camera->videosink, GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE) {
+ /* Resets the latest state change return, that would be a failure
+ * and could cause problems in a camerabin2 state change */
+ gst_element_set_state (camera->videosink, GST_STATE_NULL);
+ }
gst_element_set_state (camera->video_encodebin, GST_STATE_PLAYING);
gst_element_set_state (camera->videobin_capsfilter, GST_STATE_PLAYING);
}
@@ -916,6 +930,8 @@ gst_camera_bin_handle_message (GstBin * bin, GstMessage * message)
if (gst_structure_has_name (structure, "GstMultiFileSink")) {
GST_CAMERA_BIN2_PROCESSING_DEC (GST_CAMERA_BIN2_CAST (bin));
filename = gst_structure_get_string (structure, "filename");
+ GST_DEBUG_OBJECT (bin, "Got file save message from multifilesink, "
+ "image %s has been saved", filename);
if (filename) {
gst_image_capture_bin_post_image_done (GST_CAMERA_BIN2_CAST (bin),
filename);
@@ -930,6 +946,8 @@ gst_camera_bin_handle_message (GstBin * bin, GstMessage * message)
gst_message_parse_warning (message, &err, &debug);
if (err->domain == GST_RESOURCE_ERROR) {
/* some capturing failed */
+ GST_WARNING_OBJECT (bin, "Capture failed, reason: %s - %s",
+ err->message, debug);
GST_CAMERA_BIN2_PROCESSING_DEC (GST_CAMERA_BIN2_CAST (bin));
}
}
@@ -1152,6 +1170,17 @@ gst_camera_bin_src_notify_max_zoom_cb (GObject * self, GParamSpec * pspec,
g_object_notify (G_OBJECT (camera), "max-zoom");
}
+static void
+gst_camera_bin_src_notify_zoom_cb (GObject * self, GParamSpec * pspec,
+ gpointer user_data)
+{
+ GstCameraBin2 *camera = (GstCameraBin2 *) user_data;
+
+ g_object_get (self, "zoom", &camera->zoom, NULL);
+ GST_DEBUG_OBJECT (camera, "Zoom updated to %f", camera->zoom);
+ g_object_notify (G_OBJECT (camera), "zoom");
+}
+
static gboolean
gst_camera_bin_image_src_buffer_probe (GstPad * pad, GstBuffer * buf,
gpointer data)
@@ -1208,7 +1237,12 @@ gst_camera_bin_image_sink_event_probe (GstPad * pad, GstEvent * event,
GST_DEBUG_OBJECT (camerabin, "Setting filename to imagesink: %s",
filename);
g_object_set (camerabin->imagesink, "location", filename, NULL);
- gst_element_set_state (camerabin->imagesink, GST_STATE_PLAYING);
+ if (gst_element_set_state (camerabin->imagesink, GST_STATE_PLAYING) ==
+ GST_STATE_CHANGE_FAILURE) {
+ /* Resets the latest state change return, that would be a failure
+ * and could cause problems in a camerabin2 state change */
+ gst_element_set_state (camerabin->imagesink, GST_STATE_NULL);
+ }
}
}
break;
@@ -1495,6 +1529,8 @@ gst_camera_bin_create_elements (GstCameraBin2 * camera)
"preview-caps", camera->preview_caps, "preview-filter",
camera->preview_filter, NULL);
}
+ g_signal_connect (G_OBJECT (camera->src), "notify::zoom",
+ (GCallback) gst_camera_bin_src_notify_zoom_cb, camera);
g_object_set (camera->src, "zoom", camera->zoom, NULL);
g_signal_connect (G_OBJECT (camera->src), "notify::max-zoom",
(GCallback) gst_camera_bin_src_notify_max_zoom_cb, camera);
diff --git a/gst/hls/gsthlsdemux.c b/gst/hls/gsthlsdemux.c
index 143f36387..ad29f7837 100644
--- a/gst/hls/gsthlsdemux.c
+++ b/gst/hls/gsthlsdemux.c
@@ -1,6 +1,9 @@
/* GStreamer
* Copyright (C) 2010 Marc-Andre Lureau <marcandre.lureau@gmail.com>
* Copyright (C) 2010 Andoni Morales Alastruey <ylatuya@gmail.com>
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Youness Alaoui <youness.alaoui@collabora.co.uk>, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
*
* Gsthlsdemux.c:
*
@@ -310,6 +313,7 @@ gst_hls_demux_change_state (GstElement * element, GstStateChange transition)
case GST_STATE_CHANGE_PAUSED_TO_READY:
demux->cancelled = TRUE;
gst_hls_demux_stop (demux);
+ gst_task_join (demux->task);
gst_hls_demux_reset (demux, FALSE);
break;
default:
@@ -406,7 +410,8 @@ gst_hls_demux_src_event (GstPad * pad, GstEvent * event)
GST_M3U8_CLIENT_LOCK (demux->client);
GST_DEBUG_OBJECT (demux, "seeking to sequence %d", current_sequence);
demux->client->sequence = current_sequence;
- demux->position = start;
+ gst_m3u8_client_get_current_position (demux->client, &demux->position);
+ demux->position_shift = start - demux->position;
demux->need_segment = TRUE;
GST_M3U8_CLIENT_UNLOCK (demux->client);
@@ -462,6 +467,7 @@ gst_hls_demux_sink_event (GstPad * pad, GstEvent * event)
playlist = gst_hls_src_buf_to_utf8_playlist ((gchar *)
GST_BUFFER_DATA (demux->playlist), GST_BUFFER_SIZE (demux->playlist));
gst_buffer_unref (demux->playlist);
+ demux->playlist = NULL;
if (playlist == NULL) {
GST_WARNING_OBJECT (demux, "Error validating first playlist.");
} else if (!gst_m3u8_client_update (demux->client, playlist)) {
@@ -573,9 +579,7 @@ gst_hls_demux_fetcher_sink_event (GstPad * pad, GstEvent * event)
GST_DEBUG_OBJECT (demux, "Got EOS on the fetcher pad");
/* signal we have fetched the URI */
if (!demux->cancelled) {
- g_mutex_lock (demux->fetcher_lock);
g_cond_broadcast (demux->fetcher_cond);
- g_mutex_unlock (demux->fetcher_lock);
}
}
default:
@@ -665,7 +669,7 @@ gst_hls_demux_stop (GstHLSDemux * demux)
g_mutex_lock (demux->fetcher_lock);
gst_hls_demux_stop_fetcher_locked (demux, TRUE);
g_mutex_unlock (demux->fetcher_lock);
- gst_task_join (demux->task);
+ gst_task_stop (demux->task);
gst_hls_demux_stop_update (demux);
}
@@ -748,13 +752,15 @@ gst_hls_demux_loop (GstHLSDemux * demux)
demux->need_segment = TRUE;
}
if (demux->need_segment) {
+ GstClockTime start = demux->position + demux->position_shift;
/* And send a newsegment */
- GST_DEBUG_OBJECT (demux, "Sending new-segment. Segment start:%"
- GST_TIME_FORMAT, GST_TIME_ARGS (demux->position));
+ GST_DEBUG_OBJECT (demux, "Sending new-segment. segment start:%"
+ GST_TIME_FORMAT, GST_TIME_ARGS (start));
gst_pad_push_event (demux->srcpad,
- gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME, demux->position,
- GST_CLOCK_TIME_NONE, demux->position));
+ gst_event_new_new_segment (FALSE, 1.0, GST_FORMAT_TIME,
+ start, GST_CLOCK_TIME_NONE, start));
demux->need_segment = FALSE;
+ demux->position_shift = 0;
}
if (GST_CLOCK_TIME_IS_VALID (GST_BUFFER_DURATION (buf)))
@@ -883,6 +889,7 @@ gst_hls_demux_reset (GstHLSDemux * demux, gboolean dispose)
g_queue_clear (demux->queue);
demux->position = 0;
+ demux->position_shift = 0;
demux->need_segment = TRUE;
}
@@ -1034,6 +1041,7 @@ gst_hls_demux_cache_fragments (GstHLSDemux * demux)
demux->client->sequence -= demux->fragments_cache;
else
demux->client->sequence = 0;
+ gst_m3u8_client_get_current_position (demux->client, &demux->position);
GST_M3U8_CLIENT_UNLOCK (demux->client);
} else {
GstClockTime duration = gst_m3u8_client_get_duration (demux->client);
diff --git a/gst/hls/gsthlsdemux.h b/gst/hls/gsthlsdemux.h
index bac8ef317..a09a88b76 100644
--- a/gst/hls/gsthlsdemux.h
+++ b/gst/hls/gsthlsdemux.h
@@ -89,6 +89,7 @@ struct _GstHLSDemux
/* Position in the stream */
GstClockTime position;
+ GstClockTime position_shift;
gboolean need_segment;
};
diff --git a/gst/hls/m3u8.c b/gst/hls/m3u8.c
index c407d72d8..449b63ee9 100644
--- a/gst/hls/m3u8.c
+++ b/gst/hls/m3u8.c
@@ -468,13 +468,31 @@ _find_next (GstM3U8MediaFile * file, GstM3U8Client * client)
return TRUE;
}
+void
+gst_m3u8_client_get_current_position (GstM3U8Client * client,
+ GstClockTime * timestamp)
+{
+ GList *l;
+ GList *walk;
+
+ l = g_list_find_custom (client->current->files, client,
+ (GCompareFunc) _find_next);
+
+ *timestamp = 0;
+ for (walk = client->current->files; walk; walk = walk->next) {
+ if (walk == l)
+ break;
+ *timestamp += GST_M3U8_MEDIA_FILE (walk->data)->duration;
+ }
+ *timestamp *= GST_SECOND;
+}
+
gboolean
gst_m3u8_client_get_next_fragment (GstM3U8Client * client,
gboolean * discontinuity, const gchar ** uri, GstClockTime * duration,
GstClockTime * timestamp)
{
GList *l;
- GList *walk;
GstM3U8MediaFile *file;
g_return_val_if_fail (client != NULL, FALSE);
@@ -490,6 +508,8 @@ gst_m3u8_client_get_next_fragment (GstM3U8Client * client,
return FALSE;
}
+ gst_m3u8_client_get_current_position (client, timestamp);
+
file = GST_M3U8_MEDIA_FILE (l->data);
*discontinuity = client->sequence != file->sequence;
@@ -498,14 +518,6 @@ gst_m3u8_client_get_next_fragment (GstM3U8Client * client,
*uri = file->uri;
*duration = file->duration * GST_SECOND;
- *timestamp = 0;
- for (walk = client->current->files; walk; walk = walk->next) {
- if (walk == l)
- break;
- *timestamp += GST_M3U8_MEDIA_FILE (walk->data)->duration;
- }
- *timestamp *= GST_SECOND;
-
GST_M3U8_CLIENT_UNLOCK (client);
return TRUE;
}
diff --git a/gst/hls/m3u8.h b/gst/hls/m3u8.h
index 8c83990f8..a428a67a4 100644
--- a/gst/hls/m3u8.h
+++ b/gst/hls/m3u8.h
@@ -84,6 +84,8 @@ void gst_m3u8_client_set_current (GstM3U8Client * client, GstM3U8 * m3u8);
gboolean gst_m3u8_client_get_next_fragment (GstM3U8Client * client,
gboolean * discontinuity, const gchar ** uri, GstClockTime * duration,
GstClockTime * timestamp);
+void gst_m3u8_client_get_current_position (GstM3U8Client * client,
+ GstClockTime * timestamp);
GstClockTime gst_m3u8_client_get_duration (GstM3U8Client * client);
GstClockTime gst_m3u8_client_get_target_duration (GstM3U8Client * client);
const gchar *gst_m3u8_client_get_uri(GstM3U8Client * client);
diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c
index 986914d0c..849cda0aa 100644
--- a/gst/mpegdemux/gstmpegtsdemux.c
+++ b/gst/mpegdemux/gstmpegtsdemux.c
@@ -417,7 +417,7 @@ gst_mpegts_demux_remove_pads (GstMpegTSDemux * demux)
#endif
-static guint32 crc_tab[256] = {
+static const guint32 crc_tab[256] = {
0x00000000, 0x04c11db7, 0x09823b6e, 0x0d4326d9, 0x130476dc, 0x17c56b6b,
0x1a864db2, 0x1e475005, 0x2608edb8, 0x22c9f00f, 0x2f8ad6d6, 0x2b4bcb61,
0x350c9b64, 0x31cd86d3, 0x3c8ea00a, 0x384fbdbd, 0x4c11db70, 0x48d0c6c7,
diff --git a/gst/mpegpsmux/psmux.c b/gst/mpegpsmux/psmux.c
index 9d0493c1d..0a714d038 100644
--- a/gst/mpegpsmux/psmux.c
+++ b/gst/mpegpsmux/psmux.c
@@ -348,7 +348,7 @@ psmux_write_system_header (PsMux * mux)
bits_write (&bw, 24, PSMUX_START_CODE_PREFIX);
bits_write (&bw, 8, PSMUX_SYSTEM_HEADER);
- bits_write (&bw, 16, len); /* header_length */
+ bits_write (&bw, 16, len - 6); /* header_length (bytes after this field) */
bits_write (&bw, 1, 1); /* marker */
bits_write (&bw, 22, mux->rate_bound); /* rate_bound */
bits_write (&bw, 1, 1); /* marker */
diff --git a/gst/mpegtsdemux/mpegtsbase.c b/gst/mpegtsdemux/mpegtsbase.c
index 5542abf02..437af9d78 100644
--- a/gst/mpegtsdemux/mpegtsbase.c
+++ b/gst/mpegtsdemux/mpegtsbase.c
@@ -1,7 +1,11 @@
/*
- * mpegtsbase.c -
+ * mpegtsbase.c -
* Copyright (C) 2007 Alessandro Decina
* 2010 Edward Hervey
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Youness Alaoui <youness.alaoui@collabora.co.uk>, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ * Author: Edward Hervey <bilboed@bilboed.com>, Collabora Ltd.
*
* Authors:
* Alessandro Decina <alessandro@nnva.org>
diff --git a/gst/mpegtsdemux/mpegtsbase.h b/gst/mpegtsdemux/mpegtsbase.h
index cce4e0fd7..872e77ee8 100644
--- a/gst/mpegtsdemux/mpegtsbase.h
+++ b/gst/mpegtsdemux/mpegtsbase.h
@@ -2,6 +2,9 @@
* mpegtsbase.h - GStreamer MPEG transport stream base class
* Copyright (C) 2009 Edward Hervey <edward.hervey@collabora.co.uk>
* 2007 Alessandro Decina
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Youness Alaoui <youness.alaoui@collabora.co.uk>, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
*
* Authors:
* Alessandro Decina <alessandro@nnva.org>
diff --git a/gst/mpegtsdemux/tsdemux.c b/gst/mpegtsdemux/tsdemux.c
index 3a327a5cd..3facd6407 100644
--- a/gst/mpegtsdemux/tsdemux.c
+++ b/gst/mpegtsdemux/tsdemux.c
@@ -2,6 +2,10 @@
* tsdemux.c
* Copyright (C) 2009 Zaheer Abbas Merali
* 2010 Edward Hervey
+ * Copyright (C) 2011, Hewlett-Packard Development Company, L.P.
+ * Author: Youness Alaoui <youness.alaoui@collabora.co.uk>, Collabora Ltd.
+ * Author: Sebastian Dröge <sebastian.droege@collabora.co.uk>, Collabora Ltd.
+ * Author: Edward Hervey <bilboed@bilboed.com>, Collabora Ltd.
*
* Authors:
* Zaheer Abbas Merali <zaheerabbas at merali dot org>
diff --git a/gst/mpegvideoparse/mpegvideoparse.c b/gst/mpegvideoparse/mpegvideoparse.c
index 2f4e96cec..52a34c10f 100644
--- a/gst/mpegvideoparse/mpegvideoparse.c
+++ b/gst/mpegvideoparse/mpegvideoparse.c
@@ -1027,7 +1027,7 @@ plugin_init (GstPlugin * plugin)
"MPEG Video Parser");
return gst_element_register (plugin, "legacympegvideoparse",
- GST_RANK_PRIMARY, GST_TYPE_MPEGVIDEOPARSE);
+ GST_RANK_NONE, GST_TYPE_MPEGVIDEOPARSE);
}
GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
diff --git a/gst/pcapparse/Makefile.am b/gst/pcapparse/Makefile.am
index 08a9d25ad..6c357f209 100644
--- a/gst/pcapparse/Makefile.am
+++ b/gst/pcapparse/Makefile.am
@@ -8,10 +8,10 @@ else
endif
libgstpcapparse_la_SOURCES = \
- gstpcapparse.c
+ gstpcapparse.c gstirtspparse.c plugin.c
noinst_HEADERS = \
- gstpcapparse.h
+ gstpcapparse.h gstirtspparse.h
libgstpcapparse_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS)
libgstpcapparse_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) $(WINSOCK2_LIBS)
diff --git a/gst/pcapparse/gstirtspparse.c b/gst/pcapparse/gstirtspparse.c
new file mode 100644
index 000000000..26317e622
--- /dev/null
+++ b/gst/pcapparse/gstirtspparse.c
@@ -0,0 +1,255 @@
+/* GStreamer Interleaved RTSP parser
+ * Copyright (C) 2011 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+ * Copyright (C) 2011 Nokia Corporation. All rights reserved.
+ * Contact: Stefan Kost <stefan.kost@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+/**
+ * SECTION:element-irtspparse
+ * @short_description: Interleaved RTSP parser
+ * @see_also: #GstPcapParse
+ *
+ * This is an interleaved RTSP parser that allows extracting specific
+ * so-called "channels" from received interleaved (TCP) RTSP data
+ * (typically extracted from some network capture).
+ *
+ * <refsect2>
+ * <title>Example launch line</title>
+ * |[
+ * gst-launch-0.10 filesrc location=h264crasher.pcap ! pcapparse ! irtspparse
+ * ! rtph264depay ! ffdec_h264 ! fakesink
+ * ]| Read from a pcap dump file using filesrc, extract the raw TCP packets,
+ * depayload and decode them.
+ * </refsect2>
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <string.h>
+
+#include "gstirtspparse.h"
+#include <gst/base/gstbytereader.h>
+
+GST_DEBUG_CATEGORY_STATIC (irtsp_parse_debug);
+#define GST_CAT_DEFAULT irtsp_parse_debug
+
+enum
+{
+ PROP_0,
+ PROP_CHANNEL_ID
+};
+
+
+static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("application/x-rtp ; application/x-rtcp"));
+
+static GstStaticPadTemplate sink_template = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS_ANY);
+
+static void gst_irtsp_parse_finalize (GObject * object);
+
+static gboolean gst_irtsp_parse_start (GstBaseParse * parse);
+static gboolean gst_irtsp_parse_stop (GstBaseParse * parse);
+static gboolean gst_irtsp_parse_check_valid_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame, guint * size, gint * skipsize);
+static GstFlowReturn gst_irtsp_parse_parse_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame);
+
+static void gst_irtsp_parse_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec);
+static void gst_irtsp_parse_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec);
+
+GST_BOILERPLATE (GstIRTSPParse, gst_irtsp_parse, GstBaseParse,
+ GST_TYPE_BASE_PARSE);
+
+static void
+gst_irtsp_parse_base_init (gpointer klass)
+{
+ GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
+
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&sink_template));
+ gst_element_class_add_pad_template (element_class,
+ gst_static_pad_template_get (&src_template));
+
+ gst_element_class_set_details_simple (element_class, "IRTSPParse",
+ "Raw/Parser",
+ "Parses a raw interleaved RTSP stream",
+ "Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>");
+}
+
+static void
+gst_irtsp_parse_class_init (GstIRTSPParseClass * klass)
+{
+ GstBaseParseClass *parse_class = GST_BASE_PARSE_CLASS (klass);
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ GST_DEBUG_CATEGORY_INIT (irtsp_parse_debug, "irtspparse", 0,
+ "Interleaved RTSP stream parser");
+
+ object_class->finalize = gst_irtsp_parse_finalize;
+
+ object_class->set_property = gst_irtsp_parse_set_property;
+ object_class->get_property = gst_irtsp_parse_get_property;
+
+ g_object_class_install_property (object_class, PROP_CHANNEL_ID,
+ g_param_spec_int ("channel-id", "channel-id",
+ "Channel Identifier", 0, 255,
+ 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+ parse_class->start = GST_DEBUG_FUNCPTR (gst_irtsp_parse_start);
+ parse_class->stop = GST_DEBUG_FUNCPTR (gst_irtsp_parse_stop);
+ parse_class->check_valid_frame =
+ GST_DEBUG_FUNCPTR (gst_irtsp_parse_check_valid_frame);
+ parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_irtsp_parse_parse_frame);
+}
+
+static void
+gst_irtsp_parse_reset (GstIRTSPParse * IRTSPParse)
+{
+}
+
+static void
+gst_irtsp_parse_init (GstIRTSPParse * IRTSPParse, GstIRTSPParseClass * klass)
+{
+ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (IRTSPParse), 4);
+ gst_irtsp_parse_reset (IRTSPParse);
+}
+
+static void
+gst_irtsp_parse_finalize (GObject * object)
+{
+ G_OBJECT_CLASS (parent_class)->finalize (object);
+}
+
+static gboolean
+gst_irtsp_parse_start (GstBaseParse * parse)
+{
+ GstIRTSPParse *IRTSPParse = GST_IRTSP_PARSE (parse);
+
+ GST_DEBUG_OBJECT (parse, "starting");
+
+ gst_irtsp_parse_reset (IRTSPParse);
+
+ return TRUE;
+}
+
+static gboolean
+gst_irtsp_parse_stop (GstBaseParse * parse)
+{
+ GST_DEBUG_OBJECT (parse, "stopping");
+
+ return TRUE;
+}
+
+static gboolean
+gst_irtsp_parse_check_valid_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
+{
+ GstIRTSPParse *IRTSPParse = GST_IRTSP_PARSE (parse);
+ GstBuffer *buf = frame->buffer;
+ GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
+ gint off;
+
+ if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 4))
+ return FALSE;
+
+ off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffff0000,
+ 0x24000000 + (IRTSPParse->channel_id << 16), 0, GST_BUFFER_SIZE (buf));
+
+ GST_LOG_OBJECT (parse, "possible sync at buffer offset %d", off);
+
+ /* didn't find anything that looks like a sync word, skip */
+ if (off < 0) {
+ *skipsize = GST_BUFFER_SIZE (buf) - 3;
+ return FALSE;
+ }
+
+ /* possible frame header, but not at offset 0? skip bytes before sync */
+ if (off > 0) {
+ *skipsize = off;
+ return FALSE;
+ }
+
+ *framesize = GST_READ_UINT16_BE (GST_BUFFER_DATA (frame->buffer) + 2) + 4;
+ GST_LOG_OBJECT (parse, "got frame size %d", *framesize);
+
+ return TRUE;
+}
+
+static GstFlowReturn
+gst_irtsp_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
+{
+ /* HACK HACK skip header.
+ * could also ask baseparse to skip this,
+ * but that would give us a discontinuity for free
+ * which is a bit too much to have on all our packets */
+ GST_BUFFER_DATA (frame->buffer) += 4;
+ GST_BUFFER_SIZE (frame->buffer) -= 4;
+
+ if (!GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (parse))) {
+ GstCaps *caps;
+
+ caps = gst_caps_new_simple ("application/x-rtp", NULL);
+ gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
+ gst_caps_unref (caps);
+ }
+
+ GST_BUFFER_FLAG_UNSET (frame->buffer, GST_BUFFER_FLAG_DISCONT);
+
+ return GST_FLOW_OK;
+
+}
+
+static void
+gst_irtsp_parse_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ GstIRTSPParse *IRTSPParse = GST_IRTSP_PARSE (object);
+
+ switch (prop_id) {
+ case PROP_CHANNEL_ID:
+ IRTSPParse->channel_id = g_value_get_int (value);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+gst_irtsp_parse_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec)
+{
+ GstIRTSPParse *IRTSPParse = GST_IRTSP_PARSE (object);
+
+ switch (prop_id) {
+ case PROP_CHANNEL_ID:
+ g_value_set_int (value, IRTSPParse->channel_id);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
diff --git a/gst/pcapparse/gstirtspparse.h b/gst/pcapparse/gstirtspparse.h
new file mode 100644
index 000000000..a3d613f2a
--- /dev/null
+++ b/gst/pcapparse/gstirtspparse.h
@@ -0,0 +1,70 @@
+/* GStreamer Interleaved RTSP parser
+ * Copyright (C) 2011 Mark Nauwelaerts <mark.nauwelaerts@collabora.co.uk>
+ * Copyright (C) 2011 Nokia Corporation. All rights reserved.
+ * Contact: Stefan Kost <stefan.kost@nokia.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+
+#ifndef __GST_IRTSP_PARSE_H__
+#define __GST_IRTSP_PARSE_H__
+
+#include <gst/gst.h>
+#include <gst/base/gstbaseparse.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_IRTSP_PARSE \
+ (gst_irtsp_parse_get_type())
+#define GST_IRTSP_PARSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_CAST((obj), GST_TYPE_IRTSP_PARSE, GstIRTSPParse))
+#define GST_IRTSP_PARSE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_CAST((klass), GST_TYPE_IRTSP_PARSE, GstIRTSPParseClass))
+#define GST_IS_IRTSP_PARSE(obj) \
+ (G_TYPE_CHECK_INSTANCE_TYPE((obj), GST_TYPE_IRTSP_PARSE))
+#define GST_IS_IRTSP_PARSE_CLASS(klass) \
+ (G_TYPE_CHECK_CLASS_TYPE((klass), GST_TYPE_IRTSP_PARSE))
+
+typedef struct _GstIRTSPParse GstIRTSPParse;
+typedef struct _GstIRTSPParseClass GstIRTSPParseClass;
+
+/**
+ * GstIRTSPParse:
+ *
+ * The opaque GstIRTSPParse object
+ */
+struct _GstIRTSPParse {
+ GstBaseParse baseparse;
+
+ guint8 channel_id;
+ /*< private >*/
+};
+
+/**
+ * GstIRTSPParseClass:
+ * @parent_class: Element parent class.
+ *
+ * The opaque GstIRTSPParseClass data structure.
+ */
+struct _GstIRTSPParseClass {
+ GstBaseParseClass baseparse_class;
+};
+
+GType gst_irtsp_parse_get_type (void);
+
+G_END_DECLS
+
+#endif /* __GST_IRTSP_PARSE_H__ */
diff --git a/gst/pcapparse/gstpcapparse.c b/gst/pcapparse/gstpcapparse.c
index 596391667..16eb58c5a 100644
--- a/gst/pcapparse/gstpcapparse.c
+++ b/gst/pcapparse/gstpcapparse.c
@@ -607,17 +607,3 @@ gst_pcap_sink_event (GstPad * pad, GstEvent * event)
return ret;
}
-
-
-static gboolean
-plugin_init (GstPlugin * plugin)
-{
- return gst_element_register (plugin, "pcapparse",
- GST_RANK_NONE, GST_TYPE_PCAP_PARSE);
-}
-
-GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
- GST_VERSION_MINOR,
- "pcapparse",
- "Element parsing raw pcap streams",
- plugin_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/")
diff --git a/gst/pcapparse/plugin.c b/gst/pcapparse/plugin.c
new file mode 100644
index 000000000..d034e3d03
--- /dev/null
+++ b/gst/pcapparse/plugin.c
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2007 Ole André Vadla Ravnås <ole.andre.ravnas@tandberg.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.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include "gstpcapparse.h"
+#include "gstirtspparse.h"
+
+static gboolean
+plugin_init (GstPlugin * plugin)
+{
+ gboolean ret;
+
+ ret = gst_element_register (plugin, "pcapparse",
+ GST_RANK_NONE, GST_TYPE_PCAP_PARSE);
+ ret &= gst_element_register (plugin, "irtspparse",
+ GST_RANK_NONE, GST_TYPE_IRTSP_PARSE);
+
+ return ret;
+}
+
+GST_PLUGIN_DEFINE (GST_VERSION_MAJOR,
+ GST_VERSION_MINOR,
+ "pcapparse",
+ "Element parsing raw pcap streams",
+ plugin_init, VERSION, "LGPL", "GStreamer", "http://gstreamer.net/")
diff --git a/gst/rtpvp8/Makefile.am b/gst/rtpvp8/Makefile.am
index ef7425f1d..e1725bbb3 100644
--- a/gst/rtpvp8/Makefile.am
+++ b/gst/rtpvp8/Makefile.am
@@ -2,10 +2,12 @@ plugin_LTLIBRARIES = libgstrtpvp8.la
libgstrtpvp8_la_SOURCES = gstrtpvp8.c \
gstrtpvp8depay.c \
- gstrtpvp8pay.c
+ gstrtpvp8pay.c \
+ dboolhuff.c
noinst_HEADERS = gstrtpvp8depay.h \
- gstrtpvp8pay.h
+ gstrtpvp8pay.h \
+ dboolhuff.h
libgstrtpvp8_la_CFLAGS = $(GST_PLUGINS_BASE_CFLAGS) \
$(GST_BASE_CFLAGS) $(GST_CFLAGS)
diff --git a/gst/rtpvp8/dboolhuff.LICENSE b/gst/rtpvp8/dboolhuff.LICENSE
new file mode 100644
index 000000000..7a6f99547
--- /dev/null
+++ b/gst/rtpvp8/dboolhuff.LICENSE
@@ -0,0 +1,30 @@
+Copyright (c) 2010, Google Inc. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are
+met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+
+ * Neither the name of Google nor the names of its contributors may
+ be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
diff --git a/gst/rtpvp8/dboolhuff.c b/gst/rtpvp8/dboolhuff.c
new file mode 100644
index 000000000..0e1fd6e2f
--- /dev/null
+++ b/gst/rtpvp8/dboolhuff.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the dboolhuff.LICENSE file in this directory.
+ * See the libvpx original distribution for more information,
+ * including patent information, and author information.
+ */
+
+
+#include "dboolhuff.h"
+
+const unsigned char vp8_norm[256] __attribute__ ((aligned (16))) = {
+0, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
+ 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
+
+int
+vp8dx_start_decode (BOOL_DECODER * br,
+ const unsigned char *source, unsigned int source_sz)
+{
+ br->user_buffer_end = source + source_sz;
+ br->user_buffer = source;
+ br->value = 0;
+ br->count = -8;
+ br->range = 255;
+
+ if (source_sz && !source)
+ return 1;
+
+ /* Populate the buffer */
+ vp8dx_bool_decoder_fill (br);
+
+ return 0;
+}
+
+
+void
+vp8dx_bool_decoder_fill (BOOL_DECODER * br)
+{
+ const unsigned char *bufptr;
+ const unsigned char *bufend;
+ VP8_BD_VALUE value;
+ int count;
+ bufend = br->user_buffer_end;
+ bufptr = br->user_buffer;
+ value = br->value;
+ count = br->count;
+
+ VP8DX_BOOL_DECODER_FILL (count, value, bufptr, bufend);
+
+ br->user_buffer = bufptr;
+ br->value = value;
+ br->count = count;
+}
diff --git a/gst/rtpvp8/dboolhuff.h b/gst/rtpvp8/dboolhuff.h
new file mode 100644
index 000000000..41b0f5d9a
--- /dev/null
+++ b/gst/rtpvp8/dboolhuff.h
@@ -0,0 +1,151 @@
+/*
+ * Copyright (c) 2010 The WebM project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the dboolhuff.LICENSE file in this directory.
+ * See the libvpx original distribution for more information,
+ * including patent information, and author information.
+ */
+
+
+#ifndef DBOOLHUFF_H
+#define DBOOLHUFF_H
+#include <stddef.h>
+#include <limits.h>
+#include <glib.h>
+
+typedef size_t VP8_BD_VALUE;
+
+# define VP8_BD_VALUE_SIZE ((int)sizeof(VP8_BD_VALUE)*CHAR_BIT)
+/*This is meant to be a large, positive constant that can still be efficiently
+ loaded as an immediate (on platforms like ARM, for example).
+ Even relatively modest values like 100 would work fine.*/
+# define VP8_LOTS_OF_BITS (0x40000000)
+
+typedef struct
+{
+ const unsigned char *user_buffer_end;
+ const unsigned char *user_buffer;
+ VP8_BD_VALUE value;
+ int count;
+ unsigned int range;
+} BOOL_DECODER;
+
+extern const unsigned char vp8_norm[256] __attribute__((aligned(16)));
+
+int vp8dx_start_decode(BOOL_DECODER *br,
+ const unsigned char *source,
+ unsigned int source_sz);
+
+void vp8dx_bool_decoder_fill(BOOL_DECODER *br);
+
+/*The refill loop is used in several places, so define it in a macro to make
+ sure they're all consistent.
+ An inline function would be cleaner, but has a significant penalty, because
+ multiple BOOL_DECODER fields must be modified, and the compiler is not smart
+ enough to eliminate the stores to those fields and the subsequent reloads
+ from them when inlining the function.*/
+#define VP8DX_BOOL_DECODER_FILL(_count,_value,_bufptr,_bufend) \
+ do \
+ { \
+ int shift = VP8_BD_VALUE_SIZE - 8 - ((_count) + 8); \
+ int loop_end, x; \
+ size_t bits_left = ((_bufend)-(_bufptr))*CHAR_BIT; \
+ \
+ x = shift + CHAR_BIT - bits_left; \
+ loop_end = 0; \
+ if(x >= 0) \
+ { \
+ (_count) += VP8_LOTS_OF_BITS; \
+ loop_end = x; \
+ if(!bits_left) break; \
+ } \
+ while(shift >= loop_end) \
+ { \
+ (_count) += CHAR_BIT; \
+ (_value) |= (VP8_BD_VALUE)*(_bufptr)++ << shift; \
+ shift -= CHAR_BIT; \
+ } \
+ } \
+ while(0) \
+
+
+static int vp8dx_decode_bool(BOOL_DECODER *br, int probability) {
+ unsigned int bit = 0;
+ VP8_BD_VALUE value;
+ unsigned int split;
+ VP8_BD_VALUE bigsplit;
+ int count;
+ unsigned int range;
+
+ split = 1 + (((br->range - 1) * probability) >> 8);
+
+ if(br->count < 0)
+ vp8dx_bool_decoder_fill(br);
+
+ value = br->value;
+ count = br->count;
+
+ bigsplit = (VP8_BD_VALUE)split << (VP8_BD_VALUE_SIZE - 8);
+
+ range = split;
+
+ if (value >= bigsplit)
+ {
+ range = br->range - split;
+ value = value - bigsplit;
+ bit = 1;
+ }
+
+ {
+ register unsigned int shift = vp8_norm[range];
+ range <<= shift;
+ value <<= shift;
+ count -= shift;
+ }
+ br->value = value;
+ br->count = count;
+ br->range = range;
+
+ return bit;
+}
+
+static G_GNUC_UNUSED int vp8_decode_value(BOOL_DECODER *br, int bits)
+{
+ int z = 0;
+ int bit;
+
+ for (bit = bits - 1; bit >= 0; bit--)
+ {
+ z |= (vp8dx_decode_bool(br, 0x80) << bit);
+ }
+
+ return z;
+}
+
+static G_GNUC_UNUSED int vp8dx_bool_error(BOOL_DECODER *br)
+{
+ /* Check if we have reached the end of the buffer.
+ *
+ * Variable 'count' stores the number of bits in the 'value' buffer, minus
+ * 8. The top byte is part of the algorithm, and the remainder is buffered
+ * to be shifted into it. So if count == 8, the top 16 bits of 'value' are
+ * occupied, 8 for the algorithm and 8 in the buffer.
+ *
+ * When reading a byte from the user's buffer, count is filled with 8 and
+ * one byte is filled into the value buffer. When we reach the end of the
+ * data, count is additionally filled with VP8_LOTS_OF_BITS. So when
+ * count == VP8_LOTS_OF_BITS - 1, the user's data has been exhausted.
+ */
+ if ((br->count > VP8_BD_VALUE_SIZE) && (br->count < VP8_LOTS_OF_BITS))
+ {
+ /* We have tried to decode bits after the end of
+ * stream was encountered.
+ */
+ return 1;
+ }
+
+ /* No error. */
+ return 0;
+}
+#endif
diff --git a/gst/rtpvp8/gstrtpvp8pay.c b/gst/rtpvp8/gstrtpvp8pay.c
index c6c773dca..d3795da3b 100644
--- a/gst/rtpvp8/gstrtpvp8pay.c
+++ b/gst/rtpvp8/gstrtpvp8pay.c
@@ -25,6 +25,7 @@
#include <gst/base/gstbitreader.h>
#include <gst/rtp/gstrtppayloads.h>
#include <gst/rtp/gstrtpbuffer.h>
+#include "dboolhuff.h"
#include "gstrtpvp8pay.h"
#define FI_FRAG_UNFRAGMENTED 0x0
@@ -130,6 +131,8 @@ gst_rtp_vp8_pay_parse_frame (GstRtpVP8Pay * self, GstBuffer * buffer)
guint8 tmp8 = 0;
guint8 *data;
guint8 partitions;
+ guint offset;
+ BOOL_DECODER bc;
reader = gst_bit_reader_new_from_buffer (buffer);
@@ -150,7 +153,8 @@ gst_rtp_vp8_pay_parse_frame (GstRtpVP8Pay * self, GstBuffer * buffer)
header_size = data[2] << 11 | data[1] << 3 | (data[0] >> 5);
/* Include the uncompressed data blob in the header */
- header_size += keyframe ? 10 : 3;
+ offset = keyframe ? 10 : 3;
+ header_size += offset;
if (!gst_bit_reader_skip (reader, 24))
goto error;
@@ -166,109 +170,81 @@ gst_rtp_vp8_pay_parse_frame (GstRtpVP8Pay * self, GstBuffer * buffer)
if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 8) || tmp8 != 0x2a)
goto error;
- /* Skip horizontal size code (16 bits) vertical size code (16 bits),
- * color space (1 bit) and clamping type (1 bit) */
- if (!gst_bit_reader_skip (reader, 34))
+ /* Skip horizontal size code (16 bits) vertical size code (16 bits) */
+ if (!gst_bit_reader_skip (reader, 32))
goto error;
}
- /* segmentation_enabled */
- if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 1))
- goto error;
+ offset = keyframe ? 10 : 3;
+ vp8dx_start_decode (&bc, GST_BUFFER_DATA (buffer) + offset,
+ GST_BUFFER_SIZE (buffer) - offset);
- if (tmp8 != 0) {
- gboolean update_mb_segmentation_map;
- gboolean update_segment_feature_data;
-
- if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 2))
- goto error;
+ if (keyframe) {
+ /* color space (1 bit) and clamping type (1 bit) */
+ vp8dx_decode_bool (&bc, 0x80);
+ vp8dx_decode_bool (&bc, 0x80);
+ }
- update_mb_segmentation_map = (tmp8 & 0x2) != 0;
- update_segment_feature_data = (tmp8 & 0x1) != 0;
+ /* segmentation_enabled */
+ if (vp8dx_decode_bool (&bc, 0x80)) {
+ guint8 update_mb_segmentation_map = vp8dx_decode_bool (&bc, 0x80);
+ guint8 update_segment_feature_data = vp8dx_decode_bool (&bc, 0x80);
if (update_segment_feature_data) {
/* skip segment feature mode */
- if (!gst_bit_reader_skip (reader, 1))
- goto error;
+ vp8dx_decode_bool (&bc, 0x80);
+ /* quantizer update */
for (i = 0; i < 4; i++) {
- /* quantizer update */
- if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 1))
- goto error;
-
- if (tmp8 != 0) {
- /* skip quantizer value (7 bits) and sign (1 bit) */
- if (!gst_bit_reader_skip (reader, 8))
- goto error;
- }
+ /* skip flagged quantizer value (7 bits) and sign (1 bit) */
+ if (vp8dx_decode_bool (&bc, 0x80))
+ vp8_decode_value (&bc, 8);
}
+ /* loop filter update */
for (i = 0; i < 4; i++) {
- /* loop filter update */
- if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 1))
- goto error;
-
- if (tmp8 != 0) {
- /* skip lf update value (6 bits) and sign (1 bit) */
- if (!gst_bit_reader_skip (reader, 7))
- goto error;
- }
+ /* skip flagged lf update value (6 bits) and sign (1 bit) */
+ if (vp8dx_decode_bool (&bc, 0x80))
+ vp8_decode_value (&bc, 7);
}
}
if (update_mb_segmentation_map) {
+ /* segment prob update */
for (i = 0; i < 3; i++) {
- /* segment prob update */
- if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 1))
- goto error;
-
- if (tmp8 != 0) {
- /* skip segment prob */
- if (!gst_bit_reader_skip (reader, 8))
- goto error;
- }
+ /* skip flagged segment prob */
+ if (vp8dx_decode_bool (&bc, 0x80))
+ vp8_decode_value (&bc, 8);
}
}
}
/* skip filter type (1 bit), loop filter level (6 bits) and
* sharpness level (3 bits) */
- if (!gst_bit_reader_skip (reader, 10))
- goto error;
+ vp8_decode_value (&bc, 1);
+ vp8_decode_value (&bc, 6);
+ vp8_decode_value (&bc, 3);
/* loop_filter_adj_enabled */
- if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 1))
- goto error;
-
- if (tmp8 != 0) {
- /* loop filter adj enabled */
+ if (vp8dx_decode_bool (&bc, 0x80)) {
- /* mode_ref_lf_delta_update */
- if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 1))
- goto error;
-
- if (tmp8 != 0) {
- /* mode_ref_lf_data_update */
- int i;
+ /* delta update */
+ if (vp8dx_decode_bool (&bc, 0x80)) {
for (i = 0; i < 8; i++) {
/* 8 updates, 1 bit indicate whether there is one and if follow by a
* 7 bit update */
- if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 1))
- goto error;
-
- if (tmp8 != 0) {
- /* skip delta magnitude (6 bits) and sign (1 bit) */
- if (!gst_bit_reader_skip (reader, 7))
- goto error;
- }
+ if (vp8dx_decode_bool (&bc, 0x80))
+ vp8_decode_value (&bc, 7);
}
}
}
- if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 2))
+ if (vp8dx_bool_error (&bc))
goto error;
+ tmp8 = vp8_decode_value (&bc, 2);
+
partitions = 1 << tmp8;
/* Check if things are still sensible */
diff --git a/gst/videoparsers/Makefile.am b/gst/videoparsers/Makefile.am
index 811d5f860..ac2a51711 100644
--- a/gst/videoparsers/Makefile.am
+++ b/gst/videoparsers/Makefile.am
@@ -7,6 +7,7 @@ libgstvideoparsersbad_la_SOURCES = plugin.c \
libgstvideoparsersbad_la_CFLAGS = \
$(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
+ -DGST_USE_UNSTABLE_API \
$(GST_BASE_CFLAGS) $(GST_CFLAGS)
libgstvideoparsersbad_la_LIBADD = $(GST_PLUGINS_BASE_LIBS) \
$(top_builddir)/gst-libs/gst/codecparsers/libgstcodecparsers-$(GST_MAJORMINOR).la \
diff --git a/gst/videoparsers/dirac_parse.c b/gst/videoparsers/dirac_parse.c
index 3a3193d92..5b367c36c 100644
--- a/gst/videoparsers/dirac_parse.c
+++ b/gst/videoparsers/dirac_parse.c
@@ -165,7 +165,7 @@ dirac_sequence_header_parse (DiracSequenceHeader * header,
/* standard stuff */
-static DiracSequenceHeader schro_video_formats[] = {
+static const DiracSequenceHeader schro_video_formats[] = {
{0, 0, 0, 0,
0, /* custom */
640, 480, SCHRO_CHROMA_420,
@@ -323,7 +323,7 @@ struct _SchroFrameRate
int denominator;
};
-static SchroFrameRate schro_frame_rates[] = {
+static const SchroFrameRate schro_frame_rates[] = {
{0, 0},
{24000, 1001},
{24, 1},
diff --git a/gst/videoparsers/gstdiracparse.c b/gst/videoparsers/gstdiracparse.c
index 3feaa4192..ef99b7ae9 100644
--- a/gst/videoparsers/gstdiracparse.c
+++ b/gst/videoparsers/gstdiracparse.c
@@ -78,14 +78,19 @@ static GstStaticPadTemplate gst_dirac_parse_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-dirac, parsed=(boolean)FALSE")
+ GST_STATIC_CAPS ("video/x-dirac")
);
static GstStaticPadTemplate gst_dirac_parse_src_template =
GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-dirac, parsed=(boolean)TRUE")
+ GST_STATIC_CAPS ("video/x-dirac, parsed=(boolean)TRUE, "
+ "width=(int)[1,MAX], height=(int)[1,MAX], "
+ "framerate=(fraction)[0/1,MAX], "
+ "pixel-aspect-ratio=(fraction)[0/1,MAX], "
+ "interlaced=(boolean){TRUE,FALSE}, "
+ "profile=(int)[0,MAX], level=(int)[0,MAX]")
);
/* class initialization */
diff --git a/gst/videoparsers/gsth263parse.c b/gst/videoparsers/gsth263parse.c
index 877c75e44..4a5633f3b 100644
--- a/gst/videoparsers/gsth263parse.c
+++ b/gst/videoparsers/gsth263parse.c
@@ -39,14 +39,13 @@ static GstStaticPadTemplate srctemplate =
GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/x-h263, variant = (string) itu, "
- "parsed = (boolean) true")
+ "parsed = (boolean) true, framerate=(fraction)[0/1,MAX]")
);
static GstStaticPadTemplate sinktemplate =
GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-h263, variant = (string) itu, "
- "parsed = (boolean) false")
+ GST_STATIC_CAPS ("video/x-h263, variant = (string) itu")
);
GST_BOILERPLATE (GstH263Parse, gst_h263_parse, GstElement, GST_TYPE_BASE_PARSE);
@@ -102,7 +101,7 @@ gst_h263_parse_start (GstBaseParse * parse)
{
GstH263Parse *h263parse = GST_H263_PARSE (parse);
- GST_DEBUG ("Start");
+ GST_DEBUG_OBJECT (h263parse, "start");
h263parse->bitrate = 0;
h263parse->profile = -1;
@@ -118,7 +117,7 @@ gst_h263_parse_start (GstBaseParse * parse)
static gboolean
gst_h263_parse_stop (GstBaseParse * parse)
{
- GST_DEBUG ("Stop");
+ GST_DEBUG_OBJECT (parse, "stop");
return TRUE;
}
@@ -139,7 +138,7 @@ gst_h263_parse_sink_event (GstBaseParse * parse, GstEvent * event)
gst_event_parse_tag (event, &taglist);
if (gst_tag_list_get_uint (taglist, GST_TAG_BITRATE, &h263parse->bitrate))
- GST_DEBUG ("Got bitrate tag: %u", h263parse->bitrate);
+ GST_DEBUG_OBJECT (h263parse, "got bitrate tag: %u", h263parse->bitrate);
break;
}
@@ -201,7 +200,7 @@ gst_h263_parse_set_src_caps (GstH263Parse * h263parse,
if (sink_caps && (st = gst_caps_get_structure (sink_caps, 0)) &&
gst_structure_get_fraction (st, "framerate", &fr_num, &fr_denom)) {
/* Got it in caps - nothing more to do */
- GST_DEBUG ("Sink caps override framerate from headers");
+ GST_DEBUG_OBJECT (h263parse, "sink caps override framerate from headers");
} else {
/* Caps didn't have the framerate - get it from params */
gst_h263_parse_get_framerate (params, &fr_num, &fr_denom);
@@ -308,7 +307,8 @@ gst_h263_parse_check_valid_frame (GstBaseParse * parse,
/* XXX: After getting a keyframe, should we adjust min_frame_size to
* something smaller so we don't end up collecting too many non-keyframes? */
- GST_DEBUG ("Found a frame of size %d at pos %d", *framesize, *skipsize);
+ GST_DEBUG_OBJECT (h263parse, "found a frame of size %d at pos %d",
+ *framesize, *skipsize);
return TRUE;
diff --git a/gst/videoparsers/gsth264parse.c b/gst/videoparsers/gsth264parse.c
index 3821f0031..d2009d60e 100644
--- a/gst/videoparsers/gsth264parse.c
+++ b/gst/videoparsers/gsth264parse.c
@@ -62,12 +62,14 @@ enum
static GstStaticPadTemplate sinktemplate = GST_STATIC_PAD_TEMPLATE ("sink",
GST_PAD_SINK,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-h264, parsed = (boolean) false"));
+ GST_STATIC_CAPS ("video/x-h264"));
static GstStaticPadTemplate srctemplate = GST_STATIC_PAD_TEMPLATE ("src",
GST_PAD_SRC,
GST_PAD_ALWAYS,
- GST_STATIC_CAPS ("video/x-h264, parsed = (boolean) true"));
+ GST_STATIC_CAPS ("video/x-h264, parsed = (boolean) true, "
+ "stream-format=(string) { avc, byte-stream }, "
+ "alignment=(string) { au, nal }"));
GST_BOILERPLATE (GstH264Parse, gst_h264_parse, GstBaseParse,
GST_TYPE_BASE_PARSE);
@@ -237,8 +239,7 @@ gst_h264_parse_stop (GstBaseParse * parse)
for (i = 0; i < GST_H264_MAX_PPS_COUNT; i++)
gst_buffer_replace (&h264parse->pps_nals[i], NULL);
- g_free (h264parse->nalparser);
- h264parse->nalparser = NULL;
+ gst_h264_nal_parser_free (h264parse->nalparser);
return TRUE;
}
@@ -338,7 +339,8 @@ gst_h264_parse_wrap_nal (GstH264Parse * h264parse, guint format, guint8 * data,
GstBuffer *buf;
const guint nl = h264parse->nal_length_size;
- GST_DEBUG ("Nal length %d %d", size, h264parse->nal_length_size);
+ GST_DEBUG_OBJECT (h264parse, "nal length %d %d", size,
+ h264parse->nal_length_size);
buf = gst_buffer_new_and_alloc (size + nl + 4);
if (format == GST_H264_PARSE_FORMAT_AVC) {
@@ -364,11 +366,11 @@ gst_h264_parser_store_nal (GstH264Parse * h264parse, guint id,
if (naltype == GST_H264_NAL_SPS) {
store_size = GST_H264_MAX_SPS_COUNT;
store = h264parse->sps_nals;
- GST_DEBUG ("Storing sps %u", id);
+ GST_DEBUG_OBJECT (h264parse, "storing sps %u", id);
} else if (naltype == GST_H264_NAL_PPS) {
store_size = GST_H264_MAX_PPS_COUNT;
store = h264parse->pps_nals;
- GST_DEBUG ("Storing pps %u", id);
+ GST_DEBUG_OBJECT (h264parse, "storing pps %u", id);
} else
return;
@@ -476,8 +478,8 @@ gst_h264_parse_process_nal (GstH264Parse * h264parse, GstH264NalUnit * nalu)
/* if we need to sneak codec NALs into the stream,
* this is a good place, so fake it as IDR
* (which should be at start anyway) */
- GST_DEBUG ("Frame start: %i first_mb_in_slice %i", h264parse->frame_start,
- slice.first_mb_in_slice);
+ GST_DEBUG_OBJECT (h264parse, "frame start: %i first_mb_in_slice %i",
+ h264parse->frame_start, slice.first_mb_in_slice);
if (G_LIKELY (!h264parse->push_codec))
break;
/* fall-through */
@@ -486,7 +488,7 @@ gst_h264_parse_process_nal (GstH264Parse * h264parse, GstH264NalUnit * nalu)
if (gst_h264_parser_parse_slice_hdr (nalparser, nalu,
&slice, FALSE, FALSE) == GST_H264_PARSER_ERROR)
return;
- GST_DEBUG ("Frame start: %i first_mb_in_slice %i",
+ GST_DEBUG_OBJECT (h264parse, "frame start: %i first_mb_in_slice %i",
h264parse->frame_start, slice.first_mb_in_slice);
}
/* real frame data */
@@ -494,15 +496,17 @@ gst_h264_parse_process_nal (GstH264Parse * h264parse, GstH264NalUnit * nalu)
/* mark where config needs to go if interval expired */
/* mind replacement buffer if applicable */
- if (h264parse->format == GST_H264_PARSE_FORMAT_AVC)
- h264parse->idr_pos = gst_adapter_available (h264parse->frame_out);
- else
- h264parse->idr_pos = nalu->offset - 4;
- GST_DEBUG_OBJECT (h264parse, "marking IDR in frame at offset %d",
- h264parse->idr_pos);
+ if (h264parse->idr_pos == -1) {
+ if (h264parse->format == GST_H264_PARSE_FORMAT_AVC)
+ h264parse->idr_pos = gst_adapter_available (h264parse->frame_out);
+ else
+ h264parse->idr_pos = nalu->offset - 4;
+ GST_DEBUG_OBJECT (h264parse, "marking IDR in frame at offset %d",
+ h264parse->idr_pos);
+ }
- GST_DEBUG ("first MB: %u, slice type: %u", slice.first_mb_in_slice,
- slice.type);
+ GST_DEBUG_OBJECT (h264parse, "first MB: %u, slice type: %u",
+ slice.first_mb_in_slice, slice.type);
break;
default:
gst_h264_parser_parse_nal (nalparser, nalu);
@@ -531,7 +535,7 @@ gst_h264_parse_collect_nal (GstH264Parse * h264parse, const guint8 * data,
GstH264NalUnitType nal_type = nalu->type;
GstH264NalUnit nnalu;
- GST_DEBUG ("Parsing collecte nal");
+ GST_DEBUG_OBJECT (h264parse, "parsing collected nal");
parse_res = gst_h264_parser_identify_nalu (h264parse->nalparser, data,
nalu->offset + nalu->size, size, &nnalu);
@@ -612,16 +616,18 @@ gst_h264_parse_check_valid_frame (GstBaseParse * parse,
drain = GST_BASE_PARSE_DRAINING (parse);
current_off = h264parse->current_off;
- GST_DEBUG ("Last parse position %u", current_off);
+ GST_DEBUG_OBJECT (h264parse, "last parse position %u", current_off);
while (TRUE) {
switch (gst_h264_parser_identify_nalu (nalparser, data, current_off,
size, &nalu)) {
case GST_H264_PARSER_OK:
- GST_DEBUG ("Complete nal found. %u Off: %u, Size: %u",
+ GST_DEBUG_OBJECT (h264parse, "complete nal found. "
+ "current offset: %u, Nal offset: %u, Nal Size: %u",
current_off, nalu.offset, nalu.size);
current_off = nalu.offset + nalu.size;
- GST_DEBUG ("CURENT OFF. %u, %u", current_off, nalu.offset + nalu.size);
+ GST_DEBUG_OBJECT (h264parse, "current off. %u, %u", current_off,
+ nalu.offset + nalu.size);
if (!h264parse->nalu.size && !h264parse->nalu.valid)
h264parse->nalu = nalu;
break;
@@ -643,15 +649,15 @@ gst_h264_parse_check_valid_frame (GstBaseParse * parse,
if (nalu.sc_offset == h264parse->nalu.sc_offset) {
*skipsize = nalu.offset;
- GST_DEBUG ("Skiping broken nal");
+ GST_DEBUG_OBJECT (h264parse, "skipping broken nal");
return FALSE;
} else {
nalu.size = 0;
-
goto end;
}
case GST_H264_PARSER_NO_NAL_END:
- GST_DEBUG ("Not a complete nal found at offset %u", nalu.offset);
+ GST_DEBUG_OBJECT (h264parse, "not a complete nal found at offset %u",
+ nalu.offset);
current_off = nalu.sc_offset;
/* We keep the reference to this nal so we start over the parsing
@@ -660,8 +666,8 @@ gst_h264_parse_check_valid_frame (GstBaseParse * parse,
h264parse->nalu = nalu;
if (drain) {
- GST_DEBUG ("Drainning NAL %u %u %u", size, h264parse->nalu.offset,
- h264parse->nalu.size);
+ GST_DEBUG_OBJECT (h264parse, "drainning NAL %u %u %u", size,
+ h264parse->nalu.offset, h264parse->nalu.size);
/* Can't parse the nalu */
if (size - h264parse->nalu.offset < 2) {
*skipsize = nalu.offset;
@@ -677,8 +683,8 @@ gst_h264_parse_check_valid_frame (GstBaseParse * parse,
current_off = nalu.offset + nalu.size;
- GST_DEBUG ("%p Complete nal found. Off: %u, Size: %u", data, nalu.offset,
- nalu.size);
+ GST_DEBUG_OBJECT (h264parse, "%p complete nal found. Off: %u, Size: %u",
+ data, nalu.offset, nalu.size);
gst_h264_parse_process_nal (h264parse, &nalu);
if (gst_h264_parse_collect_nal (h264parse, data, size, &nalu) || drain)
@@ -697,7 +703,7 @@ end:
return TRUE;
parsing_error:
- GST_DEBUG ("Error parsing Nal Unit");
+ GST_DEBUG_OBJECT (h264parse, "error parsing Nal Unit");
more:
/* ask for best next available */
diff --git a/gst/videoparsers/gstmpegvideoparse.c b/gst/videoparsers/gstmpegvideoparse.c
index 12d98d5d7..5db0080a1 100644
--- a/gst/videoparsers/gstmpegvideoparse.c
+++ b/gst/videoparsers/gstmpegvideoparse.c
@@ -46,8 +46,7 @@ static GstStaticPadTemplate sink_template =
GST_STATIC_PAD_TEMPLATE ("sink", GST_PAD_SINK,
GST_PAD_ALWAYS,
GST_STATIC_CAPS ("video/mpeg, "
- "mpegversion = (int) [1, 2], "
- "parsed = (boolean) false, " "systemstream = (boolean) false")
+ "mpegversion = (int) [1, 2], " "systemstream = (boolean) false")
);
/* Properties */
@@ -72,6 +71,8 @@ static gboolean gst_mpegv_parse_check_valid_frame (GstBaseParse * parse,
static GstFlowReturn gst_mpegv_parse_parse_frame (GstBaseParse * parse,
GstBaseParseFrame * frame);
static gboolean gst_mpegv_parse_set_caps (GstBaseParse * parse, GstCaps * caps);
+static GstFlowReturn gst_mpegv_parse_pre_push_frame (GstBaseParse * parse,
+ GstBaseParseFrame * frame);
static void gst_mpegv_parse_set_property (GObject * object, guint prop_id,
const GValue * value, GParamSpec * pspec);
@@ -165,6 +166,8 @@ gst_mpegv_parse_class_init (GstMpegvParseClass * klass)
GST_DEBUG_FUNCPTR (gst_mpegv_parse_check_valid_frame);
parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_mpegv_parse_parse_frame);
parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_mpegv_parse_set_caps);
+ parse_class->pre_push_frame =
+ GST_DEBUG_FUNCPTR (gst_mpegv_parse_pre_push_frame);
}
static void
@@ -188,6 +191,7 @@ gst_mpegv_parse_reset (GstMpegvParse * mpvparse)
gst_mpegv_parse_reset_frame (mpvparse);
mpvparse->profile = 0;
mpvparse->update_caps = TRUE;
+ mpvparse->send_codec_tag = TRUE;
gst_buffer_replace (&mpvparse->config, NULL);
memset (&mpvparse->sequencehdr, 0, sizeof (mpvparse->sequencehdr));
@@ -237,13 +241,12 @@ gst_mpegv_parse_process_config (GstMpegvParse * mpvparse, GstBuffer * buf,
if (!gst_mpeg_video_parse_sequence_header (&mpvparse->sequencehdr, data,
GST_BUFFER_SIZE (buf) - mpvparse->seq_offset, 0)) {
GST_DEBUG_OBJECT (mpvparse,
- "failed to parse config data (size %" G_GSSIZE_FORMAT ") at offset %d",
+ "failed to parse config data (size %d) at offset %d",
size, mpvparse->seq_offset);
return FALSE;
}
- GST_LOG_OBJECT (mpvparse, "accepting parsed config size %" G_GSSIZE_FORMAT,
- size);
+ GST_LOG_OBJECT (mpvparse, "accepting parsed config size %d", size);
/* Set mpeg version, and parse sequence extension */
if (mpvparse->mpeg_version <= 0) {
@@ -490,15 +493,23 @@ end:
} else if (GST_BASE_PARSE_DRAINING (parse)) {
*framesize = GST_BUFFER_SIZE (buf);
ret = TRUE;
+
} else {
/* resume scan where we left it */
- mpvparse->last_sc = GST_BUFFER_SIZE (buf);
+ if (!mpvparse->last_sc)
+ *skipsize = mpvparse->last_sc = GST_BUFFER_SIZE (buf) - 3;
+ else if (mpvparse->typeoffsize)
+ mpvparse->last_sc = GST_BUFFER_SIZE (buf) - 3;
+ else
+ *skipsize = 0;
+
/* request best next available */
*framesize = G_MAXUINT;
ret = FALSE;
}
- g_list_free_full (mpvparse->typeoffsize, (GDestroyNotify) g_free);
+ g_list_foreach (mpvparse->typeoffsize, (GFunc) g_free, NULL);
+ g_list_free (mpvparse->typeoffsize);
mpvparse->typeoffsize = NULL;
return ret;
@@ -654,6 +665,37 @@ gst_mpegv_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
return GST_FLOW_OK;
}
+static GstFlowReturn
+gst_mpegv_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
+{
+ GstMpegvParse *mpvparse = GST_MPEGVIDEO_PARSE (parse);
+ GstTagList *taglist;
+
+ /* tag sending done late enough in hook to ensure pending events
+ * have already been sent */
+
+ if (G_UNLIKELY (mpvparse->send_codec_tag)) {
+ gchar *codec;
+
+ /* codec tag */
+ codec = g_strdup_printf ("MPEG %d Video", mpvparse->mpeg_version);
+ taglist = gst_tag_list_new ();
+ gst_tag_list_add (taglist, GST_TAG_MERGE_REPLACE,
+ GST_TAG_VIDEO_CODEC, codec, NULL);
+ g_free (codec);
+
+ gst_element_found_tags_for_pad (GST_ELEMENT (mpvparse),
+ GST_BASE_PARSE_SRC_PAD (mpvparse), taglist);
+
+ mpvparse->send_codec_tag = FALSE;
+ }
+
+ /* usual clipping applies */
+ frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
+
+ return GST_FLOW_OK;
+}
+
static gboolean
gst_mpegv_parse_set_caps (GstBaseParse * parse, GstCaps * caps)
{
diff --git a/gst/videoparsers/gstmpegvideoparse.h b/gst/videoparsers/gstmpegvideoparse.h
index 6837a316e..593c53e8b 100644
--- a/gst/videoparsers/gstmpegvideoparse.h
+++ b/gst/videoparsers/gstmpegvideoparse.h
@@ -56,6 +56,7 @@ struct _GstMpegvParse {
gint seq_offset;
gint pic_offset;
gboolean update_caps;
+ gboolean send_codec_tag;
GstBuffer *config;
guint8 profile;
diff --git a/gst/videoparsers/plugin.c b/gst/videoparsers/plugin.c
index a6db91d35..94a6c10fe 100644
--- a/gst/videoparsers/plugin.c
+++ b/gst/videoparsers/plugin.c
@@ -33,13 +33,13 @@ plugin_init (GstPlugin * plugin)
gboolean ret;
ret = gst_element_register (plugin, "h263parse",
- GST_RANK_NONE, GST_TYPE_H263_PARSE);
+ GST_RANK_PRIMARY + 1, GST_TYPE_H263_PARSE);
ret = gst_element_register (plugin, "h264parse",
- GST_RANK_NONE, GST_TYPE_H264_PARSE);
+ GST_RANK_PRIMARY + 1, GST_TYPE_H264_PARSE);
ret = gst_element_register (plugin, "diracparse",
GST_RANK_NONE, GST_TYPE_DIRAC_PARSE);
ret = gst_element_register (plugin, "mpegvideoparse",
- GST_RANK_NONE, GST_TYPE_MPEGVIDEO_PARSE);
+ GST_RANK_PRIMARY + 1, GST_TYPE_MPEGVIDEO_PARSE);
return ret;
}
diff --git a/tests/check/Makefile.am b/tests/check/Makefile.am
index 47bd813c9..75750ea99 100644
--- a/tests/check/Makefile.am
+++ b/tests/check/Makefile.am
@@ -185,6 +185,7 @@ check_PROGRAMS = \
elements/rtpmux \
libs/mpegvideoparser \
libs/h264parser \
+ libs/vc1parser \
$(check_schro) \
$(check_vp8) \
elements/viewfinderbin \
@@ -218,6 +219,7 @@ elements_h264parse_LDADD = libparser.la $(LDADD)
libs_mpegvideoparser_CFLAGS = \
$(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
+ -DGST_USE_UNSTABLE_API \
$(GST_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS)
libs_mpegvideoparser_LDADD = \
@@ -227,6 +229,7 @@ libs_mpegvideoparser_LDADD = \
libs_h264parser_CFLAGS = \
$(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
+ -DGST_USE_UNSTABLE_API \
$(GST_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS)
libs_h264parser_LDADD = \
@@ -234,6 +237,16 @@ libs_h264parser_LDADD = \
$(GST_PLUGINS_BAD_LIBS) -lgstcodecparsers-@GST_MAJORMINOR@ \
$(GST_BASE_LIBS) $(GST_LIBS) $(LDADD)
+libs_vc1parser_CFLAGS = \
+ $(GST_PLUGINS_BAD_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) \
+ -DGST_USE_UNSTABLE_API \
+ $(GST_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS)
+
+libs_vc1parser_LDADD = \
+ $(top_builddir)/gst-libs/gst/codecparsers/libgstcodecparsers-@GST_MAJORMINOR@.la \
+ $(GST_PLUGINS_BAD_LIBS) -lgstcodecparsers-@GST_MAJORMINOR@ \
+ $(GST_BASE_LIBS) $(GST_LIBS) $(LDADD)
+
elements_voaacenc_CFLAGS = \
$(GST_PLUGINS_BASE_CFLAGS) \
$(GST_BASE_CFLAGS) $(GST_CFLAGS) $(AM_CFLAGS)
diff --git a/tests/check/libs/h264parser.c b/tests/check/libs/h264parser.c
index 3bc8c49e5..5d87980f9 100644
--- a/tests/check/libs/h264parser.c
+++ b/tests/check/libs/h264parser.c
@@ -145,7 +145,7 @@ GST_START_TEST (test_h264_parse_slice_dpa)
assert_equals_int (res, GST_H264_PARSER_OK);
assert_equals_int (nalu.type, GST_H264_NAL_SLICE_DPA);
- g_free (parser);
+ gst_h264_nal_parser_free (parser);
}
GST_END_TEST;
diff --git a/tests/check/libs/vc1parser.c b/tests/check/libs/vc1parser.c
new file mode 100644
index 000000000..5c9ef73ee
--- /dev/null
+++ b/tests/check/libs/vc1parser.c
@@ -0,0 +1,1230 @@
+/* Gstreamer
+ * Copyright (C) <2011> Intel
+ * Copyright (C) <2011> Collabora Ltd.
+ * Copyright (C) <2011> Thibault Saunier <thibault.saunier@collabora.com>
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ */
+#include <gst/check/gstcheck.h>
+#include <gst/codecparsers/gstvc1parser.h>
+
+static guint8 sequence_fullframe[] = {
+ 0x00, 0x00, 0x01, 0x0f, 0xca, 0x86, 0x13, 0xf0, 0xef, 0x88,
+ 0x80, 0x00, 0x00, 0x01, 0x0e, 0x48, 0x3f, 0x4f, 0xc3, 0xbc,
+ 0x3f, 0x2b, 0x3f, 0x3c, 0x3f, 0x00, 0x00, 0x01, 0x0d, 0x3f,
+ 0x0c, 0x14, 0x27, 0x3f, 0x68, 0x0c, 0x03, 0x3f, 0x3f, 0x55,
+ 0x3f, 0x60, 0x71, 0x24, 0x38, 0x28, 0x1b, 0xda, 0xac, 0x01,
+ 0x3f, 0x3f, 0x3f, 0x33, 0x3f, 0x61, 0x75, 0x70, 0x3f, 0x3f,
+ 0x3f, 0x0d, 0x3f, 0x03, 0x3f, 0x3f, 0x1b, 0x3f, 0x3f, 0x61,
+ 0x1a, 0x73, 0x01, 0x26, 0x07, 0x0e, 0x29, 0x3f, 0x1d, 0x68,
+ 0xe1, 0xa2, 0x98, 0x59, 0x21, 0x3f, 0x1e, 0x7c, 0x3f, 0x3f,
+ 0x3f, 0x65, 0x49, 0x3f, 0x3f, 0x7e, 0x3f, 0x07, 0x6a, 0x0f,
+ 0xdb, 0x87, 0x3f, 0x3f, 0x3f, 0x41, 0x3f, 0x3f, 0x77, 0x3f,
+ 0x3f, 0x3f, 0x3f, 0x3f, 0x3f, 0x44, 0x3f, 0x4a, 0x50, 0x53,
+ 0x3f, 0x3f, 0x65, 0x3f, 0x2e, 0x3f, 0x3f, 0x3f, 0x08, 0x3f,
+ 0x3f, 0x04, 0x5e, 0x11, 0x7d, 0x12, 0x3f, 0x4a, 0x6b, 0x50,
+ 0x42, 0x3f, 0x15, 0x3f, 0x3f, 0x61, 0x3f, 0x3f, 0x75, 0x41,
+ 0x3f, 0x3f, 0x75, 0x71, 0x3f, 0x3f, 0x3b, 0x3f, 0x0d, 0x3f,
+ 0x3f, 0x6e, 0x3f, 0x3f, 0x06, 0x3f, 0x30, 0x08, 0x72, 0x3f,
+ 0x3b, 0x3f, 0x67, 0x6e, 0x3f, 0x50, 0x1b, 0x61, 0x5a, 0x20,
+ 0x2b, 0x70, 0x3f, 0x2c, 0x22, 0x3f, 0x36, 0x3f, 0x44, 0x40,
+ 0x00, 0x00, 0x01, 0x05, 0x3f
+};
+
+static guint8 pframe_header_main[] = {
+ 0x4e, 0x29, 0x1a, 0x11
+};
+
+static guint8 pframe_main[] = {
+ 0x6a, 0x88, 0xbc, 0x1d, 0x40, 0x16, 0x96, 0x90, 0x05, 0x82,
+ 0xac, 0x22, 0x88, 0xe0, 0x5d, 0x52, 0xca, 0x85, 0x4c, 0x47,
+ 0x9d, 0xc9, 0x25, 0x45, 0x56, 0x99, 0x44, 0x15, 0xa5, 0xc5,
+ 0xe1, 0x35, 0x11, 0x72, 0xc1, 0x27, 0x22, 0x6a, 0x08, 0x9a,
+ 0x72, 0x4e, 0xe7, 0xa3, 0xf7, 0x23, 0x9d, 0x11, 0x8d, 0xc8,
+ 0xe6, 0x4f, 0x46, 0x98, 0xe2, 0x03, 0xcc, 0x6c, 0xe8, 0x77,
+ 0xd4, 0x7c, 0xfc, 0x13, 0x39, 0x20, 0x23, 0x03, 0x24, 0xcd,
+ 0x15, 0xbf, 0x54, 0x61, 0xf2, 0x25, 0x25, 0xa0, 0x83, 0xa0,
+};
+
+static guint8 bframe_header_main[] = {
+ 0x4e, 0x39, 0x1a, 0x11
+};
+
+static guint8 bframe_main[] = {
+ 0x80, 0xae, 0x01, 0x43, 0x47, 0x6a, 0x9f, 0x53, 0x04, 0x55, 0x2a,
+ 0x8b, 0x42, 0x75, 0x8b, 0x35, 0x50, 0xf5, 0x95, 0x56, 0xf2, 0x00,
+ 0xe0, 0xa0, 0x60, 0x2c, 0xe8, 0x6b, 0x60, 0x0b, 0x20, 0x00, 0x11,
+ 0xf1, 0x51, 0xfe, 0x91, 0x60, 0x6a, 0xe6, 0x12, 0x04, 0x2c, 0xe3,
+ 0x07, 0x0a, 0x09, 0x09, 0x12, 0xcb, 0xe1, 0x42, 0x88, 0x10, 0x67,
+ 0x80, 0x4c, 0xbf, 0x26, 0x00, 0x82, 0x61, 0x07, 0x21, 0x63, 0x4c,
+ 0x0c, 0x32, 0x03, 0x53, 0x19, 0x1b, 0x4d, 0xca, 0xc9, 0xe0, 0xc1,
+ 0x6d, 0x32, 0x48, 0xc9, 0xd7, 0xa6, 0x63, 0x4d, 0xeb, 0xd4, 0x1c,
+ 0x02, 0x05, 0xfe, 0x57, 0x29, 0x00, 0x58, 0xb0, 0x67, 0x2d, 0x04,
+ 0xee, 0x1b, 0xaf, 0x53, 0x40, 0x89, 0xbe, 0xf5, 0x76, 0x20, 0x0b,
+ 0x83, 0xc1, 0x88, 0xee, 0x83, 0x94, 0xab, 0x1c, 0x79, 0xdd, 0x44,
+ 0xe5, 0x15, 0xae, 0xa5, 0xd3, 0xd5, 0x68, 0x31, 0x3e, 0x5a, 0xa4,
+ 0x6b, 0x9e, 0xe3, 0xd2, 0x49, 0x00, 0x1d, 0x6d, 0xeb, 0x0d, 0x6b,
+ 0x54, 0xcd, 0xd2, 0xaf, 0x1f, 0x2b, 0xba, 0xf3, 0xd9, 0x4c, 0x71
+};
+
+static guint8 i_bi_frame_header[] = {
+ 0x4e, 0x79, 0x1a, 0x11
+};
+
+static guint8 biframe_main[] = {
+ 0x0f, 0xe0, 0x4c, 0x56, 0x19, 0xdb, 0x40, 0x68, 0xd9, 0x14, 0x2c, 0x92,
+ 0x55, 0x1f, 0x59, 0xd5, 0x5b, 0xd8, 0x55, 0x13, 0x19, 0x64, 0x40, 0x2c,
+ 0x27, 0x38, 0x71, 0x9d, 0x05, 0x52, 0x02, 0x18, 0x7b, 0x9d, 0x22, 0x88,
+ 0x97, 0xaa, 0x54, 0x95, 0x52, 0x49, 0x23, 0x0b, 0x98, 0xee, 0x6c, 0x26,
+ 0xe6, 0xff, 0xff, 0x1a, 0x25, 0x15, 0xc3, 0x30, 0x4f, 0x1f, 0xbd, 0xb1,
+ 0x09, 0x1b, 0x55, 0x33, 0x6c, 0xcd, 0x8c, 0x11, 0x87, 0x1b, 0x86, 0x02,
+ 0x78, 0xfd, 0x69, 0xc1, 0xa2, 0x3b, 0x27, 0x08, 0xc8, 0x63, 0x5f, 0x52,
+ 0x10, 0x50, 0xe0, 0xf4, 0x4a, 0xfd, 0x83, 0x30, 0x3f, 0x20, 0x8d, 0x3a,
+ 0x88, 0xa0, 0x00, 0x23, 0xd8, 0x51, 0xd0, 0xf6, 0x8c, 0xc4, 0xe8, 0x2d,
+ 0x8c, 0x10, 0x13, 0xae, 0xb2, 0xaa, 0xc0, 0x92, 0x68, 0x33, 0x7b, 0x8f,
+ 0x63, 0x0e, 0xda, 0x35, 0xc6, 0xa1, 0x11, 0xe6, 0x44, 0xe3, 0xb1, 0x52,
+ 0xe9, 0x01, 0x05, 0x93, 0x1a, 0x36, 0x41, 0xf6, 0x62, 0x66, 0x05, 0xfb,
+ 0xd6, 0x99, 0x80, 0x8a, 0x97, 0xad, 0xa4, 0x25, 0xec, 0x1a, 0x04, 0xf3,
+ 0x0c, 0x9c, 0xe0, 0xea, 0x49, 0xfa, 0x4d, 0x58, 0xc8, 0x1b, 0x63, 0x23,
+ 0xdc, 0x07, 0x9d, 0xe9, 0x84, 0x93, 0x12, 0xc8, 0xfc, 0x86, 0x98, 0xb0,
+ 0x3d, 0xc8, 0xb4, 0xed, 0x4c, 0x18, 0xbe, 0xd8, 0x38, 0x1b, 0x6d, 0x39,
+ 0x90, 0x06, 0x43, 0x75, 0x82, 0x89, 0xc1, 0x6f, 0xf1, 0x12, 0x6d, 0x84,
+ 0x54, 0x45, 0x62, 0x2d, 0x00, 0x0a, 0x0e, 0x06, 0xf0, 0x04, 0x06, 0x5a
+};
+
+static guint8 iframe_main[] = {
+ 0x10, 0x04, 0x88, 0x18, 0x1f, 0xdf, 0xe1, 0xe1, 0xde, 0x17, 0x85, 0xe1,
+ 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e,
+ 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85,
+ 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78,
+ 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17,
+ 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1,
+ 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e,
+ 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85,
+ 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78,
+ 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17,
+ 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1,
+ 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e,
+ 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85,
+ 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78, 0x5e, 0x17, 0x85, 0xe1, 0x78
+};
+
+static guint8 iframe_adv_hdr[] = {
+ 0xdb, 0xfe, 0x3b, 0xf2, 0x1b, 0xca, 0x3b, 0xf8, 0x86, 0xf1, 0x80,
+ 0xca, 0x02, 0x02, 0x03, 0x09, 0xa5, 0xb8, 0xd7, 0x07, 0xfc
+};
+
+static guint8 entrypoint[] = {
+ 0x5a, 0xc7, 0xfc, 0xef, 0xc8, 0x6c, 0x40
+};
+
+static guint8 iframe_adv[] = {
+ 0x69, 0x1c, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x7f, 0x16, 0x0c, 0x0f, 0x13, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0,
+ 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc,
+ 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f,
+ 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f,
+ 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3,
+ 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0,
+ 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc,
+ 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f,
+ 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f,
+ 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3,
+ 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0,
+ 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc,
+ 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f,
+ 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f,
+ 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3,
+ 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0,
+ 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc,
+ 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f,
+ 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f, 0xc3, 0xf0, 0xfc, 0x3f, 0x0f
+};
+
+static guint8 bframe_adv[] = {
+ 0x46, 0x03, 0x1f, 0xf0, 0x8d, 0xd8, 0xbf, 0xc0, 0xcc, 0x14,
+ 0x24, 0xdc, 0x60, 0xe2, 0xa8, 0x5e, 0x0d, 0xff, 0xfc, 0x3b,
+ 0x12, 0xfd, 0xe1, 0x2e, 0xd1, 0x84, 0xb0, 0xc2, 0xc4, 0xc1,
+ 0x60, 0x20, 0x4a, 0x7c, 0x33, 0xff, 0xf2, 0x10, 0xd8, 0x5c,
+ 0xf6, 0x7f, 0xc4, 0xd5, 0x0e, 0x0e, 0x51, 0xa8, 0x57, 0xff,
+ 0xfa, 0x43, 0x1f, 0xd0, 0x80, 0xdc, 0x58, 0x02, 0x02, 0xaf,
+ 0x10, 0xc6, 0x10, 0x12, 0x80, 0xd8, 0x07, 0xff, 0x9d, 0x00,
+ 0x50, 0x51, 0xa8, 0x0a, 0xd3, 0xef, 0x54, 0x03, 0xcb, 0x3f,
+ 0xff, 0x2b, 0x8b, 0x21, 0xcb, 0xdb, 0xf1, 0x62, 0x4e, 0x4d,
+ 0x8b, 0x03, 0x00, 0x16, 0x53, 0xff, 0xa6, 0x65, 0x12, 0x70,
+ 0xe0, 0x3f, 0xf4, 0x85, 0xb8, 0x4b, 0xc6, 0x04, 0x52, 0xff,
+ 0xc1, 0xf0, 0x80, 0x39, 0x85, 0x9f, 0xf4, 0xca, 0x91, 0x28,
+ 0x10, 0x64, 0x2c, 0xe0, 0xff, 0xff, 0x03, 0x2c, 0x3a, 0xfe,
+ 0x03, 0xc3, 0x2d, 0x0e, 0x60, 0x61, 0x80, 0x09, 0x9f, 0xff,
+ 0x03, 0x88, 0xc5, 0xd7, 0x9f, 0xfe, 0x1c, 0x14, 0x62, 0xc0,
+ 0x62, 0xc1, 0x7f, 0xef, 0x87, 0x7d, 0x6c, 0xbf, 0xf7, 0xc2,
+ 0x00, 0x10, 0x59, 0xd7, 0xfc, 0x33, 0x15, 0xbd, 0x35, 0xec,
+ 0x17, 0x0b, 0x07, 0x20, 0xd8, 0x42, 0x7e, 0xbf, 0xfc, 0x56,
+ 0xdd, 0x1f, 0x9c, 0x3a, 0x70, 0x45, 0x93, 0x01, 0x05, 0x37,
+ 0xb7, 0xff, 0x9f, 0x25, 0x5b, 0xb1, 0xbb, 0x87, 0x35, 0x02,
+ 0x70, 0x7e, 0x89, 0xb7, 0xf8, 0x5a, 0xb8, 0xb0, 0xb5, 0x04,
+ 0x4d, 0x2e, 0x11, 0xb9, 0x74, 0xa1, 0x95, 0xf0, 0x7f, 0x7b,
+ 0x38, 0x58, 0x50, 0x61, 0x9f, 0x3f, 0x80, 0x42, 0x7d, 0x15,
+ 0x82, 0x00, 0x1d, 0x85, 0x2b, 0x85, 0xf7, 0x14, 0x94, 0x60,
+ 0x42, 0x38, 0x28, 0xa8, 0x68, 0x2d, 0x28, 0x31, 0xbc, 0x36,
+ 0x48, 0x64, 0xc0, 0x21, 0x56, 0x30, 0xb9, 0xc0, 0x45, 0x90,
+ 0xe7, 0x12, 0x83, 0x84, 0xb1, 0x25, 0x86, 0x12, 0x18, 0x2d,
+ 0x08, 0xe8, 0x2a, 0x98, 0x8e, 0x0d, 0x00, 0xaa, 0x72, 0x75,
+ 0x61, 0x87, 0x00, 0x44, 0x57, 0xd4, 0x26, 0x02, 0x23, 0x90,
+ 0xc0, 0x04, 0x90, 0x80, 0x70, 0x46, 0x11, 0xe0, 0x20, 0x26,
+ 0x8c, 0x04, 0xa2, 0x88, 0x8e, 0x30, 0xc0, 0x30, 0x60, 0xdf,
+ 0xa2, 0xdf, 0x02, 0xd0, 0x01, 0x40, 0x99, 0x4e, 0xa4, 0x7f,
+ 0x84, 0x89, 0x63, 0x07, 0x0d, 0x19, 0x1d, 0x6c, 0x88, 0xca,
+ 0x1c, 0x1d, 0x07, 0x43, 0xc1, 0x02, 0x9c, 0x60, 0xa3, 0x09,
+ 0x0b, 0xc1, 0xfd, 0xa6, 0xa8, 0x21, 0x83, 0x8c, 0x08, 0x49,
+ 0x40, 0x56, 0xf9, 0xa6, 0x6a, 0x01, 0x52, 0x0d, 0x0e, 0x12,
+ 0xe1, 0x4c, 0xbf, 0x88, 0xe5, 0xa8, 0xb8, 0x02, 0x26, 0x0c,
+ 0x24, 0x74, 0x15, 0x38, 0x70, 0x25, 0x30, 0x24, 0x5e, 0xe0,
+ 0x22, 0x70, 0x68, 0x96, 0x7f, 0xec, 0x10, 0x23, 0x94, 0x30,
+ 0x61, 0x62, 0x38, 0xb0, 0x29, 0x2d, 0x78, 0x21, 0xb3, 0xca,
+ 0x40, 0xee, 0x11, 0xa0, 0x6f, 0xf8, 0x07, 0x71, 0x70, 0x47,
+ 0xb8, 0x5f, 0x5e, 0x89, 0x6c, 0x31, 0x58, 0x22, 0x0f, 0xff,
+ 0xf7, 0x17, 0x00, 0x30, 0x85, 0xf3, 0xc2, 0xb0, 0x55, 0xfe,
+ 0xbf, 0xfe, 0x0a, 0x7c, 0x16, 0x07, 0xf0, 0xdb, 0x81, 0xf9,
+ 0x40, 0x30, 0x81, 0x84, 0xac, 0x0f, 0xff, 0xe2, 0xb3, 0x4f,
+ 0xc3, 0x8d, 0x30, 0x76, 0x9a, 0x33, 0xa0, 0x10, 0x50, 0xc8,
+ 0x60, 0xae, 0x2b, 0x22, 0xff, 0xf8, 0xa9, 0x02, 0xf9, 0xf6,
+ 0x7a, 0x44, 0x37, 0x69, 0x8b, 0x01, 0x2b, 0x9f, 0xff, 0x81,
+ 0x60, 0x7a, 0xb9, 0x01, 0x0b, 0x27, 0x70, 0x40, 0xa1, 0x50,
+ 0x60, 0xa4, 0x61, 0xa1, 0x66, 0x30, 0x91, 0x55, 0x6f, 0xff,
+ 0xe6, 0x0d, 0x14, 0xae, 0xc8, 0x1a, 0x2c, 0x23, 0x4c, 0xc9,
+ 0x94, 0x4c, 0x07, 0x61, 0x0d, 0x46, 0x63, 0x89, 0xca, 0xbf,
+ 0xff, 0xea, 0x27, 0x0c, 0x30, 0x1e, 0x66, 0x1c, 0x13, 0x50,
+ 0xb0, 0xd8, 0x34, 0x02, 0x14, 0x30, 0x01, 0x54, 0x6a, 0xbf,
+ 0xff, 0x97, 0xa2, 0x3a, 0x83, 0x85, 0x04, 0x8a, 0xc2, 0x60,
+ 0xc0, 0x85, 0x57, 0x71, 0x61, 0x45, 0x22, 0x01, 0x07, 0x00,
+ 0x22, 0xff, 0xfb, 0x5b, 0xf1, 0x80, 0x8b, 0x46, 0x81, 0x68,
+ 0x02, 0xe2, 0x71, 0x00, 0x11, 0x81, 0x86, 0x2f, 0xff, 0xf7,
+ 0x5f, 0xdd, 0x42, 0x06, 0x03, 0x38, 0xb4, 0x01, 0xf6, 0xc0,
+ 0xff, 0xc7, 0xfb, 0xb8, 0x15, 0x0b, 0xfc, 0x1c, 0x09, 0x86,
+ 0x18, 0x30, 0x34, 0x15, 0x9c, 0x6a, 0x55, 0xff, 0xff, 0xbf,
+ 0xe2, 0xc0, 0xc3, 0x86, 0xe2, 0x38, 0x18, 0xb3, 0x14, 0x81,
+ 0xc0, 0x06, 0x04, 0xc2, 0x98, 0xb0, 0x12, 0x7f, 0xff, 0x8c,
+ 0x06, 0xbf, 0x71, 0x85, 0x0c, 0x08, 0x47, 0x11, 0x87, 0xa0,
+ 0xa4, 0xe0, 0x63, 0x0a, 0x0c, 0xae, 0x0a, 0xbf, 0xfe, 0xe0,
+ 0x78, 0xb0, 0x13, 0xb8, 0x20, 0xc3, 0x5d, 0xc5, 0x21, 0x44,
+ 0x82, 0x48, 0x00, 0x18, 0x24, 0x54, 0x00, 0x03, 0x5c, 0x1b,
+ 0xff, 0xc3, 0x9a, 0x16, 0x30, 0xb1, 0x85, 0x07, 0x38, 0xc8,
+ 0x59, 0x20, 0x81, 0x4c, 0x56, 0x75, 0x27, 0x0d, 0x08, 0x71,
+ 0x58, 0x47, 0x0e, 0x12, 0x85, 0x81, 0x61, 0xbf, 0xfc, 0x5a,
+ 0x4a, 0x0c, 0x28, 0x56, 0x20, 0x03, 0x14, 0x63, 0x0a, 0x2a,
+ 0x45, 0x80, 0xd1, 0x38, 0x28, 0x68, 0x32, 0x27, 0xa2, 0x05,
+ 0xff, 0xf7, 0x03, 0xe2, 0x30, 0x3c, 0x56, 0x61, 0x4e, 0x30,
+ 0x18, 0xad, 0x80, 0xdc, 0x15, 0x04, 0xa7, 0x0c, 0x18, 0x30,
+ 0x10, 0x38, 0x62, 0xff, 0xe1, 0x87, 0x3c, 0x20, 0x60, 0x63,
+ 0x0a, 0x02, 0x29, 0xf0, 0xc2, 0xa4, 0x2c, 0x04, 0x66, 0x2b,
+ 0x02, 0x72, 0xff, 0xce, 0x07, 0xd0, 0x10, 0x0e, 0x13, 0xc5,
+ 0x22, 0xc3, 0x02, 0x96, 0x10, 0x33, 0x18, 0x08, 0x1e, 0xe7,
+ 0xff, 0x9f, 0xd0, 0x61, 0xb9, 0x0a, 0xdf, 0xdc, 0x83, 0x85,
+ 0x61, 0x38, 0x61, 0x69, 0x24, 0x12, 0x7f, 0xf0, 0x3a, 0x73,
+ 0x03, 0x09, 0x87, 0x7c, 0x30, 0xb8, 0x58, 0x9c, 0x18, 0x30,
+ 0x05, 0xd0, 0x4c, 0xff, 0xcb, 0xe3, 0x86, 0x14, 0x5a, 0xc3,
+ 0x0b, 0x8a, 0xd7, 0x05, 0x15, 0x06, 0x0a, 0x00, 0x50, 0x78,
+ 0x93, 0xff, 0x7f, 0xc6, 0xc5, 0x97, 0xf0, 0x97, 0x18, 0x70,
+ 0x71, 0x8c, 0x14, 0x58, 0x03, 0xb4, 0x61, 0xa0, 0x7f, 0xef,
+ 0xae, 0x18, 0x29, 0x84, 0xee, 0xbf, 0x88, 0xa0, 0x33, 0x0e,
+ 0x11, 0x41, 0xfc, 0xff, 0xf1, 0xa8, 0xda, 0x1c, 0xa1, 0x81,
+ 0x05, 0x8a, 0x9f, 0xf1, 0x2c, 0x30, 0x55, 0x18, 0x40, 0xc2,
+ 0x7d, 0x8b, 0xf7, 0x8a, 0x80, 0x42, 0x58, 0x94, 0x30, 0x51,
+ 0x1c, 0x00, 0x83, 0x08, 0x4b, 0x3e, 0x1c, 0x1b, 0xe2, 0xb0,
+ 0x4b, 0x06, 0x03, 0x32, 0xa8, 0xc0, 0xc6, 0x08, 0xb5, 0x6c,
+ 0x02, 0xa6, 0x00, 0x22, 0xa0, 0xd8, 0x53, 0x1a, 0x0c, 0x0d,
+ 0x78, 0x97, 0x8c, 0x1c, 0x60, 0xa2, 0x5e, 0xc3, 0x21, 0x86,
+ 0x8c, 0x0c, 0x55, 0x41, 0x28, 0x46, 0x1b, 0x82, 0x35, 0x85,
+ 0x4e, 0x03, 0xc1, 0x62, 0x31, 0x8b, 0x83, 0x0b, 0x18, 0x54,
+ 0x30, 0xbc, 0x1c, 0x38, 0x13, 0x02, 0x08, 0x03, 0x18, 0x08,
+ 0x86, 0x1a, 0x36, 0x09, 0x33, 0x15, 0x1d, 0x00, 0x0b, 0xf0,
+ 0xc1, 0x60, 0x2c, 0x0c, 0x58, 0x13, 0x01, 0xc6, 0x0e, 0xa2,
+ 0xc7, 0x87, 0x0b, 0x3e, 0x16, 0x40, 0x22, 0x88, 0xb8, 0x27,
+ 0x11, 0x07, 0x07, 0x04, 0xf4, 0xfb, 0x84, 0x30, 0x8e, 0x08,
+ 0x30, 0xb2, 0x18, 0x08, 0xd8, 0x53, 0xf8, 0x8a, 0x5f, 0x15,
+ 0x86, 0x10, 0x1b, 0x54, 0x03, 0x11, 0x40, 0x3f, 0xe8, 0x30,
+ 0x84, 0x15, 0x02, 0xc4, 0x61, 0x44, 0x61, 0x62, 0xe1, 0x7f,
+ 0xba, 0x84, 0xe1, 0x03, 0x0b, 0x1a, 0x02, 0x2c, 0xcb, 0xfc,
+ 0x39, 0xc2, 0x4c, 0x26, 0x36, 0x18, 0x68, 0x19, 0x5d, 0x7f,
+ 0x49, 0x5c, 0x61, 0xc2, 0xd0, 0xa7, 0x42, 0xfe, 0xeb, 0x9a,
+ 0x01, 0x10, 0x10, 0x9c, 0x2b, 0x46, 0x00, 0x08, 0x91, 0x60,
+ 0x61, 0x5f, 0x1a, 0x0a, 0xce, 0x2c, 0x0b, 0x30, 0xc2, 0xff,
+ 0x41, 0x1f, 0xf8, 0xc0, 0x23, 0x03, 0x18, 0x69, 0x62, 0x58,
+ 0x0f, 0xe0, 0x43, 0x02, 0x11, 0x85, 0x21, 0x84, 0xf7, 0xff,
+ 0xb7, 0xc6, 0x14, 0x50, 0xc1, 0x0c, 0x66, 0xa1, 0x2e, 0xb0,
+ 0xc0, 0xa5, 0xd0, 0xcc, 0xc6, 0x15, 0xa8, 0xa5, 0xfc, 0x38,
+ 0x4b, 0x00, 0xe1, 0xc0, 0x25, 0xc4, 0x54, 0x09, 0x14, 0x50,
+ 0x4b, 0xd2, 0x25, 0xc5, 0x68, 0xac, 0x2a, 0x04, 0xe2, 0x90,
+ 0x27, 0xf1, 0x2f, 0xdc, 0x61, 0x67, 0xe2, 0x32, 0x0d, 0xc0,
+ 0x80, 0xe2, 0xb6, 0x2b, 0x0d, 0x8a, 0x18, 0x30, 0x51, 0x4a,
+ 0xbb, 0xff, 0xfc, 0x4e, 0xfc, 0x6a, 0xa2, 0xb0, 0x97, 0x0e,
+ 0x75, 0x0c, 0x21, 0x82, 0x06, 0x8b, 0x11, 0x86, 0x8c, 0x38,
+ 0x2c, 0x0c, 0x5a, 0x97, 0xff, 0x83, 0x17, 0x87, 0x20, 0x96,
+ 0x29, 0x05, 0x8a, 0xc6, 0x10, 0x2b, 0x38, 0x20, 0xc0, 0x06,
+ 0xc0, 0x82, 0xc0, 0xc8, 0x60, 0x4a, 0x1a, 0xd1, 0xaf, 0xff,
+ 0xb8, 0xc3, 0x38, 0x43, 0x04, 0x8a, 0x31, 0x81, 0x0a, 0x30,
+ 0x81, 0x86, 0x8c, 0x2c, 0x08, 0x5c, 0x18, 0x00, 0x0b, 0x82,
+ 0x84, 0x60, 0x0e, 0x07, 0xff, 0xf1, 0x2f, 0x0c, 0x13, 0x40,
+ 0x84, 0xe5, 0x41, 0x58, 0x1d, 0xf1, 0x90, 0x70, 0x94, 0x30,
+ 0xa6, 0x02, 0x82, 0x90, 0xb5, 0x81, 0xff, 0xfc, 0xf1, 0xbe,
+ 0x60, 0x4c, 0x18, 0x30, 0xe1, 0x84, 0x0a, 0x50, 0x21, 0x80,
+ 0x90, 0xb0, 0x2d, 0x30, 0xb4, 0x34, 0x04, 0x11, 0x6f, 0xff,
+ 0xf8, 0x5c, 0x61, 0x45, 0xe0, 0x40, 0x22, 0x30, 0xaa, 0x18,
+ 0x30, 0x41, 0x2c, 0x60, 0xc3, 0x09, 0x11, 0xe8, 0x42, 0x30,
+ 0x8e, 0x04, 0x0c, 0x2b, 0x7f, 0xfe, 0x80, 0x45, 0xf8, 0x8e,
+ 0x23, 0x0d, 0xc3, 0x81, 0x04, 0x51, 0x14, 0x0f, 0xe2, 0x1a, 0x10,
+ 0x07, 0xf2, 0x48, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x29, 0x96,
+ 0x00, 0x00, 0x00, 0x08, 0x00, 0x92, 0x03, 0x42, 0x1e, 0xc1,
+ 0x80, 0xba, 0x03, 0x54, 0x13, 0xe6, 0x88, 0xc0, 0xb6, 0x28,
+ 0x30, 0x39, 0x08, 0x01, 0x48, 0x53, 0x16, 0x03, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x4c, 0x07, 0x81, 0x00, 0x00,
+ 0x00, 0x50, 0x2b, 0x0a, 0x42, 0x50, 0x45, 0x85, 0x4e, 0x08,
+ 0x64, 0x0c, 0x58, 0x86, 0x30, 0x06, 0x06, 0x70, 0x24, 0x00,
+ 0x76, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x44, 0xb6, 0x1f, 0xe4, 0xb6, 0x31, 0x25, 0x43, 0xb1, 0x87,
+ 0xc1, 0x11, 0x86, 0xa1, 0x10, 0xe4, 0x3d, 0x5e, 0x1c, 0x42,
+ 0xe9, 0x64, 0xb9, 0x6b, 0x80, 0x29, 0x85, 0xdb, 0xc3, 0x4c,
+ 0x52, 0xb0, 0x84, 0x86, 0x88, 0x0c, 0x00, 0x02, 0x43, 0xb3,
+ 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x83, 0x00, 0x00,
+ 0x0a, 0x26, 0x8a, 0x1e, 0x82, 0x98, 0x07, 0x01, 0x51, 0x85,
+ 0x80, 0x42, 0x11, 0x8f, 0xd2, 0x30, 0xbf, 0x0a, 0x09, 0xcb,
+ 0x45, 0x10, 0x98, 0x78, 0x18, 0xe0, 0xf8, 0xf4, 0x2d, 0x01,
+ 0x80, 0xc0, 0x60, 0x30, 0xb8, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x01, 0xd8, 0x24, 0x00, 0x14, 0x87, 0xe0, 0x11, 0x01, 0xc1,
+ 0x2a, 0x07, 0x07, 0x01, 0x81, 0xa1, 0x9e, 0x74, 0x38, 0x1c,
+ 0x0e, 0x04, 0x2c, 0x21, 0x84, 0x02, 0xd4, 0x31, 0x00, 0xa8,
+ 0x82, 0x36, 0x30, 0xc8, 0xe4, 0x0c, 0x32, 0xbb, 0x8a, 0xb7,
+ 0x00, 0x98, 0x08, 0x2e, 0x61, 0xec, 0x00, 0x4a, 0x60, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0xbf, 0xf8, 0x04, 0x03, 0x40, 0x00,
+ 0x45, 0xe9, 0x40, 0x40, 0xd2, 0x0a, 0x84, 0x78, 0xf4, 0x66,
+ 0xf8, 0x4a, 0x92, 0x82, 0x4c, 0xc9, 0xd0, 0x12, 0xb4, 0x68,
+ 0x83, 0x27, 0xb0, 0x36, 0x02, 0x80, 0x98, 0x09, 0x84, 0xe1,
+ 0x60, 0x0c, 0x0d, 0x03, 0x74, 0x0b, 0x86, 0x40, 0x1e, 0x89,
+ 0xf0, 0x1f, 0x81, 0x4e, 0x00, 0x2b, 0xf0, 0x04, 0x80, 0x00,
+ 0x00, 0x00, 0x00, 0x03, 0x78, 0x00, 0x00, 0x09, 0x96, 0x24,
+ 0x09, 0x0d, 0x14, 0x03, 0x87, 0x80, 0xe8, 0x54, 0x09, 0x0f,
+ 0xf4, 0x09, 0x33, 0x9e, 0xd0, 0x4e, 0x0c, 0x31, 0x80, 0x41,
+ 0x84, 0x98, 0xe3, 0xc1, 0x88, 0x27, 0xa0, 0xd2, 0x0a, 0x90,
+ 0x66, 0x4b, 0x0d, 0xc0, 0xac, 0x61, 0x97, 0x9c, 0x12, 0x1b,
+ 0xec, 0x51, 0x5c, 0x48, 0xa2, 0x9e, 0x1d, 0x03, 0x12, 0x03,
+ 0x0c, 0xe4, 0x53, 0xb2, 0x80, 0x1c, 0xe2, 0xc2, 0xc0, 0x00,
+ 0x00, 0x00, 0x00, 0x05, 0x60, 0x01, 0x57, 0x04, 0x86, 0x48,
+ 0x04, 0xf9, 0x01, 0x20, 0x2e, 0x15, 0x94, 0x01, 0x0e, 0xf2,
+ 0x9f, 0x40, 0x51, 0x6c, 0x0d, 0x06, 0x24, 0x50, 0x48, 0x00,
+ 0x83, 0x65, 0x05, 0x67, 0x25, 0x36, 0x7a, 0x26, 0x83, 0xd1,
+ 0x9e, 0xc2, 0x7f, 0x40, 0xd0, 0x2a, 0x14, 0x26, 0xb8, 0xac,
+ 0x64, 0x86, 0xd8, 0x47, 0x84, 0x89, 0x4e, 0x79, 0xc8, 0x21,
+ 0x4c, 0x24, 0x17, 0xa6, 0x6a, 0x51, 0x32, 0x6b, 0x93, 0x20,
+ 0xa1, 0x72, 0x65, 0x97, 0x77, 0x03, 0x18, 0x88, 0x41, 0xe0,
+ 0x88, 0x40, 0x21, 0x4e, 0xb6, 0x05, 0x60, 0x02, 0x40, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x78, 0x8f, 0x03, 0x44, 0xc0,
+ 0x23, 0x20, 0x06, 0x88, 0x32, 0x16, 0x19, 0xc2, 0xc9, 0x79,
+ 0xf4, 0xd9, 0x3d, 0x32, 0x22, 0xc9, 0x4e, 0x41, 0x80, 0x4c,
+ 0x34, 0x0b, 0x31, 0x82, 0x19, 0x80, 0x93, 0x3c, 0xf2, 0x04,
+ 0xa4, 0x39, 0x21, 0x8c, 0xd6, 0x12, 0x40, 0x80, 0x84, 0x1a,
+ 0x6e, 0xe3, 0x09, 0xe8, 0x4c, 0x1a, 0x00, 0xe0, 0x49, 0xa8,
+ 0x02, 0xb2, 0x31, 0x06, 0x60, 0xf8, 0x28, 0x11, 0x68, 0x24,
+ 0x14, 0x82, 0xfc, 0x82, 0xf9, 0x82, 0x07, 0x48, 0xab, 0x25,
+ 0xca, 0x0e, 0x44, 0x6a, 0x28, 0x24, 0x28, 0x54, 0x1a, 0x80,
+ 0x44, 0x46, 0x80, 0xa4, 0x63, 0x2e, 0x02, 0x90, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x21, 0xbf, 0xc1, 0xa0, 0x78, 0x2c,
+ 0xc5, 0xde, 0x80, 0xc0, 0x4c, 0x22, 0x22, 0x53, 0x01, 0xc8,
+ 0x38, 0x18, 0x42, 0xbb, 0x05, 0xb3, 0x26, 0xc0, 0xf6, 0x4b,
+ 0x01, 0xd0, 0x12, 0x01, 0xac, 0x0f, 0x18, 0x73, 0x6d, 0x2c,
+ 0x8c, 0x85, 0x28, 0x4c, 0x90, 0x80, 0x10, 0x82, 0x5d, 0x50,
+ 0x13, 0xd6, 0x34, 0xc8, 0x08, 0x4b, 0x09, 0x86, 0x64, 0x06,
+ 0xb3, 0xdd, 0xa6, 0x4b, 0xd2, 0x6c, 0x97, 0x27, 0xf0, 0x8d,
+ 0x45, 0xd1, 0x81, 0xc2, 0x0c, 0x2e, 0x44, 0x98, 0xe1, 0x26,
+ 0xbd, 0xaa, 0x12, 0x6b, 0xfb, 0x80, 0x90, 0xdc, 0x42, 0x16,
+ 0xdf, 0xd4, 0xd4, 0x08, 0x5c, 0xa3, 0x75, 0xbc, 0x82, 0x09,
+ 0x83, 0x01, 0x81, 0x70, 0xbb, 0x30, 0xb4, 0x41, 0x4c, 0x68,
+ 0x30, 0x29, 0x02, 0x82, 0x1f, 0x0c, 0x71, 0x40, 0x00, 0x00,
+ 0x00, 0x00, 0x07, 0x83, 0x80, 0x18, 0x06, 0x10, 0x47, 0x43,
+ 0xb0, 0x48, 0x81, 0xa0, 0x13, 0x6d, 0x9c, 0x84, 0xc5, 0xd9,
+ 0x85, 0x6e, 0x15, 0x79, 0x5c, 0xc5, 0x32, 0xf8, 0x51, 0x31,
+ 0x96, 0x2e, 0x00, 0x01, 0x05, 0xc0, 0x92, 0x89, 0x08, 0x60,
+ 0x9b, 0x32, 0x58, 0x25, 0xad, 0xc0, 0x8a, 0x18, 0x66, 0x43,
+ 0x58, 0x51, 0xb0, 0x11, 0x08, 0x94, 0x01, 0x22, 0x5b, 0xe0,
+ 0x4c, 0x84, 0x14, 0x80, 0x4a, 0x9c, 0x02, 0x8a, 0x00, 0x38,
+ 0xe1, 0xf5, 0x3b, 0x20, 0x21, 0x28, 0x1e, 0x0b, 0xd8, 0x80,
+ 0x81, 0x8a, 0x89, 0x64, 0xb1, 0x2f, 0xe3, 0x30, 0x2d, 0xd4,
+ 0x20, 0x08, 0x43, 0xf1, 0x19, 0x0a, 0x85, 0x9e, 0xb2, 0xd0,
+ 0x00, 0x54, 0x56, 0x50, 0x2c, 0x04, 0x80, 0xee, 0x0e, 0x8a,
+ 0x54, 0x29, 0x10, 0xa5, 0x82, 0xfb, 0x82, 0xc3, 0x80, 0x10,
+ 0x04, 0x00, 0x00, 0x00, 0x00, 0x01, 0x37, 0xf0, 0x00, 0x01,
+ 0xeb, 0x59, 0x3d, 0x83, 0x21, 0x41, 0xf6, 0xdd, 0x22, 0xc9,
+ 0x72, 0x6c, 0x8a, 0xc1, 0x04, 0x9a, 0x5b, 0x94, 0x12, 0x1e,
+ 0x5a, 0x09, 0x11, 0x2c, 0x0a, 0x2d, 0x05, 0x6b, 0x57, 0x64,
+ 0xcc, 0x34, 0x47, 0x00, 0x88, 0x2a, 0xa0, 0x7a, 0x41, 0x8b,
+ 0xb2, 0x88, 0x20, 0x9b, 0xf0, 0x24, 0x40, 0x46, 0x09, 0x54,
+ 0xe0, 0x68, 0x27, 0xf0, 0x09, 0x68, 0x80, 0xb4, 0x23, 0x53,
+ 0x38, 0x84, 0x1f, 0x02, 0x6d, 0x62, 0x05, 0x78, 0x49, 0x98,
+ 0x0e, 0x18, 0xc6, 0x43, 0x20, 0x21, 0x02, 0x0a, 0x44, 0x64,
+ 0x1c, 0x1d, 0x04, 0xa0, 0xc8, 0x07, 0x07, 0xe1, 0x28, 0xa6,
+ 0x6c, 0x37, 0xc5, 0x51, 0x86, 0xdd, 0x00, 0xbd, 0x00, 0x00,
+ 0x00, 0x00, 0x01, 0x2b, 0x80, 0x01, 0xb3, 0x13, 0xe8, 0x76,
+ 0x09, 0xea, 0x04, 0x23, 0x0b, 0x21, 0x01, 0x02, 0x18, 0x07,
+ 0x00, 0x8c, 0xd2, 0x0d, 0x64, 0xc8, 0x1b, 0x09, 0x30, 0x48,
+ 0xa5, 0x97, 0x0d, 0x20, 0xa0, 0x91, 0x27, 0x08, 0x32, 0x41,
+ 0x56, 0x04, 0x99, 0xcf, 0x20, 0x4a, 0x09, 0xb8, 0x86, 0x49,
+ 0x19, 0xc0, 0x48, 0xd4, 0xf3, 0x82, 0xae, 0x38, 0x63, 0x04,
+ 0x26, 0x16, 0x1e, 0x30, 0xd7, 0x4c, 0x80, 0x12, 0x50, 0xfd,
+ 0x92, 0xe2, 0x03, 0x9f, 0x40, 0x2b, 0x67, 0x38, 0x16, 0x17,
+ 0x4f, 0xf9, 0x76, 0xaf, 0x09, 0x8b, 0xb9, 0x84, 0x00, 0x02,
+ 0x8f, 0x2c, 0x00, 0x5d, 0x03, 0x50, 0x00, 0x42, 0x13, 0x06,
+ 0x60, 0x96, 0xc3, 0xd0, 0x00, 0x3c, 0x10, 0xc0, 0x4e, 0x02,
+ 0x00, 0x04, 0xe0, 0xf0, 0x23, 0x60, 0x00, 0x00, 0x00, 0x00,
+ 0x24, 0x1b, 0xe0, 0x00, 0x04, 0x02, 0xe9, 0x4c, 0x97, 0x26,
+ 0x40, 0x70, 0x24, 0x3b, 0x50, 0xb6, 0x40, 0x54, 0x41, 0x26,
+ 0x79, 0xa4, 0x94, 0xbc, 0xc5, 0x97, 0x18, 0x61, 0x88, 0x2e,
+ 0x70, 0x22, 0x62, 0x3c, 0x02, 0x05, 0x80, 0x90, 0xea, 0x06,
+ 0x68, 0xf4, 0xb2, 0x66, 0x06, 0x09, 0x33, 0x07, 0x54, 0x83,
+ 0x64, 0xcc, 0x28, 0xc1, 0x60, 0xba, 0x08, 0x8d, 0x1a, 0xf1,
+ 0xa0, 0x84, 0x85, 0x81, 0x94, 0x23, 0x06, 0x2f, 0x22, 0xb2,
+};
+
+static guint8 bframe2_adv[] = {
+ 0x46, 0x88, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x03, 0xf8, 0xa1, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+ 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
+};
+
+static guint8 pframe_adv[] = {
+ 0x24, 0x20, 0x04, 0xbf, 0x85, 0x88, 0x65, 0xc1, 0x00, 0xdc,
+ 0x4c, 0x06, 0xce, 0x05, 0x01, 0x01, 0x41, 0x0c, 0x60, 0x42,
+ 0x67, 0xff, 0xfb, 0x85, 0x0b, 0x9c, 0x56, 0x0d, 0x0b, 0x1b,
+ 0x8c, 0x08, 0x08, 0x47, 0x1b, 0xce, 0xc1, 0x83, 0x09, 0x8a,
+ 0xa1, 0x83, 0x09, 0x16, 0x7f, 0xff, 0x98, 0x94, 0xff, 0x81,
+ 0x4f, 0xf9, 0x41, 0xe1, 0x83, 0x01, 0xff, 0xff, 0x14, 0x40,
+ 0xcd, 0x70, 0xd7, 0xf2, 0xf7, 0xc1, 0xf1, 0x18, 0x59, 0xff,
+ 0xfc, 0x51, 0x18, 0x68, 0x2c, 0xd4, 0x54, 0x16, 0xbf, 0xfe,
+ 0x0c, 0xf1, 0x81, 0x28, 0x67, 0xff, 0x86, 0x39, 0x05, 0xe6,
+ 0x5f, 0xff, 0xe0, 0x48, 0xc0, 0xff, 0xfe, 0x61, 0x18, 0x37,
+ 0xff, 0x97, 0xdc, 0x1c, 0x45, 0x06, 0x06, 0xff, 0xf0, 0x30,
+ 0x7d, 0x17, 0xff, 0xff, 0x86, 0x07, 0x03, 0xff, 0xf9, 0x01,
+ 0xf0, 0x7f, 0xff, 0xdf, 0xc1, 0x20, 0x9f, 0xfd, 0x0c, 0x0f,
+ 0x86, 0x7f, 0xff, 0xee, 0x50, 0xef, 0xfe, 0xc1, 0xa5, 0xc6,
+ 0x1b, 0xff, 0xff, 0x86, 0x61, 0x9f, 0xfc, 0x1c, 0x1f, 0xa2,
+ 0xff, 0xff, 0xe0, 0xf8, 0x10, 0x1f, 0xfe, 0x0e, 0x0f, 0x99,
+ 0x95, 0xff, 0xff, 0xb8, 0x3e, 0xe5, 0xff, 0x81, 0x83, 0xe1,
+ 0x6b, 0xff, 0xff, 0x40, 0xc0, 0x7c, 0x30, 0xbf, 0xe0, 0xb2,
+ 0x0e, 0x09, 0x61, 0x53, 0xff, 0xfd, 0x60, 0x20, 0xfc, 0x27,
+ 0xf0, 0x96, 0x51, 0x26, 0x6c, 0xcf, 0xff, 0xff, 0xe7, 0x60,
+ 0xe0, 0xb5, 0xee, 0x82, 0xa0, 0xb8, 0x41, 0x32, 0x3f, 0x2f,
+ 0xcd, 0x3f, 0xa0, 0xa8, 0x96, 0x8e, 0x2a, 0x4c, 0x08, 0x6e,
+ 0x36, 0x1a, 0x83, 0x2a, 0x8b, 0x02, 0xcb, 0x2f, 0xff, 0xe9,
+ 0xf8, 0xa4, 0x0e, 0x00, 0x12, 0xc1, 0x88, 0xc3, 0x0c, 0x05,
+ 0x51, 0x44, 0x61, 0xa3, 0x0b, 0x18, 0x58, 0x38, 0x70, 0x97,
+ 0xff, 0xff, 0xf8, 0x8c, 0x14, 0x2c, 0x0c, 0x19, 0x86, 0x0c,
+ 0x27, 0x09, 0xc1, 0x03, 0x08, 0x62, 0xc0, 0xff, 0xff, 0xfe,
+ 0x94, 0x6d, 0x22, 0x77, 0xc0, 0x44, 0x71, 0x1c, 0x60, 0xe5,
+ 0xb7, 0xff, 0xfe, 0xbf, 0xba, 0x57, 0x82, 0x0c, 0x24, 0xc8,
+ 0x5a, 0xbf, 0xff, 0xff, 0xcb, 0x14, 0xc8, 0x30, 0x43, 0x16,
+ 0x29, 0x51, 0x86, 0x0b, 0x00, 0x51, 0x60, 0x60, 0xc0, 0x17,
+ 0x75, 0xff, 0xf9, 0x77, 0x0e, 0x18, 0x4b, 0x84, 0xc5, 0x47,
+ 0x11, 0xc5, 0x10, 0x68, 0x1b, 0x8c, 0x00, 0x6a, 0x71, 0x60,
+ 0xc0, 0x46, 0xe2, 0xe0, 0x22, 0x65, 0xff, 0xd6, 0x09, 0x0e,
+ 0x01, 0x15, 0x55, 0x85, 0x48, 0x28, 0x8f, 0xc2, 0x42, 0x06,
+ 0x1c, 0x23, 0x8b, 0x01, 0x42, 0x74, 0x08, 0x61, 0x9f, 0xff,
+ 0xc2, 0xca, 0x19, 0x81, 0x02, 0x10, 0x20, 0xc0, 0x1c, 0x5c,
+ 0x13, 0x84, 0xe6, 0x1a, 0x8b, 0x02, 0x38, 0x98, 0x09, 0x98,
+ 0xa3, 0xff, 0xfd, 0xc9, 0x05, 0x5e, 0x82, 0x18, 0xc1, 0x40,
+ 0xc6, 0xf6, 0x04, 0x14, 0x40, 0x60, 0x80, 0xfd, 0x04, 0x6f,
+ 0xff, 0xf4, 0x58, 0x0a, 0xf8, 0x86, 0x30, 0x02, 0x14, 0x44,
+ 0xe2, 0xc2, 0x43, 0x3c, 0x1b, 0xff, 0x86, 0xb5, 0x66, 0x16,
+ 0xf0, 0x7f, 0xa0, 0x9c, 0x5e, 0x84, 0x07, 0xd1, 0x73, 0xff,
+ 0xee, 0x88, 0xc2, 0xe1, 0x7f, 0xfc, 0xc0, 0xf0, 0x59, 0x65,
+ 0xfe, 0x9f, 0x70, 0xbf, 0xff, 0xdc, 0x1e, 0x2a, 0x02, 0x57,
+ 0xff, 0xc0, 0x26, 0x2d, 0x3c, 0x4d, 0x5f, 0xff, 0xc4, 0xc1,
+ 0x30, 0x11, 0x15, 0xc4, 0xaf, 0xfc, 0x5c, 0x0e, 0x0e, 0x0e,
+ 0x84, 0x8c, 0x34, 0x34, 0xbf, 0xff, 0x11, 0x81, 0x30, 0x10,
+ 0x48, 0x87, 0xf9, 0x43, 0x05, 0x25, 0x04, 0x11, 0x43, 0x70,
+ 0x4f, 0xff, 0xfd, 0x04, 0xe1, 0x0e, 0xfe, 0x6f, 0x83, 0x88,
+ 0xe1, 0x98, 0x76, 0x0f, 0xfc, 0x89, 0x0e, 0xe7, 0xc2, 0x78,
+ 0x4c, 0x24, 0xd4, 0x18, 0x8c, 0xbf, 0x27, 0x16, 0xd0, 0xb0,
+ 0xc9, 0xf4, 0x12, 0x6a, 0x08, 0xe4, 0x5c, 0x24, 0xbf, 0x46,
+ 0x60, 0xf6, 0x53, 0xf5, 0x6c, 0xff, 0x2e, 0x32, 0x09, 0x1e,
+ 0xab, 0x09, 0x00, 0x1e, 0x88, 0x56, 0x6e, 0x7a, 0x1c, 0xd0,
+ 0x30, 0x3c, 0xab, 0xf0, 0x44, 0x5a, 0x90, 0x4f, 0x9a, 0xf0,
+ 0xe6, 0x7d, 0x62, 0xc1, 0x87, 0x4b, 0xdb, 0xfd, 0x68, 0xd9,
+ 0x35, 0x3b, 0x01, 0x04, 0x81, 0x2c, 0x24, 0xee, 0xb3, 0x9b,
+ 0x65, 0x30, 0x49, 0x20, 0xa8, 0x08, 0xf6, 0xaf, 0x33, 0x80,
+ 0x38, 0x49, 0xa3, 0x94, 0x6e, 0x35, 0x06, 0x4d, 0xc3, 0x30,
+ 0x92, 0x7c, 0x3c, 0x6b, 0x9e, 0xd5, 0x31, 0x4d, 0x69, 0x87,
+ 0x2e, 0x04, 0x7e, 0x04, 0x12, 0x5f, 0xa3, 0x0a, 0xe4, 0x5b,
+ 0x21, 0x6c, 0x45, 0x54, 0x29, 0x11, 0x48, 0x8a, 0xa8, 0x52,
+ 0x22, 0xa8, 0x33, 0x06, 0xe0, 0xbd, 0xe8, 0x41, 0x00, 0x03,
+ 0x52, 0xe7, 0x00, 0x7d, 0xf0, 0x42, 0x4d, 0x0f, 0x20, 0x26,
+ 0x24, 0x09, 0xbb, 0x48, 0x1c, 0xeb, 0xa5, 0xa2, 0x0e, 0xed,
+ 0x11, 0x66, 0x97, 0x93, 0xb8, 0x4a, 0x70, 0x8a, 0x75, 0x38,
+ 0x47, 0xc1, 0x26, 0x3e, 0x50, 0x87, 0x33, 0xf2, 0x37, 0xc7,
+ 0x3b, 0x67, 0x09, 0x33, 0x44, 0xfc, 0xcd, 0xda, 0x19, 0xa6,
+ 0x3f, 0x27, 0xec, 0x24, 0x12, 0x64, 0x06, 0x13, 0xdd, 0x9e,
+ 0x81, 0x92, 0x17, 0x5f, 0xb3, 0xd9, 0x37, 0xf2, 0x0f, 0x15,
+ 0x00, 0x87, 0xb3, 0xe6, 0xc9, 0xc1, 0xbc, 0x24, 0x7f, 0x0f,
+ 0x7c, 0x76, 0x4c, 0xe0, 0xfb, 0xf7, 0x66, 0x4c, 0x9c, 0x19,
+ 0x32, 0x6f, 0xb2, 0x64, 0xfa, 0x00, 0x01, 0x26, 0xaa, 0xa4,
+ 0x16, 0x45, 0x1f, 0x94, 0xee, 0xde, 0x33, 0x09, 0x2e, 0x48,
+ 0xc2, 0x4b, 0xf4, 0x62, 0x91, 0x16, 0x00, 0x52, 0x20, 0xe2,
+ 0xba, 0xe2, 0x35, 0x42, 0xa7, 0xa0, 0x9c, 0x9e, 0xcc, 0x39,
+ 0x9d, 0x31, 0x00, 0xc3, 0xe0, 0x2a, 0x1f, 0x85, 0x61, 0xd3,
+ 0x63, 0x3f, 0x22, 0xa8, 0xd9, 0xc1, 0x50, 0x50, 0x2f, 0x21,
+ 0xb1, 0xd8, 0x49, 0x34, 0xa0, 0xb0, 0x0c, 0x7d, 0xe9, 0x53,
+ 0x27, 0x09, 0xf9, 0x1b, 0x33, 0x5d, 0x93, 0xb8, 0x48, 0x89,
+ 0xbb, 0x18, 0x4e, 0xf0, 0x44, 0x86, 0x13, 0x7a, 0x16, 0xc4,
+ 0x36, 0xc7, 0x24, 0xe2, 0x39, 0x20, 0x20, 0x62, 0xb0, 0xf1,
+ 0xa0, 0x21, 0xc7, 0x2a, 0xdf, 0xd6, 0xd1, 0x5e, 0xcf, 0xba,
+ 0x09, 0x92, 0xa4, 0xb7, 0xd6, 0x7b, 0x0b, 0xaa, 0x60, 0xe7,
+ 0x8c, 0xe2, 0xfb, 0xf8, 0xb1, 0x96, 0x70, 0xc5, 0xf7, 0x3d,
+ 0x7a, 0xce, 0x13, 0x09, 0x0f, 0xd4, 0x2c, 0xfe, 0x30, 0xdd,
+ 0xdc, 0x11, 0xb1, 0x4e, 0xab, 0x98, 0x0d, 0x45, 0xf0, 0x41,
+ 0x9d, 0x0c, 0xd6, 0xa1, 0x8e, 0x5c, 0xf4, 0xdf, 0x93, 0x88,
+ 0x3f, 0x23, 0x61, 0x23, 0x6e, 0xf4, 0x78, 0xac, 0xfa, 0x00,
+ 0x00, 0x07, 0x1f, 0x94, 0xe9, 0x13, 0xd3, 0x05, 0x61, 0x99,
+ 0x22, 0x49, 0xf8, 0x6d, 0xb9, 0xb3, 0x83, 0xa6, 0x70, 0x78,
+ 0xf3, 0x37, 0x54, 0xdf, 0xb6, 0x82, 0x67, 0x07, 0x3d, 0x66,
+ 0xea, 0x86, 0x72, 0xd3, 0x38, 0x3b, 0x0a, 0xcd, 0xd5, 0x0e,
+ 0x00, 0x07, 0x19, 0x6d, 0x92, 0x77, 0x3e, 0x0d, 0xba, 0x66,
+ 0xa6, 0x8c, 0x8d, 0x48, 0xf2, 0xe2, 0x38, 0x31, 0x7f, 0x71,
+ 0xf9, 0xe8, 0x6c, 0x46, 0xb1, 0x91, 0xc5, 0x6a, 0xbb, 0x16,
+ 0x36, 0x44, 0xb3, 0x67, 0x64, 0xcf, 0xee, 0xcc, 0x04, 0x61,
+ 0x7b, 0x91, 0x7e, 0xcd, 0x47, 0x27, 0x16, 0x0f, 0x04, 0x8f,
+ 0x02, 0x84, 0x8f, 0x85, 0xb5, 0xb3, 0x5a, 0x81, 0x23, 0xa8,
+};
+
+static guint8 pframe2_adv[] = {
+ 0x1c, 0x22, 0x1f, 0xdc, 0x9d, 0x3b, 0x81, 0x61, 0x85, 0x2,
+ 0x57, 0xa0, 0x50, 0xac, 0x03, 0x81, 0x0c, 0x39, 0x4f, 0xff,
+ 0xc2, 0x20, 0x9f, 0xf4, 0x86, 0x16, 0x8e, 0xe1, 0xda, 0x0c,
+ 0x24, 0x4b, 0x3f, 0xff, 0x03, 0x77, 0xfe, 0x05, 0x10, 0xc5,
+ 0x81, 0x3a, 0x50, 0x71, 0x4c, 0x56, 0x10, 0xfa, 0x06, 0x82,
+ 0xaf, 0xfe, 0x19, 0x49, 0x17, 0xb6, 0x42, 0xad, 0xf0, 0xe8,
+ 0x6f, 0xc0, 0x97, 0xff, 0x83, 0xd0, 0xce, 0x15, 0x16, 0x85,
+ 0xa6, 0x77, 0x09, 0xb3, 0xe1, 0x88, 0x30, 0xd0, 0x0f, 0x18,
+ 0x60, 0x40, 0x5f, 0xfe, 0x07, 0x6f, 0x6c, 0x18, 0x09, 0xdf,
+ 0xc3, 0x00, 0xee, 0x98, 0x39, 0x8b, 0x40, 0xff, 0xf8, 0x64,
+ 0xfb, 0xae, 0xae, 0x25, 0xc1, 0x61, 0xa1, 0xa1, 0x63, 0x06,
+ 0xba, 0xb8, 0x9a, 0x00, 0xe6, 0x40, 0x75, 0xff, 0x08, 0xfc,
+ 0xa2, 0x88, 0xa2, 0xf7, 0xd4, 0x47, 0xe2, 0x8b, 0x20, 0x11,
+ 0x02, 0xe0, 0xc1, 0x80, 0xdf, 0xe0, 0xff, 0xe2, 0x18, 0xe0,
+ 0x40, 0x42, 0xe0, 0xc0, 0x82, 0x59, 0x49, 0x9c, 0x4c, 0x60,
+ 0x95, 0x86, 0x60, 0xff, 0xf8, 0x22, 0x7d, 0x21, 0xa1, 0x62,
+ 0x60, 0xc0, 0x06, 0x06, 0x30, 0x90, 0xa0, 0xc1, 0xbb, 0xa0,
+ 0x10, 0x8e, 0xcf, 0xca, 0x17, 0x4f, 0xf0, 0x34, 0xfb, 0x00,
+ 0x88, 0xe0, 0xa3, 0x07, 0x04, 0x18, 0x30, 0xe2, 0xc8, 0x50,
+ 0xb4, 0x14, 0xac, 0x12, 0x9d, 0x30, 0xcf, 0xfb, 0x97, 0xeb,
+ 0x42, 0x14, 0x83, 0x45, 0x30, 0x31, 0x70, 0x4d, 0x14, 0xc5,
+ 0x10, 0x51, 0x4c, 0x61, 0x21, 0x4f, 0xf8, 0x1d, 0x7f, 0x0c,
+ 0xf8, 0x30, 0x1e, 0xa3, 0x00, 0x08, 0x0b, 0x15, 0x46, 0x0a,
+ 0x0a, 0x26, 0x87, 0x02, 0x06, 0x0a, 0xa3, 0x0a, 0x54, 0x18,
+ 0x62, 0x80, 0x70, 0x3f, 0xf0, 0xcf, 0xe6, 0x0e, 0x1a, 0x82,
+ 0x34, 0x30, 0x59, 0x14, 0xc6, 0xa3, 0x04, 0x18, 0x70, 0xc1,
+ 0x82, 0xc6, 0x05, 0x21, 0x27, 0xe0, 0x7f, 0xe1, 0x8d, 0xae,
+ 0x91, 0x6a, 0x1c, 0x04, 0x30, 0x00, 0xc1, 0xba, 0x90, 0x59,
+ 0x89, 0xda, 0xd4, 0x61, 0x8b, 0xc1, 0xfe, 0xda, 0x8c, 0x30,
+ 0xa0, 0x3d, 0xa3, 0x06, 0x0d, 0x01, 0x85, 0x08, 0x6e, 0x16,
+ 0x04, 0x30, 0x01, 0x30, 0x51, 0x06, 0x15, 0x1a, 0x03, 0xe2,
+ 0xd5, 0xeb, 0xa1, 0x98, 0x2d, 0x02, 0x97, 0x77, 0x57, 0x16,
+ 0x05, 0x61, 0x14, 0x92, 0x32, 0x50, 0x01, 0x4c, 0x46, 0x18,
+ 0x40, 0x97, 0x9a, 0x0a, 0x97, 0x70, 0xaf, 0x84, 0x84, 0xbd,
+ 0x7a, 0x45, 0x60, 0xa1, 0x14, 0x47, 0x17, 0x06, 0x00, 0x30,
+ 0x29, 0x44, 0x51, 0x24, 0x60, 0x62, 0x30, 0x15, 0x08, 0x19,
+ 0xda, 0xa2, 0x32, 0x06, 0x81, 0xf0, 0x0c, 0x30, 0x43, 0xeb,
+ 0x00, 0x06, 0x40, 0x60, 0x40, 0xb0, 0xe1, 0x68, 0x34, 0x0c,
+ 0x04, 0x6e, 0x29, 0x08, 0xc3, 0x01, 0x1b, 0x06, 0xe0, 0x00,
+ 0x37, 0x55, 0x03, 0xdc, 0x0e, 0xea, 0x04, 0xb2, 0xda, 0x09,
+ 0x21, 0x54, 0x60, 0xa2, 0x5d, 0x86, 0x02, 0x22, 0x81, 0x80,
+ 0x0b, 0x44, 0x82, 0x3d, 0x04, 0x71, 0x4a, 0x10, 0x11, 0xfc,
+ 0x61, 0x04, 0xc0, 0x5b, 0x01, 0x00, 0x46, 0x12, 0x07, 0x11,
+ 0x83, 0x05, 0x31, 0x24, 0x4a, 0x0c, 0x09, 0x04, 0x15, 0x00,
+ 0xd0, 0xdc, 0x0f, 0xd3, 0xfd, 0xc5, 0x86, 0x38, 0x5f, 0x85,
+ 0xc0, 0x42, 0xc2, 0x48, 0x61, 0x20, 0x41, 0x62, 0x48, 0xb0,
+ 0x0a, 0x49, 0x60, 0xb8, 0x96, 0xef, 0xad, 0xba, 0x60, 0x23,
+ 0x88, 0xa2, 0x39, 0x60, 0xa8, 0x23, 0x86, 0x8d, 0x02, 0x81,
+ 0x86, 0x18, 0x30, 0x23, 0x13, 0x42, 0xa3, 0x5b, 0x38, 0x14,
+ 0x20, 0x5a, 0x18, 0x4a, 0xae, 0x68, 0x8d, 0x4a, 0x8c, 0x00,
+ 0x51, 0x0e, 0x63, 0x18, 0x10, 0x9a, 0x0c, 0x70, 0x41, 0x38,
+ 0x46, 0x21, 0x18, 0x25, 0x00, 0x50, 0x95, 0xb8, 0x38, 0x75,
+ 0xe1, 0xab, 0xe8, 0xa2, 0x3f, 0x18, 0x77, 0xb9, 0xc5, 0x81,
+ 0x86, 0x0b, 0x2a, 0x21, 0x8c, 0x08, 0x2e, 0x2a, 0x0a, 0xa4,
+ 0x10, 0xd8, 0x58, 0x3e, 0x80, 0x25, 0x09, 0xcf, 0x47, 0x16,
+ 0xb9, 0x8a, 0x8e, 0x26, 0x0a, 0x76, 0x51, 0x18, 0x80, 0x19,
+ 0xa8, 0x0c, 0x9e, 0x5f, 0x6f, 0xd8, 0x59, 0xf7, 0x05, 0x13,
+ 0x14, 0x53, 0x30, 0x40, 0xa5, 0x04, 0x55, 0xb1, 0x00, 0x55,
+ 0x74, 0xf9, 0x83, 0xd4, 0xf1, 0x37, 0xee, 0x16, 0x32, 0x12,
+ 0xf4, 0x14, 0xc8, 0x4b, 0x30, 0xd4, 0x02, 0x92, 0x80, 0x61,
+ 0x02, 0x88, 0x94, 0xbf, 0xf8, 0x18, 0xc3, 0x97, 0xe5, 0x58,
+ 0xa8, 0x35, 0x98, 0x1a, 0xc1, 0x41, 0xd4, 0x19, 0xc6, 0x18,
+ 0x48, 0xb0, 0xbf, 0xfc, 0x1c, 0x56, 0x6e, 0x13, 0xcc, 0x04,
+ 0x4b, 0x07, 0x27, 0x55, 0x2f, 0x7d, 0x44, 0x61, 0x65, 0x3f,
+ 0xf0, 0xc0, 0xc0, 0xab, 0x89, 0x83, 0x0d, 0x67, 0x16, 0x00,
+ 0xc8, 0xa1, 0x84, 0x41, 0x95, 0x33, 0xb8, 0x2e, 0x18, 0x25,
+ 0xff, 0xf8, 0x18, 0x96, 0xa2, 0xc0, 0x18, 0x58, 0x06, 0x3a,
+ 0xbf, 0xc1, 0x96, 0xed, 0x10, 0xc4, 0x98, 0xc0, 0x46, 0x13,
+ 0xff, 0xe1, 0x63, 0x03, 0x17, 0x01, 0x6e, 0x74, 0x06, 0x70,
+ 0x2a, 0x6a, 0xb3, 0x74, 0x07, 0x61, 0x58, 0x2c, 0x2d, 0xbf,
+ 0xfd, 0x01, 0x42, 0x30, 0x85, 0xfb, 0xc6, 0x1a, 0x0a, 0x14,
+ 0x2c, 0x5c, 0x08, 0xbc, 0x43, 0x2f, 0xc2, 0x5f, 0x72, 0x8b,
+ 0x9c, 0x32, 0x06, 0x0a, 0x27, 0x03, 0x50, 0x61, 0x5f, 0x41,
+ 0x4e, 0x19, 0x83, 0xff, 0xfb, 0x42, 0x3e, 0x6e, 0x34, 0x12,
+ 0x7f, 0x75, 0x18, 0x04, 0x1f, 0x06, 0x86, 0x7f, 0xf9, 0x44,
+ 0x97, 0xee, 0x0d, 0xe9, 0xf2, 0x38, 0x3e, 0xf8, 0x37, 0xfe,
+ 0x98, 0x1c, 0xd6, 0x30, 0x11, 0x2f, 0xff, 0xe0, 0x76, 0x50,
+ 0x38, 0x5f, 0xfe, 0x70, 0xc4, 0x29, 0x0b, 0x82, 0x2f, 0xff,
+ 0xe0, 0x62, 0x48, 0xc3, 0x85, 0x10, 0xa1, 0x69, 0x17, 0xfe,
+ 0x50, 0xc8, 0x5f, 0x4f, 0xff, 0xfc, 0x30, 0xa0, 0x7f, 0xe9,
+ 0x0c, 0x00, 0xc2, 0x7f, 0xff, 0xf9, 0x0a, 0x82, 0x56, 0x0d,
+ 0xfe, 0xd0, 0x8e, 0xff, 0xff, 0xfd, 0x04, 0x64, 0x58, 0x5f,
+ 0xfe, 0x0f, 0xdc, 0x5a, 0xff, 0xff, 0xe0, 0x9c, 0x33, 0xfd,
+ 0x60, 0x7c, 0x38, 0x0f, 0xff, 0xff, 0x81, 0xf8, 0x1f, 0xfc,
+ 0x0f, 0x82, 0x7f, 0xff, 0xe8, 0xe5, 0x3c, 0x0f, 0xf7, 0xc0,
+ 0xf8, 0xc3, 0x17, 0xff, 0xff, 0x13, 0x37, 0xc1, 0xbf, 0xe0,
+ 0x70, 0xcc, 0xbf, 0xff, 0xf1, 0x85, 0xfc, 0x1f, 0xfe, 0x07,
+ 0x83, 0x2f, 0xff, 0xff, 0x1b, 0x7c, 0x1f, 0xfd, 0x42, 0x94,
+ 0x36, 0x9f, 0xff, 0xfc, 0x1f, 0xe0, 0xfd, 0x99, 0x86, 0x02,
+ 0x1a, 0x29, 0x81, 0x21, 0x7f, 0xff, 0xfc, 0x83, 0x95, 0x85,
+ 0x11, 0x60, 0x60, 0x22, 0xc8, 0xd0, 0xc2, 0xc4, 0xb5, 0x83,
+ 0x95, 0x27, 0xa7, 0xff, 0xfc, 0x85, 0x85, 0xb4, 0x47, 0x24,
+ 0x18, 0x28, 0xaa, 0x1a, 0x23, 0x2a, 0x84, 0xdb, 0xff, 0xff,
+ 0xf2, 0x63, 0x92, 0xc4, 0xc0, 0x21, 0xc0, 0xc2, 0xc0, 0x00,
+ 0x82, 0xc6, 0x00, 0x28, 0x89, 0x72, 0xff, 0xff, 0xef, 0x16,
+ 0x05, 0x11, 0x1c, 0x61, 0x22, 0x38, 0x50, 0xb8, 0x2a, 0xbb,
+ 0x9c, 0xe7, 0xcf, 0xff, 0xff, 0xe6, 0x30, 0xce, 0x0f, 0xc0,
+ 0x04, 0x71, 0x1d, 0xff, 0xff, 0xff, 0xfb, 0xb7, 0x07, 0xe1,
+ 0x21, 0x82, 0xc0, 0x87, 0x6b, 0xb7, 0xff, 0xff, 0xf7, 0x0c,
+ 0x10, 0xc5, 0x85, 0x40, 0x96, 0x12, 0x58, 0xe1, 0xc1, 0x5d,
+ 0xff, 0xff, 0xfb, 0x89, 0xcb, 0x84, 0x30, 0x9c, 0x2a, 0xc5,
+ 0x41, 0x64, 0x5a, 0xee, 0x0d, 0x8a, 0x61, 0x4b, 0xff, 0xff,
+ 0x0c, 0xc0, 0x86, 0x10, 0x23, 0x8a, 0x42, 0xe3, 0x0a, 0xc0,
+ 0x23, 0x07, 0x14, 0x6e, 0x2c, 0x09, 0x4e, 0x2c, 0x05, 0x82,
+ 0x01, 0x02, 0x2f, 0xff, 0xf4, 0x07, 0xb0, 0x8d, 0x02, 0x09,
+ 0x14, 0x45, 0x81, 0x86, 0xb8, 0x10, 0xb0, 0x27, 0x00, 0x30,
+ 0xaa, 0x21, 0x85, 0x80, 0x5c, 0x56, 0x2f, 0xff, 0xf0, 0x7a,
+ 0x0c, 0x01, 0x68, 0x14, 0x08, 0x1a, 0x82, 0x3d, 0xc2, 0xc4,
+ 0xe0, 0x60, 0xc0, 0x0e, 0x30, 0x10, 0x6f, 0xff, 0xf4, 0x5b,
+ 0x8b, 0x3e, 0x30, 0x92, 0x70, 0xc1, 0x86, 0x80, 0x48, 0x33,
+ 0xc0, 0x82, 0xc5, 0x8f, 0xff, 0xf0, 0xb7, 0x88, 0xed, 0xf1,
+ 0x85, 0x80, 0x7c, 0x1b, 0xa0, 0x9d, 0xff, 0xfe, 0x51, 0x47,
+ 0x45, 0xff, 0x94, 0x2f, 0x0c, 0x15, 0x46, 0xff, 0xff, 0xd3,
+ 0x0c, 0x58, 0x67, 0xfe, 0x74, 0x57, 0x11, 0x80, 0xc6, 0x14,
+ 0xe2, 0xc0, 0xa9, 0xff, 0x9d, 0xd4, 0x34, 0x61, 0xc2, 0x5a,
+ 0x09, 0x7f, 0xfa, 0x60, 0xc0, 0x80, 0x8c, 0x6e, 0x62, 0x6a,
+ 0xff, 0xc4, 0x50, 0x3c, 0x86, 0x1a, 0x70, 0x3f, 0xfe, 0x0d,
+ 0x8b, 0x90, 0xc7, 0x04, 0x10, 0xd7, 0xfe, 0x10, 0x00, 0x28,
+ 0x82, 0x0b, 0x01, 0xc3, 0x0a, 0x84, 0x7f, 0xfb, 0xc2, 0x36,
+ 0x10, 0xf3, 0xf5, 0xe1, 0x64, 0x80, 0x88, 0x0e, 0x29, 0x94,
+ 0x1f, 0xf2, 0x49, 0xcf, 0xc9, 0xe4, 0xf3, 0xf2, 0x79, 0x3c,
+ 0xfc, 0x9e, 0x4f, 0x3f, 0x27, 0x93, 0xcf, 0xc9, 0xe4, 0xf3,
+ 0xf2, 0x79, 0x3c, 0xe2, 0x2f, 0xc9, 0xc9, 0x5c, 0x62, 0x09,
+ 0x32, 0x51, 0x20, 0x69, 0x21, 0xa1, 0x4e, 0xe0, 0x60, 0x79,
+ 0xcd, 0x39, 0x96, 0x2a, 0x12, 0x65, 0x1b, 0x59, 0x45, 0x60,
+ 0x94, 0x98, 0x24, 0xd4, 0x4e, 0xc1, 0xf0, 0x48, 0x73, 0xbd,
+ 0xf8, 0xce, 0xd1, 0x9d, 0x6f, 0x70, 0xcc, 0x91, 0x08, 0xc2,
+ 0x4e, 0x77, 0x92, 0x21, 0x18, 0x49, 0xd0, 0xf7, 0x47, 0x21,
+ 0x08, 0xc2, 0x4e, 0x87, 0x92, 0x21, 0x18, 0x48, 0x90, 0xba,
+ 0x67, 0x43, 0xf2, 0x44, 0x58, 0x24, 0xe7, 0x79, 0x2b, 0xbe,
+ 0x78, 0xc2, 0x94, 0xbc, 0x90, 0x94, 0x7a, 0x84, 0xc4, 0x82,
+ 0x71, 0xeb, 0x25, 0xf2, 0x4e, 0xe6, 0x1f, 0x0f, 0x59, 0x08,
+ 0xb7, 0x41, 0xf1, 0x55, 0xc2, 0x4c, 0x29, 0x7a, 0x09, 0x33,
+ 0xd9, 0x81, 0x9e, 0x49, 0x9b, 0x2c, 0xf2, 0x79, 0xf9, 0x3c,
+ 0x9e, 0x7e, 0x4f, 0x27, 0x9f, 0x93, 0xc9, 0xe7, 0xe4, 0xf2,
+ 0x79, 0xc6, 0x63, 0x3e, 0x73, 0xc8, 0xf2, 0xe7, 0xe4, 0xf2,
+ 0x79, 0xf9, 0x3c, 0x9e, 0x7e, 0x4f, 0x27, 0x9f, 0x93, 0xc9,
+ 0xe7, 0xe4, 0xf2, 0x42, 0x4b, 0x35, 0xa2, 0x8b, 0xd5, 0x18,
+ 0x71, 0xf4, 0x0f, 0xc8, 0x49, 0x92, 0x6d, 0x61, 0xc1, 0x4a,
+ 0x94, 0x7d, 0x09, 0x15, 0x4c, 0x00, 0x48, 0xa8, 0x78, 0x12,
+ 0x29, 0xfb, 0x3f, 0x89, 0x82, 0x4d, 0xc3, 0x3a, 0x09, 0x32,
+ 0x3d, 0xf7, 0x92, 0x2e, 0x2e, 0x9b, 0xbb, 0x11, 0x8d, 0x9a,
+ 0x3f, 0x68, 0x01, 0x99, 0x0f, 0x21, 0x0a, 0xe6, 0x75, 0x0d,
+ 0x92, 0x32, 0xc9, 0xfc, 0x08, 0x25, 0xb2, 0xf7, 0xfd, 0xfc,
+ 0x01, 0xc9, 0x93, 0xc9, 0x6f, 0x08, 0x49, 0x9c, 0xf2, 0x75,
+ 0x92, 0x76, 0x09, 0x35, 0x26, 0x6f, 0x24, 0x3c, 0x82, 0x40,
+ 0x12, 0x19, 0xb6, 0x64, 0x27, 0xbf, 0x2d, 0xbb, 0x59, 0x60,
+ 0x91, 0x54, 0xe3, 0x6f, 0x64, 0x64, 0x99, 0xe4, 0xb3, 0x71,
+ 0x4c, 0xf2, 0x79, 0xfe, 0x4f, 0x27, 0x9f, 0x93, 0xc9, 0xe7,
+ 0xe4, 0xf2, 0x79, 0xf9, 0x3c, 0x9e, 0x7e, 0x4f, 0x27, 0x9f,
+ 0x93, 0xc9, 0xe7, 0xe4, 0xf2, 0x79, 0xf9, 0x3c, 0x9e, 0x7e,
+ 0x4f, 0x24, 0x24, 0x42, 0xaa, 0xc2, 0x40, 0x93, 0xc7, 0xe1,
+ 0xa8, 0xc6, 0xd9, 0x84, 0xa5, 0x02, 0xd6, 0x84, 0x8a, 0x76,
+ 0x0e, 0xc5, 0xec, 0xc7, 0x70, 0x08, 0xa8, 0x70, 0xf8, 0xa5,
+ 0x45, 0x2e, 0x09, 0x10, 0xef, 0x82, 0x40, 0x43, 0x08, 0x52,
+ 0x61, 0x86, 0x47, 0x28, 0xb1, 0xb4, 0x5f, 0x96, 0xb7, 0xec,
+ 0xd8, 0xe6, 0xec, 0xdf, 0x4d, 0xb9, 0x3c, 0x96, 0x6c, 0x2b,
+ 0x24, 0x42, 0x3d, 0xfa, 0xbc, 0xad, 0xe3, 0xa2, 0x37, 0x62,
+ 0x15, 0xf7, 0xed, 0xb0, 0xee, 0x4d, 0x5d, 0xf3, 0x81, 0x19,
+ 0x23, 0x16, 0x81, 0x9b, 0x25, 0x76, 0x65, 0x1d, 0x92, 0xf9,
+ 0x39, 0xdf, 0x7e, 0x6a, 0x3b, 0x64, 0x8e, 0x4c, 0xc1, 0x7a,
+ 0xc9, 0x3d, 0x66, 0x68, 0x4d, 0xd9, 0x27, 0x1c, 0x88, 0x74,
+ 0x24, 0x46, 0x2a, 0x68, 0xa6, 0x72, 0x70, 0x86, 0xac, 0xd0,
+ 0x46, 0x99, 0x06, 0xdb, 0x25, 0x32, 0x08, 0x7b, 0x2f, 0x04,
+ 0x5f, 0xb3, 0x9e, 0x4c, 0xfc, 0x9d, 0x94, 0x23, 0x3c, 0x9e,
+ 0x7f, 0x93, 0xc9, 0xe7, 0xe4, 0xf2, 0x79, 0xf9, 0x3c, 0x9e,
+ 0x71, 0x07, 0x10, 0x7e, 0x7e, 0x4f, 0x27, 0x9f, 0x93, 0xc9,
+ 0xe7, 0xe4, 0xf2, 0x79, 0xf9, 0x3c, 0x9e, 0x7e, 0x4f, 0x24,
+ 0x24, 0x76, 0xa5, 0xca, 0x61, 0xc4, 0x7a, 0x92, 0x3d, 0x0a,
+ 0x5c, 0x9f, 0xca, 0x47, 0x09, 0x31, 0xa2, 0x52, 0x18, 0xb5,
+ 0x65, 0x1f, 0x44, 0x65, 0xf6, 0xc2, 0x44, 0x0f, 0x91, 0xb8,
+ 0x31, 0x21, 0xc2, 0x44, 0x23, 0x70, 0x90, 0xf6, 0xe1, 0x22,
+ 0x09, 0xfc, 0x00, 0x20, 0x77, 0x61, 0x20, 0xce, 0x3b, 0x45,
+ 0x9e, 0xb5, 0xa8, 0x01, 0xb0, 0x4d, 0xe3, 0x0e, 0x7e, 0x24,
+ 0xc3, 0xbd, 0xf8, 0x64, 0x9d, 0xd9, 0x88, 0x6d, 0x93, 0xc9,
+ 0x66, 0x8b, 0x39, 0x93, 0x57, 0x59, 0xee, 0x4b, 0xe8, 0x4e,
+ 0xb2, 0x45, 0x2f, 0xb4, 0xe8, 0x64, 0xaf, 0x2d, 0xc0, 0xdf,
+ 0xb2, 0x4f, 0x31, 0x32, 0x4f, 0x2e, 0x62, 0x83, 0xf5, 0xd0,
+ 0xa1, 0xf9, 0x3a, 0x97, 0xdf, 0xdf, 0x3d, 0x53, 0x92, 0x32,
+ 0x5c, 0xc7, 0xb4, 0xcc, 0xc8, 0x71, 0xbd, 0xd9, 0xf9, 0x2c,
+ 0xf2, 0x79, 0xfe, 0x4f, 0x27, 0x9f, 0x93, 0xc9, 0xe7, 0xe4,
+ 0xf2, 0x79, 0xf9, 0x3c, 0x9e, 0x73, 0xc8, 0xf2, 0xe7, 0xe4,
+ 0xf2, 0x79, 0xf9, 0x3c, 0x9e, 0x7e, 0x4f, 0x27, 0x9f, 0x93,
+ 0xc9, 0xe7, 0x3c, 0xf9, 0x38, 0xd8, 0x8c, 0x8e, 0x98, 0x62,
+ 0x16, 0x31, 0x3d, 0xa0, 0x73, 0x1f, 0x8a, 0x46, 0x10, 0x0c,
+ 0x11, 0xcb, 0x2f, 0x57, 0x1d, 0x82, 0x4f, 0x47, 0x64, 0x58,
+ 0x01, 0x07, 0x07, 0x2c, 0x50, 0xe1, 0x4a, 0xc9, 0x29, 0xa6,
+ 0xe6, 0x66, 0x13, 0x7d, 0x84, 0x89, 0x3f, 0x00, 0x48, 0x82,
+ 0x57, 0x10, 0x8f, 0xe5, 0xe5, 0xf7, 0x3e, 0xd6, 0xf3, 0x0c,
+ 0xb7, 0xe7, 0xc9, 0x8f, 0x3e, 0x4f, 0x6a, 0xfc, 0xf3, 0xd5,
+ 0xe9, 0x4a, 0x0a, 0x46, 0x52, 0x52, 0x97, 0x88, 0xe5, 0xb8,
+ 0x7e, 0x1c, 0xdc, 0x58, 0x72, 0xdb, 0xe1, 0xe4, 0x8b, 0x6f,
+ 0xea, 0x41, 0xa1, 0x03, 0x6f, 0xd0, 0xe6, 0x5d, 0xd1, 0x90,
+ 0xeb, 0x7d, 0xb6, 0x7e, 0xe8, 0x0e, 0x8e, 0x53, 0xef, 0xe7,
+ 0xdc, 0x2c, 0x91, 0x96, 0xec, 0x12, 0x28, 0x9b, 0x93, 0xb9,
+ 0x74, 0xaf, 0x00, 0xd8, 0x90, 0xd5, 0x99, 0x21, 0xe5, 0x9d,
+ 0x03, 0x5f, 0x5c, 0x95, 0x22, 0x9b, 0x09, 0x38, 0x1e, 0x48,
+ 0xcf, 0x24, 0x39, 0x4c, 0xcd, 0x8d, 0x64, 0x8e, 0x82, 0x4d
+};
+
+GST_START_TEST (test_vc1_identify_bdu)
+{
+ GstVC1ParseResult res;
+ GstVC1BDU bdu;
+ GstVC1SeqHdr hdr;
+ GstVC1EntryPointHdr entrypt;
+
+ res = gst_vc1_identify_next_bdu (sequence_fullframe,
+ sizeof (sequence_fullframe), &bdu);
+
+ assert_equals_int (res, GST_VC1_PARSER_OK);
+ assert_equals_int (bdu.type, GST_VC1_SEQUENCE);
+
+ res = gst_vc1_parse_sequence_header (bdu.data + bdu.offset, bdu.size, &hdr);
+ assert_equals_int (res, GST_VC1_PARSER_OK);
+ assert_equals_int (hdr.profiletype, GST_VC1_PROFILE_ADVANCED);
+
+ assert_equals_int (hdr.profile.advanced.level, GST_VC1_LEVEL_L1);
+ assert_equals_int (hdr.colordiff_format, 1);
+
+ res = gst_vc1_identify_next_bdu (sequence_fullframe + bdu.sc_offset +
+ bdu.size, sizeof (sequence_fullframe) - bdu.sc_offset - bdu.size, &bdu);
+
+ fail_unless (res == GST_VC1_PARSER_OK);
+ fail_unless (bdu.type == GST_VC1_ENTRYPOINT);
+
+ res = gst_vc1_parse_entry_point_header (bdu.data + bdu.offset,
+ bdu.size, &entrypt, &hdr);
+ fail_unless (res == GST_VC1_PARSER_OK);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vc1_parse_p_frame_header_main)
+{
+ GstVC1FrameHdr framehdr;
+ GstVC1SeqHdr seqhdr;
+
+ GstVC1SimpleMainSeqHdr *simplehdr = &seqhdr.profile.simplemain;
+ GstVC1PicSimpleMain *pic = &framehdr.pic.simple;
+
+ assert_equals_int (gst_vc1_parse_sequence_header (pframe_header_main,
+ sizeof (pframe_header_main), &seqhdr), GST_VC1_PARSER_OK);
+
+ assert_equals_int (seqhdr.profiletype, GST_VC1_PROFILE_MAIN);
+
+ simplehdr->coded_height = 240;
+ simplehdr->coded_width = 320;
+
+ assert_equals_int (seqhdr.frmrtq_postproc, 7);
+ assert_equals_int (seqhdr.bitrtq_postproc, 2);
+ assert_equals_int (simplehdr->loop_filter, 1);
+ assert_equals_int (simplehdr->multires, 0);
+ assert_equals_int (simplehdr->extended_mv, 0);
+ assert_equals_int (simplehdr->rangered, 0);
+ assert_equals_int (simplehdr->vstransform, 1);
+ assert_equals_int (simplehdr->overlap, 1);
+ assert_equals_int (simplehdr->syncmarker, 0);
+ assert_equals_int (simplehdr->dquant, 1);
+ assert_equals_int (simplehdr->quantizer, 0);
+ assert_equals_int (simplehdr->maxbframes, 1);
+
+ assert_equals_int (gst_vc1_parse_frame_header (pframe_main,
+ sizeof (pframe_main), &framehdr, &seqhdr), GST_VC1_PARSER_OK);
+ assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_P);
+ assert_equals_int (framehdr.interpfrm, 0);
+ assert_equals_int (pic->frmcnt, 1);
+ assert_equals_int (pic->rangeredfrm, 0);
+ assert_equals_int (framehdr.pqindex, 10);
+ assert_equals_int (framehdr.pquant, 7);
+ assert_equals_int (framehdr.halfqp, 0);
+ assert_equals_int (framehdr.pquantizer, 0);
+
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vc1_parse_b_frame_header_main)
+{
+ GstVC1FrameHdr framehdr;
+ GstVC1SeqHdr seqhdr;
+
+ GstVC1SimpleMainSeqHdr *simplehdr = &seqhdr.profile.simplemain;
+ GstVC1PicSimpleMain *pic = &framehdr.pic.simple;
+
+ assert_equals_int (gst_vc1_parse_sequence_header (bframe_header_main,
+ sizeof (bframe_header_main), &seqhdr), GST_VC1_PARSER_OK);
+
+ assert_equals_int (seqhdr.profiletype, GST_VC1_PROFILE_MAIN);
+
+ simplehdr->coded_height = 240;
+ simplehdr->coded_width = 320;
+
+ assert_equals_int (seqhdr.frmrtq_postproc, 7);
+ assert_equals_int (seqhdr.bitrtq_postproc, 3);
+ assert_equals_int (simplehdr->loop_filter, 1);
+ assert_equals_int (simplehdr->multires, 0);
+ assert_equals_int (simplehdr->extended_mv, 0);
+ assert_equals_int (simplehdr->rangered, 0);
+ assert_equals_int (simplehdr->vstransform, 1);
+ assert_equals_int (simplehdr->overlap, 1);
+ assert_equals_int (simplehdr->syncmarker, 0);
+ assert_equals_int (simplehdr->dquant, 1);
+ assert_equals_int (simplehdr->quantizer, 0);
+ assert_equals_int (simplehdr->maxbframes, 1);
+
+ assert_equals_int (gst_vc1_parse_frame_header (bframe_main,
+ sizeof (bframe_main), &framehdr, &seqhdr), GST_VC1_PARSER_OK);
+
+ assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_B);
+ assert_equals_int (framehdr.interpfrm, 0);
+
+ assert_equals_int (pic->frmcnt, 2);
+ assert_equals_int (pic->rangeredfrm, 0);
+ assert_equals_int (pic->ttmbf, 0);
+ assert_equals_int (pic->mvtab, 2);
+ assert_equals_int (pic->cbptab, 1);
+ assert_equals_int (framehdr.pquant, 7);
+ assert_equals_int (framehdr.halfqp, 0);
+ assert_equals_int (framehdr.pquantizer, 0);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vc1_parse_bi_frame_header_main)
+{
+ GstVC1FrameHdr framehdr;
+ GstVC1SeqHdr seqhdr;
+
+ GstVC1SimpleMainSeqHdr *simplehdr = &seqhdr.profile.simplemain;
+ GstVC1PicSimpleMain *pic = &framehdr.pic.simple;
+ simplehdr->coded_height = 240;
+ simplehdr->coded_width = 320;
+
+ assert_equals_int (gst_vc1_parse_sequence_header (i_bi_frame_header,
+ sizeof (i_bi_frame_header), &seqhdr), GST_VC1_PARSER_OK);
+
+ assert_equals_int (seqhdr.profiletype, GST_VC1_PROFILE_MAIN);
+ assert_equals_int (seqhdr.frmrtq_postproc, 7);
+ assert_equals_int (seqhdr.bitrtq_postproc, 7);
+ assert_equals_int (simplehdr->loop_filter, 1);
+ assert_equals_int (simplehdr->multires, 0);
+ assert_equals_int (simplehdr->extended_mv, 0);
+ assert_equals_int (simplehdr->rangered, 0);
+ assert_equals_int (simplehdr->vstransform, 1);
+ assert_equals_int (simplehdr->overlap, 1);
+ assert_equals_int (simplehdr->syncmarker, 0);
+ assert_equals_int (simplehdr->dquant, 1);
+ assert_equals_int (simplehdr->quantizer, 0);
+ assert_equals_int (simplehdr->maxbframes, 1);
+
+ assert_equals_int (gst_vc1_parse_frame_header (biframe_main,
+ sizeof (biframe_main), &framehdr, &seqhdr), GST_VC1_PARSER_OK);
+ assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_BI);
+ assert_equals_int (framehdr.interpfrm, 0);
+
+ assert_equals_int (pic->frmcnt, 0);
+ assert_equals_int (pic->rangeredfrm, 0);
+ assert_equals_int (framehdr.pqindex, 6);
+ assert_equals_int (framehdr.pquant, 6);
+ assert_equals_int (framehdr.halfqp, 0);
+ assert_equals_int (framehdr.pquantizer, 1);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vc1_parse_i_frame_header_main)
+{
+ GstVC1FrameHdr framehdr;
+ GstVC1SeqHdr seqhdr;
+
+ GstVC1SimpleMainSeqHdr *simplehdr = &seqhdr.profile.simplemain;
+ GstVC1PicSimpleMain *pic = &framehdr.pic.simple;
+
+ simplehdr->coded_height = 240;
+ simplehdr->coded_width = 320;
+
+ assert_equals_int (gst_vc1_parse_sequence_header (i_bi_frame_header,
+ sizeof (i_bi_frame_header), &seqhdr), GST_VC1_PARSER_OK);
+
+ assert_equals_int (seqhdr.profiletype, GST_VC1_PROFILE_MAIN);
+ assert_equals_int (seqhdr.frmrtq_postproc, 7);
+ assert_equals_int (seqhdr.bitrtq_postproc, 7);
+ assert_equals_int (simplehdr->loop_filter, 1);
+ assert_equals_int (simplehdr->multires, 0);
+ assert_equals_int (simplehdr->extended_mv, 0);
+ assert_equals_int (simplehdr->rangered, 0);
+ assert_equals_int (simplehdr->vstransform, 1);
+ assert_equals_int (simplehdr->overlap, 1);
+ assert_equals_int (simplehdr->syncmarker, 0);
+ assert_equals_int (simplehdr->dquant, 1);
+ assert_equals_int (simplehdr->quantizer, 0);
+ assert_equals_int (simplehdr->maxbframes, 1);
+
+ assert_equals_int (gst_vc1_parse_frame_header (iframe_main,
+ sizeof (iframe_main), &framehdr, &seqhdr), GST_VC1_PARSER_OK);
+ assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_I);
+ assert_equals_int (framehdr.interpfrm, 0);
+
+ assert_equals_int (pic->frmcnt, 0);
+ assert_equals_int (pic->rangeredfrm, 0);
+ assert_equals_int (framehdr.pqindex, 4);
+ assert_equals_int (framehdr.pquant, 4);
+ assert_equals_int (framehdr.halfqp, 1);
+ assert_equals_int (framehdr.pquantizer, 1);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vc1_parse_i_frame_header_adv)
+{
+ GstVC1FrameHdr framehdr;
+ GstVC1SeqHdr seqhdr;
+
+ GstVC1AdvancedSeqHdr *advhdr = &seqhdr.profile.advanced;
+ GstVC1EntryPointHdr *entrypt = &advhdr->entrypoint;
+ GstVC1PicAdvanced *pic = &framehdr.pic.advanced;
+
+ assert_equals_int (gst_vc1_parse_sequence_header (iframe_adv_hdr,
+ sizeof (iframe_adv_hdr), &seqhdr), GST_VC1_PARSER_OK);
+
+ assert_equals_int (seqhdr.profiletype, GST_VC1_PROFILE_ADVANCED);
+ assert_equals_int (advhdr->level, GST_VC1_LEVEL_L3);
+ assert_equals_int (seqhdr.frmrtq_postproc, 7);
+ assert_equals_int (seqhdr.bitrtq_postproc, 31);
+ assert_equals_int (advhdr->postprocflag, 0);
+ assert_equals_int (advhdr->max_coded_width, 1920);
+ assert_equals_int (advhdr->max_coded_height, 1080);
+ assert_equals_int (advhdr->interlace, 1);
+ assert_equals_int (advhdr->tfcntrflag, 0);
+ assert_equals_int (seqhdr.finterpflag, 0);
+
+ assert_equals_int (advhdr->display_ext, 1);
+ assert_equals_int (advhdr->disp_horiz_size, 1920);
+ assert_equals_int (advhdr->disp_vert_size, 1080);
+
+ assert_equals_int (gst_vc1_parse_entry_point_header (entrypoint,
+ sizeof (entrypoint), entrypt, &seqhdr), GST_VC1_PARSER_OK);
+
+ assert_equals_int (entrypt->broken_link, 0);
+ assert_equals_int (entrypt->closed_entry, 1);
+ assert_equals_int (entrypt->panscan_flag, 0);
+ assert_equals_int (entrypt->refdist_flag, 1);
+ assert_equals_int (entrypt->loopfilter, 1);
+ assert_equals_int (entrypt->fastuvmc, 0);
+ assert_equals_int (entrypt->extended_mv, 1);
+ assert_equals_int (entrypt->dquant, 1);
+ assert_equals_int (entrypt->vstransform, 1);
+ assert_equals_int (entrypt->overlap, 0);
+ assert_equals_int (entrypt->quantizer, 0);
+ assert_equals_int (entrypt->coded_height, 1080);
+ assert_equals_int (entrypt->coded_width, 1920);
+
+ assert_equals_int (gst_vc1_parse_frame_header (iframe_adv,
+ sizeof (iframe_adv), &framehdr, &seqhdr), GST_VC1_PARSER_OK);
+
+ assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_I);
+ assert_equals_int (framehdr.pqindex, 3);
+ assert_equals_int (framehdr.pquant, 3);
+ assert_equals_int (framehdr.halfqp, 1);
+ assert_equals_int (framehdr.pquantizer, 1);
+
+ assert_equals_int (pic->fcm, 0);
+ assert_equals_int (pic->tff, 1);
+ assert_equals_int (pic->rff, 0);
+ assert_equals_int (pic->rndctrl, 0);
+}
+
+GST_END_TEST;
+
+GST_START_TEST (test_vc1_parse_b_frame_header_adv)
+{
+ GstVC1FrameHdr framehdr;
+ GstVC1SeqHdr seqhdr;
+
+ GstVC1AdvancedSeqHdr *advhdr = &seqhdr.profile.advanced;
+ GstVC1EntryPointHdr *entrypt = &advhdr->entrypoint;
+ GstVC1PicAdvanced *pic = &framehdr.pic.advanced;
+
+ assert_equals_int (gst_vc1_parse_sequence_header (iframe_adv_hdr,
+ sizeof (iframe_adv_hdr), &seqhdr), GST_VC1_PARSER_OK);
+
+ assert_equals_int (seqhdr.profiletype, GST_VC1_PROFILE_ADVANCED);
+ assert_equals_int (advhdr->level, GST_VC1_LEVEL_L3);
+ assert_equals_int (seqhdr.frmrtq_postproc, 7);
+ assert_equals_int (seqhdr.bitrtq_postproc, 31);
+ assert_equals_int (advhdr->postprocflag, 0);
+ assert_equals_int (advhdr->max_coded_width, 1920);
+ assert_equals_int (advhdr->max_coded_height, 1080);
+ assert_equals_int (advhdr->interlace, 1);
+ assert_equals_int (advhdr->tfcntrflag, 0);
+ assert_equals_int (seqhdr.finterpflag, 0);
+
+ assert_equals_int (advhdr->display_ext, 1);
+ assert_equals_int (advhdr->disp_horiz_size, 1920);
+ assert_equals_int (advhdr->disp_vert_size, 1080);
+
+ assert_equals_int (gst_vc1_parse_entry_point_header (entrypoint,
+ sizeof (entrypoint), entrypt, &seqhdr), GST_VC1_PARSER_OK);
+
+ assert_equals_int (entrypt->broken_link, 0);
+ assert_equals_int (entrypt->closed_entry, 1);
+ assert_equals_int (entrypt->panscan_flag, 0);
+ assert_equals_int (entrypt->refdist_flag, 1);
+ assert_equals_int (entrypt->loopfilter, 1);
+ assert_equals_int (entrypt->fastuvmc, 0);
+ assert_equals_int (entrypt->extended_mv, 1);
+ assert_equals_int (entrypt->dquant, 1);
+ assert_equals_int (entrypt->vstransform, 1);
+ assert_equals_int (entrypt->overlap, 0);
+ assert_equals_int (entrypt->quantizer, 0);
+
+ assert_equals_int (gst_vc1_parse_frame_header (bframe_adv,
+ sizeof (bframe_adv), &framehdr, &seqhdr), GST_VC1_PARSER_OK);
+
+ assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_B);
+ assert_equals_int (framehdr.pqindex, 1);
+ assert_equals_int (framehdr.pquant, 1);
+ assert_equals_int (framehdr.halfqp, 1);
+ assert_equals_int (framehdr.pquantizer, 1);
+
+ assert_equals_int (framehdr.vopdquant.dquantfrm, 0);
+ assert_equals_int (framehdr.transacfrm, 1);
+
+ assert_equals_int (gst_vc1_parse_frame_header (bframe2_adv,
+ sizeof (bframe2_adv), &framehdr, &seqhdr), GST_VC1_PARSER_OK);
+ assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_B);
+ assert_equals_int (framehdr.pqindex, 4);
+ assert_equals_int (framehdr.pquant, 4);
+ assert_equals_int (framehdr.halfqp, 0);
+ assert_equals_int (framehdr.pquantizer, 1);
+ assert_equals_int (framehdr.transacfrm, 0);
+
+ assert_equals_int (pic->mvrange, 0);
+ assert_equals_int (pic->mvmode, 0);
+}
+
+
+GST_END_TEST;
+
+GST_START_TEST (test_vc1_parse_p_frame_header_adv)
+{
+ GstVC1FrameHdr framehdr;
+ GstVC1SeqHdr seqhdr;
+
+ GstVC1AdvancedSeqHdr *advhdr = &seqhdr.profile.advanced;
+ GstVC1EntryPointHdr *entrypt = &advhdr->entrypoint;
+ GstVC1PicAdvanced *pic = &framehdr.pic.advanced;
+
+ assert_equals_int (gst_vc1_parse_sequence_header (iframe_adv_hdr,
+ sizeof (iframe_adv_hdr), &seqhdr), GST_VC1_PARSER_OK);
+
+ assert_equals_int (seqhdr.profiletype, GST_VC1_PROFILE_ADVANCED);
+ assert_equals_int (advhdr->level, GST_VC1_LEVEL_L3);
+ assert_equals_int (seqhdr.frmrtq_postproc, 7);
+ assert_equals_int (seqhdr.bitrtq_postproc, 31);
+ assert_equals_int (advhdr->postprocflag, 0);
+ assert_equals_int (advhdr->max_coded_width, 1920);
+ assert_equals_int (advhdr->max_coded_height, 1080);
+ assert_equals_int (advhdr->interlace, 1);
+ assert_equals_int (advhdr->tfcntrflag, 0);
+ assert_equals_int (seqhdr.finterpflag, 0);
+
+ assert_equals_int (advhdr->display_ext, 1);
+ assert_equals_int (advhdr->disp_horiz_size, 1920);
+ assert_equals_int (advhdr->disp_vert_size, 1080);
+
+ assert_equals_int (gst_vc1_parse_entry_point_header (entrypoint,
+ sizeof (entrypoint), entrypt, &seqhdr), GST_VC1_PARSER_OK);
+ assert_equals_int (entrypt->broken_link, 0);
+ assert_equals_int (entrypt->closed_entry, 1);
+ assert_equals_int (entrypt->panscan_flag, 0);
+ assert_equals_int (entrypt->refdist_flag, 1);
+ assert_equals_int (entrypt->loopfilter, 1);
+ assert_equals_int (entrypt->fastuvmc, 0);
+ assert_equals_int (entrypt->extended_mv, 1);
+ assert_equals_int (entrypt->dquant, 1);
+ assert_equals_int (entrypt->vstransform, 1);
+ assert_equals_int (entrypt->overlap, 0);
+ assert_equals_int (entrypt->quantizer, 0);
+ assert_equals_int (entrypt->coded_height, 1080);
+ assert_equals_int (entrypt->coded_width, 1920);
+
+
+ assert_equals_int (gst_vc1_parse_frame_header (pframe_adv,
+ sizeof (pframe_adv), &framehdr, &seqhdr), GST_VC1_PARSER_OK);
+ assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_P);
+ assert_equals_int (framehdr.pqindex, 1);
+ assert_equals_int (framehdr.pquant, 1);
+ assert_equals_int (framehdr.halfqp, 0);
+ assert_equals_int (framehdr.pquantizer, 1);
+
+ assert_equals_int (pic->mvmode, 0);
+ assert_equals_int (pic->mvrange, 0);
+
+ assert_equals_int (gst_vc1_parse_frame_header (pframe2_adv,
+ sizeof (pframe2_adv), &framehdr, &seqhdr), GST_VC1_PARSER_OK);
+ assert_equals_int (framehdr.ptype, GST_VC1_PICTURE_TYPE_P);
+ assert_equals_int (framehdr.pqindex, 1);
+ assert_equals_int (framehdr.pquant, 1);
+ assert_equals_int (framehdr.halfqp, 0);
+ assert_equals_int (framehdr.pquantizer, 1);
+
+ assert_equals_int (pic->mvmode, 3);
+ assert_equals_int (pic->mvrange, 0);
+}
+
+GST_END_TEST static Suite *
+vc1parser_suite (void)
+{
+ Suite *s = suite_create ("VC1 Parser library");
+
+ TCase *tc_chain = tcase_create ("general");
+
+ suite_add_tcase (s, tc_chain);
+ tcase_add_test (tc_chain, test_vc1_identify_bdu);
+ tcase_add_test (tc_chain, test_vc1_parse_p_frame_header_main);
+ tcase_add_test (tc_chain, test_vc1_parse_b_frame_header_main);
+ tcase_add_test (tc_chain, test_vc1_parse_bi_frame_header_main);
+ tcase_add_test (tc_chain, test_vc1_parse_i_frame_header_main);
+ tcase_add_test (tc_chain, test_vc1_parse_i_frame_header_adv);
+ tcase_add_test (tc_chain, test_vc1_parse_b_frame_header_adv);
+ tcase_add_test (tc_chain, test_vc1_parse_p_frame_header_adv);
+
+ return s;
+}
+
+int
+main (int argc, char **argv)
+{
+ int nf;
+
+ Suite *s = vc1parser_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;
+}