/gst-libs/gst/audio/audio-marshal.[ch]
/gst-libs/gst/video/video-marshal.[ch]
+/tests/examples/playback/playback-test
tmp-orc.c
gst*orc.h
ac_cppflags_save="$CPPFLAGS"
CPPFLAGS="`$PKG_CONFIG --cflags libxml-2.0`"
-AC_COMPILE_IFELSE(
- AC_LANG_PROGRAM([
+AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
#include <libxml/HTMLparser.h>
- ],[
+]],[[
#ifndef LIBXML_HTML_ENABLED
#error libxml2 has no HTML support
#endif /* LIBXML_HTML_ENABLED */
- ]), HAVE_LIBXML_HTML="yes", HAVE_LIBXML_HTML="no")
+]])], [
+ HAVE_LIBXML_HTML="yes"
+], [
+ HAVE_LIBXML_HTML="no"
+])
CPPFLAGS="$ac_cppflags_save"
AM_CONDITIONAL(HAVE_LIBXML_HTML, test "x$HAVE_LIBXML_HTML" = "xyes")
if test "x$HAVE_VORBIS" = "xyes"; then
ac_cflags_save="$CFLAGS"
- AC_COMPILE_IFELSE(
- AC_LANG_PROGRAM([
+ AC_COMPILE_IFELSE([
+ AC_LANG_PROGRAM([[
#include <vorbis/codec.h>
- ],[
+ ]],[[
vorbis_dsp_state *v;
vorbis_synthesis_restart (v);
- ]), HAVE_VSR=yes, HAVE_VSR=no)
+ ]])], HAVE_VSR=yes, HAVE_VSR=no)
if test "x$HAVE_VSR" = "xyes"; then
AC_DEFINE_UNQUOTED(HAVE_VORBIS_SYNTHESIS_RESTART, 1,
[defined if vorbis_synthesis_restart is present])
#ifndef TREMOR
-#include <vorbis/codec.h>
-
-typedef float vorbis_sample_t;
-typedef ogg_packet ogg_packet_wrapper;
-
#define GST_VORBIS_DEC_DESCRIPTION "decode raw vorbis streams to float audio"
#define GST_VORBIS_AUDIO_FORMAT GST_AUDIO_FORMAT_F32
#define GST_VORBIS_DEC_GLIB_TYPE_NAME GstVorbisDec
+#else /* TREMOR */
+
+#define GST_VORBIS_DEC_DESCRIPTION "decode raw vorbis streams to integer audio"
+
+#define GST_VORBIS_AUDIO_FORMAT GST_AUDIO_FORMAT_S16
+#define GST_VORBIS_AUDIO_FORMAT_STR GST_AUDIO_NE (S16)
+
+#define GST_VORBIS_DEC_SRC_CAPS \
+ GST_STATIC_CAPS ("audio/x-raw, " \
+ "format = (string) " GST_VORBIS_AUDIO_FORMAT_STR ", " \
+ "rate = (int) [ 1, MAX ], " \
+ "channels = (int) [ 1, 6 ]")
+
+#define GST_VORBIS_DEC_DEFAULT_SAMPLE_WIDTH (16)
+
+/* we need a different type name here */
+#define GST_VORBIS_DEC_GLIB_TYPE_NAME GstIVorbisDec
+
+/* and still have it compile */
+typedef struct _GstVorbisDec GstIVorbisDec;
+typedef struct _GstVorbisDecClass GstIVorbisDecClass;
+
+#endif /* TREMOR */
+
+#ifndef USE_TREMOLO
+
+#ifdef TREMOR
+ #include <tremor/ivorbiscodec.h>
+ typedef ogg_int32_t vorbis_sample_t;
+#else
+ #include <vorbis/codec.h>
+ typedef float vorbis_sample_t;
+#endif
+
+typedef ogg_packet ogg_packet_wrapper;
+
static inline guint8 *
gst_ogg_packet_data (ogg_packet * p)
{
return packet;
}
-#else
-
-#ifdef USE_TREMOLO
- #include <Tremolo/ivorbiscodec.h>
- #include <Tremolo/codec_internal.h>
- typedef ogg_int16_t vorbis_sample_t;
-#else
- #include <tremor/ivorbiscodec.h>
- typedef ogg_int32_t vorbis_sample_t;
-#endif
+#else /* USE_TREMOLO */
+#include <Tremolo/ivorbiscodec.h>
+#include <Tremolo/codec_internal.h>
+typedef ogg_int16_t vorbis_sample_t;
typedef struct _ogg_packet_wrapper ogg_packet_wrapper;
struct _ogg_packet_wrapper {
ogg_buffer buf;
};
-#define GST_VORBIS_DEC_DESCRIPTION "decode raw vorbis streams to integer audio"
-
-#define GST_VORBIS_AUDIO_FORMAT GST_AUDIO_FORMAT_S16
-#define GST_VORBIS_AUDIO_FORMAT_STR GST_AUDIO_NE (S16)
-
-#define GST_VORBIS_DEC_SRC_CAPS \
- GST_STATIC_CAPS ("audio/x-raw, " \
- "format = (string) " GST_VORBIS_AUDIO_FORMAT_STR ", " \
- "rate = (int) [ 1, MAX ], " \
- "channels = (int) [ 1, 6 ]")
-
-/* we need a different type name here */
-#define GST_VORBIS_DEC_GLIB_TYPE_NAME GstIVorbisDec
-
-/* and still have it compile */
-typedef struct _GstVorbisDec GstIVorbisDec;
-typedef struct _GstVorbisDecClass GstIVorbisDecClass;
-
/* compensate minor variation */
#define vorbis_synthesis(a, b) vorbis_synthesis (a, b, 1)
return &(packet->packet);
}
-#endif
+#endif /* USE_TREMOLO */
typedef void (*CopySampleFunc)(vorbis_sample_t *out, vorbis_sample_t **in,
guint samples, gint channels);
gst_audio_decoder_change_state (GstElement * element, GstStateChange transition)
{
GstAudioDecoder *codec;
+ GstAudioDecoderClass *klass;
GstStateChangeReturn ret;
codec = GST_AUDIO_DECODER (element);
+ klass = GST_AUDIO_DECODER_GET_CLASS (codec);
switch (transition) {
case GST_STATE_CHANGE_NULL_TO_READY:
+ if (klass->open) {
+ if (!klass->open (codec))
+ goto open_failed;
+ }
break;
case GST_STATE_CHANGE_READY_TO_PAUSED:
if (!gst_audio_decoder_start (codec)) {
}
break;
case GST_STATE_CHANGE_READY_TO_NULL:
+ if (klass->close) {
+ if (!klass->close (codec))
+ goto close_failed;
+ }
break;
default:
break;
GST_ELEMENT_ERROR (codec, LIBRARY, INIT, (NULL), ("Failed to stop codec"));
return GST_STATE_CHANGE_FAILURE;
}
+open_failed:
+ {
+ GST_ELEMENT_ERROR (codec, LIBRARY, INIT, (NULL), ("Failed to open codec"));
+ return GST_STATE_CHANGE_FAILURE;
+ }
+close_failed:
+ {
+ GST_ELEMENT_ERROR (codec, LIBRARY, INIT, (NULL), ("Failed to close codec"));
+ return GST_STATE_CHANGE_FAILURE;
+ }
}
GstFlowReturn
* Called just prior to pushing (encoded data) buffer downstream.
* Subclass has full discretionary access to buffer,
* and a not OK flow return will abort downstream pushing.
+ * @open: Optional.
+ * Called when the element changes to GST_STATE_READY.
+ * Allows opening external resources. Since: 0.10.37.
+ * @close: Optional.
+ * Called when the element changes to GST_STATE_NULL.
+ * Allows closing external resources. Since: 0.10.37.
*
* Subclasses can override any of the available virtual methods or not, as
* needed. At minimum @handle_frame (and likely @set_format) needs to be
gboolean (*event) (GstAudioDecoder *dec,
GstEvent *event);
+ gboolean (*open) (GstAudioDecoder *dec);
+
+ gboolean (*close) (GstAudioDecoder *dec);
+
/*< private >*/
- gpointer _gst_reserved[GST_PADDING_LARGE];
+ gpointer _gst_reserved[GST_PADDING_LARGE-2];
};
GType gst_audio_decoder_get_type (void);
GstQuery * query);
static gboolean gst_audio_encoder_sink_query (GstPad * pad, GstObject * parent,
GstQuery * query);
+static GstStateChangeReturn gst_audio_encoder_change_state (GstElement *
+ element, GstStateChange transition);
static void
gst_audio_encoder_class_init (GstAudioEncoderClass * klass)
{
GObjectClass *gobject_class;
+ GstElementClass *gstelement_class;
gobject_class = G_OBJECT_CLASS (klass);
+ gstelement_class = GST_ELEMENT_CLASS (klass);
parent_class = g_type_class_peek_parent (klass);
GST_DEBUG_CATEGORY_INIT (gst_audio_encoder_debug, "audioencoder", 0,
0, G_MAXINT64, DEFAULT_TOLERANCE,
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+ gstelement_class->change_state =
+ GST_DEBUG_FUNCPTR (gst_audio_encoder_change_state);
+
klass->getcaps = gst_audio_encoder_getcaps_default;
klass->event = gst_audio_encoder_sink_event_default;
}
G_OBJECT_CLASS (parent_class)->finalize (object);
}
+static GstStateChangeReturn
+gst_audio_encoder_change_state (GstElement * element, GstStateChange transition)
+{
+ GstStateChangeReturn ret = GST_STATE_CHANGE_SUCCESS;
+ GstAudioEncoder *enc = GST_AUDIO_ENCODER (element);
+ GstAudioEncoderClass *klass = GST_AUDIO_ENCODER_GET_CLASS (enc);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_NULL_TO_READY:
+ if (klass->open) {
+ if (!klass->open (enc))
+ goto open_failed;
+ }
+ default:
+ break;
+ }
+
+ ret = GST_ELEMENT_CLASS (parent_class)->change_state (element, transition);
+
+ switch (transition) {
+ case GST_STATE_CHANGE_READY_TO_NULL:
+ if (klass->close) {
+ if (!klass->close (enc))
+ goto close_failed;
+ }
+ default:
+ break;
+ }
+
+ return ret;
+
+open_failed:
+ {
+ GST_ELEMENT_ERROR (enc, LIBRARY, INIT, (NULL), ("Failed to open codec"));
+ return GST_STATE_CHANGE_FAILURE;
+ }
+close_failed:
+ {
+ GST_ELEMENT_ERROR (enc, LIBRARY, INIT, (NULL), ("Failed to close codec"));
+ return GST_STATE_CHANGE_FAILURE;
+ }
+}
+
/**
* gst_audio_encoder_finish_frame:
* @enc: a #GstAudioEncoder
* for multichannel input specification). If not implemented,
* default returns gst_audio_encoder_proxy_getcaps
* applied to sink template caps.
+ * @open: Optional.
+ * Called when the element changes to GST_STATE_READY.
+ * Allows opening external resources. Since: 0.10.37.
+ * @close: Optional.
+ * Called when the element changes to GST_STATE_NULL.
+ * Allows closing external resources. Since: 0.10.37.
*
* Subclasses can override any of the available virtual methods or not, as
* needed. At minimum @set_format and @handle_frame needs to be overridden.
GstCaps * (*getcaps) (GstAudioEncoder *enc, GstCaps *filter);
+ gboolean (*open) (GstAudioEncoder *enc);
+
+ gboolean (*close) (GstAudioEncoder *enc);
+
/*< private >*/
- gpointer _gst_reserved[GST_PADDING_LARGE];
+ gpointer _gst_reserved[GST_PADDING_LARGE-2];
};
GType gst_audio_encoder_get_type (void);
#define GST_RIFF_INFO_IMED GST_MAKE_FOURCC ('I','M','E','D') /* medium */
#define GST_RIFF_INFO_INAM GST_MAKE_FOURCC ('I','N','A','M') /* name */
#define GST_RIFF_INFO_IPLT GST_MAKE_FOURCC ('I','P','L','T') /* palette setting */
-#define GST_RIFF_INFO_IPRD GST_MAKE_FOURCC ('I','P','R','D') /* product */
+#define GST_RIFF_INFO_IPRD GST_MAKE_FOURCC ('I','P','R','D') /* product (album) */
#define GST_RIFF_INFO_ISBJ GST_MAKE_FOURCC ('I','S','B','J') /* subject */
#define GST_RIFF_INFO_ISFT GST_MAKE_FOURCC ('I','S','F','T') /* software */
#define GST_RIFF_INFO_ISHP GST_MAKE_FOURCC ('I','S','H','P') /* sharpness */
#define GST_RIFF_INFO_ISRF GST_MAKE_FOURCC ('I','S','R','F') /* source form */
#define GST_RIFF_INFO_ITCH GST_MAKE_FOURCC ('I','T','C','H') /* technician(s) */
+#define GST_RIFF_INFO_IAAR GST_MAKE_FOURCC ('I','A','A','R') /* album artist */
+#define GST_RIFF_INFO_ITRK GST_MAKE_FOURCC ('I','T','R','K') /* track number */
+
/*********Chunk Names***************/
#define GST_RIFF_FF00 GST_MAKE_FOURCC (0xFF,0xFF,0x00,0x00)
#define GST_RIFF_00 GST_MAKE_FOURCC ('0', '0',0x00,0x00)
while (left > 8) {
tag = GST_READ_UINT32_LE (ptr);
tsize = GST_READ_UINT32_LE (ptr + 4);
+
+ GST_MEMDUMP_OBJECT (element, "tag chunk", ptr, MIN (tsize + 8, left));
+
left -= 8;
ptr += 8;
tsize = left;
}
+ /* make uppercase */
+ tag = tag & 0xDFDFDFDF;
+
/* find out the type of metadata */
switch (tag) {
case GST_RIFF_INFO_IARL:
type = GST_TAG_LOCATION;
break;
+ case GST_RIFF_INFO_IAAR:
+ type = GST_TAG_ALBUM_ARTIST;
+ break;
case GST_RIFF_INFO_IART:
type = GST_TAG_ARTIST;
break;
type = NULL; /*"Palette"; */
break;
case GST_RIFF_INFO_IPRD:
- type = NULL; /*"Product"; */
+ type = GST_TAG_ALBUM;
break;
case GST_RIFF_INFO_ISBJ:
type = NULL; /*"Subject"; */
case GST_RIFF_INFO_ITCH:
type = NULL; /*"Technician"; */
break;
+ case GST_RIFF_INFO_ITRK:
+ type = GST_TAG_TRACK_NUMBER;
+ break;
default:
type = NULL;
GST_WARNING_OBJECT (element,
static const gchar *env_vars[] = { "GST_AVI_TAG_ENCODING",
"GST_RIFF_TAG_ENCODING", "GST_TAG_ENCODING", NULL
};
+ GType tag_type;
gchar *val;
+ GST_DEBUG_OBJECT (element, "mapped tag %" GST_FOURCC_FORMAT " to tag %s",
+ GST_FOURCC_ARGS (tag), type);
+
+ tag_type = gst_tag_get_type (type);
val = gst_tag_freeform_string_to_utf8 ((gchar *) ptr, tsize, env_vars);
- if (val) {
- gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, type, val, NULL);
+ if (val != NULL) {
+ if (tag_type == G_TYPE_STRING) {
+ gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, type, val, NULL);
+ } else {
+ GValue tag_val = { 0, };
+
+ g_value_init (&tag_val, tag_type);
+ if (gst_value_deserialize (&tag_val, val)) {
+ gst_tag_list_add_value (taglist, GST_TAG_MERGE_APPEND, type,
+ &tag_val);
+ } else {
+ GST_WARNING_OBJECT (element, "could not deserialize '%s' into a "
+ "tag %s of type %s", val, type, g_type_name (tag_type));
+ }
+ g_value_unset (&tag_val);
+ }
g_free (val);
} else {
GST_WARNING_OBJECT (element, "could not extract %s tag", type);
}
if (!gst_tag_list_is_empty (taglist)) {
+ GST_INFO_OBJECT (element, "extracted tags: %" GST_PTR_FORMAT, taglist);
*_taglist = taglist;
} else {
*_taglist = NULL;
rectangle->render_height = render_height;
}
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+# define ARGB_A 3
+# define ARGB_R 2
+# define ARGB_G 1
+# define ARGB_B 0
+#else
+# define ARGB_A 0
+# define ARGB_R 1
+# define ARGB_G 2
+# define ARGB_B 3
+#endif
+
+/* FIXME: orc-ify */
static void
gst_video_overlay_rectangle_premultiply (GstBlendVideoFormatInfo * info)
{
for (j = 0; j < info->height; ++j) {
guint8 *line = info->pixels + info->stride[0] * j;
for (i = 0; i < info->width; ++i) {
- int a = line[0];
- line[1] = line[1] * a / 255;
- line[2] = line[2] * a / 255;
- line[3] = line[3] * a / 255;
+ int a = line[ARGB_A];
+ line[ARGB_R] = line[ARGB_R] * a / 255;
+ line[ARGB_G] = line[ARGB_G] * a / 255;
+ line[ARGB_B] = line[ARGB_B] * a / 255;
line += 4;
}
}
}
+/* FIXME: orc-ify */
static void
gst_video_overlay_rectangle_unpremultiply (GstBlendVideoFormatInfo * info)
{
for (j = 0; j < info->height; ++j) {
guint8 *line = info->pixels + info->stride[0] * j;
for (i = 0; i < info->width; ++i) {
- int a = line[0];
+ int a = line[ARGB_A];
if (a) {
- line[1] = MIN ((line[1] * 255 + a / 2) / a, 255);
- line[2] = MIN ((line[2] * 255 + a / 2) / a, 255);
- line[3] = MIN ((line[3] * 255 + a / 2) / a, 255);
+ line[ARGB_R] = MIN ((line[ARGB_R] * 255 + a / 2) / a, 255);
+ line[ARGB_G] = MIN ((line[ARGB_G] * 255 + a / 2) / a, 255);
+ line[ARGB_B] = MIN ((line[ARGB_B] * 255 + a / 2) / a, 255);
}
line += 4;
}
rectangle, guint * stride, GstVideoOverlayFormatFlags flags,
gboolean unscaled)
{
+ GstVideoOverlayFormatFlags new_flags;
GstVideoOverlayRectangle *scaled_rect = NULL;
GstBlendVideoFormatInfo info;
GstBuffer *buf;
if (r->width == wanted_width &&
r->height == wanted_height &&
- gst_video_overlay_rectangle_is_same_alpha_type (rectangle->flags,
- flags)) {
+ gst_video_overlay_rectangle_is_same_alpha_type (r->flags, flags)) {
/* we'll keep these rectangles around until finalize, so it's ok not
* to take our own ref here */
scaled_rect = r;
if (wanted_width != rectangle->width || wanted_height != rectangle->height) {
video_blend_scale_linear_RGBA (&info, wanted_height, wanted_width);
+ } else {
+ /* if we don't have to scale, we have to modify the alpha values, so we
+ * need to make a copy of the pixel memory (and we take ownership below) */
+ info.pixels = g_memdup (info.pixels, info.size);
}
+ new_flags = rectangle->flags;
if (!gst_video_overlay_rectangle_is_same_alpha_type (rectangle->flags, flags)) {
if (rectangle->flags & GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA) {
gst_video_overlay_rectangle_unpremultiply (&info);
+ new_flags &= ~GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA;
} else {
gst_video_overlay_rectangle_premultiply (&info);
+ new_flags |= GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA;
}
}
scaled_rect = gst_video_overlay_rectangle_new_argb (buf,
wanted_width, wanted_height, info.stride[0],
- 0, 0, wanted_width, wanted_height, rectangle->flags);
+ 0, 0, wanted_width, wanted_height, new_flags);
gst_buffer_unref (buf);
GST_DEBUG_OBJECT (playbin, "reusing existing uridecodebin");
uridecodebin = group->uridecodebin;
gst_element_set_state (uridecodebin, GST_STATE_READY);
- gst_bin_add (GST_BIN_CAST (playbin), gst_object_ref (uridecodebin));
+ /* no need to take extra ref, we already have one
+ * and the bin will add one since it is no longer floating,
+ * as it was at least added once before (below) */
+ gst_bin_add (GST_BIN_CAST (playbin), uridecodebin);
} else {
GST_DEBUG_OBJECT (playbin, "making new uridecodebin");
uridecodebin = gst_element_factory_make ("uridecodebin", NULL);
GST_DEBUG_OBJECT (playbin, "reusing existing suburidecodebin");
suburidecodebin = group->suburidecodebin;
gst_element_set_state (suburidecodebin, GST_STATE_READY);
- gst_bin_add (GST_BIN_CAST (playbin), gst_object_ref (suburidecodebin));
+ /* no need to take extra ref, we already have one
+ * and the bin will add one since it is no longer floating,
+ * as it was at least added once before (below) */
+ gst_bin_add (GST_BIN_CAST (playbin), suburidecodebin);
} else {
GST_DEBUG_OBJECT (playbin, "making new suburidecodebin");
suburidecodebin = gst_element_factory_make ("uridecodebin", NULL);
if (blocked && playsink->video_block_id == 0) {
playsink->video_block_id =
gst_pad_add_probe (opad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
- sinkpad_blocked_cb, gst_object_ref (playsink),
- (GDestroyNotify) gst_object_unref);
+ sinkpad_blocked_cb, playsink, NULL);
} else if (!blocked && playsink->video_block_id) {
gst_pad_remove_probe (opad, playsink->video_block_id);
PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_VIDEO_RAW);
if (blocked && playsink->audio_block_id == 0) {
playsink->audio_block_id =
gst_pad_add_probe (opad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
- sinkpad_blocked_cb, gst_object_ref (playsink),
- (GDestroyNotify) gst_object_unref);
+ sinkpad_blocked_cb, playsink, NULL);
} else if (!blocked && playsink->audio_block_id) {
gst_pad_remove_probe (opad, playsink->audio_block_id);
PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_AUDIO_RAW);
if (blocked && playsink->text_block_id == 0) {
playsink->text_block_id =
gst_pad_add_probe (opad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
- sinkpad_blocked_cb, gst_object_ref (playsink),
- (GDestroyNotify) gst_object_unref);
+ sinkpad_blocked_cb, playsink, NULL);
} else if (!blocked && playsink->text_block_id) {
gst_pad_remove_probe (opad, playsink->text_block_id);
PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_TEXT);
*block_id =
gst_pad_add_probe (blockpad, GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM,
- sinkpad_blocked_cb, gst_object_ref (playsink),
- (GDestroyNotify) gst_object_unref);
+ sinkpad_blocked_cb, playsink, NULL);
PENDING_FLAG_SET (playsink, type);
gst_object_unref (blockpad);
}
gst_navigation_send_event (GST_NAVIGATION (nav), structure);
structure = NULL;
gst_object_unref (nav);
+ } else {
+ GstEvent *event = gst_event_new_navigation (structure);
+ structure = NULL;
+ gst_element_send_event (GST_ELEMENT (bin), event);
}
gst_object_unref (bin);
if (self->sink_proxypad_block_id == 0) {
self->sink_proxypad_block_id =
gst_pad_add_probe (self->sink_proxypad,
- GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, pad_blocked_cb,
- gst_object_ref (self), (GDestroyNotify) gst_object_unref);
+ GST_PAD_PROBE_TYPE_BLOCK_DOWNSTREAM, pad_blocked_cb, self, NULL);
}
}
caps = DEFAULT_CAPS;
g_object_set (decoder, "caps", caps, NULL);
gst_caps_unref (caps);
+ /* make it freshly floating again */
+ g_object_force_floating (G_OBJECT (decoder));
bin->pending_decodebins =
g_slist_prepend (bin->pending_decodebins, decoder);
* Copyright (C) <2003> David A. Schleef <ds@schleef.org>
* Copyright (C) <2006> Jan Schmidt <thaytan@mad.scientist.com>
* Copyright (C) <2008,2011> Tim-Philipp Müller <tim centricular net>
+ * Copyright (C) <2012> Collabora Ltd. <tim.muller@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
GST_END_TEST;
-#undef ASSERT_CRITICAL
-#define ASSERT_CRITICAL(code) while(0){} /* nothing */
-
#if 0
/* FIXME 0.11: port overlay composition to buffer meta */
GST_START_TEST (test_overlay_composition)
fail_unless (gst_video_buffer_get_overlay_composition (buf) == NULL);
gst_buffer_ref (buf);
+ /* buffer now has refcount of 2, so its metadata is not writable */
ASSERT_CRITICAL (gst_video_buffer_set_overlay_composition (buf, comp1));
gst_buffer_unref (buf);
gst_video_buffer_set_overlay_composition (buf, comp1);
}
GST_END_TEST;
+
+GST_START_TEST (test_overlay_composition_premultiplied_alpha)
+{
+ GstVideoOverlayRectangle *rect1;
+ GstBuffer *pix1, *pix2, *pix3, *pix4, *pix5;
+ GstBuffer *pix6, *pix7, *pix8, *pix9, *pix10;
+ guint8 *data5, *data7;
+ guint w, h, stride, w2, h2, stride2;
+
+ pix1 = gst_buffer_new_and_alloc (200 * sizeof (guint32) * 50);
+ memset (GST_BUFFER_DATA (pix1), 0x80, GST_BUFFER_SIZE (pix1));
+
+ rect1 = gst_video_overlay_rectangle_new_argb (pix1, 200, 50, 200 * 4,
+ 600, 50, 300, 50, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
+ gst_buffer_unref (pix1);
+
+ /* same flags, unscaled, should be the same buffer */
+ pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_argb (rect1, &w, &h,
+ &stride, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
+ fail_unless (pix1 == pix2);
+
+ /* same flags, but scaled */
+ pix3 = gst_video_overlay_rectangle_get_pixels_argb (rect1, &stride,
+ GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
+ fail_if (pix3 == pix1 || pix3 == pix2);
+
+ /* same again, should hopefully get the same (cached) buffer as before */
+ pix4 = gst_video_overlay_rectangle_get_pixels_argb (rect1, &stride,
+ GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
+ fail_unless (pix4 == pix3);
+
+ /* just to update the vars */
+ pix2 = gst_video_overlay_rectangle_get_pixels_unscaled_argb (rect1, &w, &h,
+ &stride, GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
+
+ /* now, let's try to get premultiplied alpha from the unpremultiplied input */
+ pix5 = gst_video_overlay_rectangle_get_pixels_unscaled_argb (rect1, &w2, &h2,
+ &stride2, GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
+ fail_if (pix5 == pix1 || pix5 == pix2 || pix5 == pix3);
+ fail_unless_equals_int (stride, stride2);
+ fail_unless_equals_int (w, w2);
+ fail_unless_equals_int (h, h2);
+ fail_unless_equals_int (GST_BUFFER_SIZE (pix2), GST_BUFFER_SIZE (pix5));
+ data5 = GST_BUFFER_DATA (pix5);
+ fail_if (memcmp (data5, GST_BUFFER_DATA (pix2), GST_BUFFER_SIZE (pix5)) == 0);
+
+ /* make sure it actually did what we expected it to do (input=0x80808080) */
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ /* B - G - R - A */
+ fail_unless_equals_int (data5[0], 0x40);
+ fail_unless_equals_int (data5[1], 0x40);
+ fail_unless_equals_int (data5[2], 0x40);
+ fail_unless_equals_int (data5[3], 0x80);
+#else
+ /* A - R - G - B */
+ fail_unless_equals_int (data5[0], 0x40);
+ fail_unless_equals_int (data5[1], 0x40);
+ fail_unless_equals_int (data5[2], 0x40);
+ fail_unless_equals_int (data5[3], 0x80);
+#endif
+
+ /* same again, now we should be getting back the same buffer as before,
+ * as it should have been cached */
+ pix6 = gst_video_overlay_rectangle_get_pixels_unscaled_argb (rect1, &w2, &h2,
+ &stride2, GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
+ fail_unless (pix6 == pix5);
+
+ /* just to update the stride var */
+ pix3 = gst_video_overlay_rectangle_get_pixels_argb (rect1, &stride,
+ GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
+ fail_unless (pix3 == pix4);
+
+ /* now try to get scaled premultiplied alpha from unpremultiplied input */
+ pix7 = gst_video_overlay_rectangle_get_pixels_argb (rect1, &stride2,
+ GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
+ fail_if (pix7 == pix1 || pix7 == pix2 || pix7 == pix3 || pix7 == pix5);
+ fail_unless_equals_int (stride, stride2);
+
+ data7 = GST_BUFFER_DATA (pix7);
+ /* make sure it actually did what we expected it to do (input=0x80808080)
+ * hoping that the scaling didn't mess up our values */
+#if G_BYTE_ORDER == G_LITTLE_ENDIAN
+ /* B - G - R - A */
+ fail_unless_equals_int (data7[0], 0x40);
+ fail_unless_equals_int (data7[1], 0x40);
+ fail_unless_equals_int (data7[2], 0x40);
+ fail_unless_equals_int (data7[3], 0x80);
+#else
+ /* A - R - G - B */
+ fail_unless_equals_int (data7[0], 0x40);
+ fail_unless_equals_int (data7[1], 0x40);
+ fail_unless_equals_int (data7[2], 0x40);
+ fail_unless_equals_int (data7[3], 0x80);
+#endif
+
+ /* and the same again, it should be cached now */
+ pix8 = gst_video_overlay_rectangle_get_pixels_argb (rect1, &stride2,
+ GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
+ fail_unless (pix8 == pix7);
+
+ /* make sure other cached stuff is still there */
+ pix9 = gst_video_overlay_rectangle_get_pixels_argb (rect1, &stride,
+ GST_VIDEO_OVERLAY_FORMAT_FLAG_NONE);
+ fail_unless (pix9 == pix3);
+ pix10 = gst_video_overlay_rectangle_get_pixels_unscaled_argb (rect1, &w2, &h2,
+ &stride2, GST_VIDEO_OVERLAY_FORMAT_FLAG_PREMULTIPLIED_ALPHA);
+ fail_unless (pix10 == pix5);
+
+ gst_video_overlay_rectangle_unref (rect1);
+}
+
+GST_END_TEST;
#endif
static Suite *
#if 0
/* FIXME 0.11: port overlay compositions */
tcase_add_test (tc_chain, test_overlay_composition);
+ tcase_add_test (tc_chain, test_overlay_composition_premultiplied_alpha);
#endif
return s;