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/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;
diff --git a/gst-plugins-bad.spec.in b/gst-plugins-bad.spec.in
index f2f91096a0..b57186fc62 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/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 */
diff --git a/gst/mpegdemux/gstmpegdefs.h b/gst/mpegdemux/gstmpegdefs.h
index 4055113727..ef2bd46a44 100644
--- a/gst/mpegdemux/gstmpegdefs.h
+++ b/gst/mpegdemux/gstmpegdefs.h
@@ -178,14 +178,15 @@
#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
#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/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;
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 2ab639bc4c..e7226f00ce 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) \
@@ -138,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? */
@@ -206,6 +205,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
@@ -304,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;
}
@@ -330,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;
@@ -484,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
@@ -563,7 +542,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 +638,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,10 +655,42 @@ 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:
+ {
+ 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);
+ } 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:
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;
@@ -686,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;
@@ -2833,7 +2852,6 @@ beach:
return res;
}
-
static FORCE_INLINE gint
is_mpegts_sync (const guint8 * in_data, const guint8 * end_data,
guint packetsize)
@@ -2859,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,
@@ -2867,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);
@@ -2880,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;
@@ -3105,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;
@@ -3158,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;
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 */
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;
};
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
diff --git a/gst/siren/gstsirenenc.c b/gst/siren/gstsirenenc.c
index fbf2b6e074..9b6a2a8b26 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",
@@ -77,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
@@ -117,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);
@@ -135,106 +140,185 @@ 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)
{
- GstSirenEnc *enc = GST_SIREN_ENC (gst_pad_get_parent_element (pad));
+ GstSirenEnc *enc;
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);
+ enc = GST_SIREN_ENC (GST_PAD_PARENT (pad));
+
+ 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);
- 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);
- size /= 16;
- size -= size % 40;
- if (size == 0) {
- GST_OBJECT_UNLOCK (enc);
- goto out;
- }
+ GST_LOG_OBJECT (enc, "Received buffer of size %d with adapter of size : %d",
+ GST_BUFFER_SIZE (buf), size);
- data = gst_adapter_take (enc->adapter, size * 16);
+ /* we need to process 640 input bytes to produce 40 output bytes */
+ /* calculate the amount of frames we will handle */
+ num_frames = size / 640;
- GST_OBJECT_UNLOCK (enc);
+ /* no frames, wait some more */
+ if (num_frames == 0)
+ goto done;
- ret = gst_pad_alloc_buffer_and_set_caps (enc->srcpad,
- GST_BUFFER_OFFSET (buf) / 16, size, enc->srccaps, &encoded);
+ /* this is the input/output size */
+ in_size = num_frames * 640;
+ out_size = num_frames * 40;
+ 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, GST_PAD_CAPS (enc->srcpad), &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 */
+ if (timestamp != -1)
+ 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 +327,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..1d63628dc4 100644
--- a/gst/siren/gstsirenenc.h
+++ b/gst/siren/gstsirenenc.h
@@ -52,13 +52,12 @@ struct _GstSirenEnc
/* protected by the stream lock */
SirenEncoder encoder;
- /* protected by the object lock */
GstAdapter *adapter;
+ gboolean discont;
+
GstPad *srcpad;
GstPad *sinkpad;
-
- GstCaps *srccaps;
};
struct _GstSirenEncClass
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)
diff --git a/sys/dshowsrcwrapper/gstdshow.cpp b/sys/dshowsrcwrapper/gstdshow.cpp
old mode 100644
new mode 100755
index 8b77b5857a..d5425438a8
--- a/sys/dshowsrcwrapper/gstdshow.cpp
+++ b/sys/dshowsrcwrapper/gstdshow.cpp
@@ -321,3 +321,67 @@ 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, GstCapturePinMediaType *pin_mediatype)
+{
+ GstCaps *video_caps = NULL;
+ GstStructure *video_structure = NULL;
+ VIDEOINFOHEADER *video_info = (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat;
+
+ 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) {
+ 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);
+
+ /* 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,
+ "framerate", GST_TYPE_FRACTION_RANGE,
+ (gint) (10000000 / vscc->MaxFrameInterval), 1,
+ (gint) (10000000 / vscc->MinFrameInterval), 1,
+ NULL);
+
+ return video_caps;
+}
diff --git a/sys/dshowsrcwrapper/gstdshow.h b/sys/dshowsrcwrapper/gstdshow.h
old mode 100644
new mode 100755
index 4491e50d66..3b9110943f
--- a/sys/dshowsrcwrapper/gstdshow.h
+++ b/sys/dshowsrcwrapper/gstdshow.h
@@ -22,29 +22,29 @@
#ifndef _GSTDSHOW_
#define _GSTDSHOW_
-#ifdef __cplusplus
#include
-#endif
#include
#include
#include
#include
-#include
+#include
+#include
typedef struct _GstCapturePinMediaType
{
AM_MEDIA_TYPE *mediatype;
IPin *capture_pin;
+
+ //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
} GstCapturePinMediaType;
-#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);
@@ -71,9 +71,9 @@ 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);
-
-#ifdef __cplusplus
-}
-#endif
+
+/* 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, GstCapturePinMediaType *pin_mediatype);
#endif /* _GSTDSHOW_ */
\ No newline at end of file
diff --git a/sys/dshowsrcwrapper/gstdshowvideosrc.cpp b/sys/dshowsrcwrapper/gstdshowvideosrc.cpp
old mode 100644
new mode 100755
index 1f4ff4abc2..726b1d0be5
--- 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);
@@ -573,7 +568,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);
}
@@ -695,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;
@@ -720,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;
@@ -896,161 +878,46 @@ 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);
pin->AddRef();
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);
+ } 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)) {
- video_info = (VIDEOINFOHEADER *) pin_mediatype->mediatype->pbFormat;
+ mediacaps = gst_dshow_new_video_caps (GST_VIDEO_FORMAT_I420, NULL, &vscc, pin_mediatype);
- 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;
+ } 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, pin_mediatype);
- 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);
+ } 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, pin_mediatype);
- 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 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, pin_mediatype);
+
+ pin_mediatype->granularityWidth = 0;
+ pin_mediatype->granularityHeight = 0;
}
- /* 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);
-
- 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;
+ if (mediacaps) {
+ src->pins_mediatypes =
+ g_list_append (src->pins_mediatypes, pin_mediatype);
+ gst_caps_append (caps, mediacaps);
+ } else {
+ gst_dshow_free_pin_mediatype (pin_mediatype);
}
- /* 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);
-
- 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;
-
- //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);
-
- 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);
}
}
diff --git a/sys/dshowsrcwrapper/gstdshowvideosrc.h b/sys/dshowsrcwrapper/gstdshowvideosrc.h
old mode 100644
new mode 100755
index 415830719b..9fe0f452b7
--- 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
{
@@ -67,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;