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;