From 95d894fd965dd3c20c3d62f9d32dc3a89a459497 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Wed, 2 Sep 2009 13:35:02 +0100 Subject: [PATCH 01/19] mpegsmux, mpegpsmux: fix unused variable warning with the debugging system in core disabled --- gst/mpegpsmux/mpegpsmux.c | 3 +-- gst/mpegtsmux/mpegtsmux.c | 3 +-- gst/mpegtsmux/mpegtsmux.h | 2 ++ 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/gst/mpegpsmux/mpegpsmux.c b/gst/mpegpsmux/mpegpsmux.c index da31f28a4f..59c19aa5bb 100644 --- a/gst/mpegpsmux/mpegpsmux.c +++ b/gst/mpegpsmux/mpegpsmux.c @@ -484,14 +484,13 @@ mpegpsmux_collected (GstCollectPads * pads, MpegPsMux * mux) if (best != NULL) { /* @*buf : the buffer to be processed */ GstBuffer *buf = best->queued_buf; - GstCollectData *c_data = (GstCollectData *) best; gint64 pts = -1; g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); GST_DEBUG_OBJECT (mux, "Chose stream from pad %" GST_PTR_FORMAT " for output (PID: 0x%04x)", - c_data->pad, best->stream_id); + best->collect.pad, best->stream_id); /* set timestamp */ if (GST_CLOCK_TIME_IS_VALID (best->cur_ts)) { diff --git a/gst/mpegtsmux/mpegtsmux.c b/gst/mpegtsmux/mpegtsmux.c index 4ad22e7458..d0d02fa5bf 100644 --- a/gst/mpegtsmux/mpegtsmux.c +++ b/gst/mpegtsmux/mpegtsmux.c @@ -630,11 +630,10 @@ mpegtsmux_collected (GstCollectPads * pads, MpegTsMux * mux) if (G_UNLIKELY (prog->pcr_stream == NULL)) { if (best) { - MpegTsPadData *ts_data = (MpegTsPadData *) best; /* Take the first data stream for the PCR */ GST_DEBUG_OBJECT (COLLECT_DATA_PAD (best), "Use stream (pid=%d) from pad as PCR for program (prog_id = %d)", - ts_data->pid, ts_data->prog_id); + MPEG_TS_PAD_DATA (best)->pid, MPEG_TS_PAD_DATA (best)->prog_id); /* Set the chosen PCR stream */ tsmux_program_set_pcr_stream (prog, best->stream); diff --git a/gst/mpegtsmux/mpegtsmux.h b/gst/mpegtsmux/mpegtsmux.h index 2ebb7251dc..81668ba891 100644 --- a/gst/mpegtsmux/mpegtsmux.h +++ b/gst/mpegtsmux/mpegtsmux.h @@ -126,6 +126,8 @@ struct MpegTsMuxClass { GstElementClass parent_class; }; +#define MPEG_TS_PAD_DATA(data) ((MpegTsPadData *)(data)) + struct MpegTsPadData { GstCollectData collect; /* Parent */ From 3bb2efeea07fb69ffb6a300088aeb26806a0dab3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Thu, 3 Sep 2009 00:28:16 +0100 Subject: [PATCH 02/19] xdgmime: move xdg typefinder to the other typefinders in -base Remove the xdgmime plugin which now barely contains any code at all and move the functionality into gst-plugins-base next to the other typefinders. --- configure.ac | 4 - docs/plugins/inspect/plugin-xdgmime.xml | 14 ---- gst-plugins-bad.spec.in | 1 - gst/xdgmime/Makefile.am | 9 --- gst/xdgmime/gstxdgmime.c | 100 ------------------------ 5 files changed, 128 deletions(-) delete mode 100644 docs/plugins/inspect/plugin-xdgmime.xml delete mode 100644 gst/xdgmime/Makefile.am delete mode 100644 gst/xdgmime/gstxdgmime.c diff --git a/configure.ac b/configure.ac index 06e5758a15..438b2cd5cb 100644 --- a/configure.ac +++ b/configure.ac @@ -124,7 +124,6 @@ dnl check for libm, for sin() etc. AC_CHECK_LIBM AC_SUBST(LIBM) -dnl needed for gst/xdgmime AC_FUNC_MMAP dnl *** checks for header files *** @@ -298,7 +297,6 @@ AG_GST_CHECK_PLUGIN(tta) AG_GST_CHECK_PLUGIN(valve) AG_GST_CHECK_PLUGIN(videosignal) AG_GST_CHECK_PLUGIN(vmnc) -AG_GST_CHECK_PLUGIN(xdgmime) dnl *** plug-ins to exclude *** @@ -312,7 +310,6 @@ dnl disable experimental plug-ins #if test "x$BUILD_EXPERIMENTAL" != "xyes"; then #fi -# For xdgmime, to use g_content_type_guess() # This will always succeed because we depend on GLib >= 2.16 PKG_CHECK_MODULES(GIO, gio-2.0 >= 2.16, HAVE_GIO=yes, HAVE_GIO=no) AC_SUBST(GIO_CFLAGS) @@ -1749,7 +1746,6 @@ gst/tta/Makefile gst/valve/Makefile gst/videosignal/Makefile gst/vmnc/Makefile -gst/xdgmime/Makefile gst-libs/Makefile gst-libs/gst/Makefile gst-libs/gst/interfaces/Makefile diff --git a/docs/plugins/inspect/plugin-xdgmime.xml b/docs/plugins/inspect/plugin-xdgmime.xml deleted file mode 100644 index aecd94d252..0000000000 --- a/docs/plugins/inspect/plugin-xdgmime.xml +++ /dev/null @@ -1,14 +0,0 @@ - - xdgmime - XDG-MIME - ../../gst/xdgmime/.libs/libgstxdgmime.so - libgstxdgmime.so - 0.10.14.1 - LGPL - gst-plugins-bad - GStreamer Bad Plug-ins git/prerelease - Unknown package origin - - - - \ No newline at end of file diff --git a/gst-plugins-bad.spec.in b/gst-plugins-bad.spec.in index 66fa5d460d..c3e8ad0d92 100644 --- a/gst-plugins-bad.spec.in +++ b/gst-plugins-bad.spec.in @@ -121,7 +121,6 @@ rm -rf $RPM_BUILD_ROOT %{_libdir}/gstreamer-%{majorminor}/libgstliveadder.so %{_libdir}/gstreamer-%{majorminor}/libgstrtpmux.so %{_libdir}/gstreamer-%{majorminor}/libgstsiren.so -%{_libdir}/gstreamer-%{majorminor}/libgstxdgmime.so %{_libdir}/gstreamer-%{majorminor}/libgstadpcmdec.so %{_libdir}/gstreamer-%{majorminor}/libgstid3tag.so %{_libdir}/gstreamer-%{majorminor}/libgsthdvparse.so diff --git a/gst/xdgmime/Makefile.am b/gst/xdgmime/Makefile.am deleted file mode 100644 index f338a85d18..0000000000 --- a/gst/xdgmime/Makefile.am +++ /dev/null @@ -1,9 +0,0 @@ -plugin_LTLIBRARIES = libgstxdgmime.la - -libgstxdgmime_la_SOURCES = gstxdgmime.c - -libgstxdgmime_la_CFLAGS = $(GIO_CFLAGS) $(GST_CFLAGS) -libgstxdgmime_la_LIBADD = $(GIO_LIBS) $(GST_LIBS) -libgstxdgmime_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) -libgstxdgmime_la_LIBTOOLFLAGS = --tag=disable-static - diff --git a/gst/xdgmime/gstxdgmime.c b/gst/xdgmime/gstxdgmime.c deleted file mode 100644 index 2bc9d02a78..0000000000 --- a/gst/xdgmime/gstxdgmime.c +++ /dev/null @@ -1,100 +0,0 @@ -/* GStreamer - * Copyright (C) <2009> Sebastian Dröge - * - * 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 - -GST_DEBUG_CATEGORY (xdgmime_debug); -#define GST_CAT_DEFAULT xdgmime_debug - -#include - -static void -xdgmime_typefind (GstTypeFind * find, gpointer user_data) -{ - gchar *mimetype; - gsize length = 16384; - guint64 tf_length; - guint8 *data; - gchar *tmp; - - if ((tf_length = gst_type_find_get_length (find)) > 0) - length = MIN (length, tf_length); - - if ((data = gst_type_find_peek (find, 0, length)) == NULL) - return; - - - tmp = g_content_type_guess (NULL, data, length, NULL); - if (tmp == NULL || g_content_type_is_unknown (tmp)) { - g_free (tmp); - return; - } - - mimetype = g_content_type_get_mime_type (tmp); - g_free (tmp); - - if (mimetype == NULL) - return; - - GST_DEBUG ("Got mimetype '%s'", mimetype); - - /* Ignore audio/video types: - * - our own typefinders in -base are likely to be better at this - * (and if they're not, we really want to fix them, that's why we don't - * report xdg-detected audio/video types at all, not even with a low - * probability) - * - we want to detect GStreamer media types and not MIME types - * - the purpose of this xdg mime finder is mainly to prevent false - * positives of non-media formats, not to typefind audio/video formats */ - if (g_str_has_prefix (mimetype, "audio/") || - g_str_has_prefix (mimetype, "video/")) { - GST_LOG ("Ignoring audio/video mime type"); - g_free (mimetype); - return; - } - - /* Again, we mainly want the xdg typefinding to prevent false-positives on - * non-media formats, so suggest the type with a probability that trumps - * uncertain results of our typefinders, but not more than that. */ - GST_LOG ("Suggesting '%s' with probability POSSIBLE", mimetype); - gst_type_find_suggest_simple (find, GST_TYPE_FIND_POSSIBLE, mimetype, NULL); - g_free (mimetype); -} - -static gboolean -plugin_init (GstPlugin * plugin) -{ - gboolean ret; - - GST_DEBUG_CATEGORY_INIT (xdgmime_debug, "xdgmime", 0, "XDG-MIME"); - - ret = gst_type_find_register (plugin, - "xdgmime", GST_RANK_MARGINAL, xdgmime_typefind, NULL, NULL, NULL, NULL); - - return ret; -} - -GST_PLUGIN_DEFINE (GST_VERSION_MAJOR, - GST_VERSION_MINOR, - "xdgmime", - "XDG-MIME", - plugin_init, VERSION, "LGPL", GST_PACKAGE_NAME, GST_PACKAGE_ORIGIN) From 1e865242a7a30ca398af3dcb89908785b46b7862 Mon Sep 17 00:00:00 2001 From: Josep Torra Date: Thu, 3 Sep 2009 15:40:14 +0200 Subject: [PATCH 03/19] mpegtsdemux: Implement EAC3 handling according some ATSC specs. Fixes bug #594030. --- gst/mpegdemux/gstmpegdefs.h | 1 + gst/mpegdemux/gstmpegtsdemux.c | 14 +++++++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/gst/mpegdemux/gstmpegdefs.h b/gst/mpegdemux/gstmpegdefs.h index 4055113727..35ee967bfb 100644 --- a/gst/mpegdemux/gstmpegdefs.h +++ b/gst/mpegdemux/gstmpegdefs.h @@ -178,6 +178,7 @@ #define ST_BD_AUDIO_AC3_TRUE_HD 0x83 #define ST_BD_AUDIO_AC3_PLUS 0x84 #define ST_BD_AUDIO_DTS_HD 0x85 +#define ST_BD_AUDIO_EAC3 0x87 #define ST_BD_PGS_SUBPICTURE 0x90 #define ST_BD_IGS 0x91 #define ST_BD_SUBTITLE 0x92 diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index 2ab639bc4c..6723afb0a6 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -669,9 +669,21 @@ gst_mpegts_demux_fill_stream (GstMpegTSStream * stream, guint8 id, NULL); break; case ST_BD_AUDIO_AC3: + if (gst_mpeg_descriptor_find (stream->ES_info, DESC_DVB_AC3)) { + template = klass->audio_template; + name = g_strdup_printf ("audio_%04x", stream->PID); + caps = gst_caps_new_simple ("audio/x-ac3", NULL); + } else if (gst_mpeg_descriptor_find (stream->ES_info, + DESC_DVB_ENHANCED_AC3)) { + template = klass->audio_template; + name = g_strdup_printf ("audio_%04x", stream->PID); + caps = gst_caps_new_simple ("audio/x-eac3", NULL); + } + break; + case ST_BD_AUDIO_EAC3: template = klass->audio_template; name = g_strdup_printf ("audio_%04x", stream->PID); - caps = gst_caps_new_simple ("audio/x-ac3", NULL); + caps = gst_caps_new_simple ("audio/x-eac3", NULL); break; case ST_PS_AUDIO_DTS: template = klass->audio_template; From 77fa16cf44cfc31080965d9f67b8f6620ba42064 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Thu, 3 Sep 2009 15:45:06 +0200 Subject: [PATCH 04/19] mpegtsdemux: If stream type is AC3 and no EAC3 descriptor is found assume AC3 --- gst/mpegdemux/gstmpegtsdemux.c | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index 6723afb0a6..14cddfea0a 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -669,15 +669,19 @@ gst_mpegts_demux_fill_stream (GstMpegTSStream * stream, guint8 id, NULL); break; case ST_BD_AUDIO_AC3: - if (gst_mpeg_descriptor_find (stream->ES_info, DESC_DVB_AC3)) { - template = klass->audio_template; - name = g_strdup_printf ("audio_%04x", stream->PID); - caps = gst_caps_new_simple ("audio/x-ac3", NULL); - } else if (gst_mpeg_descriptor_find (stream->ES_info, - DESC_DVB_ENHANCED_AC3)) { + if (gst_mpeg_descriptor_find (stream->ES_info, DESC_DVB_ENHANCED_AC3)) { template = klass->audio_template; name = g_strdup_printf ("audio_%04x", stream->PID); caps = gst_caps_new_simple ("audio/x-eac3", NULL); + } else { + if (!gst_mpeg_descriptor_find (stream->ES_info, DESC_DVB_AC3)) { + GST_WARNING ("AC3 stream type found but no corresponding " + "descriptor to differentiate between AC3 and EAC3. " + "Assuming plain AC3."); + } + template = klass->audio_template; + name = g_strdup_printf ("audio_%04x", stream->PID); + caps = gst_caps_new_simple ("audio/x-ac3", NULL); } break; case ST_BD_AUDIO_EAC3: From 0f10b769bf3893758da0085c3c9dab4d91f84b39 Mon Sep 17 00:00:00 2001 From: Julien Isorce Date: Thu, 3 Sep 2009 17:12:26 +0200 Subject: [PATCH 05/19] dshowvideosrc: factorize dshow video format parsing --- sys/dshowsrcwrapper/gstdshow.cpp | 56 ++++++++++++++++++ sys/dshowsrcwrapper/gstdshow.h | 20 +++++++ sys/dshowsrcwrapper/gstdshowvideosrc.cpp | 73 +++++------------------- sys/dshowsrcwrapper/gstdshowvideosrc.h | 11 ---- 4 files changed, 90 insertions(+), 70 deletions(-) mode change 100644 => 100755 sys/dshowsrcwrapper/gstdshow.cpp mode change 100644 => 100755 sys/dshowsrcwrapper/gstdshow.h mode change 100644 => 100755 sys/dshowsrcwrapper/gstdshowvideosrc.cpp mode change 100644 => 100755 sys/dshowsrcwrapper/gstdshowvideosrc.h diff --git a/sys/dshowsrcwrapper/gstdshow.cpp b/sys/dshowsrcwrapper/gstdshow.cpp old mode 100644 new mode 100755 index 8b77b5857a..e3a4f4a618 --- a/sys/dshowsrcwrapper/gstdshow.cpp +++ b/sys/dshowsrcwrapper/gstdshow.cpp @@ -321,3 +321,59 @@ gst_dshow_show_propertypage (IBaseFilter *base_filter) } return ret; } + +GstCaps *gst_dshow_new_video_caps (GstVideoFormat video_format, const gchar* name, + const VIDEO_STREAM_CONFIG_CAPS * vscc, const VIDEOINFOHEADER *video_info, + GstCaptureVideoDefault *video_default) +{ + GstCaps *video_caps = NULL; + GstStructure *video_structure = NULL; + + video_default->defaultWidth = video_info->bmiHeader.biWidth; + video_default->defaultHeight = video_info->bmiHeader.biHeight; + video_default->defaultFPS = (gint) (10000000 / video_info->AvgTimePerFrame); + video_default->granularityWidth = vscc->OutputGranularityX; + video_default->granularityHeight = vscc->OutputGranularityY; + + /* raw video format */ + switch (video_format) { + case GST_VIDEO_FORMAT_BGR: + video_caps = gst_caps_from_string (GST_VIDEO_CAPS_BGR); + break; + case GST_VIDEO_FORMAT_I420: + video_caps = gst_caps_from_string (GST_VIDEO_CAPS_YUV ("I420")); + default: + break; + } + + /* other video format */ + if (!video_caps){ + if (g_strcasecmp (name, "video/x-dv, systemstream=FALSE") == 0) { + video_caps = gst_caps_new_simple ("video/x-dv", + "systemstream", G_TYPE_BOOLEAN, FALSE, + "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('d', 'v', 's', 'd'), + NULL); + } else if (g_strcasecmp (name, "video/x-dv, systemstream=TRUE") == 0) { + video_caps = gst_caps_new_simple ("video/x-dv", + "systemstream", G_TYPE_BOOLEAN, TRUE, NULL); + return video_caps; + } + } + + if (!video_caps) + return NULL; + + video_structure = gst_caps_get_structure (video_caps, 0); + + gst_structure_set (video_structure, + "width", GST_TYPE_INT_RANGE, vscc->MinOutputSize.cx, vscc->MaxOutputSize.cx, + "height", GST_TYPE_INT_RANGE, vscc->MinOutputSize.cy, vscc->MaxOutputSize.cy, + "framerate", GST_TYPE_FRACTION_RANGE, + (gint) (10000000 / vscc->MaxFrameInterval), 1, + (gint) (10000000 / vscc->MinFrameInterval), 1, + NULL); + + g_print ("caps are %s\n", gst_caps_to_string (video_caps)); + + return video_caps; +} diff --git a/sys/dshowsrcwrapper/gstdshow.h b/sys/dshowsrcwrapper/gstdshow.h old mode 100644 new mode 100755 index 4491e50d66..f13d9a8d28 --- a/sys/dshowsrcwrapper/gstdshow.h +++ b/sys/dshowsrcwrapper/gstdshow.h @@ -31,6 +31,8 @@ #include #include +#include +#include typedef struct _GstCapturePinMediaType { @@ -38,6 +40,18 @@ typedef struct _GstCapturePinMediaType IPin *capture_pin; } GstCapturePinMediaType; +/* video default properties associated to a video format (YUY2, I420, RGB24 ...) */ +typedef struct _GstCaptureVideoDefault +{ + gint defaultWidth; + gint defaultHeight; + gint defaultFPS; + + gint granularityWidth; //will be removed when GST_TYPE_INT_RANGE_STEP exits + gint granularityHeight; //will be removed when GST_TYPE_INT_RANGE_STEP exits + +} GstCaptureVideoDefault; + #ifdef __cplusplus extern "C" { #endif @@ -71,6 +85,12 @@ gchar *gst_dshow_getdevice_from_devicename (const GUID *device_category, gchar * /* show the capture filter property page (generally used to setup the device). the page is modal*/ gboolean gst_dshow_show_propertypage (IBaseFilter *base_filter); + +/* transform a dshow video caps to a gstreamer video caps */ +GstCaps *gst_dshow_new_video_caps (GstVideoFormat video_format, const gchar* name, + const VIDEO_STREAM_CONFIG_CAPS * vscc, const VIDEOINFOHEADER *video_info, + GstCaptureVideoDefault *video_default); + #ifdef __cplusplus } diff --git a/sys/dshowsrcwrapper/gstdshowvideosrc.cpp b/sys/dshowsrcwrapper/gstdshowvideosrc.cpp old mode 100644 new mode 100755 index 1f4ff4abc2..32c19f86ff --- a/sys/dshowsrcwrapper/gstdshowvideosrc.cpp +++ b/sys/dshowsrcwrapper/gstdshowvideosrc.cpp @@ -924,21 +924,9 @@ gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin, /* I420 */ if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_I420, FORMAT_VideoInfo)) { - video_info = (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat; - video_default->defaultWidth = video_info->bmiHeader.biWidth; - video_default->defaultHeight = video_info->bmiHeader.biHeight; - video_default->defaultFPS = (int) (10000000 / video_info->AvgTimePerFrame); - video_default->granularityWidth = vscc.OutputGranularityX; - video_default->granularityHeight = vscc.OutputGranularityY; - - mediacaps = gst_caps_new_simple ("video/x-raw-yuv", - "width", GST_TYPE_INT_RANGE, vscc.MinOutputSize.cx, vscc.MaxOutputSize.cx, - "height", GST_TYPE_INT_RANGE, vscc.MinOutputSize.cy, vscc.MaxOutputSize.cy, - "framerate", GST_TYPE_FRACTION_RANGE, - (int) (10000000 / vscc.MaxFrameInterval), 1, - (int) (10000000 / vscc.MinFrameInterval), 1, - "format", GST_TYPE_FOURCC, MAKEFOURCC ('I', '4', '2', '0'), NULL); + mediacaps = gst_dshow_new_video_caps (GST_VIDEO_FORMAT_I420, NULL, &vscc, + (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat, video_default); if (mediacaps) { src->pins_mediatypes = @@ -955,27 +943,9 @@ gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin, /* BGR */ if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_RGB24, FORMAT_VideoInfo)) { - video_info = (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat; - video_default->defaultWidth = video_info->bmiHeader.biWidth; - video_default->defaultHeight = video_info->bmiHeader.biHeight; - video_default->defaultFPS = (int) (10000000 / video_info->AvgTimePerFrame); - video_default->granularityWidth = vscc.OutputGranularityX; - video_default->granularityHeight = vscc.OutputGranularityY; - - /* ffmpegcolorspace handles RGB24 in BIG_ENDIAN */ - mediacaps = gst_caps_new_simple ("video/x-raw-rgb", - "bpp", G_TYPE_INT, 24, - "depth", G_TYPE_INT, 24, - "width", GST_TYPE_INT_RANGE, vscc.MinOutputSize.cx, vscc.MaxOutputSize.cx, - "height", GST_TYPE_INT_RANGE, vscc.MinOutputSize.cy, vscc.MaxOutputSize.cy, - "framerate", GST_TYPE_FRACTION_RANGE, - (int) (10000000 / vscc.MaxFrameInterval), 1, - (int) (10000000 / vscc.MinFrameInterval), 1, - "endianness", G_TYPE_INT, G_BIG_ENDIAN, - "red_mask", G_TYPE_INT, 255, - "green_mask", G_TYPE_INT, 65280, - "blue_mask", G_TYPE_INT, 16711680, NULL); + mediacaps = gst_dshow_new_video_caps (GST_VIDEO_FORMAT_BGR, NULL, &vscc, + (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat, video_default); if (mediacaps) { src->pins_mediatypes = @@ -992,22 +962,10 @@ gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin, /* DVSD */ if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_dvsd, FORMAT_VideoInfo)) { - video_info = (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat; - - video_default->defaultWidth = video_info->bmiHeader.biWidth; - video_default->defaultHeight = video_info->bmiHeader.biHeight; - video_default->defaultFPS = (int) (10000000 / video_info->AvgTimePerFrame); - video_default->granularityWidth = vscc.OutputGranularityX; - video_default->granularityHeight = vscc.OutputGranularityY; - - mediacaps = gst_caps_new_simple ("video/x-dv", - "systemstream", G_TYPE_BOOLEAN, FALSE, - "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('d', 'v', 's', 'd'), - "framerate", GST_TYPE_FRACTION_RANGE, - (int) (10000000 / vscc.MaxFrameInterval), 1, - (int) (10000000 / vscc.MinFrameInterval), 1, - "width", GST_TYPE_INT_RANGE, vscc.MinOutputSize.cx, vscc.MaxOutputSize.cx, - "height", GST_TYPE_INT_RANGE, vscc.MinOutputSize.cy, vscc.MaxOutputSize.cy, NULL); + + mediacaps = gst_dshow_new_video_caps (GST_VIDEO_FORMAT_UNKNOWN, + "video/x-dv, systemstream=FALSE", &vscc, (VIDEOINFOHEADER *) + pin_mediatype->mediatype->pbFormat, video_default); if (mediacaps) { src->pins_mediatypes = @@ -1026,15 +984,12 @@ gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin, if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_dvsd, FORMAT_DvInfo)) { video_info = (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat; - //No video size in caps when stream ? I do know if the following fields exist - video_default->defaultWidth = video_info->bmiHeader.biWidth; - video_default->defaultHeight = video_info->bmiHeader.biHeight; - video_default->defaultFPS = (int) (10000000 / video_info->AvgTimePerFrame); - video_default->granularityWidth = vscc.OutputGranularityX; - video_default->granularityHeight = vscc.OutputGranularityY; - - mediacaps = gst_caps_new_simple ("video/x-dv", - "systemstream", G_TYPE_BOOLEAN, TRUE, NULL); + video_default->granularityWidth = 0; + video_default->granularityHeight = 0; + + mediacaps = gst_dshow_new_video_caps (GST_VIDEO_FORMAT_UNKNOWN, + "video/x-dv, systemstream=TRUE", &vscc, (VIDEOINFOHEADER *) + pin_mediatype->mediatype->pbFormat, video_default); if (mediacaps) { src->pins_mediatypes = diff --git a/sys/dshowsrcwrapper/gstdshowvideosrc.h b/sys/dshowsrcwrapper/gstdshowvideosrc.h old mode 100644 new mode 100755 index 415830719b..bced6bef68 --- a/sys/dshowsrcwrapper/gstdshowvideosrc.h +++ b/sys/dshowsrcwrapper/gstdshowvideosrc.h @@ -42,17 +42,6 @@ G_BEGIN_DECLS typedef struct _GstDshowVideoSrc GstDshowVideoSrc; typedef struct _GstDshowVideoSrcClass GstDshowVideoSrcClass; -/* video default properties associated to a video format (YUY2, I420, RGB24 ...) */ -typedef struct _GstCaptureVideoDefault -{ - gint defaultWidth; - gint defaultHeight; - gint defaultFPS; - - gint granularityWidth; //will be removed when GST_TYPE_INT_RANGE_STEP exits - gint granularityHeight; //will be removed when GST_TYPE_INT_RANGE_STEP exits - -} GstCaptureVideoDefault; struct _GstDshowVideoSrc { From a22eca4e67b3bff1c4018187156005c3d5897644 Mon Sep 17 00:00:00 2001 From: Julien Isorce Date: Thu, 3 Sep 2009 17:20:47 +0200 Subject: [PATCH 06/19] dshowsrcwrapper: remove cplusplus condition --- sys/dshowsrcwrapper/gstdshow.cpp | 2 -- sys/dshowsrcwrapper/gstdshow.h | 15 --------------- 2 files changed, 17 deletions(-) diff --git a/sys/dshowsrcwrapper/gstdshow.cpp b/sys/dshowsrcwrapper/gstdshow.cpp index e3a4f4a618..319d4df80b 100755 --- a/sys/dshowsrcwrapper/gstdshow.cpp +++ b/sys/dshowsrcwrapper/gstdshow.cpp @@ -373,7 +373,5 @@ GstCaps *gst_dshow_new_video_caps (GstVideoFormat video_format, const gchar* nam (gint) (10000000 / vscc->MinFrameInterval), 1, NULL); - g_print ("caps are %s\n", gst_caps_to_string (video_caps)); - return video_caps; } diff --git a/sys/dshowsrcwrapper/gstdshow.h b/sys/dshowsrcwrapper/gstdshow.h index f13d9a8d28..553b42fe63 100755 --- a/sys/dshowsrcwrapper/gstdshow.h +++ b/sys/dshowsrcwrapper/gstdshow.h @@ -22,15 +22,12 @@ #ifndef _GSTDSHOW_ #define _GSTDSHOW_ -#ifdef __cplusplus #include -#endif #include #include #include #include -#include #include #include @@ -52,13 +49,6 @@ typedef struct _GstCaptureVideoDefault } GstCaptureVideoDefault; -#ifdef __cplusplus -extern "C" { -#endif - -/* register fake filters as COM object and as Direct Show filters in the registry */ -//HRESULT gst_dshow_register_fakefilters (); - /* free memory of the input pin mediatype */ void gst_dshow_free_pin_mediatype (gpointer pt); @@ -91,9 +81,4 @@ GstCaps *gst_dshow_new_video_caps (GstVideoFormat video_format, const gchar* nam const VIDEO_STREAM_CONFIG_CAPS * vscc, const VIDEOINFOHEADER *video_info, GstCaptureVideoDefault *video_default); - -#ifdef __cplusplus -} -#endif - #endif /* _GSTDSHOW_ */ \ No newline at end of file From 9a1597e58b9b4420dcf0237afe92bbd266944ffe Mon Sep 17 00:00:00 2001 From: Julien Isorce Date: Thu, 3 Sep 2009 17:49:41 +0200 Subject: [PATCH 07/19] dshowvideosrc: factorize dshow format to gst caps conversion --- sys/dshowsrcwrapper/gstdshow.cpp | 10 +++ sys/dshowsrcwrapper/gstdshowvideosrc.cpp | 103 +++++------------------ 2 files changed, 31 insertions(+), 82 deletions(-) diff --git a/sys/dshowsrcwrapper/gstdshow.cpp b/sys/dshowsrcwrapper/gstdshow.cpp index 319d4df80b..afec3ce944 100755 --- a/sys/dshowsrcwrapper/gstdshow.cpp +++ b/sys/dshowsrcwrapper/gstdshow.cpp @@ -365,6 +365,16 @@ GstCaps *gst_dshow_new_video_caps (GstVideoFormat video_format, const gchar* nam video_structure = gst_caps_get_structure (video_caps, 0); + /* Hope GST_TYPE_INT_RANGE_STEP will exits in future gstreamer releases */ + /* because we could use : */ + /* "width", GST_TYPE_INT_RANGE_STEP, video_default->minWidth, video_default->maxWidth, video_default->granularityWidth */ + /* instead of : */ + /* "width", GST_TYPE_INT_RANGE, video_default->minWidth, video_default->maxWidth */ + + /* For framerate we do not need a step (granularity) because */ + /* "The IAMStreamConfig::SetFormat method will set the frame rate to the closest */ + /* value that the filter supports" as it said in the VIDEO_STREAM_CONFIG_CAPS dshwo doc */ + gst_structure_set (video_structure, "width", GST_TYPE_INT_RANGE, vscc->MinOutputSize.cx, vscc->MaxOutputSize.cx, "height", GST_TYPE_INT_RANGE, vscc->MinOutputSize.cy, vscc->MaxOutputSize.cy, diff --git a/sys/dshowsrcwrapper/gstdshowvideosrc.cpp b/sys/dshowsrcwrapper/gstdshowvideosrc.cpp index 32c19f86ff..5dbbb0b4e6 100755 --- a/sys/dshowsrcwrapper/gstdshowvideosrc.cpp +++ b/sys/dshowsrcwrapper/gstdshowvideosrc.cpp @@ -573,7 +573,6 @@ gst_dshowvideosrc_get_caps (GstBaseSrc * basesrc) } if (src->caps) { - GST_LOG ("getcaps returned %s", gst_caps_to_string (src->caps)); return gst_caps_ref (src->caps); } @@ -896,6 +895,8 @@ gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin, if (isize != sizeof (vscc)) return NULL; + caps = gst_caps_new_empty (); + for (; i < icount; i++) { GstCapturePinMediaType *pin_mediatype = g_new0 (GstCapturePinMediaType, 1); GstCaptureVideoDefault *video_default = g_new0 (GstCaptureVideoDefault, 1); @@ -904,85 +905,26 @@ gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin, pin_mediatype->capture_pin = pin; hres = streamcaps->GetStreamCaps(i, &pin_mediatype->mediatype, (BYTE *) & vscc); - if (hres == S_OK && pin_mediatype->mediatype) { - VIDEOINFOHEADER *video_info; + if (FAILED (hres) || !pin_mediatype->mediatype) { + gst_dshow_free_pin_mediatype (pin_mediatype); + g_free (video_default); + } else { GstCaps *mediacaps = NULL; - if (!caps) - caps = gst_caps_new_empty (); - - /* some remarks: */ - /* Hope GST_TYPE_INT_RANGE_STEP will exits in future gstreamer releases */ - /* because we could use : */ - /* "width", GST_TYPE_INT_RANGE_STEP, video_default->minWidth, video_default->maxWidth, video_default->granularityWidth */ - /* instead of : */ - /* "width", GST_TYPE_INT_RANGE, video_default->minWidth, video_default->maxWidth */ - - /* For framerate we do not need a step (granularity) because */ - /* "The IAMStreamConfig::SetFormat method will set the frame rate to the closest */ - /* value that the filter supports" as it said in the VIDEO_STREAM_CONFIG_CAPS dshwo doc */ - - /* I420 */ if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_I420, FORMAT_VideoInfo)) { - mediacaps = gst_dshow_new_video_caps (GST_VIDEO_FORMAT_I420, NULL, &vscc, (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat, video_default); - if (mediacaps) { - src->pins_mediatypes = - g_list_append (src->pins_mediatypes, pin_mediatype); - src->video_defaults = - g_list_append (src->video_defaults, video_default); - gst_caps_append (caps, mediacaps); - } else { - gst_dshow_free_pin_mediatype (pin_mediatype); - g_free (video_default); - } - continue; - } - - /* BGR */ - if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_RGB24, FORMAT_VideoInfo)) { - + } else if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_RGB24, FORMAT_VideoInfo)) { mediacaps = gst_dshow_new_video_caps (GST_VIDEO_FORMAT_BGR, NULL, &vscc, (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat, video_default); - if (mediacaps) { - src->pins_mediatypes = - g_list_append (src->pins_mediatypes, pin_mediatype); - src->video_defaults = - g_list_append (src->video_defaults, video_default); - gst_caps_append (caps, mediacaps); - } else { - gst_dshow_free_pin_mediatype (pin_mediatype); - g_free (video_default); - } - continue; - } - - /* DVSD */ - if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_dvsd, FORMAT_VideoInfo)) { - + } else if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_dvsd, FORMAT_VideoInfo)) { mediacaps = gst_dshow_new_video_caps (GST_VIDEO_FORMAT_UNKNOWN, "video/x-dv, systemstream=FALSE", &vscc, (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat, video_default); - if (mediacaps) { - src->pins_mediatypes = - g_list_append (src->pins_mediatypes, pin_mediatype); - src->video_defaults = - g_list_append (src->video_defaults, video_default); - gst_caps_append (caps, mediacaps); - } else { - gst_dshow_free_pin_mediatype (pin_mediatype); - g_free (video_default); - } - continue; - } - - /* DV stream */ - if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_dvsd, FORMAT_DvInfo)) { - video_info = (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat; + } else if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_dvsd, FORMAT_DvInfo)) { video_default->granularityWidth = 0; video_default->granularityHeight = 0; @@ -990,22 +932,19 @@ gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin, mediacaps = gst_dshow_new_video_caps (GST_VIDEO_FORMAT_UNKNOWN, "video/x-dv, systemstream=TRUE", &vscc, (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat, video_default); - - if (mediacaps) { - src->pins_mediatypes = - g_list_append (src->pins_mediatypes, pin_mediatype); - src->video_defaults = - g_list_append (src->video_defaults, video_default); - gst_caps_append (caps, mediacaps); - } else { - gst_dshow_free_pin_mediatype (pin_mediatype); - g_free (video_default); - } - continue; } - } else { - gst_dshow_free_pin_mediatype (pin_mediatype); - g_free (video_default); + + if (mediacaps) { + src->pins_mediatypes = + g_list_append (src->pins_mediatypes, pin_mediatype); + src->video_defaults = + g_list_append (src->video_defaults, video_default); + gst_caps_append (caps, mediacaps); + } else { + gst_dshow_free_pin_mediatype (pin_mediatype); + g_free (video_default); + } + } } From 823f06f039a11920a9c0337821b7528eaab4b33b Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 3 Sep 2009 18:43:26 +0200 Subject: [PATCH 08/19] sirenenc: fix timestamping Handle DISCONT and reset adapter. code cleanups. Put timestamps and discont flags on output buffers. Fix error handling. Remove bogus object locks, it's all protected by the STREAM_LOCK. --- gst/siren/gstsirenenc.c | 133 ++++++++++++++++++++++++++++------------ gst/siren/gstsirenenc.h | 3 +- 2 files changed, 95 insertions(+), 41 deletions(-) diff --git a/gst/siren/gstsirenenc.c b/gst/siren/gstsirenenc.c index fbf2b6e074..e21da4fc49 100644 --- a/gst/siren/gstsirenenc.c +++ b/gst/siren/gstsirenenc.c @@ -40,6 +40,8 @@ GST_DEBUG_CATEGORY (sirenenc_debug); #define GST_CAT_DEFAULT (sirenenc_debug) +#define FRAME_DURATION (20 * GST_MSECOND) + /* elementfactory information */ static const GstElementDetails gst_siren_enc_details = GST_ELEMENT_DETAILS ("Siren Encoder element", @@ -176,14 +178,22 @@ gst_siren_enc_chain (GstPad * pad, GstBuffer * buf) { GstSirenEnc *enc = GST_SIREN_ENC (gst_pad_get_parent_element (pad)); GstFlowReturn ret = GST_FLOW_OK; - GstBuffer *encoded = NULL; - guint8 *data = NULL; - gint out_offset = 0; - gint encode_ret = 0; - gint size = 0; - guint in_offset = 0; + GstBuffer *out_buf; + guint8 *in_data, *out_data; + guint8 *to_free = NULL; + guint i, size, num_frames; + gint out_size, in_size; + gint encode_ret; + gboolean discont; + GstClockTime timestamp; + guint64 distance; - GST_OBJECT_LOCK (enc); + discont = GST_BUFFER_IS_DISCONT (buf); + if (discont) { + GST_DEBUG_OBJECT (enc, "received DISCONT, flush adapter"); + gst_adapter_clear (enc->adapter); + enc->discont = TRUE; + } gst_adapter_push (enc->adapter, buf); @@ -191,50 +201,90 @@ gst_siren_enc_chain (GstPad * pad, GstBuffer * buf) GST_BUFFER_SIZE (buf), gst_adapter_available (enc->adapter)); size = gst_adapter_available (enc->adapter); - size /= 16; - size -= size % 40; - if (size == 0) { - GST_OBJECT_UNLOCK (enc); - goto out; - } + /* we need to process 640 input bytes to produce 40 output bytes */ + /* calculate the amount of frames we will handle */ + num_frames = size / 640; - data = gst_adapter_take (enc->adapter, size * 16); + /* no frames, wait some more */ + if (num_frames == 0) + goto done; - GST_OBJECT_UNLOCK (enc); + /* this is the output size */ + in_size = num_frames * 640; + out_size = num_frames * 40; - ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad, - GST_BUFFER_OFFSET (buf) / 16, size, enc->srccaps, &encoded); + GST_LOG_OBJECT (enc, "we have %u frames, %u in, %u out", num_frames, in_size, + out_size); + /* get a buffer */ + ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad, -1, + out_size, enc->srccaps, &out_buf); if (ret != GST_FLOW_OK) - goto out; + goto alloc_failed; - while (out_offset < size && ret == GST_FLOW_OK) { - GST_LOG_OBJECT (enc, "Encoding frame"); + /* get the timestamp for the output buffer */ + timestamp = gst_adapter_prev_timestamp (enc->adapter, &distance); - encode_ret = Siren7_EncodeFrame (enc->encoder, - data + in_offset, GST_BUFFER_DATA (encoded) + out_offset); - if (encode_ret != 0) { - GST_ERROR_OBJECT (enc, "Siren7_EncodeFrame returned %d", encode_ret); - ret = GST_FLOW_ERROR; - gst_buffer_unref (encoded); - goto out; - } + /* add the amount of time taken by the distance */ + timestamp += gst_util_uint64_scale_int (distance / 2, GST_SECOND, 16000); - out_offset += 40; - in_offset += 640; + GST_LOG_OBJECT (enc, + "timestamp %" GST_TIME_FORMAT ", distance %" G_GUINT64_FORMAT, + GST_TIME_ARGS (timestamp), distance); + + /* get the input data for all the frames */ + to_free = in_data = gst_adapter_take (enc->adapter, in_size); + out_data = GST_BUFFER_DATA (out_buf); + + for (i = 0; i < num_frames; i++) { + GST_LOG_OBJECT (enc, "Encoding frame %u/%u", i, num_frames); + + /* encode 640 input bytes to 40 output bytes */ + encode_ret = Siren7_EncodeFrame (enc->encoder, in_data, out_data); + if (encode_ret != 0) + goto encode_error; + + /* move to next frame */ + out_data += 40; + in_data += 640; } - GST_LOG_OBJECT (enc, "Finished encoding : %d", out_offset); + GST_LOG_OBJECT (enc, "Finished encoding"); - ret = gst_pad_push (enc->srcpad, encoded); + /* mark discont */ + if (enc->discont) { + GST_BUFFER_FLAG_SET (out_buf, GST_BUFFER_FLAG_DISCONT); + enc->discont = FALSE; + } + GST_BUFFER_TIMESTAMP (out_buf) = timestamp; + GST_BUFFER_DURATION (out_buf) = num_frames * FRAME_DURATION; -out: - if (data) - g_free (data); + ret = gst_pad_push (enc->srcpad, out_buf); + +done: + if (to_free) + g_free (to_free); gst_object_unref (enc); + return ret; + + /* ERRORS */ +alloc_failed: + { + GST_DEBUG_OBJECT (enc, "failed to pad_alloc buffer: %d (%d)", ret, + gst_flow_get_name (ret)); + goto done; + } +encode_error: + { + GST_ELEMENT_ERROR (enc, STREAM, ENCODE, (NULL), + ("Error encoding frame: %d", encode_ret)); + ret = GST_FLOW_ERROR; + gst_buffer_unref (out_buf); + goto done; + } } static GstStateChangeReturn @@ -243,16 +293,19 @@ gst_siren_change_state (GstElement * element, GstStateChange transition) GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; GstSirenEnc *enc = GST_SIREN_ENC (element); - ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + enc->discont = FALSE; + break; + default: + break; + } - if (ret == GST_STATE_CHANGE_FAILURE) - return ret; + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); switch (transition) { case GST_STATE_CHANGE_PAUSED_TO_READY: - GST_OBJECT_LOCK (element); gst_adapter_clear (enc->adapter); - GST_OBJECT_UNLOCK (element); break; default: break; diff --git a/gst/siren/gstsirenenc.h b/gst/siren/gstsirenenc.h index 47e05bc788..66709be89d 100644 --- a/gst/siren/gstsirenenc.h +++ b/gst/siren/gstsirenenc.h @@ -52,9 +52,10 @@ struct _GstSirenEnc /* protected by the stream lock */ SirenEncoder encoder; - /* protected by the object lock */ GstAdapter *adapter; + gboolean discont; + GstPad *srcpad; GstPad *sinkpad; From 00f395e82f2732ba33f7e396da7b8f77ec4c7dca Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Thu, 3 Sep 2009 19:04:33 +0200 Subject: [PATCH 09/19] sirenenc: fix events and caps Add an event function that clears the adapter. Add a setcaps function to configure caps on the srcpad. Remove the instance variable for the caps. --- gst/siren/gstsirenenc.c | 75 +++++++++++++++++++++++++++++------------ gst/siren/gstsirenenc.h | 2 -- 2 files changed, 54 insertions(+), 23 deletions(-) diff --git a/gst/siren/gstsirenenc.c b/gst/siren/gstsirenenc.c index e21da4fc49..b0dfbc64d7 100644 --- a/gst/siren/gstsirenenc.c +++ b/gst/siren/gstsirenenc.c @@ -79,7 +79,10 @@ enum -static void gst_siren_enc_dispose (GObject * object); +static void gst_siren_enc_finalize (GObject * object); + +static gboolean gst_siren_enc_sink_setcaps (GstPad * pad, GstCaps * caps); +static gboolean gst_siren_enc_sink_event (GstPad * pad, GstEvent * event); static GstFlowReturn gst_siren_enc_chain (GstPad * pad, GstBuffer * buf); static GstStateChangeReturn @@ -119,7 +122,7 @@ gst_siren_enc_class_init (GstSirenEncClass * klass) GST_DEBUG ("Initializing Class"); - gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_siren_enc_dispose); + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_siren_enc_finalize); gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_siren_change_state); @@ -137,42 +140,72 @@ gst_siren_enc_init (GstSirenEnc * enc, GstSirenEncClass * klass) enc->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink"); enc->srcpad = gst_pad_new_from_static_template (&srctemplate, "src"); + gst_pad_set_setcaps_function (enc->sinkpad, + GST_DEBUG_FUNCPTR (gst_siren_enc_sink_setcaps)); + gst_pad_set_event_function (enc->sinkpad, + GST_DEBUG_FUNCPTR (gst_siren_enc_sink_event)); gst_pad_set_chain_function (enc->sinkpad, GST_DEBUG_FUNCPTR (gst_siren_enc_chain)); gst_element_add_pad (GST_ELEMENT (enc), enc->sinkpad); gst_element_add_pad (GST_ELEMENT (enc), enc->srcpad); - enc->srccaps = gst_static_pad_template_get_caps (&srctemplate); - GST_DEBUG_OBJECT (enc, "Init done"); } static void -gst_siren_enc_dispose (GObject * object) +gst_siren_enc_finalize (GObject * object) { GstSirenEnc *enc = GST_SIREN_ENC (object); GST_DEBUG_OBJECT (object, "Disposing"); - if (enc->encoder) { - Siren7_CloseEncoder (enc->encoder); - enc->encoder = NULL; - } - - if (enc->adapter) { - g_object_unref (enc->adapter); - enc->adapter = NULL; - } - - if (enc->srccaps) { - gst_caps_unref (enc->srccaps); - enc->srccaps = NULL; - } + Siren7_CloseEncoder (enc->encoder); + g_object_unref (enc->adapter); G_OBJECT_CLASS (parent_class)->dispose (object); } +static gboolean +gst_siren_enc_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstSirenEnc *enc; + gboolean res; + GstCaps *outcaps; + + enc = GST_SIREN_ENC (GST_PAD_PARENT (pad)); + + outcaps = gst_static_pad_template_get_caps (&srctemplate); + res = gst_pad_set_caps (enc->srcpad, outcaps); + gst_caps_unref (outcaps); + + return res; +} + +static gboolean +gst_siren_enc_sink_event (GstPad * pad, GstEvent * event) +{ + GstSirenEnc *enc; + gboolean res; + + enc = GST_SIREN_ENC (GST_PAD_PARENT (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + gst_adapter_clear (enc->adapter); + res = gst_pad_push_event (enc->srcpad, event); + break; + case GST_EVENT_FLUSH_STOP: + gst_adapter_clear (enc->adapter); + res = gst_pad_push_event (enc->srcpad, event); + break; + default: + res = gst_pad_push_event (enc->srcpad, event); + break; + } + return res; +} + static GstFlowReturn gst_siren_enc_chain (GstPad * pad, GstBuffer * buf) { @@ -210,7 +243,7 @@ gst_siren_enc_chain (GstPad * pad, GstBuffer * buf) if (num_frames == 0) goto done; - /* this is the output size */ + /* this is the input/output size */ in_size = num_frames * 640; out_size = num_frames * 40; @@ -219,7 +252,7 @@ gst_siren_enc_chain (GstPad * pad, GstBuffer * buf) /* get a buffer */ ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad, -1, - out_size, enc->srccaps, &out_buf); + out_size, GST_PAD_CAPS (enc->srcpad), &out_buf); if (ret != GST_FLOW_OK) goto alloc_failed; diff --git a/gst/siren/gstsirenenc.h b/gst/siren/gstsirenenc.h index 66709be89d..1d63628dc4 100644 --- a/gst/siren/gstsirenenc.h +++ b/gst/siren/gstsirenenc.h @@ -58,8 +58,6 @@ struct _GstSirenEnc GstPad *srcpad; GstPad *sinkpad; - - GstCaps *srccaps; }; struct _GstSirenEncClass From a333fef08ce5bb558dc3ac39d514b84c0d392462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Olivier=20Cr=C3=AAte?= Date: Tue, 1 Sep 2009 21:30:35 -0400 Subject: [PATCH 10/19] pcapparse: Set the GStreamer timestamp according to the pcap timestamps --- gst/pcapparse/gstpcapparse.c | 37 ++++++++++++++++++++++++++++++++++++ gst/pcapparse/gstpcapparse.h | 4 ++++ 2 files changed, 41 insertions(+) diff --git a/gst/pcapparse/gstpcapparse.c b/gst/pcapparse/gstpcapparse.c index 546ffbe30e..6e20212694 100644 --- a/gst/pcapparse/gstpcapparse.c +++ b/gst/pcapparse/gstpcapparse.c @@ -87,6 +87,7 @@ static void gst_pcap_parse_set_property (GObject * object, guint prop_id, static void gst_pcap_parse_reset (GstPcapParse * self); static GstFlowReturn gst_pcap_parse_chain (GstPad * pad, GstBuffer * buffer); +static gboolean gst_pcap_sink_event (GstPad * pad, GstEvent * event); GST_BOILERPLATE (GstPcapParse, gst_pcap_parse, GstElement, GST_TYPE_ELEMENT); @@ -146,6 +147,8 @@ gst_pcap_parse_init (GstPcapParse * self, GstPcapParseClass * gclass) gst_pad_set_chain_function (self->sink_pad, GST_DEBUG_FUNCPTR (gst_pcap_parse_chain)); gst_pad_use_fixed_caps (self->sink_pad); + gst_pad_set_event_function (self->sink_pad, + GST_DEBUG_FUNCPTR (gst_pcap_sink_event)); gst_element_add_pad (GST_ELEMENT (self), self->sink_pad); self->src_pad = gst_pad_new_from_static_template (&src_template, "src"); @@ -261,6 +264,8 @@ gst_pcap_parse_reset (GstPcapParse * self) self->swap_endian = FALSE; self->cur_packet_size = -1; self->buffer_offset = 0; + self->cur_ts = GST_CLOCK_TIME_NONE; + self->newsegment_sent = FALSE; gst_adapter_clear (self->adapter); } @@ -402,7 +407,18 @@ gst_pcap_parse_chain (GstPad * pad, GstBuffer * buffer) GST_PAD_CAPS (self->src_pad), &out_buf); if (ret == GST_FLOW_OK) { + memcpy (GST_BUFFER_DATA (out_buf), payload_data, payload_size); + GST_BUFFER_TIMESTAMP (out_buf) = self->cur_ts; + + if (!self->newsegment_sent && + GST_CLOCK_TIME_IS_VALID (self->cur_ts)) { + GstEvent *newsegment = + gst_event_new_new_segment (FALSE, 1, GST_FORMAT_TIME, + self->cur_ts, -1, 0); + gst_pad_push_event (self->src_pad, newsegment); + self->newsegment_sent = TRUE; + } ret = gst_pad_push (self->src_pad, out_buf); @@ -432,6 +448,7 @@ gst_pcap_parse_chain (GstPad * pad, GstBuffer * buffer) gst_adapter_flush (self->adapter, 16); + self->cur_ts = ts_sec * GST_SECOND + ts_usec * GST_USECOND; self->cur_packet_size = incl_len; } } else { @@ -464,6 +481,26 @@ gst_pcap_parse_chain (GstPad * pad, GstBuffer * buffer) return ret; } +static gboolean +gst_pcap_sink_event (GstPad * pad, GstEvent * event) +{ + gboolean ret = TRUE; + GstPcapParse *self = GST_PCAP_PARSE (gst_pad_get_parent (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_NEWSEGMENT: + /* Drop it, we'll replace it with our own */ + break; + default: + ret = gst_pad_push_event (self->src_pad, event); + } + + gst_object_unref (self); + + return ret; +} + + static gboolean plugin_init (GstPlugin * plugin) { diff --git a/gst/pcapparse/gstpcapparse.h b/gst/pcapparse/gstpcapparse.h index cc1b55f682..caaa52e2bb 100644 --- a/gst/pcapparse/gstpcapparse.h +++ b/gst/pcapparse/gstpcapparse.h @@ -70,6 +70,10 @@ struct _GstPcapParse gboolean initialized; gboolean swap_endian; gint64 cur_packet_size; + GstClockTime cur_ts; + + gboolean newsegment_sent; + gint64 buffer_offset; }; From bf4c1f354142fede7c34128eb31e08ef9a9f76f7 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Thu, 16 Jul 2009 10:06:36 +0100 Subject: [PATCH 11/19] Try to fit subtitles within the video frame when they're too large --- gst/dvdspu/gstspu-vobsub-render.c | 155 ++++++++++++++++++++---------- 1 file changed, 106 insertions(+), 49 deletions(-) diff --git a/gst/dvdspu/gstspu-vobsub-render.c b/gst/dvdspu/gstspu-vobsub-render.c index 3709d82ab1..30de0eb801 100644 --- a/gst/dvdspu/gstspu-vobsub-render.c +++ b/gst/dvdspu/gstspu-vobsub-render.c @@ -172,7 +172,7 @@ gstspu_vobsub_draw_rle_run (SpuState * state, gint16 x, gint16 end, x++; } /* Update the compositing buffer so we know how much to blend later */ - *(state->vobsub.comp_last_x_ptr) = end; + *(state->vobsub.comp_last_x_ptr) = end - 1; /* end is the start of the *next* run */ } } @@ -194,7 +194,7 @@ static void gstspu_vobsub_render_line (SpuState * state, guint8 * planes[3], guint16 * rle_offset) { - gint16 x, next_x, end, rle_code; + gint16 x, next_x, end, rle_code, next_draw_x; SpuColour *colour; /* Check for special case of chg_col info to use (either highlight or @@ -226,8 +226,11 @@ gstspu_vobsub_render_line (SpuState * state, guint8 * planes[3], rle_code = gstspu_vobsub_get_rle_code (state, rle_offset); colour = &state->vobsub.main_pal[rle_code & 3]; next_x = rle_end_x (rle_code, x, end); + next_draw_x = next_x; + if (next_draw_x > state->vobsub.clip_rect.right) + next_draw_x = state->vobsub.clip_rect.right; /* ensure no overflow */ /* Now draw the run between [x,next_x) */ - gstspu_vobsub_draw_rle_run (state, x, next_x, colour); + gstspu_vobsub_draw_rle_run (state, x, next_draw_x, colour); x = next_x; } } @@ -265,7 +268,7 @@ gstspu_vobsub_render_line_with_chgcol (SpuState * state, guint8 * planes[3], { SpuVobsubLineCtrlI *chg_col = state->vobsub.cur_chg_col; - gint16 x, next_x, disp_end, rle_code, run_end; + gint16 x, next_x, disp_end, rle_code, run_end, run_draw_end; SpuColour *colour; SpuVobsubPixCtrlI *cur_pix_ctrl; SpuVobsubPixCtrlI *next_pix_ctrl; @@ -313,9 +316,13 @@ gstspu_vobsub_render_line_with_chgcol (SpuState * state, guint8 * planes[3], while (x < next_x) { run_end = MIN (next_x, cur_reg_end); + run_draw_end = run_end; + if (run_draw_end > state->vobsub.clip_rect.right) + run_draw_end = state->vobsub.clip_rect.right; /* ensure no overflow */ + if (G_LIKELY (x < run_end)) { colour = &cur_pix_ctrl->pal_cache[rle_code & 3]; - gstspu_vobsub_draw_rle_run (state, x, run_end, colour); + gstspu_vobsub_draw_rle_run (state, x, run_draw_end, colour); x = run_end; } @@ -340,14 +347,17 @@ gstspu_vobsub_blend_comp_buffers (SpuState * state, guint8 * planes[3]) state->comp_right = MAX (state->vobsub.comp_last_x[0], state->vobsub.comp_last_x[1]); + state->comp_left = MAX (state->comp_left, state->vobsub.clip_rect.left); + state->comp_right = MIN (state->comp_right, state->vobsub.clip_rect.right); + gstspu_blend_comp_buffers (state, planes); } static void gstspu_vobsub_clear_comp_buffers (SpuState * state) { - state->comp_left = state->vobsub.disp_rect.left; - state->comp_right = state->vobsub.disp_rect.right; + state->comp_left = state->vobsub.clip_rect.left; + state->comp_right = state->vobsub.clip_rect.right; gstspu_clear_comp_buffers (state); @@ -375,13 +385,15 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf) g_return_if_fail (planes[2] + (state->UV_height * state->UV_stride) <= GST_BUFFER_DATA (buf) + GST_BUFFER_SIZE (buf)); - GST_DEBUG ("Rendering SPU. disp_rect %d,%d to %d,%d. hl_rect %d,%d to %d,%d", + GST_DEBUG_OBJECT (dvdspu, + "Rendering SPU. disp_rect %d,%d to %d,%d. hl_rect %d,%d to %d,%d", state->vobsub.disp_rect.left, state->vobsub.disp_rect.top, state->vobsub.disp_rect.right, state->vobsub.disp_rect.bottom, state->vobsub.hl_rect.left, state->vobsub.hl_rect.top, state->vobsub.hl_rect.right, state->vobsub.hl_rect.bottom); - GST_DEBUG ("vid_disp %d,%d", state->vid_width, state->vid_height); + GST_DEBUG_OBJECT (dvdspu, "video size %d,%d", state->vid_width, + state->vid_height); /* When reading RLE data, we track the offset in nibbles... */ state->vobsub.cur_offsets[0] = state->vobsub.pix_data[0] * 2; @@ -402,6 +414,74 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf) } else state->vobsub.cur_chg_col = NULL; + state->vobsub.clip_rect.left = state->vobsub.disp_rect.left; + state->vobsub.clip_rect.right = state->vobsub.disp_rect.right; + + /* center the image when display rectangle exceeds the video width */ + if (state->vid_width <= state->vobsub.disp_rect.right) { + gint left, disp_width; + + disp_width = state->vobsub.disp_rect.right - state->vobsub.disp_rect.left + + 1; + left = (state->vid_width - disp_width) / 2; + state->vobsub.disp_rect.left = left; + state->vobsub.disp_rect.right = left + disp_width - 1; + + /* if it clips to the right, shift it left, but only till zero */ + if (state->vobsub.disp_rect.right >= state->vid_width) { + gint shift = state->vobsub.disp_rect.right - state->vid_width - 1; + if (shift > state->vobsub.disp_rect.left) + shift = state->vobsub.disp_rect.left; + state->vobsub.disp_rect.left -= shift; + state->vobsub.disp_rect.right -= shift; + } + + /* init clip to disp */ + state->vobsub.clip_rect.left = state->vobsub.disp_rect.left; + state->vobsub.clip_rect.right = state->vobsub.disp_rect.right; + + /* clip right after the shift */ + if (state->vobsub.clip_rect.right >= state->vid_width) + state->vobsub.clip_rect.right = state->vid_width - 1; + + GST_DEBUG_OBJECT (dvdspu, + "clipping width to %d,%d", state->vobsub.clip_rect.left, + state->vobsub.clip_rect.right); + } + + /* for the height, bring it up till it fits as well as it can. We + * assume the picture is in the lower part. We should better check where it + * is and do something more clever. */ + state->vobsub.clip_rect.top = state->vobsub.disp_rect.top; + state->vobsub.clip_rect.bottom = state->vobsub.disp_rect.bottom; + if (state->vid_height <= state->vobsub.disp_rect.bottom) { + + /* shift it up, but only till zero */ + gint shift = state->vobsub.disp_rect.bottom - state->vid_height - 1; + if (shift > state->vobsub.disp_rect.top) + shift = state->vobsub.disp_rect.top; + state->vobsub.disp_rect.top -= shift; + state->vobsub.disp_rect.bottom -= shift; + + /* start on even line */ + if (state->vobsub.disp_rect.top & 1) { + state->vobsub.disp_rect.top--; + state->vobsub.disp_rect.bottom--; + } + + /* init clip to disp */ + state->vobsub.clip_rect.top = state->vobsub.disp_rect.top; + state->vobsub.clip_rect.bottom = state->vobsub.disp_rect.bottom; + + /* clip right after the shift */ + if (state->vobsub.clip_rect.bottom >= state->vid_height) + state->vobsub.clip_rect.bottom = state->vid_height - 1; + + GST_DEBUG_OBJECT (dvdspu, + "clipping height to %d,%d", state->vobsub.clip_rect.top, + state->vobsub.clip_rect.bottom); + } + /* We start rendering from the first line of the display rect */ y = state->vobsub.disp_rect.top; /* start_y is always an even number and we render lines in pairs from there, @@ -409,40 +489,10 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf) * single line at the end if the display rect ends on an even line too. */ last_y = (state->vobsub.disp_rect.bottom - 1) & ~(0x01); - /* center the image when display rectangle exceeds the video width */ - if (state->vid_width < state->vobsub.disp_rect.right) { - gint diff, disp_width; - - disp_width = state->vobsub.disp_rect.left - state->vobsub.disp_rect.right; - diff = (disp_width - state->vid_width) / 2; - - /* fixme, this is not used yet */ - state->vobsub.clip_rect.left = state->vobsub.disp_rect.left + diff; - state->vobsub.clip_rect.right = state->vobsub.disp_rect.right - diff; - - GST_DEBUG ("clipping width to %d,%d", state->vobsub.clip_rect.left, - state->vobsub.clip_rect.right); - } else { - state->vobsub.clip_rect.left = state->vobsub.disp_rect.left; - state->vobsub.clip_rect.right = state->vobsub.disp_rect.right; - } - - /* for the height, chop off the bottom bits of the diplay rectangle because we - * assume the picture is in the lower part. We should better check where it - * is and do something more clever. */ - state->vobsub.clip_rect.bottom = state->vobsub.disp_rect.bottom; - if (state->vid_height < state->vobsub.disp_rect.bottom) { - state->vobsub.clip_rect.top = - state->vobsub.disp_rect.bottom - state->vid_height; - GST_DEBUG ("clipping height to %d,%d", state->vobsub.clip_rect.top, - state->vobsub.clip_rect.bottom); - } else { - state->vobsub.clip_rect.top = state->vobsub.disp_rect.top; - /* Update our plane references to the first line of the disp_rect */ - planes[0] += state->Y_stride * y; - planes[1] += state->UV_stride * (y / 2); - planes[2] += state->UV_stride * (y / 2); - } + /* Update our plane references to the first line of the disp_rect */ + planes[0] += state->Y_stride * y; + planes[1] += state->UV_stride * (y / 2); + planes[2] += state->UV_stride * (y / 2); for (state->vobsub.cur_Y = y; state->vobsub.cur_Y <= last_y; state->vobsub.cur_Y++) { @@ -476,14 +526,21 @@ gstspu_vobsub_render (GstDVDSpu * dvdspu, GstBuffer * buf) } } if (state->vobsub.cur_Y == state->vobsub.disp_rect.bottom) { + gboolean clip; + + clip = (state->vobsub.cur_Y < state->vobsub.clip_rect.top + || state->vobsub.cur_Y > state->vobsub.clip_rect.bottom); + g_assert ((state->vobsub.disp_rect.bottom & 0x01) == 0); - /* Render a remaining lone last even line. y already has the correct value - * after the above loop exited. */ - gstspu_vobsub_clear_comp_buffers (state); - state->vobsub.comp_last_x_ptr = state->vobsub.comp_last_x; - gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[0]); - gstspu_vobsub_blend_comp_buffers (state, planes); + if (!clip) { + /* Render a remaining lone last even line. y already has the correct value + * after the above loop exited. */ + gstspu_vobsub_clear_comp_buffers (state); + state->vobsub.comp_last_x_ptr = state->vobsub.comp_last_x; + gstspu_vobsub_render_line (state, planes, &state->vobsub.cur_offsets[0]); + gstspu_vobsub_blend_comp_buffers (state, planes); + } } /* for debugging purposes, draw a faint rectangle at the edges of the disp_rect */ From c67dc212bfc4f1ef2bbcbd29096f1ae29036d854 Mon Sep 17 00:00:00 2001 From: Josep Torra Date: Fri, 4 Sep 2009 12:02:18 +0200 Subject: [PATCH 12/19] mpegtsdemux: some more handling of VC1 and EAC3 If the PMT have the register descriptor HDMV assume EAC3 For VC1 make the code more aligned to RP227. --- gst/mpegdemux/gstmpegdefs.h | 4 ++-- gst/mpegdemux/gstmpegdesc.h | 4 ++++ gst/mpegdemux/gstmpegtsdemux.c | 34 ++++++++++++++++++++++++++++++---- 3 files changed, 36 insertions(+), 6 deletions(-) diff --git a/gst/mpegdemux/gstmpegdefs.h b/gst/mpegdemux/gstmpegdefs.h index 35ee967bfb..ef2bd46a44 100644 --- a/gst/mpegdemux/gstmpegdefs.h +++ b/gst/mpegdemux/gstmpegdefs.h @@ -185,8 +185,8 @@ #define ST_BD_SECONDARY_AC3_PLUS 0xa1 #define ST_BD_SECONDARY_DTS_HD 0xa2 -/* VC1 extension */ -#define ST_VIDEO_VC1 0xea +/* defined for VC1 extension in RP227 */ +#define ST_PRIVATE_EA 0xea /* HDV AUX stream mapping * 0xA0 ISO/IEC 61834-11 diff --git a/gst/mpegdemux/gstmpegdesc.h b/gst/mpegdemux/gstmpegdesc.h index 71b74aa2d0..09a9a7c6cd 100644 --- a/gst/mpegdemux/gstmpegdesc.h +++ b/gst/mpegdemux/gstmpegdesc.h @@ -319,6 +319,10 @@ /* DVB Carousel Identifier Descriptor */ #define DESC_DVB_CAROUSEL_IDENTIFIER_carousel_id(desc) (GST_READ_UINT32_BE((desc) + 2)) +/* registration_descriptor format IDs */ +#define DRF_ID_HDMV 0x48444d56 +#define DRF_ID_VC1 0x56432D31 /* defined in RP227 */ + typedef struct { guint n_desc; guint8 data_length; diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index 14cddfea0a..f6d3b1171f 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -206,6 +206,9 @@ static MpegTsPmtInfo *mpegts_demux_build_pmt_info (GstMpegTSDemux * demux, static GstElementClass *parent_class = NULL; +static FORCE_INLINE GstMpegTSStream + * gst_mpegts_demux_get_stream_for_PID (GstMpegTSDemux * demux, guint16 PID); + /*static guint gst_mpegts_demux_signals[LAST_SIGNAL] = { 0 };*/ GType @@ -563,7 +566,6 @@ gst_mpegts_stream_is_video (GstMpegTSStream * stream) case ST_VIDEO_MPEG2: case ST_VIDEO_MPEG4: case ST_VIDEO_H264: - case ST_VIDEO_VC1: return TRUE; case ST_VIDEO_DIRAC: return gst_mpegts_is_dirac_stream (stream); @@ -660,7 +662,16 @@ gst_mpegts_demux_fill_stream (GstMpegTSStream * stream, guint8 id, caps = gst_caps_new_simple ("video/x-dirac", NULL); } break; - case ST_VIDEO_VC1: + case ST_PRIVATE_EA: /* Try to detect a VC1 stream */ + { + guint8 *desc = NULL; + + if (stream->ES_info) + desc = gst_mpeg_descriptor_find (stream->ES_info, DESC_REGISTRATION); + if (!(desc && DESC_REGISTRATION_format_identifier (desc) == DRF_ID_VC1)) { + GST_WARNING ("0xea private stream type found but no descriptor " + "for VC1. Assuming plain VC1."); + } template = klass->video_template; name = g_strdup_printf ("video_%04x", stream->PID); caps = gst_caps_new_simple ("video/x-wmv", @@ -668,8 +679,23 @@ gst_mpegts_demux_fill_stream (GstMpegTSStream * stream, guint8 id, "format", GST_TYPE_FOURCC, GST_MAKE_FOURCC ('W', 'V', 'C', '1'), NULL); break; + } case ST_BD_AUDIO_AC3: - if (gst_mpeg_descriptor_find (stream->ES_info, DESC_DVB_ENHANCED_AC3)) { + { + GstMpegTSStream *PMT_stream = + gst_mpegts_demux_get_stream_for_PID (stream->demux, stream->PMT_pid); + GstMPEGDescriptor *program_info = PMT_stream->PMT.program_info; + guint8 *desc = NULL; + + if (program_info) + desc = gst_mpeg_descriptor_find (program_info, DESC_REGISTRATION); + + if (desc && DESC_REGISTRATION_format_identifier (desc) == DRF_ID_HDMV) { + template = klass->audio_template; + name = g_strdup_printf ("audio_%04x", stream->PID); + caps = gst_caps_new_simple ("audio/x-eac3", NULL); + } else if (gst_mpeg_descriptor_find (stream->ES_info, + DESC_DVB_ENHANCED_AC3)) { template = klass->audio_template; name = g_strdup_printf ("audio_%04x", stream->PID); caps = gst_caps_new_simple ("audio/x-eac3", NULL); @@ -684,6 +710,7 @@ gst_mpegts_demux_fill_stream (GstMpegTSStream * stream, guint8 id, caps = gst_caps_new_simple ("audio/x-ac3", NULL); } break; + } case ST_BD_AUDIO_EAC3: template = klass->audio_template; name = g_strdup_printf ("audio_%04x", stream->PID); @@ -2849,7 +2876,6 @@ beach: return res; } - static FORCE_INLINE gint is_mpegts_sync (const guint8 * in_data, const guint8 * end_data, guint packetsize) From d321799bfbb3d350bfeb8f2bffa088f4788ae7f0 Mon Sep 17 00:00:00 2001 From: Julien Isorce Date: Fri, 4 Sep 2009 12:08:02 +0200 Subject: [PATCH 13/19] dshowvideosrc: move default video caps into GstCapturePinMediaType --- sys/dshowsrcwrapper/gstdshow.cpp | 14 ++--- sys/dshowsrcwrapper/gstdshow.h | 11 +--- sys/dshowsrcwrapper/gstdshowvideosrc.cpp | 71 ++++++++---------------- sys/dshowsrcwrapper/gstdshowvideosrc.h | 3 - 4 files changed, 32 insertions(+), 67 deletions(-) diff --git a/sys/dshowsrcwrapper/gstdshow.cpp b/sys/dshowsrcwrapper/gstdshow.cpp index afec3ce944..d5425438a8 100755 --- a/sys/dshowsrcwrapper/gstdshow.cpp +++ b/sys/dshowsrcwrapper/gstdshow.cpp @@ -323,17 +323,17 @@ gst_dshow_show_propertypage (IBaseFilter *base_filter) } GstCaps *gst_dshow_new_video_caps (GstVideoFormat video_format, const gchar* name, - const VIDEO_STREAM_CONFIG_CAPS * vscc, const VIDEOINFOHEADER *video_info, - GstCaptureVideoDefault *video_default) + const VIDEO_STREAM_CONFIG_CAPS * vscc, GstCapturePinMediaType *pin_mediatype) { GstCaps *video_caps = NULL; GstStructure *video_structure = NULL; + VIDEOINFOHEADER *video_info = (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat; - video_default->defaultWidth = video_info->bmiHeader.biWidth; - video_default->defaultHeight = video_info->bmiHeader.biHeight; - video_default->defaultFPS = (gint) (10000000 / video_info->AvgTimePerFrame); - video_default->granularityWidth = vscc->OutputGranularityX; - video_default->granularityHeight = vscc->OutputGranularityY; + pin_mediatype->defaultWidth = video_info->bmiHeader.biWidth; + pin_mediatype->defaultHeight = video_info->bmiHeader.biHeight; + pin_mediatype->defaultFPS = (gint) (10000000 / video_info->AvgTimePerFrame); + pin_mediatype->granularityWidth = vscc->OutputGranularityX; + pin_mediatype->granularityHeight = vscc->OutputGranularityY; /* raw video format */ switch (video_format) { diff --git a/sys/dshowsrcwrapper/gstdshow.h b/sys/dshowsrcwrapper/gstdshow.h index 553b42fe63..3b9110943f 100755 --- a/sys/dshowsrcwrapper/gstdshow.h +++ b/sys/dshowsrcwrapper/gstdshow.h @@ -35,19 +35,15 @@ typedef struct _GstCapturePinMediaType { AM_MEDIA_TYPE *mediatype; IPin *capture_pin; -} GstCapturePinMediaType; -/* video default properties associated to a video format (YUY2, I420, RGB24 ...) */ -typedef struct _GstCaptureVideoDefault -{ + //default caps gint defaultWidth; gint defaultHeight; gint defaultFPS; gint granularityWidth; //will be removed when GST_TYPE_INT_RANGE_STEP exits gint granularityHeight; //will be removed when GST_TYPE_INT_RANGE_STEP exits - -} GstCaptureVideoDefault; +} GstCapturePinMediaType; /* free memory of the input pin mediatype */ void gst_dshow_free_pin_mediatype (gpointer pt); @@ -78,7 +74,6 @@ gboolean gst_dshow_show_propertypage (IBaseFilter *base_filter); /* transform a dshow video caps to a gstreamer video caps */ GstCaps *gst_dshow_new_video_caps (GstVideoFormat video_format, const gchar* name, - const VIDEO_STREAM_CONFIG_CAPS * vscc, const VIDEOINFOHEADER *video_info, - GstCaptureVideoDefault *video_default); + const VIDEO_STREAM_CONFIG_CAPS * vscc, GstCapturePinMediaType *pin_mediatype); #endif /* _GSTDSHOW_ */ \ No newline at end of file diff --git a/sys/dshowsrcwrapper/gstdshowvideosrc.cpp b/sys/dshowsrcwrapper/gstdshowvideosrc.cpp index 5dbbb0b4e6..726b1d0be5 100755 --- a/sys/dshowsrcwrapper/gstdshowvideosrc.cpp +++ b/sys/dshowsrcwrapper/gstdshowvideosrc.cpp @@ -203,7 +203,6 @@ gst_dshowvideosrc_init (GstDshowVideoSrc * src, GstDshowVideoSrcClass * klass) src->media_filter = NULL; src->filter_graph = NULL; src->caps = NULL; - src->video_defaults = NULL; src->pins_mediatypes = NULL; src->is_rgb = FALSE; @@ -237,12 +236,12 @@ gst_dshowvideosrc_src_fixate (GstBaseSrc * bsrc, GstCaps * caps) } if (res != -1) { - GList *type_video_default = g_list_nth (src->video_defaults, res); - if (type_video_default) { - GstCaptureVideoDefault *video_default = (GstCaptureVideoDefault *) type_video_default->data; - gst_structure_fixate_field_nearest_int (structure, "width", video_default->defaultWidth); - gst_structure_fixate_field_nearest_int (structure, "height", video_default->defaultHeight); - gst_structure_fixate_field_nearest_fraction (structure, "framerate", video_default->defaultFPS, 1); + GList *type_pin_mediatype = g_list_nth (src->pins_mediatypes, res); + if (type_pin_mediatype) { + GstCapturePinMediaType *pin_mediatype = (GstCapturePinMediaType *) type_pin_mediatype->data; + gst_structure_fixate_field_nearest_int (structure, "width", pin_mediatype->defaultWidth); + gst_structure_fixate_field_nearest_int (structure, "height", pin_mediatype->defaultHeight); + gst_structure_fixate_field_nearest_fraction (structure, "framerate", pin_mediatype->defaultFPS, 1); } } } @@ -267,11 +266,6 @@ gst_dshowvideosrc_dispose (GObject * gobject) src->caps = NULL; } - if (src->video_defaults) { - g_list_free (src->video_defaults); - src->video_defaults = NULL; - } - if (src->pins_mediatypes) { gst_dshow_free_pins_mediatypes (src->pins_mediatypes); src->pins_mediatypes = NULL; @@ -551,6 +545,7 @@ gst_dshowvideosrc_get_caps (GstBaseSrc * basesrc) GstCaps *caps = gst_dshowvideosrc_getcaps_from_streamcaps (src, capture_pin, streamcaps); + g_print ("caps: %s\n", gst_caps_to_string(caps)); if (caps) { gst_caps_append (src->caps, caps); @@ -694,15 +689,10 @@ gst_dshowvideosrc_set_caps (GstBaseSrc * bsrc, GstCaps * caps) if (res != -1 && src->pins_mediatypes) { /* get the corresponding media type and build the dshow graph */ - GList *type = g_list_nth (src->pins_mediatypes, res); + GList *type_pin_mediatype = g_list_nth (src->pins_mediatypes, res); - //will be removed when GST_TYPE_INT_RANGE_STEP exits - GList *type_video_default = g_list_nth (src->video_defaults, res); - - if (type && type_video_default) { - //will be removed when GST_TYPE_INT_RANGE_STEP exits - GstCaptureVideoDefault *video_default = (GstCaptureVideoDefault *) type_video_default->data; - GstCapturePinMediaType *pin_mediatype = NULL; + if (type_pin_mediatype) { + GstCapturePinMediaType *pin_mediatype = (GstCapturePinMediaType *) type_pin_mediatype->data; gchar *caps_string = NULL; gchar *src_caps_string = NULL; @@ -719,17 +709,10 @@ gst_dshowvideosrc_set_caps (GstBaseSrc * bsrc, GstCaps * caps) /* check if the desired video size is valid about granularity */ /* This check will be removed when GST_TYPE_INT_RANGE_STEP exits */ /* See remarks in gst_dshowvideosrc_getcaps_from_streamcaps function */ - if (video_default->granularityWidth != 0 && width % video_default->granularityWidth != 0) - g_warning ("your desired video size is not valid : %d mod %d !=0\n", width, video_default->granularityWidth) ; - if (video_default->granularityHeight !=0 && height % video_default->granularityHeight != 0) - g_warning ("your desired video size is not valid : %d mod %d !=0\n", height, video_default->granularityHeight) ; - - /* display all capabilities when using --gst-debug-level=3 */ - src_caps_string = gst_caps_to_string (src->caps); - GST_LOG (src_caps_string); - g_free (src_caps_string); - - pin_mediatype = (GstCapturePinMediaType *) type->data; + if (pin_mediatype->granularityWidth != 0 && width % pin_mediatype->granularityWidth != 0) + g_warning ("your desired video size is not valid : %d mod %d !=0\n", width, pin_mediatype->granularityWidth) ; + if (pin_mediatype->granularityHeight !=0 && height % pin_mediatype->granularityHeight != 0) + g_warning ("your desired video size is not valid : %d mod %d !=0\n", height, pin_mediatype->granularityHeight) ; /* update mediatype */ video_info = (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat; @@ -899,7 +882,6 @@ gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin, for (; i < icount; i++) { GstCapturePinMediaType *pin_mediatype = g_new0 (GstCapturePinMediaType, 1); - GstCaptureVideoDefault *video_default = g_new0 (GstCaptureVideoDefault, 1); pin->AddRef(); pin_mediatype->capture_pin = pin; @@ -907,42 +889,33 @@ gst_dshowvideosrc_getcaps_from_streamcaps (GstDshowVideoSrc * src, IPin * pin, hres = streamcaps->GetStreamCaps(i, &pin_mediatype->mediatype, (BYTE *) & vscc); if (FAILED (hres) || !pin_mediatype->mediatype) { gst_dshow_free_pin_mediatype (pin_mediatype); - g_free (video_default); } else { GstCaps *mediacaps = NULL; if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_I420, FORMAT_VideoInfo)) { - mediacaps = gst_dshow_new_video_caps (GST_VIDEO_FORMAT_I420, NULL, &vscc, - (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat, video_default); + mediacaps = gst_dshow_new_video_caps (GST_VIDEO_FORMAT_I420, NULL, &vscc, pin_mediatype); } else if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_RGB24, FORMAT_VideoInfo)) { - mediacaps = gst_dshow_new_video_caps (GST_VIDEO_FORMAT_BGR, NULL, &vscc, - (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat, video_default); + mediacaps = gst_dshow_new_video_caps (GST_VIDEO_FORMAT_BGR, NULL, &vscc, pin_mediatype); } else if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_dvsd, FORMAT_VideoInfo)) { mediacaps = gst_dshow_new_video_caps (GST_VIDEO_FORMAT_UNKNOWN, - "video/x-dv, systemstream=FALSE", &vscc, (VIDEOINFOHEADER *) - pin_mediatype->mediatype->pbFormat, video_default); + "video/x-dv, systemstream=FALSE", &vscc, pin_mediatype); - } else if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_dvsd, FORMAT_DvInfo)) { - - video_default->granularityWidth = 0; - video_default->granularityHeight = 0; - + } else if (gst_dshow_check_mediatype (pin_mediatype->mediatype, MEDIASUBTYPE_dvsd, FORMAT_DvInfo)) { mediacaps = gst_dshow_new_video_caps (GST_VIDEO_FORMAT_UNKNOWN, - "video/x-dv, systemstream=TRUE", &vscc, (VIDEOINFOHEADER *) - pin_mediatype->mediatype->pbFormat, video_default); + "video/x-dv, systemstream=TRUE", &vscc, pin_mediatype); + + pin_mediatype->granularityWidth = 0; + pin_mediatype->granularityHeight = 0; } if (mediacaps) { src->pins_mediatypes = g_list_append (src->pins_mediatypes, pin_mediatype); - src->video_defaults = - g_list_append (src->video_defaults, video_default); gst_caps_append (caps, mediacaps); } else { gst_dshow_free_pin_mediatype (pin_mediatype); - g_free (video_default); } } diff --git a/sys/dshowsrcwrapper/gstdshowvideosrc.h b/sys/dshowsrcwrapper/gstdshowvideosrc.h index bced6bef68..9fe0f452b7 100755 --- a/sys/dshowsrcwrapper/gstdshowvideosrc.h +++ b/sys/dshowsrcwrapper/gstdshowvideosrc.h @@ -56,9 +56,6 @@ struct _GstDshowVideoSrc /* list of caps created from the list of supported media types of the dshow capture filter */ GstCaps *caps; - /* list of dshow default video properties from filter's capture pins */ - GList *video_defaults; - /* list of dshow media types from the filter's capture pins */ GList *pins_mediatypes; From 659e90f8f6be64caece8a011c2398111c36a78f3 Mon Sep 17 00:00:00 2001 From: Josep Torra Date: Fri, 4 Sep 2009 12:30:18 +0200 Subject: [PATCH 14/19] mpegtsdemux: added autodetect of packet size and removed m2ts mode property --- gst/mpegdemux/gstmpegtsdemux.c | 70 ++++++++++++++++------------------ gst/mpegdemux/gstmpegtsdemux.h | 4 +- 2 files changed, 35 insertions(+), 39 deletions(-) diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index f6d3b1171f..a0b1901067 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -103,7 +103,6 @@ enum PROP_PROGRAM_NUMBER, PROP_PAT_INFO, PROP_PMT_INFO, - PROP_M2TS }; #define GSTTIME_TO_BYTES(time) \ @@ -307,11 +306,6 @@ gst_mpegts_demux_class_init (GstMpegTSDemuxClass * klass) "about the currently selected program and its streams", MPEGTS_TYPE_PMT_INFO, G_PARAM_READABLE)); - g_object_class_install_property (gobject_class, PROP_M2TS, - g_param_spec_boolean ("m2ts_mode", "M2TS(192 bytes) Mode", - "Defines if the input is normal TS ie .ts(188 bytes)" - "or Blue-Ray Format ie .m2ts(192 bytes).", FALSE, G_PARAM_READWRITE)); - gstelement_class->change_state = gst_mpegts_demux_change_state; gstelement_class->provide_clock = gst_mpegts_demux_provide_clock; } @@ -333,8 +327,6 @@ gst_mpegts_demux_init (GstMpegTSDemux * demux) demux->nb_elementary_pids = 0; demux->check_crc = DEFAULT_PROP_CHECK_CRC; demux->program_number = DEFAULT_PROP_PROGRAM_NUMBER; - demux->packetsize = MPEGTS_NORMAL_TS_PACKETSIZE; - demux->m2ts_mode = FALSE; demux->sync_lut = NULL; demux->sync_lut_len = 0; demux->bitrate = -1; @@ -487,34 +479,18 @@ static gboolean gst_mpegts_demux_sink_setcaps (GstPad * pad, GstCaps * caps) { GstMpegTSDemux *demux = GST_MPEGTS_DEMUX (gst_pad_get_parent (pad)); - gboolean ret = FALSE; GstStructure *structure = NULL; - gint expected_packetsize = - (demux->m2ts_mode ? MPEGTS_M2TS_TS_PACKETSIZE : - MPEGTS_NORMAL_TS_PACKETSIZE); - gint packetsize = expected_packetsize; structure = gst_caps_get_structure (caps, 0); GST_DEBUG_OBJECT (demux, "setcaps called with %" GST_PTR_FORMAT, caps); - if (!gst_structure_get_int (structure, "packetsize", &packetsize)) { + if (!gst_structure_get_int (structure, "packetsize", &demux->packetsize)) { GST_DEBUG_OBJECT (demux, "packetsize parameter not found in sink caps"); } - if (packetsize < expected_packetsize) { - GST_WARNING_OBJECT (demux, "packetsize = %" G_GINT32_FORMAT "is less then" - "expected packetsize of %d bytes", packetsize, expected_packetsize); - goto beach; - } - - /* here we my have a correct value for packet size */ - demux->packetsize = packetsize; - ret = TRUE; - -beach: gst_object_unref (demux); - return ret; + return TRUE; } static FORCE_INLINE guint32 @@ -2901,6 +2877,26 @@ is_mpegts_sync (const guint8 * in_data, const guint8 * end_data, return ret; } +static inline void +gst_mpegts_demux_detect_packet_size (GstMpegTSDemux * demux, guint len) +{ + guint i, packetsize; + + for (i = 1; i < len; i++) { + packetsize = demux->sync_lut[i] - demux->sync_lut[i - 1]; + if (packetsize == MPEGTS_NORMAL_TS_PACKETSIZE || + packetsize == MPEGTS_M2TS_TS_PACKETSIZE || + packetsize == MPEGTS_DVB_ASI_TS_PACKETSIZE || + packetsize == MPEGTS_ATSC_TS_PACKETSIZE) + goto done; + else + packetsize = 0; + } + +done: + demux->packetsize = (packetsize ? packetsize : MPEGTS_NORMAL_TS_PACKETSIZE); + GST_DEBUG_OBJECT (demux, "packet_size set to %d bytes", demux->packetsize); +} static FORCE_INLINE guint gst_mpegts_demux_sync_scan (GstMpegTSDemux * demux, const guint8 * in_data, @@ -2909,10 +2905,12 @@ gst_mpegts_demux_sync_scan (GstMpegTSDemux * demux, const guint8 * in_data, guint sync_count = 0; const guint8 *end_scan = in_data + size - demux->packetsize; guint8 *ptr_data = (guint8 *) in_data; + guint packetsize = + (demux->packetsize ? demux->packetsize : MPEGTS_NORMAL_TS_PACKETSIZE); /* Check if the LUT table is big enough */ - if (G_UNLIKELY (demux->sync_lut_len < (size / MPEGTS_NORMAL_TS_PACKETSIZE))) { - demux->sync_lut_len = size / MPEGTS_NORMAL_TS_PACKETSIZE; + if (G_UNLIKELY (demux->sync_lut_len < (size / packetsize))) { + demux->sync_lut_len = size / packetsize; if (demux->sync_lut) g_free (demux->sync_lut); demux->sync_lut = g_new0 (guint8 *, demux->sync_lut_len); @@ -2922,22 +2920,24 @@ gst_mpegts_demux_sync_scan (GstMpegTSDemux * demux, const guint8 * in_data, while (ptr_data <= end_scan && sync_count < demux->sync_lut_len) { /* if sync code is found try to store it in the LUT */ - guint chance = is_mpegts_sync (ptr_data, end_scan, demux->packetsize); + guint chance = is_mpegts_sync (ptr_data, end_scan, packetsize); if (G_LIKELY (chance > 50)) { /* skip paketsize bytes and try find next */ - guint8 *next_sync = ptr_data + demux->packetsize; + guint8 *next_sync = ptr_data + packetsize; if (next_sync < end_scan) { demux->sync_lut[sync_count] = ptr_data; sync_count++; - ptr_data += demux->packetsize; + ptr_data += packetsize; } else goto done; - } else { ptr_data++; } } done: + if (G_UNLIKELY (!demux->packetsize)) + gst_mpegts_demux_detect_packet_size (demux, sync_count); + *flush = ptr_data - in_data; return sync_count; @@ -3147,9 +3147,6 @@ gst_mpegts_demux_set_property (GObject * object, guint prop_id, case PROP_PROGRAM_NUMBER: demux->program_number = g_value_get_int (value); break; - case PROP_M2TS: - demux->m2ts_mode = g_value_get_boolean (value); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -3200,9 +3197,6 @@ gst_mpegts_demux_get_property (GObject * object, guint prop_id, } break; } - case PROP_M2TS: - g_value_set_boolean (value, demux->m2ts_mode); - break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; diff --git a/gst/mpegdemux/gstmpegtsdemux.h b/gst/mpegdemux/gstmpegtsdemux.h index fde68926d4..693ece1e19 100644 --- a/gst/mpegdemux/gstmpegtsdemux.h +++ b/gst/mpegdemux/gstmpegtsdemux.h @@ -59,6 +59,8 @@ G_BEGIN_DECLS #define MPEGTS_MAX_PID 0x1fff #define MPEGTS_NORMAL_TS_PACKETSIZE 188 #define MPEGTS_M2TS_TS_PACKETSIZE 192 +#define MPEGTS_DVB_ASI_TS_PACKETSIZE 204 +#define MPEGTS_ATSC_TS_PACKETSIZE 208 #define IS_MPEGTS_SYNC(data) (((data)[0] == 0x47) && \ (((data)[1] & 0x80) == 0x00) && \ @@ -200,7 +202,7 @@ struct _GstMpegTSDemux { /* indicates that we need to close our pad group, because we've added * at least one pad */ gboolean need_no_more_pads; - guint16 packetsize; + gint packetsize; gboolean m2ts_mode; /* clocking */ GstClock * clock; From b60d71482ffe47486fa300eb83bc0e3f15a8b837 Mon Sep 17 00:00:00 2001 From: Josep Torra Date: Fri, 4 Sep 2009 12:35:31 +0200 Subject: [PATCH 15/19] mpegtsdemux: set specific caps for lpcm in private stream In the clips that I've found those streams, the lpcm header is different than the DVD case. Then the decoder need to know this in order to be able parse it. --- gst/mpegdemux/gstmpegtsdemux.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/mpegdemux/gstmpegtsdemux.c b/gst/mpegdemux/gstmpegtsdemux.c index a0b1901067..e7226f00ce 100644 --- a/gst/mpegdemux/gstmpegtsdemux.c +++ b/gst/mpegdemux/gstmpegtsdemux.c @@ -137,7 +137,7 @@ enum "mute = (boolean) { FALSE, TRUE }; " \ "audio/x-ac3; audio/x-eac3;" \ "audio/x-dts;" \ - "audio/x-private1-lpcm" \ + "audio/x-private-ts-lpcm" \ ) /* Can also use the subpicture pads for text subtitles? */ @@ -705,7 +705,7 @@ gst_mpegts_demux_fill_stream (GstMpegTSStream * stream, guint8 id, case ST_BD_AUDIO_LPCM: template = klass->audio_template; name = g_strdup_printf ("audio_%04x", stream->PID); - caps = gst_caps_new_simple ("audio/x-private1-lpcm", NULL); + caps = gst_caps_new_simple ("audio/x-private-ts-lpcm", NULL); break; case ST_PS_DVD_SUBPICTURE: template = klass->subpicture_template; From ef999c5df7e3edf825187a7727acd0a1dddfdfbd Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 4 Sep 2009 12:40:07 +0200 Subject: [PATCH 16/19] sirenenc: cleanups --- gst/siren/gstsirenenc.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/gst/siren/gstsirenenc.c b/gst/siren/gstsirenenc.c index b0dfbc64d7..9b6a2a8b26 100644 --- a/gst/siren/gstsirenenc.c +++ b/gst/siren/gstsirenenc.c @@ -209,7 +209,7 @@ gst_siren_enc_sink_event (GstPad * pad, GstEvent * event) static GstFlowReturn gst_siren_enc_chain (GstPad * pad, GstBuffer * buf) { - GstSirenEnc *enc = GST_SIREN_ENC (gst_pad_get_parent_element (pad)); + GstSirenEnc *enc; GstFlowReturn ret = GST_FLOW_OK; GstBuffer *out_buf; guint8 *in_data, *out_data; @@ -221,6 +221,8 @@ gst_siren_enc_chain (GstPad * pad, GstBuffer * buf) GstClockTime timestamp; guint64 distance; + enc = GST_SIREN_ENC (GST_PAD_PARENT (pad)); + discont = GST_BUFFER_IS_DISCONT (buf); if (discont) { GST_DEBUG_OBJECT (enc, "received DISCONT, flush adapter"); @@ -230,11 +232,11 @@ gst_siren_enc_chain (GstPad * pad, GstBuffer * buf) gst_adapter_push (enc->adapter, buf); - GST_LOG_OBJECT (enc, "Received buffer of size %d with adapter of size : %d", - GST_BUFFER_SIZE (buf), gst_adapter_available (enc->adapter)); - size = gst_adapter_available (enc->adapter); + GST_LOG_OBJECT (enc, "Received buffer of size %d with adapter of size : %d", + GST_BUFFER_SIZE (buf), size); + /* we need to process 640 input bytes to produce 40 output bytes */ /* calculate the amount of frames we will handle */ num_frames = size / 640; @@ -260,7 +262,8 @@ gst_siren_enc_chain (GstPad * pad, GstBuffer * buf) timestamp = gst_adapter_prev_timestamp (enc->adapter, &distance); /* add the amount of time taken by the distance */ - timestamp += gst_util_uint64_scale_int (distance / 2, GST_SECOND, 16000); + if (timestamp != -1) + timestamp += gst_util_uint64_scale_int (distance / 2, GST_SECOND, 16000); GST_LOG_OBJECT (enc, "timestamp %" GST_TIME_FORMAT ", distance %" G_GUINT64_FORMAT, @@ -299,8 +302,6 @@ done: if (to_free) g_free (to_free); - gst_object_unref (enc); - return ret; /* ERRORS */ From d557572e66ea9de7b74e409074d0d048ffd49cea Mon Sep 17 00:00:00 2001 From: Wim Taymans Date: Fri, 4 Sep 2009 12:40:40 +0200 Subject: [PATCH 17/19] sirendec: rewrite sirendec Add setcaps and event functions. Add state change functions to clean variables. Use adapter. Add timestamps and duration on outgoing buffers. Add DISCONT handling. --- gst/siren/gstsirendec.c | 235 ++++++++++++++++++++++++++++++---------- gst/siren/gstsirendec.h | 5 +- 2 files changed, 181 insertions(+), 59 deletions(-) diff --git a/gst/siren/gstsirendec.c b/gst/siren/gstsirendec.c index edf728fca8..d6eb35ed6f 100644 --- a/gst/siren/gstsirendec.c +++ b/gst/siren/gstsirendec.c @@ -40,6 +40,8 @@ GST_DEBUG_CATEGORY (sirendec_debug); #define GST_CAT_DEFAULT (sirendec_debug) +#define FRAME_DURATION (20 * GST_MSECOND) + /* elementfactory information */ static const GstElementDetails gst_siren_dec_details = GST_ELEMENT_DETAILS ("Siren Decoder element", @@ -75,11 +77,15 @@ enum ARG_0, }; +static void gst_siren_dec_finalize (GObject * object); +static GstStateChangeReturn +gst_siren_change_state (GstElement * element, GstStateChange transition); + +static gboolean gst_siren_dec_sink_setcaps (GstPad * pad, GstCaps * caps); +static gboolean gst_siren_dec_sink_event (GstPad * pad, GstEvent * event); static GstFlowReturn gst_siren_dec_chain (GstPad * pad, GstBuffer * buf); -static void gst_siren_dec_dispose (GObject * object); - static void _do_init (GType type) { @@ -113,7 +119,9 @@ gst_siren_dec_class_init (GstSirenDecClass * klass) GST_DEBUG ("Initializing Class"); - gobject_class->dispose = GST_DEBUG_FUNCPTR (gst_siren_dec_dispose); + gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_siren_dec_finalize); + + gstelement_class->change_state = GST_DEBUG_FUNCPTR (gst_siren_change_state); GST_DEBUG ("Class Init done"); } @@ -128,102 +136,215 @@ gst_siren_dec_init (GstSirenDec * dec, GstSirenDecClass * klass) dec->sinkpad = gst_pad_new_from_static_template (&sinktemplate, "sink"); dec->srcpad = gst_pad_new_from_static_template (&srctemplate, "src"); + gst_pad_set_setcaps_function (dec->sinkpad, + GST_DEBUG_FUNCPTR (gst_siren_dec_sink_setcaps)); + gst_pad_set_event_function (dec->sinkpad, + GST_DEBUG_FUNCPTR (gst_siren_dec_sink_event)); gst_pad_set_chain_function (dec->sinkpad, GST_DEBUG_FUNCPTR (gst_siren_dec_chain)); gst_element_add_pad (GST_ELEMENT (dec), dec->sinkpad); gst_element_add_pad (GST_ELEMENT (dec), dec->srcpad); - dec->srccaps = gst_static_pad_template_get_caps (&srctemplate); + dec->adapter = gst_adapter_new (); GST_DEBUG_OBJECT (dec, "Init done"); } static void -gst_siren_dec_dispose (GObject * object) +gst_siren_dec_finalize (GObject * object) { GstSirenDec *dec = GST_SIREN_DEC (object); - GST_DEBUG_OBJECT (dec, "Disposing"); + GST_DEBUG_OBJECT (dec, "Finalize"); - if (dec->decoder) { - Siren7_CloseDecoder (dec->decoder); - dec->decoder = NULL; + Siren7_CloseDecoder (dec->decoder); + g_object_unref (dec->adapter); + + G_OBJECT_CLASS (parent_class)->finalize (object); +} + +static gboolean +gst_siren_dec_sink_setcaps (GstPad * pad, GstCaps * caps) +{ + GstSirenDec *dec; + gboolean res; + GstCaps *outcaps; + + dec = GST_SIREN_DEC (GST_PAD_PARENT (pad)); + + outcaps = gst_static_pad_template_get_caps (&srctemplate); + res = gst_pad_set_caps (dec->srcpad, outcaps); + gst_caps_unref (outcaps); + + return res; +} + +static gboolean +gst_siren_dec_sink_event (GstPad * pad, GstEvent * event) +{ + GstSirenDec *dec; + gboolean res; + + dec = GST_SIREN_DEC (GST_PAD_PARENT (pad)); + + switch (GST_EVENT_TYPE (event)) { + case GST_EVENT_EOS: + gst_adapter_clear (dec->adapter); + res = gst_pad_push_event (dec->srcpad, event); + break; + case GST_EVENT_FLUSH_STOP: + gst_adapter_clear (dec->adapter); + res = gst_pad_push_event (dec->srcpad, event); + break; + default: + res = gst_pad_push_event (dec->srcpad, event); + break; } - - if (dec->srccaps) { - gst_caps_unref (dec->srccaps); - dec->srccaps = NULL; - } - - G_OBJECT_CLASS (parent_class)->dispose (object); + return res; } static GstFlowReturn gst_siren_dec_chain (GstPad * pad, GstBuffer * buf) { - GstSirenDec *dec = GST_SIREN_DEC (gst_pad_get_parent_element (pad)); + GstSirenDec *dec; GstFlowReturn ret = GST_FLOW_OK; - GstBuffer *decoded = NULL; - guint in_offset = 0; - guint out_offset = 0; - gint decode_ret = 0; - guint size = 0; + GstBuffer *out_buf; + guint8 *in_data, *out_data; + guint8 *to_free = NULL; + guint i, size, num_frames; + gint out_size, in_size; + gint decode_ret; + gboolean discont; + GstClockTime timestamp; + guint64 distance; - GST_LOG_OBJECT (dec, "Decoding buffer of size %d", GST_BUFFER_SIZE (buf)); + dec = GST_SIREN_DEC (GST_PAD_PARENT (pad)); - size = GST_BUFFER_SIZE (buf) * 16; - size -= size % 640; - - if (size == 0) { - GST_LOG_OBJECT (dec, "Got buffer smaller than framesize: %u < 40", - GST_BUFFER_SIZE (buf)); - return GST_FLOW_OK; + discont = GST_BUFFER_IS_DISCONT (buf); + if (discont) { + GST_DEBUG_OBJECT (dec, "received DISCONT, flush adapter"); + gst_adapter_clear (dec->adapter); + dec->discont = TRUE; } - if (GST_BUFFER_SIZE (buf) % 40 != 0) - GST_LOG_OBJECT (dec, "Got buffer with size not a multiple for frame size," - " ignoring last %u bytes", GST_BUFFER_SIZE (buf) % 40); + gst_adapter_push (dec->adapter, buf); - ret = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, - GST_BUFFER_OFFSET (buf) * 16, size, dec->srccaps, &decoded); + size = gst_adapter_available (dec->adapter); + + GST_LOG_OBJECT (dec, "Received buffer of size %u with adapter of size : %u", + GST_BUFFER_SIZE (buf), size); + + /* process 40 input bytes into 640 output bytes */ + num_frames = size / 40; + + if (num_frames == 0) + goto done; + + /* this is the input/output size */ + in_size = num_frames * 40; + out_size = num_frames * 640; + + GST_LOG_OBJECT (dec, "we have %u frames, %u in, %u out", num_frames, in_size, + out_size); + + /* get a buffer */ + ret = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, -1, + out_size, GST_PAD_CAPS (dec->srcpad), &out_buf); if (ret != GST_FLOW_OK) - return ret; + goto alloc_failed; - GST_BUFFER_TIMESTAMP (decoded) = GST_BUFFER_TIMESTAMP (buf); + /* get the timestamp for the output buffer */ + timestamp = gst_adapter_prev_timestamp (dec->adapter, &distance); - while ((in_offset + 40 <= GST_BUFFER_SIZE (buf)) && ret == GST_FLOW_OK) { + /* add the amount of time taken by the distance, each frame is 20ms */ + if (timestamp != -1) + timestamp += (distance / 40) * FRAME_DURATION; - GST_LOG_OBJECT (dec, "Decoding frame"); + GST_LOG_OBJECT (dec, + "timestamp %" GST_TIME_FORMAT ", distance %" G_GUINT64_FORMAT, + GST_TIME_ARGS (timestamp), distance); - decode_ret = Siren7_DecodeFrame (dec->decoder, - GST_BUFFER_DATA (buf) + in_offset, - GST_BUFFER_DATA (decoded) + out_offset); - if (decode_ret != 0) { - GST_ERROR_OBJECT (dec, "Siren7_DecodeFrame returned %d", decode_ret); - ret = GST_FLOW_ERROR; - } + /* get the input data for all the frames */ + to_free = in_data = gst_adapter_take (dec->adapter, in_size); + out_data = GST_BUFFER_DATA (out_buf); - in_offset += 40; - out_offset += 640; + for (i = 0; i < num_frames; i++) { + GST_LOG_OBJECT (dec, "Decoding frame %u/%u", i, num_frames); + + /* decode 40 input bytes to 640 output bytes */ + decode_ret = Siren7_DecodeFrame (dec->decoder, in_data, out_data); + if (decode_ret != 0) + goto decode_error; + + /* move to next frame */ + out_data += 640; + in_data += 40; } - GST_LOG_OBJECT (dec, "Finished decoding : %d", out_offset); - if (out_offset != GST_BUFFER_SIZE (decoded)) { - GST_ERROR_OBJECT (dec, - "didn't decode enough : offfset (%d) != BUFFER_SIZE (%d)", - out_offset, GST_BUFFER_SIZE (decoded)); - return GST_FLOW_ERROR; + GST_LOG_OBJECT (dec, "Finished decoding"); + + /* mark discont */ + if (dec->discont) { + GST_BUFFER_FLAG_SET (out_buf, GST_BUFFER_FLAG_DISCONT); + dec->discont = FALSE; } - ret = gst_pad_push (dec->srcpad, decoded); + GST_BUFFER_TIMESTAMP (out_buf) = timestamp; + GST_BUFFER_DURATION (out_buf) = num_frames * FRAME_DURATION; - gst_object_unref (dec); + ret = gst_pad_push (dec->srcpad, out_buf); + +done: + if (to_free) + g_free (to_free); + + return ret; + + /* ERRORS */ +alloc_failed: + { + GST_DEBUG_OBJECT (dec, "failed to pad_alloc buffer: %d (%d)", ret, + gst_flow_get_name (ret)); + goto done; + } +decode_error: + { + GST_ELEMENT_ERROR (dec, STREAM, DECODE, (NULL), + ("Error decoding frame: %d", decode_ret)); + ret = GST_FLOW_ERROR; + gst_buffer_unref (out_buf); + goto done; + } +} + +static GstStateChangeReturn +gst_siren_change_state (GstElement * element, GstStateChange transition) +{ + GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS; + GstSirenDec *dec = GST_SIREN_DEC (element); + + switch (transition) { + case GST_STATE_CHANGE_READY_TO_PAUSED: + dec->discont = FALSE; + break; + default: + break; + } + + ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition); + + switch (transition) { + case GST_STATE_CHANGE_PAUSED_TO_READY: + gst_adapter_clear (dec->adapter); + break; + default: + break; + } return ret; } - gboolean gst_siren_dec_plugin_init (GstPlugin * plugin) { diff --git a/gst/siren/gstsirendec.h b/gst/siren/gstsirendec.h index 90321cf906..7c020896f8 100644 --- a/gst/siren/gstsirendec.h +++ b/gst/siren/gstsirendec.h @@ -53,10 +53,11 @@ struct _GstSirenDec /* Protected by stream lock */ SirenDecoder decoder; + GstAdapter *adapter; + gboolean discont; + GstPad *sinkpad; GstPad *srcpad; - - GstCaps *srccaps; }; struct _GstSirenDecClass From 7fa795a725cb15859b19e4fd8e1529d902c2a0e2 Mon Sep 17 00:00:00 2001 From: Josep Torra Date: Fri, 4 Sep 2009 12:53:36 +0200 Subject: [PATCH 18/19] mpegpsdemux: in seeking use a factor for SCR interpolation Fixes seeking on clips where PTS are unalignded with SCR. --- gst/mpegdemux/gstmpegdemux.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gst/mpegdemux/gstmpegdemux.c b/gst/mpegdemux/gstmpegdemux.c index 5fe277118b..e4be2054fa 100644 --- a/gst/mpegdemux/gstmpegdemux.c +++ b/gst/mpegdemux/gstmpegdemux.c @@ -1037,6 +1037,12 @@ gst_flups_demux_do_seek (GstFluPSDemux * demux, GstSegment * seeksegment) guint64 scr_rate_n = demux->last_scr_offset - demux->first_scr_offset; guint64 scr_rate_d = demux->last_scr - demux->first_scr; + /* In some clips the PTS values are completely unaligned with SCR values. + * To improve the seek in that situation we apply a factor considering the + * relationship between last PTS and last SCR */ + if (demux->last_scr > demux->last_pts) + scr = gst_util_uint64_scale (scr, demux->last_scr, demux->last_pts); + scr = MIN (demux->last_scr, scr); scr = MAX (demux->first_scr, scr); fscr = scr; From 806746a388633154fcd5f2b4eef4694a6b8a4598 Mon Sep 17 00:00:00 2001 From: Josep Torra Date: Fri, 4 Sep 2009 13:13:39 +0200 Subject: [PATCH 19/19] neonhttpsrc: handle all redirection http status codes --- ext/neon/gstneonhttpsrc.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/ext/neon/gstneonhttpsrc.c b/ext/neon/gstneonhttpsrc.c index 1af733db31..cceb2689fb 100644 --- a/ext/neon/gstneonhttpsrc.c +++ b/ext/neon/gstneonhttpsrc.c @@ -27,12 +27,14 @@ #include +#define STATUS_IS_REDIRECTION(status) ((status) >= 300 && (status) < 400) + GST_DEBUG_CATEGORY_STATIC (neonhttpsrc_debug); #define GST_CAT_DEFAULT neonhttpsrc_debug #define MAX_READ_SIZE (4 * 1024) -/* max number of HTTP redirects, when iterating over a sequence of HTTP 302/303 status code */ +/* max number of HTTP redirects, when iterating over a sequence of HTTP 3xx status code */ #define MAX_HTTP_REDIRECTS_NUMBER 5 static const GstElementDetails gst_neonhttp_src_details = @@ -199,7 +201,7 @@ gst_neonhttp_src_class_init (GstNeonhttpSrcClass * klass) g_object_class_install_property (gobject_class, PROP_AUTOMATIC_REDIRECT, g_param_spec_boolean ("automatic-redirect", "automatic-redirect", - "Automatically follow HTTP redirects (HTTP Status Code 302/303)", + "Automatically follow HTTP redirects (HTTP Status Code 3xx)", TRUE, G_PARAM_READWRITE)); g_object_class_install_property @@ -816,7 +818,7 @@ ssl_verify_callback (void *data, int failures, const ne_ssl_certificate * cert) } /* Try to send the HTTP request to the Icecast server, and if possible deals with - * all the probable redirections (HTTP status code == 302/303) + * all the probable redirections (HTTP status code == 3xx) */ static gint gst_neonhttp_src_send_request_and_redirect (GstNeonhttpSrc * src, @@ -862,10 +864,10 @@ gst_neonhttp_src_send_request_and_redirect (GstNeonhttpSrc * src, res = ne_begin_request (request); if (res == NE_OK) { - /* When the HTTP status code is 302/303, it is not the SHOUTcast streaming content yet; + /* When the HTTP status code is 3xx, it is not the SHOUTcast streaming content yet; * Reload the HTTP request with a new URI value */ http_status = ne_get_status (request)->code; - if ((http_status == 302 || http_status == 303) && do_redir) { + if (STATUS_IS_REDIRECTION (http_status) && do_redir) { const gchar *redir; /* the new URI value to go when redirecting can be found on the 'Location' HTTP header */ @@ -881,21 +883,21 @@ gst_neonhttp_src_send_request_and_redirect (GstNeonhttpSrc * src, if ((res != NE_OK) || (offset == 0 && http_status != 200) || - (offset > 0 && http_status != 206 && http_status != 302 - && http_status != 303)) { + (offset > 0 && http_status != 206 && + !STATUS_IS_REDIRECTION (http_status))) { ne_request_destroy (request); request = NULL; ne_close_connection (session); ne_session_destroy (session); session = NULL; - if (offset > 0 && http_status != 206 && http_status != 302 - && http_status != 303) { + if (offset > 0 && http_status != 206 && + !STATUS_IS_REDIRECTION (http_status)) { src->seekable = FALSE; } } /* if - NE_OK */ - if ((http_status == 302 || http_status == 303) && do_redir) { + if (STATUS_IS_REDIRECTION (http_status) && do_redir) { ++request_count; GST_LOG_OBJECT (src, "redirect request_count is now %d", request_count); if (request_count < MAX_HTTP_REDIRECTS_NUMBER && do_redir) { @@ -909,7 +911,7 @@ gst_neonhttp_src_send_request_and_redirect (GstNeonhttpSrc * src, } /* do the redirect, go back to send another HTTP request now using the 'Location' */ } while (do_redir && (request_count < MAX_HTTP_REDIRECTS_NUMBER) - && (http_status == 302 || http_status == 303)); + && STATUS_IS_REDIRECTION (http_status)); if (session) { *ses = session;