mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-03-30 12:49:40 +00:00
Merge branch 'master' of ssh://uraeus@git.freedesktop.org/git/gstreamer/gst-plugins-bad
This commit is contained in:
commit
bdbcbc743c
25 changed files with 709 additions and 563 deletions
|
@ -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
|
||||
|
|
|
@ -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>
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)) {
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -126,6 +126,8 @@ struct MpegTsMuxClass {
|
|||
GstElementClass parent_class;
|
||||
};
|
||||
|
||||
#define MPEG_TS_PAD_DATA(data) ((MpegTsPadData *)(data))
|
||||
|
||||
struct MpegTsPadData {
|
||||
GstCollectData collect; /* Parent */
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -70,6 +70,10 @@ struct _GstPcapParse
|
|||
gboolean initialized;
|
||||
gboolean swap_endian;
|
||||
gint64 cur_packet_size;
|
||||
GstClockTime cur_ts;
|
||||
|
||||
gboolean newsegment_sent;
|
||||
|
||||
gint64 buffer_offset;
|
||||
};
|
||||
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
|
|
|
@ -53,10 +53,11 @@ struct _GstSirenDec
|
|||
/* Protected by stream lock */
|
||||
SirenDecoder decoder;
|
||||
|
||||
GstAdapter *adapter;
|
||||
gboolean discont;
|
||||
|
||||
GstPad *sinkpad;
|
||||
GstPad *srcpad;
|
||||
|
||||
GstCaps *srccaps;
|
||||
};
|
||||
|
||||
struct _GstSirenDecClass
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
@ -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
64
sys/dshowsrcwrapper/gstdshow.cpp
Normal file → Executable 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
28
sys/dshowsrcwrapper/gstdshow.h
Normal file → Executable 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
207
sys/dshowsrcwrapper/gstdshowvideosrc.cpp
Normal file → Executable 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
14
sys/dshowsrcwrapper/gstdshowvideosrc.h
Normal file → Executable 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;
|
||||
|
||||
|
|
Loading…
Reference in a new issue