From 573f1858746e6deba1d811365f7072e18ccc2823 Mon Sep 17 00:00:00 2001 From: Stefan Sauer Date: Tue, 6 Sep 2011 21:25:00 +0200 Subject: [PATCH 01/69] Automatic update of common submodule From a39eb83 to 11f0cd5 --- common | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common b/common index a39eb835fb..11f0cd5a3f 160000 --- a/common +++ b/common @@ -1 +1 @@ -Subproject commit a39eb835fb3be2a4c5a6a89b5ca5cc064e79b2e2 +Subproject commit 11f0cd5a3fba36f85cf3e434150bfe66b1bf08d4 From 754071b2f12a6851e0768d4cd36e494aad0464a4 Mon Sep 17 00:00:00 2001 From: Christian Fredrik Kalager Schaller Date: Tue, 6 Sep 2011 22:48:30 +0100 Subject: [PATCH 02/69] Update for latest new plugins and moved plugins --- gst-plugins-bad.spec.in | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/gst-plugins-bad.spec.in b/gst-plugins-bad.spec.in index adbd33df61..eac41e081a 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 From 12f77b27e26e22b09bf9efee254b8f27c0f4cdc7 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 6 Sep 2011 10:49:04 -0300 Subject: [PATCH 03/69] camerabin2: preview: No need for appsink to store the last buffer There is no need for preview's appsink to keep a reference to the last buffer, so disable the property to make it unref the buffers sooner. --- gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c b/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c index b916d7f6b3..5dd82dad16 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); From 29a358e8cda0dc6025d538abb39b14cf94dceacb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 7 Sep 2011 11:06:46 +0200 Subject: [PATCH 04/69] diracparse: Constify some arrays --- gst/videoparsers/dirac_parse.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/videoparsers/dirac_parse.c b/gst/videoparsers/dirac_parse.c index 3a3193d925..5b367c36ce 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}, From 456335eab4a4079e5700bda2f06165743040af37 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 7 Sep 2011 11:14:36 +0200 Subject: [PATCH 05/69] h264parse: Change rank to PRIMARY+1 to have h264parse autoplugged --- gst/videoparsers/plugin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/videoparsers/plugin.c b/gst/videoparsers/plugin.c index a6db91d357..1473ffc9ff 100644 --- a/gst/videoparsers/plugin.c +++ b/gst/videoparsers/plugin.c @@ -35,7 +35,7 @@ plugin_init (GstPlugin * plugin) ret = gst_element_register (plugin, "h263parse", GST_RANK_NONE, 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", From d4147a279875dafe9ae79e3e02137eb1f8d89883 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 7 Sep 2011 11:17:54 +0200 Subject: [PATCH 06/69] h264parse: Put stream-format and alignment into the src template caps Also remove the parsed field from the sink template caps. --- gst/videoparsers/gsth264parse.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/gst/videoparsers/gsth264parse.c b/gst/videoparsers/gsth264parse.c index 3821f0031f..d3fbb29fd4 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); From 2adf76eb5218d3d2e57fe618eed120cb0f37d86b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 7 Sep 2011 11:22:07 +0200 Subject: [PATCH 07/69] videoparsers: Allow parsed streams to be passed through the parsers --- gst/videoparsers/gstdiracparse.c | 2 +- gst/videoparsers/gsth263parse.c | 3 +-- gst/videoparsers/gstmpegvideoparse.c | 3 +-- 3 files changed, 3 insertions(+), 5 deletions(-) diff --git a/gst/videoparsers/gstdiracparse.c b/gst/videoparsers/gstdiracparse.c index 3feaa41926..47ab93588d 100644 --- a/gst/videoparsers/gstdiracparse.c +++ b/gst/videoparsers/gstdiracparse.c @@ -78,7 +78,7 @@ 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 = diff --git a/gst/videoparsers/gsth263parse.c b/gst/videoparsers/gsth263parse.c index 877c75e44f..9e55efe998 100644 --- a/gst/videoparsers/gsth263parse.c +++ b/gst/videoparsers/gsth263parse.c @@ -45,8 +45,7 @@ GST_STATIC_PAD_TEMPLATE ("src", GST_PAD_SRC, 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); diff --git a/gst/videoparsers/gstmpegvideoparse.c b/gst/videoparsers/gstmpegvideoparse.c index 12d98d5d77..aac1f35bc6 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 */ From 89aa5dae9d8d9ded8536b0b5d35e8285b5bcc40b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 7 Sep 2011 11:24:14 +0200 Subject: [PATCH 08/69] diracparse: Add all fields to the src template caps --- gst/videoparsers/gstdiracparse.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/gst/videoparsers/gstdiracparse.c b/gst/videoparsers/gstdiracparse.c index 47ab93588d..ef99b7ae90 100644 --- a/gst/videoparsers/gstdiracparse.c +++ b/gst/videoparsers/gstdiracparse.c @@ -85,7 +85,12 @@ 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 */ From e86e66e86cb2222274aaf69561669167683f836d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 7 Sep 2011 11:27:56 +0200 Subject: [PATCH 09/69] h263parse: Add all always present fields to the src template caps --- gst/videoparsers/gsth263parse.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/videoparsers/gsth263parse.c b/gst/videoparsers/gsth263parse.c index 9e55efe998..d83f8ef2ef 100644 --- a/gst/videoparsers/gsth263parse.c +++ b/gst/videoparsers/gsth263parse.c @@ -39,7 +39,7 @@ 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 = From ddf32e2c49e4169bce2894466a445b4aa91de571 Mon Sep 17 00:00:00 2001 From: George Kiagiadakis Date: Mon, 5 Sep 2011 20:02:57 +0300 Subject: [PATCH 10/69] h264parse: Fix IDR position marking when the IDR is split into several NALs --- gst/videoparsers/gsth264parse.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/gst/videoparsers/gsth264parse.c b/gst/videoparsers/gsth264parse.c index d3fbb29fd4..e818e6eb44 100644 --- a/gst/videoparsers/gsth264parse.c +++ b/gst/videoparsers/gsth264parse.c @@ -496,12 +496,14 @@ 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); From 724d7a3defb209d75529edd1320a91d505544e87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Wed, 7 Sep 2011 13:46:49 +0200 Subject: [PATCH 11/69] videoparsers: Make the h263 and (new) mpeg video parser autopluggable --- gst/mpegvideoparse/mpegvideoparse.c | 2 +- gst/videoparsers/plugin.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gst/mpegvideoparse/mpegvideoparse.c b/gst/mpegvideoparse/mpegvideoparse.c index 2f4e96cecf..52a34c10f0 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/videoparsers/plugin.c b/gst/videoparsers/plugin.c index 1473ffc9ff..94a6c10fe3 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_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; } From 1a6dbe1e273dff4e5a6e9e9c7936589ce62a7eca Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 7 Sep 2011 12:32:48 +0100 Subject: [PATCH 12/69] mpegvideoparse: make this build with older glib g_list_free_full is a new convenience function. Replace it with g_list_foreach and g_list_free. https://bugzilla.gnome.org/show_bug.cgi?id=658450 --- gst/videoparsers/gstmpegvideoparse.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst/videoparsers/gstmpegvideoparse.c b/gst/videoparsers/gstmpegvideoparse.c index aac1f35bc6..2be478c6ee 100644 --- a/gst/videoparsers/gstmpegvideoparse.c +++ b/gst/videoparsers/gstmpegvideoparse.c @@ -497,7 +497,8 @@ end: 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; From e21c4abc5046f00360a420d94d4283d2c207e2bc Mon Sep 17 00:00:00 2001 From: Stefan Sauer Date: Wed, 7 Sep 2011 15:37:53 +0200 Subject: [PATCH 13/69] kateparse: fix crap in object macros --- ext/kate/gstkateparse.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/kate/gstkateparse.h b/ext/kate/gstkateparse.h index 509f6c4988..f9dd041cde 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; From b931841e3c998dd24abc23d3381a238d9452b08a Mon Sep 17 00:00:00 2001 From: Stefan Sauer Date: Wed, 7 Sep 2011 15:42:37 +0200 Subject: [PATCH 14/69] docs: fix camerabin2 names in sections.txt --- docs/plugins/gst-plugins-bad-plugins-sections.txt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/plugins/gst-plugins-bad-plugins-sections.txt b/docs/plugins/gst-plugins-bad-plugins-sections.txt index 29315d4af2..d7fc96e957 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 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
From dbcec90989637c5afd851aeb56592bb4ee542fd6 Mon Sep 17 00:00:00 2001 From: Stefan Sauer Date: Wed, 7 Sep 2011 15:48:33 +0200 Subject: [PATCH 15/69] docs: cleanup makefiles Remove commented out parts that we don't need. Remove "the wingo addition" - no so useful after all. Narrow down file-globs for plugin docs. --- docs/libs/Makefile.am | 52 ++++++++-------------------------------- docs/plugins/Makefile.am | 43 +++++++++------------------------ 2 files changed, 21 insertions(+), 74 deletions(-) diff --git a/docs/libs/Makefile.am b/docs/libs/Makefile.am index e93bbda17b..aaa35658d7 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/plugins/Makefile.am b/docs/plugins/Makefile.am index 4f8f0cfcd9..a948927df3 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) From baf875b928a1321d30046cf643736f3459c55d7f Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Wed, 7 Sep 2011 20:09:12 +0000 Subject: [PATCH 16/69] hlsdemux: Do not join the task from the task's thread itself. join it only in the state change --- gst/hls/gsthlsdemux.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/gst/hls/gsthlsdemux.c b/gst/hls/gsthlsdemux.c index 143f36387d..ea23ef604a 100644 --- a/gst/hls/gsthlsdemux.c +++ b/gst/hls/gsthlsdemux.c @@ -310,6 +310,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: @@ -665,7 +666,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); } From 61ee9918beea424c26496e104671af315f1d4973 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Tue, 6 Sep 2011 22:11:06 -0400 Subject: [PATCH 17/69] spandsp: Adding spandsp plugin with spanplc element for packet loss concealment --- configure.ac | 13 ++ ext/Makefile.am | 8 ++ ext/spandsp/Makefile.am | 9 ++ ext/spandsp/gstspandsp.c | 40 ++++++ ext/spandsp/gstspanplc.c | 300 +++++++++++++++++++++++++++++++++++++++ ext/spandsp/gstspanplc.h | 60 ++++++++ 6 files changed, 430 insertions(+) create mode 100644 ext/spandsp/Makefile.am create mode 100644 ext/spandsp/gstspandsp.c create mode 100644 ext/spandsp/gstspanplc.c create mode 100644 ext/spandsp/gstspanplc.h diff --git a/configure.ac b/configure.ac index b41d54b888..03a367be77 100644 --- a/configure.ac +++ b/configure.ac @@ -1718,6 +1718,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, [ @@ -1780,6 +1791,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) @@ -2029,6 +2041,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/ext/Makefile.am b/ext/Makefile.am index 2a6f8ec760..95ba3da754 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/spandsp/Makefile.am b/ext/spandsp/Makefile.am new file mode 100644 index 0000000000..46585958a4 --- /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 0000000000..ad1c3a8171 --- /dev/null +++ b/ext/spandsp/gstspandsp.c @@ -0,0 +1,40 @@ +/* + * (C) 2011 Collabora Ltd. + * Contact: Youness Alaoui + * + * 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 +#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 0000000000..90a7c10920 --- /dev/null +++ b/ext/spandsp/gstspanplc.c @@ -0,0 +1,300 @@ +/* + * (C) 2011 Collabora Ltd. + * Contact: Youness Alaoui + * + * 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 +#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 "); +} + +/* 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, "spandlc", + 0, "spandlc'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 0000000000..86c10ac232 --- /dev/null +++ b/ext/spandsp/gstspanplc.h @@ -0,0 +1,60 @@ +/* + * (C) 2011 Collabora Ltd. + * Contact: Youness Alaoui + * + * 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 + +#include + +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; + + /* */ + 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 From 84e67767a32deca18a50bd554dc21c5dd471f12a Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 8 Sep 2011 18:25:00 +0000 Subject: [PATCH 18/69] hlsdemux: Do not lock the mutex of the fetcher during EOS The fetch_location might call stop_fetcher which could generate an EOS and cause a deadlock --- gst/hls/gsthlsdemux.c | 2 -- 1 file changed, 2 deletions(-) diff --git a/gst/hls/gsthlsdemux.c b/gst/hls/gsthlsdemux.c index ea23ef604a..7b8f0ecc25 100644 --- a/gst/hls/gsthlsdemux.c +++ b/gst/hls/gsthlsdemux.c @@ -574,9 +574,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: From 609bdd66424e7d5496c8533d89e3c5fe13840fca Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 8 Sep 2011 20:29:42 +0000 Subject: [PATCH 19/69] hlsdemux: set playlist to NULL after unreffing it to avoid a double-unref in the dispose --- gst/hls/gsthlsdemux.c | 1 + 1 file changed, 1 insertion(+) diff --git a/gst/hls/gsthlsdemux.c b/gst/hls/gsthlsdemux.c index 7b8f0ecc25..f1ad5deae8 100644 --- a/gst/hls/gsthlsdemux.c +++ b/gst/hls/gsthlsdemux.c @@ -463,6 +463,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)) { From 894ac8f4931c2eab2f7bb8d38daec4762821fe05 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 8 Sep 2011 22:13:19 +0000 Subject: [PATCH 20/69] hlsdemux/tsdemux: Add HP copyright on work done on HLS --- gst/hls/gsthlsdemux.c | 3 +++ gst/mpegtsdemux/mpegtsbase.c | 6 +++++- gst/mpegtsdemux/mpegtsbase.h | 3 +++ gst/mpegtsdemux/tsdemux.c | 4 ++++ 4 files changed, 15 insertions(+), 1 deletion(-) diff --git a/gst/hls/gsthlsdemux.c b/gst/hls/gsthlsdemux.c index f1ad5deae8..f87bf3a222 100644 --- a/gst/hls/gsthlsdemux.c +++ b/gst/hls/gsthlsdemux.c @@ -1,6 +1,9 @@ /* GStreamer * Copyright (C) 2010 Marc-Andre Lureau * Copyright (C) 2010 Andoni Morales Alastruey + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Youness Alaoui , Collabora Ltd. + * Author: Sebastian Dröge , Collabora Ltd. * * Gsthlsdemux.c: * diff --git a/gst/mpegtsdemux/mpegtsbase.c b/gst/mpegtsdemux/mpegtsbase.c index 5542abf029..437af9d785 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 , Collabora Ltd. + * Author: Sebastian Dröge , Collabora Ltd. + * Author: Edward Hervey , Collabora Ltd. * * Authors: * Alessandro Decina diff --git a/gst/mpegtsdemux/mpegtsbase.h b/gst/mpegtsdemux/mpegtsbase.h index cce4e0fd72..872e77ee87 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 * 2007 Alessandro Decina + * Copyright (C) 2011, Hewlett-Packard Development Company, L.P. + * Author: Youness Alaoui , Collabora Ltd. + * Author: Sebastian Dröge , Collabora Ltd. * * Authors: * Alessandro Decina diff --git a/gst/mpegtsdemux/tsdemux.c b/gst/mpegtsdemux/tsdemux.c index 3a327a5cd9..3facd64073 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 , Collabora Ltd. + * Author: Sebastian Dröge , Collabora Ltd. + * Author: Edward Hervey , Collabora Ltd. * * Authors: * Zaheer Abbas Merali From 55e420615976bf88b1fa882e158e78e1cdeb04b0 Mon Sep 17 00:00:00 2001 From: Youness Alaoui Date: Thu, 8 Sep 2011 23:56:33 +0000 Subject: [PATCH 21/69] hlsdemux: Report the correct timestamp for live streams Buffers would always start with timestamp 0 and we'd start streaming from the first buffer, but live streams always start streaming from the last fragment - 3 fragments in the playlist, which makes its timestamp, as returned by get_next_fragment, be whatever position they had in the playlist. This makes sure the position correctly reports the position of the buffer in the playlist, and added a shifting variable to allow seeking in the middle of fragments. --- gst/hls/gsthlsdemux.c | 15 ++++++++++----- gst/hls/gsthlsdemux.h | 1 + gst/hls/m3u8.c | 24 ++++++++++++++++++++++-- gst/hls/m3u8.h | 2 ++ 4 files changed, 35 insertions(+), 7 deletions(-) diff --git a/gst/hls/gsthlsdemux.c b/gst/hls/gsthlsdemux.c index f87bf3a222..ad29f78370 100644 --- a/gst/hls/gsthlsdemux.c +++ b/gst/hls/gsthlsdemux.c @@ -410,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); @@ -751,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))) @@ -886,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; } @@ -1037,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 bac8ef3174..a09a88b769 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 c407d72d83..cffca7d37b 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; + GList *l, *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; diff --git a/gst/hls/m3u8.h b/gst/hls/m3u8.h index 8c83990f87..a428a67a48 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); From 24517ba7845cca5bdcde5d3162098076fea31600 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Fri, 9 Sep 2011 12:27:57 +0200 Subject: [PATCH 22/69] hlsdemux: Fix merge mistake from last commit --- gst/hls/m3u8.c | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/gst/hls/m3u8.c b/gst/hls/m3u8.c index cffca7d37b..449b63ee9d 100644 --- a/gst/hls/m3u8.c +++ b/gst/hls/m3u8.c @@ -492,7 +492,7 @@ gst_m3u8_client_get_next_fragment (GstM3U8Client * client, gboolean * discontinuity, const gchar ** uri, GstClockTime * duration, GstClockTime * timestamp) { - GList *l, *walk; + GList *l; GstM3U8MediaFile *file; g_return_val_if_fail (client != NULL, FALSE); @@ -518,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; } From 8b268bd49d62ce221aedc2565ee751bafabd2e8f Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Tue, 6 Sep 2011 21:28:45 -0300 Subject: [PATCH 23/69] codecparsers: h264: Update the documentation Fix a few error. Document missing parts. Add links to the specifications --- gst-libs/gst/codecparsers/gsth264parser.c | 92 ++++++++++++++++------- 1 file changed, 65 insertions(+), 27 deletions(-) diff --git a/gst-libs/gst/codecparsers/gsth264parser.c b/gst-libs/gst/codecparsers/gsth264parser.c index 869aa6122b..36f2ee4ad8 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: * * - * 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 * * - * 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 * * * * 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: + * + * + * From #GST_H264_NAL_SLICE to #GST_H264_NAL_SLICE_IDR: #gst_h264_parser_parse_slice_hdr + * + * + * #GST_H264_NAL_SEI: #gst_h264_parser_parse_sei + * + * + * #GST_H264_NAL_SPS: #gst_h264_parser_parse_sps + * + * + * #GST_H264_NAL_PPS: #gst_h264_parser_parse_pps + * + * + * Any other: #gst_h264_parser_parse_nal + * + * * * 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: + * + * + * + * ITU-T H.264: http://www.itu.int/rec/T-REC-H.264 + * + * + * ISO/IEC 14496-10: http://www.iso.org/iso/iso_catalogue/catalogue_tc/catalogue_detail.htm?csnumber=56538 + * + * */ #ifdef HAVE_CONFIG_H @@ -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 */ @@ -1110,11 +1138,11 @@ gst_h264_nal_parser_new (void) * 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 */ @@ -1180,12 +1208,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 +1251,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 you don'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) { @@ -1242,10 +1283,10 @@ 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. + * @slice: 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 */ @@ -1270,10 +1311,10 @@ 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. + * @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 */ @@ -1441,12 +1482,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. + * @pps: The #GstH264PPS to fill. * - * Parses the @data, and sets the @pps. + * Parses @data, and fills the @pps structure. * * Returns: a #GstH264ParserResult */ @@ -1572,12 +1611,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. + * @pps: The #GstH264PPS to fill. * - * Parses the @data, and sets the @pps. + * Parses @data, and fills the @pps structure. * * Returns: a #GstH264ParserResult */ @@ -1599,12 +1636,13 @@ gst_h264_parser_parse_pps (GstH264NalParser * nalparser, /** * gst_h264_parser_parse_slice_hdr: + * @nalparser: a #GstH264NalParser * @nalu: The #GST_H264_NAL_SLICE #GstH264NalUnit you want to parse - * @slice: The #GstH264SliceHdr to set. + * @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 */ @@ -1777,9 +1815,9 @@ 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. + * @sei: The #GstH264SEIMessage to fill. * - * Parses the @data, and sets the @pps. + * Parses @data, and fills the @sei structures. * * Returns: a #GstH264ParserResult */ From 949ba4e895f03b74c8788ff4e66d52712e21d0b6 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Tue, 6 Sep 2011 21:29:28 -0300 Subject: [PATCH 24/69] codecparsers: h264: Use g_slice instead of g_malloc in nal_parser_new --- gst-libs/gst/codecparsers/gsth264parser.c | 2 +- tests/check/libs/h264parser.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gst-libs/gst/codecparsers/gsth264parser.c b/gst-libs/gst/codecparsers/gsth264parser.c index 36f2ee4ad8..e9986178ca 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.c +++ b/gst-libs/gst/codecparsers/gsth264parser.c @@ -1127,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"); diff --git a/tests/check/libs/h264parser.c b/tests/check/libs/h264parser.c index 3bc8c49e57..6d75917f5d 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); + g_slice_free (GstH264NalParser, parser); } GST_END_TEST; From edebb4ed92c8809132cd0ccd73baf669ca5560ce Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Fri, 9 Sep 2011 14:15:21 -0300 Subject: [PATCH 25/69] codecparsers: h264: Implement the nal_parser_free function --- gst-libs/gst/codecparsers/gsth264parser.c | 14 ++++++++++++++ tests/check/libs/h264parser.c | 2 +- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/gst-libs/gst/codecparsers/gsth264parser.c b/gst-libs/gst/codecparsers/gsth264parser.c index e9986178ca..29c40f5c8d 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.c +++ b/gst-libs/gst/codecparsers/gsth264parser.c @@ -1134,6 +1134,20 @@ gst_h264_nal_parser_new (void) return nalparser; } +/** + * 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 diff --git a/tests/check/libs/h264parser.c b/tests/check/libs/h264parser.c index 6d75917f5d..5d87980f9a 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_slice_free (GstH264NalParser, parser); + gst_h264_nal_parser_free (parser); } GST_END_TEST; From 404c18ab18932d53275508afd8ad1c9098aec26b Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Fri, 9 Sep 2011 14:22:39 -0300 Subject: [PATCH 26/69] h264parse: Make use of the h264_nal_parser_free function --- gst/videoparsers/gsth264parse.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/gst/videoparsers/gsth264parse.c b/gst/videoparsers/gsth264parse.c index e818e6eb44..c64361ccdd 100644 --- a/gst/videoparsers/gsth264parse.c +++ b/gst/videoparsers/gsth264parse.c @@ -239,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; } From 6e9873038bb19620d1e3eff571151cd3105bd96c Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Mon, 12 Sep 2011 10:23:19 +0200 Subject: [PATCH 27/69] mpegvideoparse: fix compiler warnings --- gst/videoparsers/gstmpegvideoparse.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/gst/videoparsers/gstmpegvideoparse.c b/gst/videoparsers/gstmpegvideoparse.c index 2be478c6ee..bbf4194f9e 100644 --- a/gst/videoparsers/gstmpegvideoparse.c +++ b/gst/videoparsers/gstmpegvideoparse.c @@ -236,13 +236,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) { From 668b0ab4f86b11f07a1479468ab4bca2802c821f Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Mon, 12 Sep 2011 10:33:06 +0200 Subject: [PATCH 28/69] codecparsers: fix compiler warnings --- gst-libs/gst/codecparsers/gsth264parser.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gst-libs/gst/codecparsers/gsth264parser.c b/gst-libs/gst/codecparsers/gsth264parser.c index 29c40f5c8d..1378d3ac51 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.c +++ b/gst-libs/gst/codecparsers/gsth264parser.c @@ -1091,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++) { @@ -1167,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; } From f33b78abd16bab4a53f30bbbb7e5b9ecef5f1f65 Mon Sep 17 00:00:00 2001 From: Alessandro Decina Date: Mon, 29 Aug 2011 08:00:22 +0200 Subject: [PATCH 29/69] rtmpsink: don't block the main thread with RTMP_Connect Move the RTMP_Connect call from the main thread (::start) to the streaming thread (::render). --- ext/rtmp/gstrtmpsink.c | 29 +++++++++++++++-------------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/ext/rtmp/gstrtmpsink.c b/ext/rtmp/gstrtmpsink.c index e3933b1503..90a1a79ec8 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", From 00e635e78676fd6680d2a0789dcad77e61c25d54 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Mon, 12 Sep 2011 16:50:10 -0300 Subject: [PATCH 30/69] camerabin2: Check zoom notify callback from camera-source Camerabin2 has a zoom property that is simply proxied to its internal camera-source element. This patch makes camerabin2 listen to 'notify' signals from it so it can update its zoom property value when camera-source changes its zoom as a side-effect of another operation or because the user set the zoom directly to it, instead of doing it from camerabin2. --- gst/camerabin2/gstcamerabin2.c | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 1caa164048..e554d5b24e 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -1152,6 +1152,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) @@ -1495,6 +1506,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); From a31d541f0757e5a7446acec03c9d1eb20d409ad1 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Wed, 14 Sep 2011 16:14:24 +0200 Subject: [PATCH 31/69] mpegvideoparse: send a video-codec tag https://bugzilla.gnome.org/show_bug.cgi?id=569305 --- gst/videoparsers/gstmpegvideoparse.c | 36 ++++++++++++++++++++++++++++ gst/videoparsers/gstmpegvideoparse.h | 1 + 2 files changed, 37 insertions(+) diff --git a/gst/videoparsers/gstmpegvideoparse.c b/gst/videoparsers/gstmpegvideoparse.c index bbf4194f9e..f1593e1066 100644 --- a/gst/videoparsers/gstmpegvideoparse.c +++ b/gst/videoparsers/gstmpegvideoparse.c @@ -71,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); @@ -164,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 @@ -187,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)); @@ -653,6 +658,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 6837a316e4..593c53e8b8 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; From 10215d26de0b8731b66d3d970a985ed652c6323b Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Mon, 12 Sep 2011 13:41:41 -0300 Subject: [PATCH 32/69] codecparsers: mpegvideo: Change broken_gop to broken_link This way we respect the standard naming --- gst-libs/gst/codecparsers/gstmpegvideoparser.c | 2 +- gst-libs/gst/codecparsers/gstmpegvideoparser.h | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstmpegvideoparser.c b/gst-libs/gst/codecparsers/gstmpegvideoparser.c index 44df76ad5e..6ac70d965d 100644 --- a/gst-libs/gst/codecparsers/gstmpegvideoparser.c +++ b/gst-libs/gst/codecparsers/gstmpegvideoparser.c @@ -745,7 +745,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 a42792b81b..e5b1af2e4f 100644 --- a/gst-libs/gst/codecparsers/gstmpegvideoparser.h +++ b/gst-libs/gst/codecparsers/gstmpegvideoparser.h @@ -314,7 +314,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 +325,7 @@ struct _GstMpegVideoGop guint8 hour, minute, second, frame; guint8 closed_gop; - guint8 broken_gop; + guint8 broken_link; }; /** From 309df7e1e89ac3108162f6f7b5adb4724c0c9117 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Mon, 12 Sep 2011 13:54:37 -0300 Subject: [PATCH 33/69] codecparsers: mpegvideo: Add the ChromaType enum --- gst-libs/gst/codecparsers/gstmpegvideoparser.h | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/gst-libs/gst/codecparsers/gstmpegvideoparser.h b/gst-libs/gst/codecparsers/gstmpegvideoparser.h index e5b1af2e4f..13653e5df1 100644 --- a/gst-libs/gst/codecparsers/gstmpegvideoparser.h +++ b/gst-libs/gst/codecparsers/gstmpegvideoparser.h @@ -111,6 +111,22 @@ typedef enum { GST_MPEG_VIDEO_PROFILE_SIMPLE = 0x05 } GstMpegVideoProfile; +/** + * GstMpegVideoChromaFormat: + * @GST_MPEG_VIDEO_CHROMA_RES, + * @GST_MPEG_VIDEO_CHROMA_420, + * @GST_MPEG_VIDEO_CHROMA_422, + * @GST_MPEG_VIDEO_CHROMA_444, + * + * Indicates the chroma 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 From f396baa3af7486abf5fb2449b24807ed3058d7a4 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Tue, 13 Sep 2011 20:38:27 -0300 Subject: [PATCH 34/69] codecparsers: mpegvideo: Debugging symbols enhancements --- gst-libs/gst/codecparsers/gstmpegvideoparser.c | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstmpegvideoparser.c b/gst-libs/gst/codecparsers/gstmpegvideoparser.c index 6ac70d965d..c8a300e30c 100644 --- a/gst-libs/gst/codecparsers/gstmpegvideoparser.c +++ b/gst-libs/gst/codecparsers/gstmpegvideoparser.c @@ -654,24 +654,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,7 +701,7 @@ 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; } } From df551c0af4d2893e157afcc8af9c274d5546596b Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Tue, 13 Sep 2011 20:40:35 -0300 Subject: [PATCH 35/69] mpegvideoparse: Handle properly frame detection Handle the case where we have buffers containing no startcode in the middle of a frame properly. --- gst/videoparsers/gstmpegvideoparse.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/gst/videoparsers/gstmpegvideoparse.c b/gst/videoparsers/gstmpegvideoparse.c index f1593e1066..5db0080a1b 100644 --- a/gst/videoparsers/gstmpegvideoparse.c +++ b/gst/videoparsers/gstmpegvideoparse.c @@ -493,9 +493,16 @@ 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; From b872f84c9696b4c9f562d56f87859059e8443717 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Thu, 15 Sep 2011 18:17:24 -0400 Subject: [PATCH 36/69] spanplc: Fix typos --- ext/spandsp/gstspanplc.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/ext/spandsp/gstspanplc.c b/ext/spandsp/gstspanplc.c index 90a7c10920..58edce9f4a 100644 --- a/ext/spandsp/gstspanplc.c +++ b/ext/spandsp/gstspanplc.c @@ -94,8 +94,8 @@ gst_span_plc_class_init (GstSpanPlcClass * klass) gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_span_plc_change_state); - GST_DEBUG_CATEGORY_INIT (gst_span_plc_debug, "spandlc", - 0, "spandlc's packet loss concealment"); + GST_DEBUG_CATEGORY_INIT (gst_span_plc_debug, "spanplc", + 0, "spanDSP's packet loss concealment"); } static void From cc27a7fe3a4b3df3e629b539271dd992ea3c577f Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Thu, 15 Sep 2011 17:35:44 -0300 Subject: [PATCH 37/69] camerabin2: Reset last state change result on state-locked elements An element stores the result for the last state change it did and GstBin's state change handler will use this last result for state locked elements to decide if its state change was successfull or not. In camerabin2, the filesinks have their state locked and when they fail switching states, this last failure will be used if the application tries to change camerabin2's state, causing any state change to fail. This patch makes camerabin2 reset this last change failure, avoiding that camerabin2 fails on its next state changes. --- gst/camerabin2/gstcamerabin2.c | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index e554d5b24e..aac9cc3d19 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -485,7 +485,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); } @@ -1219,7 +1224,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; From 25c3ce9a7aeb80f500b8c6070c9ee2a1290ac0a9 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 14 Sep 2011 15:20:09 +0100 Subject: [PATCH 38/69] camerabin2: replace deprecated g_atomic_int_exchange_and_add It was replaced by g_atomic_int_add, which now returns the old value. https://bugzilla.gnome.org/show_bug.cgi?id=659061 --- gst/camerabin2/gstcamerabin2.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index aac9cc3d19..812f1bfddd 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -166,9 +166,15 @@ #include #include +#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", \ From b8f9c3b39d18e1b16bc167a0112df7a4de045ce6 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Fri, 16 Sep 2011 00:32:02 -0300 Subject: [PATCH 39/69] camerabin2: Adding 2 more log messages --- gst/camerabin2/gstcamerabin2.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index 812f1bfddd..d55dd5c2a3 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -927,6 +927,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); @@ -941,6 +943,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)); } } From ac5121eb018ec7da6a76c28cc4dcb41474731261 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Mon, 12 Sep 2011 11:17:20 +0100 Subject: [PATCH 40/69] h264parse: do not try to read from a non existent VUI https://bugzilla.gnome.org/show_bug.cgi?id=658800 --- gst-libs/gst/codecparsers/gsth264parser.c | 30 ++++++++++++++--------- 1 file changed, 18 insertions(+), 12 deletions(-) diff --git a/gst-libs/gst/codecparsers/gsth264parser.c b/gst-libs/gst/codecparsers/gsth264parser.c index 1378d3ac51..237190c16e 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.c +++ b/gst-libs/gst/codecparsers/gsth264parser.c @@ -1468,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 (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); + 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; From c8bda2ed76c09d3caae00b69bee486c114b31331 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Tue, 13 Sep 2011 16:24:32 +0100 Subject: [PATCH 41/69] kate: flush on seek, and ensure we cancel any waiting buffer This is what pango textoverlay does, and I've had that condition variable get stuck once. https://bugzilla.gnome.org/show_bug.cgi?id=658940 --- ext/kate/gstkatetiger.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/kate/gstkatetiger.c b/ext/kate/gstkatetiger.c index 81ac6f7555..2916460c8b 100644 --- a/ext/kate/gstkatetiger.c +++ b/ext/kate/gstkatetiger.c @@ -858,9 +858,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) { From 90b2484648e3370edce45d53b29a3a9af6d4cd90 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 14 Sep 2011 17:07:50 +0100 Subject: [PATCH 42/69] celtenc: allow actually overriding frame size https://bugzilla.gnome.org/show_bug.cgi?id=659087 --- ext/celt/gstceltenc.c | 7 ++++++- ext/celt/gstceltenc.h | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/ext/celt/gstceltenc.c b/ext/celt/gstceltenc.c index 74815798e1..5579bef17a 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; @@ -1090,7 +1094,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 ec8a283c03..86fbc36f37 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; From 37e688197d65b632606e32d2dd758b10a2767d0b Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 14 Sep 2011 17:26:05 +0100 Subject: [PATCH 43/69] celtdec: fix error checking with libcelt 0.11 The return value of celt_decode has changed, newer versions now return positive values on success. https://bugzilla.gnome.org/show_bug.cgi?id=659087 --- ext/celt/gstceltdec.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/ext/celt/gstceltdec.c b/ext/celt/gstceltdec.c index f80e5cdb18..bb4acdfe3a 100644 --- a/ext/celt/gstceltdec.c +++ b/ext/celt/gstceltdec.c @@ -760,7 +760,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; } From 06764fcd3f6c738075cf52f8858a157cf8a350b9 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 14 Sep 2011 19:09:30 +0100 Subject: [PATCH 44/69] celtenc: do not use invalid buffer timestamps https://bugzilla.gnome.org/show_bug.cgi?id=659087 --- ext/celt/gstceltenc.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/celt/gstceltenc.c b/ext/celt/gstceltenc.c index 5579bef17a..e602e09f06 100644 --- a/ext/celt/gstceltenc.c +++ b/ext/celt/gstceltenc.c @@ -970,6 +970,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; From d8684fffa12a13d32efb8e74b8cd23519b3d76f6 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 14 Sep 2011 19:56:40 +0100 Subject: [PATCH 45/69] celtenc: cleanup header creation Avoid an extra copy via a temporary fixed size stack buffer. Use libcelt's header size to allocate a buffer of the correct size in the first place (libcelt has an off by 4 there, so account for this). While there, make size unsigned, and granpos signed. https://bugzilla.gnome.org/show_bug.cgi?id=659087 --- ext/celt/gstceltenc.c | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) diff --git a/ext/celt/gstceltenc.c b/ext/celt/gstceltenc.c index e602e09f06..2b09238d25 100644 --- a/ext/celt/gstceltenc.c +++ b/ext/celt/gstceltenc.c @@ -699,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; } @@ -907,11 +909,13 @@ 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); + celt_header_to_packet (&enc->header, data, header_size); + buf1 = gst_celt_enc_buffer_from_data (enc, data, header_size, 0); /* create comment buffer */ buf2 = gst_celt_enc_create_metadata_buffer (enc); From fe0a2ec885226b2fa004b8d30514ce0f81ed3e28 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 14 Sep 2011 20:22:42 +0100 Subject: [PATCH 46/69] celt: a bit more error checking on header parsing https://bugzilla.gnome.org/show_bug.cgi?id=659087 --- ext/celt/gstceltdec.c | 5 ++++- ext/celt/gstceltenc.c | 13 ++++++++++++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/ext/celt/gstceltdec.c b/ext/celt/gstceltdec.c index bb4acdfe3a..6d3d9433c6 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; diff --git a/ext/celt/gstceltenc.c b/ext/celt/gstceltenc.c index 2b09238d25..9e6944df0f 100644 --- a/ext/celt/gstceltenc.c +++ b/ext/celt/gstceltenc.c @@ -914,7 +914,11 @@ gst_celt_enc_chain (GstPad * pad, GstBuffer * buf) unsigned char *data = g_malloc (header_size); /* create header buffer */ - celt_header_to_packet (&enc->header, data, header_size); + 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 */ @@ -1047,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; + } } From 837500af07124c19fbad891a9edf57a38d15c025 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Sat, 10 Sep 2011 11:31:20 +0100 Subject: [PATCH 47/69] rtpvp8: fix bitstream parsing using the wrong kind of bitreader VP8 uses a probabilistic bool coder, not a straight bit coder. This fixes parsing when error-resilient is set. This commit includes a copy of libvpx's bool coder, BSD licensed. https://bugzilla.gnome.org/show_bug.cgi?id=652694 --- gst/rtpvp8/Makefile.am | 6 +- gst/rtpvp8/dboolhuff.LICENSE | 30 +++++++ gst/rtpvp8/dboolhuff.c | 68 ++++++++++++++++ gst/rtpvp8/dboolhuff.h | 151 +++++++++++++++++++++++++++++++++++ gst/rtpvp8/gstrtpvp8pay.c | 112 ++++++++++---------------- 5 files changed, 297 insertions(+), 70 deletions(-) create mode 100644 gst/rtpvp8/dboolhuff.LICENSE create mode 100644 gst/rtpvp8/dboolhuff.c create mode 100644 gst/rtpvp8/dboolhuff.h diff --git a/gst/rtpvp8/Makefile.am b/gst/rtpvp8/Makefile.am index ef7425f1d7..e1725bbb38 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 0000000000..7a6f99547d --- /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 0000000000..0e1fd6e2fa --- /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 0000000000..41b0f5d9a4 --- /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 +#include +#include + +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 c6c773dcaf..d3795da3ba 100644 --- a/gst/rtpvp8/gstrtpvp8pay.c +++ b/gst/rtpvp8/gstrtpvp8pay.c @@ -25,6 +25,7 @@ #include #include #include +#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; } + offset = keyframe ? 10 : 3; + vp8dx_start_decode (&bc, GST_BUFFER_DATA (buffer) + offset, + GST_BUFFER_SIZE (buffer) - offset); + + if (keyframe) { + /* color space (1 bit) and clamping type (1 bit) */ + vp8dx_decode_bool (&bc, 0x80); + vp8dx_decode_bool (&bc, 0x80); + } + /* segmentation_enabled */ - if (!gst_bit_reader_get_bits_uint8 (reader, &tmp8, 1)) - goto error; - - 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; - - update_mb_segmentation_map = (tmp8 & 0x2) != 0; - update_segment_feature_data = (tmp8 & 0x1) != 0; + 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 (vp8dx_decode_bool (&bc, 0x80)) { - if (tmp8 != 0) { - /* loop filter adj enabled */ - - /* 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 */ From e6212219ed29fecdc0640bc91fa438290ae8ae93 Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Mon, 19 Sep 2011 13:41:44 +0200 Subject: [PATCH 48/69] codecparsinglibs: Doc and indentation fixes --- gst-libs/gst/codecparsers/gsth264parser.c | 18 +-- gst-libs/gst/codecparsers/gsth264parser.h | 35 +++--- .../gst/codecparsers/gstmpegvideoparser.c | 48 ++++---- .../gst/codecparsers/gstmpegvideoparser.h | 111 ++++++++++-------- 4 files changed, 114 insertions(+), 98 deletions(-) diff --git a/gst-libs/gst/codecparsers/gsth264parser.c b/gst-libs/gst/codecparsers/gsth264parser.c index 237190c16e..b496c0fef1 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.c +++ b/gst-libs/gst/codecparsers/gsth264parser.c @@ -1136,7 +1136,7 @@ gst_h264_nal_parser_new (void) /** * gst_h264_nal_parser_free: - * @nalparser the #GstH264NalParser to free + * @nalparser: the #GstH264NalParser to free * * Frees @nalparser and sets it to %NULL */ @@ -1270,7 +1270,7 @@ gst_h264_parser_identify_nalu_avc (GstH264NalParser * nalparser, * @nalparser: a #GstH264NalParser * @nalu: The #GstH264NalUnit to parse * - * This function should be called in the case you don't need to + * 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. * @@ -1296,8 +1296,8 @@ 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 fill. + * @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 @data, and fills the @sps structure. @@ -1324,7 +1324,7 @@ gst_h264_parser_parse_sps (GstH264NalParser * nalparser, GstH264NalUnit * nalu, /** * gst_h264_parse_sps: - * @nalu: The #GST_H264_NAL_SPS #GstH264NalUnit you want to parse + * @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 * @@ -1502,7 +1502,7 @@ error: /** * gst_h264_parse_pps: * @nalparser: a #GstH264NalParser - * @nalu: The #GST_H264_NAL_PPS #GstH264NalUnit you want to parse + * @nalu: The #GST_H264_NAL_PPS #GstH264NalUnit to parse * @pps: The #GstH264PPS to fill. * * Parses @data, and fills the @pps structure. @@ -1631,7 +1631,7 @@ error: /** * gst_h264_parser_parse_pps: * @nalparser: a #GstH264NalParser - * @nalu: The #GST_H264_NAL_PPS #GstH264NalUnit you want to parse + * @nalu: The #GST_H264_NAL_PPS #GstH264NalUnit to parse * @pps: The #GstH264PPS to fill. * * Parses @data, and fills the @pps structure. @@ -1657,7 +1657,7 @@ gst_h264_parser_parse_pps (GstH264NalParser * nalparser, /** * gst_h264_parser_parse_slice_hdr: * @nalparser: a #GstH264NalParser - * @nalu: The #GST_H264_NAL_SLICE #GstH264NalUnit you want to parse + * @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 @@ -1834,7 +1834,7 @@ error: /** * gst_h264_parser_parse_sei: * @nalparser: a #GstH264NalParser - * @nalu: The #GST_H264_NAL_SEI #GstH264NalUnit you want to parse + * @nalu: The #GST_H264_NAL_SEI #GstH264NalUnit to parse * @sei: The #GstH264SEIMessage to fill. * * Parses @data, and fills the @sei structures. diff --git a/gst-libs/gst/codecparsers/gsth264parser.h b/gst-libs/gst/codecparsers/gsth264parser.h index 84577f686b..ea808a6770 100644 --- a/gst-libs/gst/codecparsers/gsth264parser.h +++ b/gst-libs/gst/codecparsers/gsth264parser.h @@ -45,19 +45,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 +81,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 +101,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 +294,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 +363,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 +429,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 c8a300e30c..1a2ddcc262 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 */ @@ -373,12 +373,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. */ @@ -400,12 +400,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. */ @@ -464,12 +464,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, @@ -537,12 +537,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. @@ -636,14 +636,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, @@ -708,13 +709,12 @@ failed: /** * 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. */ diff --git a/gst-libs/gst/codecparsers/gstmpegvideoparser.h b/gst-libs/gst/codecparsers/gstmpegvideoparser.h index 13653e5df1..8bdf684770 100644 --- a/gst-libs/gst/codecparsers/gstmpegvideoparser.h +++ b/gst-libs/gst/codecparsers/gstmpegvideoparser.h @@ -56,33 +56,44 @@ typedef enum { GST_MPEG_VIDEO_PACKET_NONE = 0xff } 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 +104,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, @@ -113,12 +124,12 @@ typedef enum { /** * GstMpegVideoChromaFormat: - * @GST_MPEG_VIDEO_CHROMA_RES, - * @GST_MPEG_VIDEO_CHROMA_420, - * @GST_MPEG_VIDEO_CHROMA_422, - * @GST_MPEG_VIDEO_CHROMA_444, + * @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) * - * Indicates the chroma type + * Chroma subsampling type. */ typedef enum { GST_MPEG_VIDEO_CHROMA_RES = 0x00, @@ -129,12 +140,12 @@ typedef enum { /** * 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, @@ -147,9 +158,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, @@ -184,20 +195,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; }; /** @@ -210,7 +221,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 @@ -238,14 +249,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 */ @@ -355,11 +366,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); From 66f644cfcc2106d5387a02ada91ff29af098ad38 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 19 Sep 2011 14:07:52 +0200 Subject: [PATCH 49/69] h264parse: bring debug statements up to desired specs --- gst/videoparsers/gsth264parse.c | 43 ++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/gst/videoparsers/gsth264parse.c b/gst/videoparsers/gsth264parse.c index c64361ccdd..d2009d60ef 100644 --- a/gst/videoparsers/gsth264parse.c +++ b/gst/videoparsers/gsth264parse.c @@ -339,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) { @@ -365,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; @@ -477,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 */ @@ -487,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 */ @@ -504,8 +505,8 @@ gst_h264_parse_process_nal (GstH264Parse * h264parse, GstH264NalUnit * nalu) 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); @@ -534,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); @@ -615,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; @@ -646,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 @@ -663,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; @@ -680,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) @@ -700,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 */ From b142663ca53c8d2bb8d4d03ded72ec960d2ca8a4 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 19 Sep 2011 14:54:11 +0200 Subject: [PATCH 50/69] h263parse: bring debug statements up to desired specs --- gst/videoparsers/gsth263parse.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/gst/videoparsers/gsth263parse.c b/gst/videoparsers/gsth263parse.c index d83f8ef2ef..4a5633f3bc 100644 --- a/gst/videoparsers/gsth263parse.c +++ b/gst/videoparsers/gsth263parse.c @@ -101,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; @@ -117,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; } @@ -138,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; } @@ -200,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); @@ -307,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; From 7d5bd1992ecfab4d511199b8b70ff13169cf2a5f Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Mon, 19 Sep 2011 16:32:58 +0200 Subject: [PATCH 51/69] codecparsers: Add checks to input, and fix size checking --- .../gst/codecparsers/gstmpegvideoparser.c | 25 +++++++++++++------ 1 file changed, 18 insertions(+), 7 deletions(-) diff --git a/gst-libs/gst/codecparsers/gstmpegvideoparser.c b/gst-libs/gst/codecparsers/gstmpegvideoparser.c index 1a2ddcc262..e871017fa0 100644 --- a/gst-libs/gst/codecparsers/gstmpegvideoparser.c +++ b/gst-libs/gst/codecparsers/gstmpegvideoparser.c @@ -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", @@ -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); @@ -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"); @@ -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"); @@ -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; @@ -724,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; From 43ec4f46b8b4ebdc5aae2aef0667db5c188621d0 Mon Sep 17 00:00:00 2001 From: Thiago Santos Date: Tue, 20 Sep 2011 13:00:49 -0300 Subject: [PATCH 52/69] basecamerasrc: Fail state change if preview pipeline fails creation If the preview pipeline fails creation, for any reason, we should fail basecamerasrc state change. Also adds a missing g_return_if_fail check to preview pipeline functions --- gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c | 6 +++++- gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c | 2 ++ 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c b/gst-libs/gst/basecamerabinsrc/gstbasecamerasrc.c index 56bdc6cf68..d5b8ed7728 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 5dd82dad16..be42c98dc1 100644 --- a/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c +++ b/gst-libs/gst/basecamerabinsrc/gstcamerabinpreview.c @@ -231,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; From 70be630427c47c3e9cfe1d98b5e9487fd76444ac Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Tue, 20 Sep 2011 16:54:32 +0100 Subject: [PATCH 53/69] kate: forward return code from setting src pad caps https://bugzilla.gnome.org/show_bug.cgi?id=659606 --- ext/kate/gstkatetiger.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/ext/kate/gstkatetiger.c b/ext/kate/gstkatetiger.c index 2916460c8b..41da4db151 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 From c8a35679233a6d1f3c2616bc37fad0e2d7da86bc Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Wed, 21 Sep 2011 16:01:28 +0200 Subject: [PATCH 54/69] faac: port to audioencoder --- ext/faac/Makefile.am | 3 +- ext/faac/gstfaac.c | 545 ++++++++++++------------------------------- ext/faac/gstfaac.h | 42 ++-- 3 files changed, 174 insertions(+), 416 deletions(-) diff --git a/ext/faac/Makefile.am b/ext/faac/Makefile.am index 13918ed3ea..2aafa02298 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 c0db878d5b..b18733fd10 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,35 +113,39 @@ enum PROP_SHORTCTL }; +enum +{ + VBR = 1, + ABR +}; + 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); 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 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); static GstElementClass *parent_class = NULL; 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 @@ -169,17 +167,9 @@ gst_faac_get_type (void) 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, + gst_faac_type = g_type_register_static (GST_TYPE_AUDIO_ENCODER, "GstFaac", &gst_faac_info, 0); - - g_type_add_interface_static (gst_faac_type, GST_TYPE_PRESET, - &preset_interface_info); } return gst_faac_type; @@ -248,96 +238,53 @@ 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) { - 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) -{ - faac->handle = NULL; - faac->samplerate = -1; - faac->channels = -1; - faac->offset = 0; - gst_adapter_clear (faac->adapter); -} - -static void -gst_faac_finalize (GObject * object) -{ - GstFaac *faac = (GstFaac *) object; - - g_object_unref (faac->adapter); - - G_OBJECT_CLASS (parent_class)->finalize (object); } static void @@ -346,8 +293,25 @@ gst_faac_close_encoder (GstFaac * faac) if (faac->handle) faacEncClose (faac->handle); faac->handle = NULL; - gst_adapter_clear (faac->adapter); - faac->offset = 0; +} + +static gboolean +gst_faac_start (GstAudioEncoder * enc) +{ + GstFaac *faac = GST_FAAC (enc); + + GST_DEBUG_OBJECT (faac, "start"); + return TRUE; +} + +static gboolean +gst_faac_stop (GstAudioEncoder * enc) +{ + 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 +344,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,12 +397,78 @@ 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); + return gst_audio_encoder_proxy_getcaps (enc, (GstCaps *) sinkcaps); +} + +static gboolean +gst_faac_set_format (GstAudioEncoder * enc, GstAudioInfo * info) +{ + GstFaac *faac = GST_FAAC (enc); + faacEncHandle *handle; + gint channels, samplerate, width; + gulong samples, bytes, fmt = 0, bps = 0; + gboolean result = FALSE; + + /* base class takes care */ + channels = GST_AUDIO_INFO_CHANNELS (info); + samplerate = GST_AUDIO_INFO_RATE (info); + width = GST_AUDIO_INFO_WIDTH (info); + + if (GST_AUDIO_INFO_IS_INTEGER (info)) { + switch (width) { + case 16: + fmt = FAAC_INPUT_16BIT; + bps = 2; + break; + case 24: + case 32: + fmt = FAAC_INPUT_32BIT; + bps = 4; + break; + default: + g_return_val_if_reached (FALSE); + } + } else { + fmt = FAAC_INPUT_FLOAT; + bps = 4; + } + + /* clean up in case of re-configure */ + gst_faac_close_encoder (faac); + + if (!(handle = faacEncOpen (samplerate, channels, &samples, &bytes))) + goto setup_failed; + + /* ok, record and set up */ + faac->format = fmt; + faac->bps = bps; + faac->handle = handle; + faac->bytes = bytes; + faac->samples = samples; + faac->channels = channels; + faac->samplerate = samplerate; + + /* finish up */ + result = gst_faac_configure_source_pad (faac); + + /* report needs to base class */ + gst_audio_encoder_set_frame_samples (enc, samples); + gst_audio_encoder_set_frame_max (enc, 1); + +done: + return result; + + /* ERRORS */ +setup_failed: + { + GST_ELEMENT_ERROR (faac, LIBRARY, SETTINGS, (NULL), (NULL)); + goto done; + } } /* check downstream caps to configure format */ @@ -447,7 +477,12 @@ gst_faac_negotiate (GstFaac * faac) { GstCaps *caps; - caps = gst_pad_get_allowed_caps (faac->srcpad); + /* 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); @@ -494,94 +529,6 @@ gst_faac_negotiate (GstFaac * faac) gst_caps_unref (caps); } -static gboolean -gst_faac_sink_setcaps (GstPad * pad, GstCaps * caps) -{ - GstFaac *faac = GST_FAAC (gst_pad_get_parent (pad)); - GstStructure *structure = gst_caps_get_structure (caps, 0); - 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; - } - - if (gst_structure_has_name (structure, "audio/x-raw-int")) { - gst_structure_get_int (structure, "width", &width); - switch (width) { - case 16: - fmt = FAAC_INPUT_16BIT; - bps = 2; - break; - case 24: - case 32: - fmt = FAAC_INPUT_32BIT; - bps = 4; - break; - default: - g_return_val_if_reached (FALSE); - } - } else if (gst_structure_has_name (structure, "audio/x-raw-float")) { - 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); - } - - if (!(handle = faacEncOpen (samplerate, channels, &samples, &bytes))) - goto setup_failed; - - /* ok, record and set up */ - faac->format = fmt; - faac->bps = bps; - faac->handle = handle; - faac->bytes = bytes; - faac->samples = samples; - faac->channels = channels; - faac->samplerate = samplerate; - - gst_faac_negotiate (faac); - - /* finish up */ - result = gst_faac_configure_source_pad (faac); - -done: - gst_object_unref (faac); - return result; - - /* ERRORS */ -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; - } -} - static gboolean gst_faac_configure_source_pad (GstFaac * faac) { @@ -590,6 +537,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 +648,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 +667,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; + out_buf = gst_buffer_new_and_alloc (faac->bytes); - 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) */ - - /* 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 +706,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 +776,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 f5ab5ab4f6..5bd0574937 100644 --- a/ext/faac/gstfaac.h +++ b/ext/faac/gstfaac.h @@ -21,8 +21,8 @@ #define __GST_FAAC_H__ #include -#include -#include +#include + #include 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, - quality, - bitrate, - brtype, + bps; + + /* input frame size */ + gulong samples; + /* required output buffer size */ + gulong bytes; + + /* negotiated */ + gint mpegversion, outputformat; + + /* properties */ + gint bitrate, profile, - mpegversion, - shortctl, - outputformat; + quality, + brtype, + 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); From a7ed9677ba1c1a7cf755ff637e801ebf28091dd3 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Wed, 21 Sep 2011 16:11:27 +0200 Subject: [PATCH 55/69] faac: use some more boilerplate --- ext/faac/gstfaac.c | 35 +++-------------------------------- 1 file changed, 3 insertions(+), 32 deletions(-) diff --git a/ext/faac/gstfaac.c b/ext/faac/gstfaac.c index b18733fd10..0f3f9520b6 100644 --- a/ext/faac/gstfaac.c +++ b/ext/faac/gstfaac.c @@ -119,10 +119,6 @@ enum ABR }; -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_set_property (GObject * object, guint prop_id, const GValue * value, GParamSpec * pspec); static void gst_faac_get_property (GObject * object, @@ -138,8 +134,6 @@ static gboolean gst_faac_set_format (GstAudioEncoder * enc, static GstFlowReturn gst_faac_handle_frame (GstAudioEncoder * enc, GstBuffer * in_buf); -static GstElementClass *parent_class = NULL; - GST_DEBUG_CATEGORY_STATIC (faac_debug); #define GST_CAT_DEFAULT faac_debug @@ -150,33 +144,10 @@ GST_DEBUG_CATEGORY_STATIC (faac_debug); #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, - }; - - gst_faac_type = g_type_register_static (GST_TYPE_AUDIO_ENCODER, - "GstFaac", &gst_faac_info, 0); - } - - 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); @@ -283,7 +254,7 @@ gst_faac_class_init (GstFaacClass * klass) } static void -gst_faac_init (GstFaac * faac) +gst_faac_init (GstFaac * faac, GstFaacClass * klass) { } From 7234914e0ffa64b9efb1855a26dbb5d243bccc54 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 22 Sep 2011 09:49:21 +0200 Subject: [PATCH 56/69] faad: port to audiodecoder --- ext/faad/Makefile.am | 3 +- ext/faad/gstfaad.c | 718 ++++++------------------------------------- ext/faad/gstfaad.h | 28 +- 3 files changed, 105 insertions(+), 644 deletions(-) diff --git a/ext/faad/Makefile.am b/ext/faad/Makefile.am index 957ad78496..cc7636dca9 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 1f9c3d228a..0bd47a9f91 100644 --- a/ext/faad/gstfaad.c +++ b/ext/faad/gstfaad.c @@ -144,19 +144,16 @@ 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_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); -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); @@ -180,7 +177,7 @@ gst_faad_get_type (void) (GInstanceInitFunc) gst_faad_init, }; - gst_faad_type = g_type_register_static (GST_TYPE_ELEMENT, + gst_faad_type = g_type_register_static (GST_TYPE_AUDIO_DECODER, "GstFaad", &gst_faad_info, 0); } @@ -208,47 +205,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) { - 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 +233,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); - G_OBJECT_CLASS (parent_class)->finalize (object); + /* 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); + + 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_DEBUG_OBJECT (dec, "stop"); + gst_faad_reset (faad); + gst_faad_close_decoder (faad); - gst_tag_list_add (tags, GST_TAG_MERGE_REPLACE, - GST_TAG_AUDIO_CODEC, "MPEG-4 AAC audio", NULL); - - gst_element_found_tags (GST_ELEMENT (faad), tags); + return TRUE; } static gint @@ -327,9 +302,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 +327,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 +366,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 +396,6 @@ gst_faad_setcaps (GstPad * pad, GstCaps * caps) } } - gst_object_unref (faad); return TRUE; /* ERRORS */ @@ -535,349 +506,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 +563,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 +578,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; GST_LOG_OBJECT (faad, "Finding syncpoint"); @@ -968,8 +597,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); @@ -1013,6 +640,7 @@ gst_faad_sync (GstFaad * faad, guint8 * data, guint size, gboolean next, exit: *off = n; + *length = len; if (!ret) GST_LOG_OBJECT (faad, "Found no syncpoint"); @@ -1038,78 +666,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, FALSE); + + 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)); + faad = GST_FAAD (dec); - 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))); + /* no fancy draining */ + if (G_UNLIKELY (!buffer)) + return GST_FLOW_OK; - 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; - - 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; - } - - 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 +745,6 @@ init: } faad->init = TRUE; - gst_faad_send_tags (faad); /* make sure we create new caps below */ faad->samplerate = 0; @@ -1151,18 +752,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 +772,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 +788,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 (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; - /* 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)); - 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); - } + ret = gst_audio_decoder_finish_frame (dec, outbuf, 1); } - - /* 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; - } - } + } 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 +829,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 +847,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 +889,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 4552250477..deb98b831d 100644 --- a/ext/faad/gstfaad.h +++ b/ext/faad/gstfaad.h @@ -21,7 +21,8 @@ #define __GST_FAAD_H__ #include -#include +#include + #ifdef FAAD_IS_NEAAC #include #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); From 131df954cefe12e98ba2df1737f27ddf1863ee2a Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 22 Sep 2011 16:01:56 +0200 Subject: [PATCH 57/69] faad: use some more boilerplate --- ext/faad/gstfaad.c | 34 +++------------------------------- 1 file changed, 3 insertions(+), 31 deletions(-) diff --git a/ext/faad/gstfaad.c b/ext/faad/gstfaad.c index 0bd47a9f91..ae851da8a1 100644 --- a/ext/faad/gstfaad.c +++ b/ext/faad/gstfaad.c @@ -140,9 +140,6 @@ 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 gboolean gst_faad_start (GstAudioDecoder * dec); @@ -157,35 +154,10 @@ static void gst_faad_flush (GstAudioDecoder * dec, gboolean hard); static gboolean gst_faad_open_decoder (GstFaad * faad); static void gst_faad_close_decoder (GstFaad * faad); -static GstElementClass *parent_class; /* NULL */ - -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_AUDIO_DECODER, - "GstFaad", &gst_faad_info, 0); - } - - 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); @@ -218,7 +190,7 @@ gst_faad_class_init (GstFaadClass * klass) } static void -gst_faad_init (GstFaad * faad) +gst_faad_init (GstFaad * faad, GstFaadClass * klass) { gst_faad_reset (faad); } From 3900dc94ed20f6f990e5673d5206924a991f8f7e Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Thu, 22 Sep 2011 18:23:32 +0200 Subject: [PATCH 58/69] faac: fixup misunderstanding in sample counting ... between codec and audioencoder regarding whether or not channel count is already considered. Fixes #659836. --- ext/faac/gstfaac.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/ext/faac/gstfaac.c b/ext/faac/gstfaac.c index 0f3f9520b6..5530c0a8c7 100644 --- a/ext/faac/gstfaac.c +++ b/ext/faac/gstfaac.c @@ -415,6 +415,9 @@ gst_faac_set_format (GstAudioEncoder * enc, GstAudioInfo * info) 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; From 76dccf91fd5bdbb48e7b066c57b50a2416c78ecc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 22 Sep 2011 20:09:32 +0100 Subject: [PATCH 59/69] docs: add ignore rules for libs docs directory --- docs/libs/.gitignore | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) create mode 100644 docs/libs/.gitignore diff --git a/docs/libs/.gitignore b/docs/libs/.gitignore new file mode 100644 index 0000000000..83bf78579c --- /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 + From ad1883f54d100e0bb2d6aa6ec3463accc6cc26cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 22 Sep 2011 20:11:21 +0100 Subject: [PATCH 60/69] psmux: fix writing of system header, which makes VLC not skip the adjacent PSM and play embedded H.264 streams header_length contains the length in bytes after the header_length field, excluding the 6 byte start code and header_length field. H.264 streams and some other formats need to be announced in the PSM. VLC wouldn't play files created with mpegpsmux containing H.264 because we claim the system header is larger than it actually is, which makes VLC skip the program stream map which follows the system header, which in turn makes it not recognise our H.264 video stream. --- gst/mpegpsmux/psmux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/mpegpsmux/psmux.c b/gst/mpegpsmux/psmux.c index 9d0493c1d9..0a714d038a 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 */ From c9f7e9b26dc83b861f87739febd51a22d6701ebf Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 23 Sep 2011 09:57:01 +0100 Subject: [PATCH 61/69] faad: parse wants a GstFlowReturn return value, not a gboolean --- ext/faad/gstfaad.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/faad/gstfaad.c b/ext/faad/gstfaad.c index ae851da8a1..cc72760275 100644 --- a/ext/faad/gstfaad.c +++ b/ext/faad/gstfaad.c @@ -650,7 +650,7 @@ gst_faad_parse (GstAudioDecoder * dec, GstAdapter * adapter, faad = GST_FAAD (dec); size = gst_adapter_available (adapter); - g_return_val_if_fail (size > 0, FALSE); + g_return_val_if_fail (size > 0, GST_FLOW_ERROR); gst_audio_decoder_get_parse_state (dec, &sync, &eos); From e37634e9f99bf07f36f98af1624f518da094ba48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Fri, 23 Sep 2011 10:10:37 +0100 Subject: [PATCH 62/69] faad: fix compiler warning gstfaad.c: In function 'gst_faad_parse': gstfaad.c:615:11: error: 'len' may be used uninitialized in this function --- ext/faad/gstfaad.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/ext/faad/gstfaad.c b/ext/faad/gstfaad.c index cc72760275..252e9529de 100644 --- a/ext/faad/gstfaad.c +++ b/ext/faad/gstfaad.c @@ -556,7 +556,7 @@ gst_faad_sync (GstFaad * faad, const guint8 * data, guint size, gboolean next, guint n = 0; gint snc; gboolean ret = FALSE; - guint len; + guint len = 0; GST_LOG_OBJECT (faad, "Finding syncpoint"); @@ -611,11 +611,14 @@ gst_faad_sync (GstFaad * faad, const guint8 * data, guint size, gboolean next, } exit: - *off = n; - *length = len; - if (!ret) + *off = n; + + if (ret) { + *length = len; + } else { GST_LOG_OBJECT (faad, "Found no syncpoint"); + } return ret; } From e615cf15a972c07950c65d1358df3a6bfb38e150 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Tue, 20 Sep 2011 16:29:55 +0200 Subject: [PATCH 63/69] irtspparse: add Interleaved RTSP parser element --- gst/pcapparse/Makefile.am | 4 +- gst/pcapparse/gstirtspparse.c | 255 ++++++++++++++++++++++++++++++++++ gst/pcapparse/gstirtspparse.h | 70 ++++++++++ gst/pcapparse/gstpcapparse.c | 14 -- gst/pcapparse/plugin.c | 44 ++++++ 5 files changed, 371 insertions(+), 16 deletions(-) create mode 100644 gst/pcapparse/gstirtspparse.c create mode 100644 gst/pcapparse/gstirtspparse.h create mode 100644 gst/pcapparse/plugin.c diff --git a/gst/pcapparse/Makefile.am b/gst/pcapparse/Makefile.am index 08a9d25ada..6c357f2097 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 0000000000..26317e622b --- /dev/null +++ b/gst/pcapparse/gstirtspparse.c @@ -0,0 +1,255 @@ +/* GStreamer Interleaved RTSP parser + * Copyright (C) 2011 Mark Nauwelaerts + * Copyright (C) 2011 Nokia Corporation. All rights reserved. + * Contact: Stefan Kost + * + * 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). + * + * + * Example launch line + * |[ + * 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. + * + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include + +#include "gstirtspparse.h" +#include + +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 "); +} + +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 0000000000..a3d613f2ab --- /dev/null +++ b/gst/pcapparse/gstirtspparse.h @@ -0,0 +1,70 @@ +/* GStreamer Interleaved RTSP parser + * Copyright (C) 2011 Mark Nauwelaerts + * Copyright (C) 2011 Nokia Corporation. All rights reserved. + * Contact: Stefan Kost + * + * 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 +#include + +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 5963916679..16eb58c5ab 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 0000000000..d034e3d03c --- /dev/null +++ b/gst/pcapparse/plugin.c @@ -0,0 +1,44 @@ +/* + * Copyright 2007 Ole André Vadla Ravnås + * + * 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/") From 38cdb54112734ff0fd0f894324d9469e0b04ab3e Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Mon, 26 Sep 2011 11:44:02 +0100 Subject: [PATCH 64/69] mpegtsdemux: keep CRC table in .rodata https://bugzilla.gnome.org/show_bug.cgi?id=660118 --- gst/mpegdemux/gstmpegtsdemux.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index 986914d0c9..849cda0aa3 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, From 2c928aba19f7dd6caad556ada8060704e3184550 Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Fri, 16 Sep 2011 19:03:31 -0300 Subject: [PATCH 65/69] codecparsers: Declare the new APIs as unstable for the time being --- gst-libs/gst/codecparsers/gsth264parser.h | 5 +++++ gst-libs/gst/codecparsers/gstmpegvideoparser.h | 5 +++++ gst/videoparsers/Makefile.am | 1 + tests/check/Makefile.am | 2 ++ 4 files changed, 13 insertions(+) diff --git a/gst-libs/gst/codecparsers/gsth264parser.h b/gst-libs/gst/codecparsers/gsth264parser.h index ea808a6770..2dfe2d7b63 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 G_BEGIN_DECLS diff --git a/gst-libs/gst/codecparsers/gstmpegvideoparser.h b/gst-libs/gst/codecparsers/gstmpegvideoparser.h index 8bdf684770..a212a94445 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 G_BEGIN_DECLS diff --git a/gst/videoparsers/Makefile.am b/gst/videoparsers/Makefile.am index 811d5f860a..ac2a517119 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/tests/check/Makefile.am b/tests/check/Makefile.am index 47bd813c98..d09991db1e 100644 --- a/tests/check/Makefile.am +++ b/tests/check/Makefile.am @@ -218,6 +218,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 +228,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 = \ From 705a80d957fe8ebb703c465068b034798b9b0d8c Mon Sep 17 00:00:00 2001 From: Thibault Saunier Date: Tue, 23 Aug 2011 18:25:20 -0300 Subject: [PATCH 66/69] codecparser: VC1: Implement a VC1 parsing library --- docs/libs/gst-plugins-bad-libs-docs.sgml | 1 + docs/libs/gst-plugins-bad-libs-sections.txt | 34 + gst-libs/gst/codecparsers/Makefile.am | 20 +- gst-libs/gst/codecparsers/gstvc1parser.c | 1442 +++++++++++++++++++ gst-libs/gst/codecparsers/gstvc1parser.h | 468 ++++++ tests/check/Makefile.am | 11 + tests/check/libs/vc1parser.c | 1230 ++++++++++++++++ 7 files changed, 3201 insertions(+), 5 deletions(-) create mode 100644 gst-libs/gst/codecparsers/gstvc1parser.c create mode 100644 gst-libs/gst/codecparsers/gstvc1parser.h create mode 100644 tests/check/libs/vc1parser.c diff --git a/docs/libs/gst-plugins-bad-libs-docs.sgml b/docs/libs/gst-plugins-bad-libs-docs.sgml index f137ca3c2f..bc648842e5 100644 --- a/docs/libs/gst-plugins-bad-libs-docs.sgml +++ b/docs/libs/gst-plugins-bad-libs-docs.sgml @@ -30,6 +30,7 @@ + diff --git a/docs/libs/gst-plugins-bad-libs-sections.txt b/docs/libs/gst-plugins-bad-libs-sections.txt index 73cc720197..cd515e6af6 100644 --- a/docs/libs/gst-plugins-bad-libs-sections.txt +++ b/docs/libs/gst-plugins-bad-libs-sections.txt @@ -44,6 +44,40 @@ gst_h264_parse_pps
+
+gstvc1parser +vc1parser +gst/codecparsers/gstvc1parser.h +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 + + +
+
gstmpegvideoparser mpegvideoparser diff --git a/gst-libs/gst/codecparsers/Makefile.am b/gst-libs/gst/codecparsers/Makefile.am index 7fa44f1585..c3dfe93077 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/gstvc1parser.c b/gst-libs/gst/codecparsers/gstvc1parser.c new file mode 100644 index 0000000000..8b0b785672 --- /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 + * + * 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 +#include +#include + +#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, ¤t, 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 0000000000..511df64170 --- /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 + * + * 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 + +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/tests/check/Makefile.am b/tests/check/Makefile.am index d09991db1e..75750ea99f 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 \ @@ -236,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/vc1parser.c b/tests/check/libs/vc1parser.c new file mode 100644 index 0000000000..5c9ef73ee5 --- /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 + * + * 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 +#include + +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; +} From 874da87b252946c70a24aca7b510045f42ef7478 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 26 Sep 2011 16:05:40 +0200 Subject: [PATCH 67/69] faac: Simple fix for GstAudioEncoder API change --- ext/faac/gstfaac.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/faac/gstfaac.c b/ext/faac/gstfaac.c index 5530c0a8c7..22dfa6ec2b 100644 --- a/ext/faac/gstfaac.c +++ b/ext/faac/gstfaac.c @@ -431,7 +431,7 @@ gst_faac_set_format (GstAudioEncoder * enc, GstAudioInfo * info) result = gst_faac_configure_source_pad (faac); /* report needs to base class */ - gst_audio_encoder_set_frame_samples (enc, samples); + gst_audio_encoder_set_frame_samples_min (enc, samples); gst_audio_encoder_set_frame_max (enc, 1); done: From fc2434fd97fee9cae4a32f4e2865e044fcf5b679 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 26 Sep 2011 16:26:31 +0200 Subject: [PATCH 68/69] faac: Also set maximum number of samples that the subclass wants --- ext/faac/gstfaac.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/faac/gstfaac.c b/ext/faac/gstfaac.c index 22dfa6ec2b..eb132d3b4c 100644 --- a/ext/faac/gstfaac.c +++ b/ext/faac/gstfaac.c @@ -432,6 +432,7 @@ gst_faac_set_format (GstAudioEncoder * enc, GstAudioInfo * info) /* 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: From f4e744ff4921bef432b40128bdd0b33786e44732 Mon Sep 17 00:00:00 2001 From: Robert Swain Date: Mon, 26 Sep 2011 17:23:41 +0200 Subject: [PATCH 69/69] camerabin2: Stop the audio source between captures Move the audio source setting of state to NULL to _stop_capture () to avoid the audio source running between captures. --- gst/camerabin2/gstcamerabin2.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/gst/camerabin2/gstcamerabin2.c b/gst/camerabin2/gstcamerabin2.c index d55dd5c2a3..5a227138e2 100644 --- a/gst/camerabin2/gstcamerabin2.c +++ b/gst/camerabin2/gstcamerabin2.c @@ -380,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); @@ -452,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); } }