Merge branch 'master' of ssh://uraeus@git.freedesktop.org/git/gstreamer/gst-plugins-bad

This commit is contained in:
christian schaller 2009-09-04 14:11:33 +01:00
commit bdbcbc743c
25 changed files with 709 additions and 563 deletions

View file

@ -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

View file

@ -1,14 +0,0 @@
<plugin>
<name>xdgmime</name>
<description>XDG-MIME</description>
<filename>../../gst/xdgmime/.libs/libgstxdgmime.so</filename>
<basename>libgstxdgmime.so</basename>
<version>0.10.14.1</version>
<license>LGPL</license>
<source>gst-plugins-bad</source>
<package>GStreamer Bad Plug-ins git/prerelease</package>
<origin>Unknown package origin</origin>
<elements>
</elements>
</plugin>

View file

@ -27,12 +27,14 @@
#include <ne_redirect.h>
#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;

View file

@ -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

View file

@ -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 */

View file

@ -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

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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;

View file

@ -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)) {

View file

@ -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);

View file

@ -126,6 +126,8 @@ struct MpegTsMuxClass {
GstElementClass parent_class;
};
#define MPEG_TS_PAD_DATA(data) ((MpegTsPadData *)(data))
struct MpegTsPadData {
GstCollectData collect; /* Parent */

View file

@ -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)
{

View file

@ -70,6 +70,10 @@ struct _GstPcapParse
gboolean initialized;
gboolean swap_endian;
gint64 cur_packet_size;
GstClockTime cur_ts;
gboolean newsegment_sent;
gint64 buffer_offset;
};

View file

@ -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)
{

View file

@ -53,10 +53,11 @@ struct _GstSirenDec
/* Protected by stream lock */
SirenDecoder decoder;
GstAdapter *adapter;
gboolean discont;
GstPad *sinkpad;
GstPad *srcpad;
GstCaps *srccaps;
};
struct _GstSirenDecClass

View file

@ -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;

View file

@ -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

View file

@ -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

View file

@ -1,100 +0,0 @@
/* GStreamer
* Copyright (C) <2009> Sebastian Dröge <sebastian.droege@collabora.co.uk>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <gst/gst.h>
GST_DEBUG_CATEGORY (xdgmime_debug);
#define GST_CAT_DEFAULT xdgmime_debug
#include <gio/gio.h>
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)

64
sys/dshowsrcwrapper/gstdshow.cpp Normal file → Executable file
View file

@ -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;
}

28
sys/dshowsrcwrapper/gstdshow.h Normal file → Executable file
View file

@ -22,29 +22,29 @@
#ifndef _GSTDSHOW_
#define _GSTDSHOW_
#ifdef __cplusplus
#include <streams.h>
#endif
#include <windows.h>
#include <objbase.h>
#include <dshow.h>
#include <Rpc.h>
#include <glib.h>
#include <gst/gst.h>
#include <gst/video/video.h>
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_ */

207
sys/dshowsrcwrapper/gstdshowvideosrc.cpp Normal file → Executable file
View file

@ -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);
}
}

14
sys/dshowsrcwrapper/gstdshowvideosrc.h Normal file → Executable file
View file

@ -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;