Merge branch 'master' into 0.11

This commit is contained in:
Wim Taymans 2011-08-17 19:01:39 +02:00
commit 52d48bb142
25 changed files with 747 additions and 484 deletions

View file

@ -734,7 +734,12 @@ celt_dec_chain_parse_data (GstCeltDec * dec, GstBuffer * buf,
} }
if (dec->discont) { if (dec->discont) {
#ifdef CELT_GET_LOOKAHEAD_REQUEST
/* what will be 0.11.5, I guess, but no versioning yet in git */
celt_decoder_ctl (dec->state, CELT_GET_LOOKAHEAD_REQUEST, &skip);
#else
celt_mode_info (dec->mode, CELT_GET_LOOKAHEAD, &skip); celt_mode_info (dec->mode, CELT_GET_LOOKAHEAD, &skip);
#endif
} }
res = gst_pad_alloc_buffer_and_set_caps (dec->srcpad, res = gst_pad_alloc_buffer_and_set_caps (dec->srcpad,

View file

@ -145,8 +145,6 @@ static GstFlowReturn gst_dirac_enc_handle_frame (GstBaseVideoEncoder *
base_video_encoder, GstVideoFrame * frame); base_video_encoder, GstVideoFrame * frame);
static GstFlowReturn gst_dirac_enc_shape_output (GstBaseVideoEncoder * static GstFlowReturn gst_dirac_enc_shape_output (GstBaseVideoEncoder *
base_video_encoder, GstVideoFrame * frame); base_video_encoder, GstVideoFrame * frame);
static GstCaps *gst_dirac_enc_get_caps (GstBaseVideoEncoder *
base_video_encoder);
static void gst_dirac_enc_create_codec_data (GstDiracEnc * dirac_enc, static void gst_dirac_enc_create_codec_data (GstDiracEnc * dirac_enc,
GstBuffer * seq_header); GstBuffer * seq_header);
@ -314,7 +312,6 @@ gst_dirac_enc_class_init (GstDiracEncClass * klass)
GST_DEBUG_FUNCPTR (gst_dirac_enc_handle_frame); GST_DEBUG_FUNCPTR (gst_dirac_enc_handle_frame);
basevideoencoder_class->shape_output = basevideoencoder_class->shape_output =
GST_DEBUG_FUNCPTR (gst_dirac_enc_shape_output); GST_DEBUG_FUNCPTR (gst_dirac_enc_shape_output);
basevideoencoder_class->get_caps = GST_DEBUG_FUNCPTR (gst_dirac_enc_get_caps);
} }
static void static void
@ -331,29 +328,10 @@ gst_dirac_enc_set_format (GstBaseVideoEncoder * base_video_encoder,
{ {
GstDiracEnc *dirac_enc = GST_DIRAC_ENC (base_video_encoder); GstDiracEnc *dirac_enc = GST_DIRAC_ENC (base_video_encoder);
GstCaps *caps; GstCaps *caps;
GstStructure *structure; gboolean ret;
GST_DEBUG ("set_format"); GST_DEBUG ("set_format");
caps =
gst_pad_get_allowed_caps (GST_BASE_VIDEO_CODEC_SRC_PAD
(base_video_encoder));
if (caps == NULL) {
caps =
gst_caps_copy (gst_pad_get_pad_template_caps
(GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder)));
}
if (gst_caps_is_empty (caps)) {
gst_caps_unref (caps);
return FALSE;
}
structure = gst_caps_get_structure (caps, 0);
gst_caps_unref (caps);
gst_base_video_encoder_set_latency_fields (base_video_encoder, 2 * 2); gst_base_video_encoder_set_latency_fields (base_video_encoder, 2 * 2);
switch (state->format) { switch (state->format) {
@ -402,7 +380,18 @@ gst_dirac_enc_set_format (GstBaseVideoEncoder * base_video_encoder,
dirac_enc->encoder = dirac_encoder_init (&dirac_enc->enc_ctx, FALSE); dirac_enc->encoder = dirac_encoder_init (&dirac_enc->enc_ctx, FALSE);
return TRUE; caps = gst_caps_new_simple ("video/x-dirac",
"width", G_TYPE_INT, state->width,
"height", G_TYPE_INT, state->height,
"framerate", GST_TYPE_FRACTION, state->fps_n,
state->fps_d,
"pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
state->par_d, NULL);
ret = gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (dirac_enc), caps);
gst_caps_unref (caps);
return ret;
} }
static void static void
@ -1112,7 +1101,7 @@ static GstFlowReturn
gst_dirac_enc_process (GstDiracEnc * dirac_enc, gboolean end_sequence) gst_dirac_enc_process (GstDiracEnc * dirac_enc, gboolean end_sequence)
{ {
GstBuffer *outbuf; GstBuffer *outbuf;
GstFlowReturn ret; GstFlowReturn ret = GST_FLOW_OK;
int parse_code; int parse_code;
int state; int state;
GstVideoFrame *frame; GstVideoFrame *frame;
@ -1174,7 +1163,28 @@ gst_dirac_enc_process (GstDiracEnc * dirac_enc, gboolean end_sequence)
} }
if (!dirac_enc->codec_data) { if (!dirac_enc->codec_data) {
GstCaps *caps;
const GstVideoState *state = gst_base_video_encoder_get_state (GST_BASE_VIDEO_ENCODER (dirac_enc));
gst_dirac_enc_create_codec_data (dirac_enc, outbuf); gst_dirac_enc_create_codec_data (dirac_enc, outbuf);
caps = gst_caps_new_simple ("video/x-dirac",
"width", G_TYPE_INT, state->width,
"height", G_TYPE_INT, state->height,
"framerate", GST_TYPE_FRACTION, state->fps_n,
state->fps_d,
"pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
state->par_d, "streamheader", GST_TYPE_BUFFER, dirac_enc->codec_data,
NULL);
if (!gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (dirac_enc), caps))
ret = GST_FLOW_NOT_NEGOTIATED;
gst_caps_unref (caps);
if (ret != GST_FLOW_OK) {
GST_ERROR ("Failed to set srcpad caps");
gst_buffer_unref (outbuf);
return ret;
}
} }
frame->src_buffer = outbuf; frame->src_buffer = outbuf;
@ -1245,10 +1255,6 @@ static GstFlowReturn
gst_dirac_enc_shape_output (GstBaseVideoEncoder * base_video_encoder, gst_dirac_enc_shape_output (GstBaseVideoEncoder * base_video_encoder,
GstVideoFrame * frame) GstVideoFrame * frame)
{ {
GstDiracEnc *dirac_enc;
dirac_enc = GST_DIRAC_ENC (base_video_encoder);
gst_dirac_enc_shape_output_ogg (base_video_encoder, frame); gst_dirac_enc_shape_output_ogg (base_video_encoder, frame);
return GST_FLOW_ERROR; return GST_FLOW_ERROR;
@ -1286,25 +1292,4 @@ gst_dirac_enc_create_codec_data (GstDiracEnc * dirac_enc,
dirac_enc->codec_data = buf; dirac_enc->codec_data = buf;
} }
static GstCaps *
gst_dirac_enc_get_caps (GstBaseVideoEncoder * base_video_encoder)
{
GstCaps *caps;
const GstVideoState *state;
GstDiracEnc *dirac_enc;
dirac_enc = GST_DIRAC_ENC (base_video_encoder);
state = gst_base_video_encoder_get_state (base_video_encoder);
caps = gst_caps_new_simple ("video/x-dirac",
"width", G_TYPE_INT, state->width,
"height", G_TYPE_INT, state->height,
"framerate", GST_TYPE_FRACTION, state->fps_n,
state->fps_d,
"pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
state->par_d,
"streamheader", GST_TYPE_BUFFER, dirac_enc->codec_data, NULL);
return caps;
}

View file

@ -117,16 +117,27 @@ create_fingerprint (GstOFA * ofa)
GstBuffer *buf; GstBuffer *buf;
gint rate = GST_AUDIO_FILTER (ofa)->format.rate; gint rate = GST_AUDIO_FILTER (ofa)->format.rate;
gint channels = GST_AUDIO_FILTER (ofa)->format.channels; gint channels = GST_AUDIO_FILTER (ofa)->format.channels;
gint endianness = gint endianness;
(GST_AUDIO_FILTER (ofa)->format.
bigend) ? OFA_BIG_ENDIAN : OFA_LITTLE_ENDIAN;
GstTagList *tags; GstTagList *tags;
guint available;
available = gst_adapter_available (ofa->adapter);
if (available == 0) {
GST_WARNING_OBJECT (ofa, "No data to take fingerprint from");
ofa->record = FALSE;
return;
}
if (GST_AUDIO_FILTER (ofa)->format.bigend)
endianness = OFA_BIG_ENDIAN;
else
endianness = OFA_LITTLE_ENDIAN;
GST_DEBUG ("Generating fingerprint"); GST_DEBUG ("Generating fingerprint");
buf = buf = gst_adapter_take_buffer (ofa->adapter, available);
gst_adapter_take_buffer (ofa->adapter,
gst_adapter_available (ofa->adapter));
ofa->fingerprint = g_strdup (ofa_create_print (GST_BUFFER_DATA (buf), ofa->fingerprint = g_strdup (ofa_create_print (GST_BUFFER_DATA (buf),
endianness, GST_BUFFER_SIZE (buf) / 2, rate, endianness, GST_BUFFER_SIZE (buf) / 2, rate,

View file

@ -105,9 +105,6 @@ GST_DEBUG_CATEGORY_STATIC (gst_motion_cells_debug);
POINTER = NULL;\ POINTER = NULL;\
} }
int instanceCounter = 0;
gboolean element_id_was_max = false;
/* Filter signals and args */ /* Filter signals and args */
enum enum
{ {
@ -396,8 +393,7 @@ gst_motion_cells_init (GstMotioncells * filter, GstMotioncellsClass * gclass)
filter->datafileidx = 0; filter->datafileidx = 0;
g_mutex_lock (filter->propset_mutex); g_mutex_lock (filter->propset_mutex);
filter->id = instanceCounter; filter->id = motion_cells_init ();
motion_cells_init ();
g_mutex_unlock (filter->propset_mutex); g_mutex_unlock (filter->propset_mutex);
} }

View file

@ -46,12 +46,13 @@
#include <limits.h> #include <limits.h>
#include "motioncells_wrapper.h" #include "motioncells_wrapper.h"
extern int instanceCounter; static int instanceCounter = 0;
extern bool element_id_was_max; static gboolean element_id_was_max = false;
MotionCells *mc; MotionCells *mc;
char p_str[] = "idx failed"; char p_str[] = "idx failed";
void int
motion_cells_init () motion_cells_init ()
{ {
mc = new MotionCells (); mc = new MotionCells ();
@ -67,6 +68,7 @@ motion_cells_init ()
instanceCounter = motioncellsfreeids.back (); instanceCounter = motioncellsfreeids.back ();
motioncellsfreeids.pop_back (); motioncellsfreeids.pop_back ();
} }
return tmpmc.id;
} }
int int

View file

@ -62,7 +62,7 @@ extern "C"
{ {
#endif #endif
void motion_cells_init (); int motion_cells_init ();
int perform_detection_motion_cells (IplImage * p_image, double p_sensitivity, int perform_detection_motion_cells (IplImage * p_image, double p_sensitivity,
double p_framerate, int p_gridx, int p_gridy, double p_framerate, int p_gridx, int p_gridy,
long int p_timestamp_millisec, bool p_isVisible, bool p_useAlpha, long int p_timestamp_millisec, bool p_isVisible, bool p_useAlpha,

View file

@ -60,7 +60,6 @@ struct _GstSchroEnc
/* state */ /* state */
SchroEncoder *encoder; SchroEncoder *encoder;
SchroVideoFormat *video_format; SchroVideoFormat *video_format;
GstBuffer *seq_header_buffer;
guint64 last_granulepos; guint64 last_granulepos;
guint64 granule_offset; guint64 granule_offset;
@ -102,8 +101,6 @@ static GstFlowReturn gst_schro_enc_handle_frame (GstBaseVideoEncoder *
base_video_encoder, GstVideoFrame * frame); base_video_encoder, GstVideoFrame * frame);
static GstFlowReturn gst_schro_enc_shape_output (GstBaseVideoEncoder * static GstFlowReturn gst_schro_enc_shape_output (GstBaseVideoEncoder *
base_video_encoder, GstVideoFrame * frame); base_video_encoder, GstVideoFrame * frame);
static GstCaps *gst_schro_enc_get_caps (GstBaseVideoEncoder *
base_video_encoder);
static GstStaticPadTemplate gst_schro_enc_sink_template = static GstStaticPadTemplate gst_schro_enc_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink", GST_STATIC_PAD_TEMPLATE ("sink",
@ -219,7 +216,6 @@ gst_schro_enc_class_init (GstSchroEncClass * klass)
GST_DEBUG_FUNCPTR (gst_schro_enc_handle_frame); GST_DEBUG_FUNCPTR (gst_schro_enc_handle_frame);
basevideocoder_class->shape_output = basevideocoder_class->shape_output =
GST_DEBUG_FUNCPTR (gst_schro_enc_shape_output); GST_DEBUG_FUNCPTR (gst_schro_enc_shape_output);
basevideocoder_class->get_caps = GST_DEBUG_FUNCPTR (gst_schro_enc_get_caps);
} }
static void static void
@ -241,28 +237,12 @@ static gboolean
gst_schro_enc_set_format (GstBaseVideoEncoder * base_video_encoder, gst_schro_enc_set_format (GstBaseVideoEncoder * base_video_encoder,
GstVideoState * state) GstVideoState * state)
{ {
GstCaps *caps;
GstStructure *structure;
GstSchroEnc *schro_enc = GST_SCHRO_ENC (base_video_encoder); GstSchroEnc *schro_enc = GST_SCHRO_ENC (base_video_encoder);
GstCaps *caps;
GstBuffer *seq_header_buffer;
gboolean ret;
GST_DEBUG ("set_output_caps"); GST_DEBUG ("set_output_caps");
caps =
gst_pad_get_allowed_caps (GST_BASE_VIDEO_CODEC_SRC_PAD
(base_video_encoder));
if (caps == NULL) {
caps =
gst_caps_copy (gst_pad_get_pad_template_caps
(GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder)));
}
if (gst_caps_is_empty (caps)) {
gst_caps_unref (caps);
return FALSE;
}
structure = gst_caps_get_structure (caps, 0);
gst_caps_unref (caps);
gst_base_video_encoder_set_latency_fields (base_video_encoder, gst_base_video_encoder_set_latency_fields (base_video_encoder,
2 * (int) schro_encoder_setting_get_double (schro_enc->encoder, 2 * (int) schro_encoder_setting_get_double (schro_enc->encoder,
@ -311,13 +291,58 @@ gst_schro_enc_set_format (GstBaseVideoEncoder * base_video_encoder,
schro_encoder_set_video_format (schro_enc->encoder, schro_enc->video_format); schro_encoder_set_video_format (schro_enc->encoder, schro_enc->video_format);
schro_encoder_start (schro_enc->encoder); schro_encoder_start (schro_enc->encoder);
schro_enc->seq_header_buffer = seq_header_buffer =
gst_schro_wrap_schro_buffer (schro_encoder_encode_sequence_header gst_schro_wrap_schro_buffer (schro_encoder_encode_sequence_header
(schro_enc->encoder)); (schro_enc->encoder));
schro_enc->granule_offset = ~0; schro_enc->granule_offset = ~0;
return TRUE; caps = gst_caps_new_simple ("video/x-dirac",
"width", G_TYPE_INT, state->width,
"height", G_TYPE_INT, state->height,
"framerate", GST_TYPE_FRACTION, state->fps_n,
state->fps_d,
"pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
state->par_d, NULL);
GST_BUFFER_FLAG_SET (seq_header_buffer, GST_BUFFER_FLAG_IN_CAPS);
{
GValue array = { 0 };
GValue value = { 0 };
GstBuffer *buf;
int size;
g_value_init (&array, GST_TYPE_ARRAY);
g_value_init (&value, GST_TYPE_BUFFER);
size = GST_BUFFER_SIZE (seq_header_buffer);
buf = gst_buffer_new_and_alloc (size + SCHRO_PARSE_HEADER_SIZE);
/* ogg(mux) expects the header buffers to have 0 timestamps -
set OFFSET and OFFSET_END accordingly */
GST_BUFFER_OFFSET (buf) = 0;
GST_BUFFER_OFFSET_END (buf) = 0;
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
memcpy (GST_BUFFER_DATA (buf), GST_BUFFER_DATA (seq_header_buffer), size);
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + size + 0, 0x42424344);
GST_WRITE_UINT8 (GST_BUFFER_DATA (buf) + size + 4,
SCHRO_PARSE_CODE_END_OF_SEQUENCE);
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + size + 5, 0);
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + size + 9, size);
gst_value_set_buffer (&value, buf);
gst_buffer_unref (buf);
gst_value_array_append_value (&array, &value);
gst_structure_set_value (gst_caps_get_structure (caps, 0),
"streamheader", &array);
g_value_unset (&value);
g_value_unset (&array);
}
gst_buffer_unref (seq_header_buffer);
ret = gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (schro_enc), caps);
gst_caps_unref (caps);
return ret;
} }
static void static void
@ -404,10 +429,6 @@ gst_schro_enc_stop (GstBaseVideoEncoder * base_video_encoder)
schro_encoder_free (schro_enc->encoder); schro_encoder_free (schro_enc->encoder);
schro_enc->encoder = NULL; schro_enc->encoder = NULL;
} }
if (schro_enc->seq_header_buffer) {
gst_buffer_unref (schro_enc->seq_header_buffer);
schro_enc->seq_header_buffer = NULL;
}
if (schro_enc->video_format) { if (schro_enc->video_format) {
g_free (schro_enc->video_format); g_free (schro_enc->video_format);
schro_enc->video_format = NULL; schro_enc->video_format = NULL;
@ -458,91 +479,6 @@ gst_schro_enc_handle_frame (GstBaseVideoEncoder * base_video_encoder,
return ret; return ret;
} }
#if 0
static void
gst_caps_add_streamheader (GstCaps * caps, GList * list)
{
GValue array = { 0 };
GValue value = { 0 };
GstBuffer *buf;
GList *g;
g_value_init (&array, GST_TYPE_ARRAY);
for (g = g_list_first (list); g; g = g_list_next (list)) {
g_value_init (&value, GST_TYPE_BUFFER);
buf = gst_buffer_copy (GST_BUFFER (g->data));
gst_value_set_buffer (&value, buf);
gst_buffer_unref (buf);
gst_value_array_append_value (&array, &value);
g_value_unset (&value);
}
gst_structure_set_value (gst_caps_get_structure (caps, 0),
"streamheader", &array);
g_value_unset (&array);
}
#endif
static GstCaps *
gst_schro_enc_get_caps (GstBaseVideoEncoder * base_video_encoder)
{
GstCaps *caps;
const GstVideoState *state;
GstSchroEnc *schro_enc;
schro_enc = GST_SCHRO_ENC (base_video_encoder);
state = gst_base_video_encoder_get_state (base_video_encoder);
caps = gst_caps_new_simple ("video/x-dirac",
"width", G_TYPE_INT, state->width,
"height", G_TYPE_INT, state->height,
"framerate", GST_TYPE_FRACTION, state->fps_n,
state->fps_d,
"pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
state->par_d, NULL);
GST_BUFFER_FLAG_SET (schro_enc->seq_header_buffer, GST_BUFFER_FLAG_IN_CAPS);
{
GValue array = { 0 };
GValue value = { 0 };
GstBuffer *buf;
int size;
g_value_init (&array, GST_TYPE_ARRAY);
g_value_init (&value, GST_TYPE_BUFFER);
size = GST_BUFFER_SIZE (schro_enc->seq_header_buffer);
buf = gst_buffer_new_and_alloc (size + SCHRO_PARSE_HEADER_SIZE);
/* ogg(mux) expects the header buffers to have 0 timestamps -
set OFFSET and OFFSET_END accordingly */
GST_BUFFER_OFFSET (buf) = 0;
GST_BUFFER_OFFSET_END (buf) = 0;
GST_BUFFER_FLAG_SET (buf, GST_BUFFER_FLAG_IN_CAPS);
memcpy (GST_BUFFER_DATA (buf),
GST_BUFFER_DATA (schro_enc->seq_header_buffer), size);
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + size + 0, 0x42424344);
GST_WRITE_UINT8 (GST_BUFFER_DATA (buf) + size + 4,
SCHRO_PARSE_CODE_END_OF_SEQUENCE);
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + size + 5, 0);
GST_WRITE_UINT32_BE (GST_BUFFER_DATA (buf) + size + 9, size);
gst_value_set_buffer (&value, buf);
gst_buffer_unref (buf);
gst_value_array_append_value (&array, &value);
gst_structure_set_value (gst_caps_get_structure (caps, 0),
"streamheader", &array);
g_value_unset (&value);
g_value_unset (&array);
}
return caps;
}
static GstFlowReturn static GstFlowReturn
gst_schro_enc_shape_output (GstBaseVideoEncoder * base_video_encoder, gst_schro_enc_shape_output (GstBaseVideoEncoder * base_video_encoder,
GstVideoFrame * frame) GstVideoFrame * frame)

View file

@ -220,7 +220,6 @@ static GstFlowReturn gst_vp8_enc_shape_output (GstBaseVideoEncoder * encoder,
GstVideoFrame * frame); GstVideoFrame * frame);
static gboolean gst_vp8_enc_sink_event (GstBaseVideoEncoder * static gboolean gst_vp8_enc_sink_event (GstBaseVideoEncoder *
base_video_encoder, GstEvent * event); base_video_encoder, GstEvent * event);
static GstCaps *gst_vp8_enc_get_caps (GstBaseVideoEncoder * base_video_encoder);
static GstStaticPadTemplate gst_vp8_enc_sink_template = static GstStaticPadTemplate gst_vp8_enc_sink_template =
GST_STATIC_PAD_TEMPLATE ("sink", GST_STATIC_PAD_TEMPLATE ("sink",
@ -291,7 +290,6 @@ gst_vp8_enc_class_init (GstVP8EncClass * klass)
base_video_encoder_class->finish = gst_vp8_enc_finish; base_video_encoder_class->finish = gst_vp8_enc_finish;
base_video_encoder_class->shape_output = gst_vp8_enc_shape_output; base_video_encoder_class->shape_output = gst_vp8_enc_shape_output;
base_video_encoder_class->event = gst_vp8_enc_sink_event; base_video_encoder_class->event = gst_vp8_enc_sink_event;
base_video_encoder_class->get_caps = gst_vp8_enc_get_caps;
g_object_class_install_property (gobject_class, PROP_BITRATE, g_object_class_install_property (gobject_class, PROP_BITRATE,
g_param_spec_int ("bitrate", "Bit rate", g_param_spec_int ("bitrate", "Bit rate",
@ -695,6 +693,8 @@ gst_vp8_enc_set_format (GstBaseVideoEncoder * base_video_encoder,
vpx_codec_err_t status; vpx_codec_err_t status;
vpx_image_t *image; vpx_image_t *image;
guint8 *data = NULL; guint8 *data = NULL;
GstCaps *caps;
gboolean ret;
encoder = GST_VP8_ENC (base_video_encoder); encoder = GST_VP8_ENC (base_video_encoder);
GST_DEBUG_OBJECT (base_video_encoder, "set_format"); GST_DEBUG_OBJECT (base_video_encoder, "set_format");
@ -845,23 +845,6 @@ gst_vp8_enc_set_format (GstBaseVideoEncoder * base_video_encoder,
data + gst_video_format_get_component_offset (state->format, 2, data + gst_video_format_get_component_offset (state->format, 2,
state->width, state->height); state->width, state->height);
return TRUE;
}
static GstCaps *
gst_vp8_enc_get_caps (GstBaseVideoEncoder * base_video_encoder)
{
GstCaps *caps;
const GstVideoState *state;
GstTagList *tags = NULL;
const GstTagList *iface_tags;
GstBuffer *stream_hdr, *vorbiscomment;
guint8 *data;
GstStructure *s;
GValue array = { 0 };
GValue value = { 0 };
state = gst_base_video_encoder_get_state (base_video_encoder);
caps = gst_caps_new_simple ("video/x-vp8", caps = gst_caps_new_simple ("video/x-vp8",
"width", G_TYPE_INT, state->width, "width", G_TYPE_INT, state->width,
@ -870,56 +853,66 @@ gst_vp8_enc_get_caps (GstBaseVideoEncoder * base_video_encoder)
state->fps_d, state->fps_d,
"pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n, "pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
state->par_d, NULL); state->par_d, NULL);
{
GstStructure *s;
GstBuffer *stream_hdr, *vorbiscomment;
const GstTagList *iface_tags;
GstTagList *tags;
GValue array = { 0, };
GValue value = { 0, };
s = gst_caps_get_structure (caps, 0);
s = gst_caps_get_structure (caps, 0); /* put buffers in a fixed list */
g_value_init (&array, GST_TYPE_ARRAY);
/* put buffers in a fixed list */
g_value_init (&array, GST_TYPE_ARRAY);
g_value_init (&value, GST_TYPE_BUFFER);
/* Create Ogg stream-info */
stream_hdr = gst_buffer_new_and_alloc (26);
data = GST_BUFFER_DATA (stream_hdr);
GST_WRITE_UINT8 (data, 0x4F);
GST_WRITE_UINT32_BE (data + 1, 0x56503830); /* "VP80" */
GST_WRITE_UINT8 (data + 5, 0x01); /* stream info header */
GST_WRITE_UINT8 (data + 6, 1); /* Major version 1 */
GST_WRITE_UINT8 (data + 7, 0); /* Minor version 0 */
GST_WRITE_UINT16_BE (data + 8, state->width);
GST_WRITE_UINT16_BE (data + 10, state->height);
GST_WRITE_UINT24_BE (data + 12, state->par_n);
GST_WRITE_UINT24_BE (data + 15, state->par_d);
GST_WRITE_UINT32_BE (data + 18, state->fps_n);
GST_WRITE_UINT32_BE (data + 22, state->fps_d);
GST_BUFFER_FLAG_SET (stream_hdr, GST_BUFFER_FLAG_IN_CAPS);
gst_value_set_buffer (&value, stream_hdr);
gst_value_array_append_value (&array, &value);
g_value_unset (&value);
gst_buffer_unref (stream_hdr);
iface_tags =
gst_tag_setter_get_tag_list (GST_TAG_SETTER (base_video_encoder));
if (iface_tags) {
vorbiscomment =
gst_tag_list_to_vorbiscomment_buffer ((iface_tags) ? iface_tags : tags,
(const guint8 *) "OVP80\2 ", 7,
"Encoded with GStreamer vp8enc " PACKAGE_VERSION);
GST_BUFFER_FLAG_SET (vorbiscomment, GST_BUFFER_FLAG_IN_CAPS);
g_value_init (&value, GST_TYPE_BUFFER); g_value_init (&value, GST_TYPE_BUFFER);
gst_value_set_buffer (&value, vorbiscomment);
/* Create Ogg stream-info */
stream_hdr = gst_buffer_new_and_alloc (26);
data = GST_BUFFER_DATA (stream_hdr);
GST_WRITE_UINT8 (data, 0x4F);
GST_WRITE_UINT32_BE (data + 1, 0x56503830); /* "VP80" */
GST_WRITE_UINT8 (data + 5, 0x01); /* stream info header */
GST_WRITE_UINT8 (data + 6, 1); /* Major version 1 */
GST_WRITE_UINT8 (data + 7, 0); /* Minor version 0 */
GST_WRITE_UINT16_BE (data + 8, state->width);
GST_WRITE_UINT16_BE (data + 10, state->height);
GST_WRITE_UINT24_BE (data + 12, state->par_n);
GST_WRITE_UINT24_BE (data + 15, state->par_d);
GST_WRITE_UINT32_BE (data + 18, state->fps_n);
GST_WRITE_UINT32_BE (data + 22, state->fps_d);
GST_BUFFER_FLAG_SET (stream_hdr, GST_BUFFER_FLAG_IN_CAPS);
gst_value_set_buffer (&value, stream_hdr);
gst_value_array_append_value (&array, &value); gst_value_array_append_value (&array, &value);
g_value_unset (&value); g_value_unset (&value);
gst_buffer_unref (vorbiscomment); gst_buffer_unref (stream_hdr);
iface_tags =
gst_tag_setter_get_tag_list (GST_TAG_SETTER (base_video_encoder));
if (iface_tags) {
vorbiscomment =
gst_tag_list_to_vorbiscomment_buffer ((iface_tags) ? iface_tags :
tags, (const guint8 *) "OVP80\2 ", 7,
"Encoded with GStreamer vp8enc " PACKAGE_VERSION);
GST_BUFFER_FLAG_SET (vorbiscomment, GST_BUFFER_FLAG_IN_CAPS);
g_value_init (&value, GST_TYPE_BUFFER);
gst_value_set_buffer (&value, vorbiscomment);
gst_value_array_append_value (&array, &value);
g_value_unset (&value);
gst_buffer_unref (vorbiscomment);
}
gst_structure_set_value (s, "streamheader", &array);
g_value_unset (&array);
} }
gst_structure_set_value (s, "streamheader", &array); ret = gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (encoder), caps);
g_value_unset (&array); gst_caps_unref (caps);
return caps; return ret;
} }
static GstFlowReturn static GstFlowReturn

View file

@ -1917,11 +1917,9 @@ gst_base_video_decoder_alloc_src_buffer (GstBaseVideoDecoder *
{ {
GstBuffer *buffer; GstBuffer *buffer;
GstFlowReturn flow_ret; GstFlowReturn flow_ret;
int num_bytes;
GstVideoState *state = &GST_BASE_VIDEO_CODEC (base_video_decoder)->state; GstVideoState *state = &GST_BASE_VIDEO_CODEC (base_video_decoder)->state;
int num_bytes = state->bytes_per_picture;
num_bytes = gst_video_format_get_size (state->format, state->width,
state->height);
GST_DEBUG ("alloc src buffer caps=%" GST_PTR_FORMAT, GST_DEBUG ("alloc src buffer caps=%" GST_PTR_FORMAT,
GST_PAD_CAPS (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_decoder))); GST_PAD_CAPS (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_decoder)));
flow_ret = flow_ret =

View file

@ -91,7 +91,7 @@
* <itemizedlist> * <itemizedlist>
* <listitem><para>Provide pad templates</para></listitem> * <listitem><para>Provide pad templates</para></listitem>
* <listitem><para> * <listitem><para>
* Provide source pad caps in @get_caps. * Provide source pad caps before pushing the first buffer
* </para></listitem> * </para></listitem>
* <listitem><para> * <listitem><para>
* Accept data in @handle_frame and provide encoded results to * Accept data in @handle_frame and provide encoded results to
@ -117,6 +117,7 @@ static void gst_base_video_encoder_finalize (GObject * object);
static gboolean gst_base_video_encoder_sink_setcaps (GstPad * pad, static gboolean gst_base_video_encoder_sink_setcaps (GstPad * pad,
GstCaps * caps); GstCaps * caps);
static GstCaps *gst_base_video_encoder_sink_getcaps (GstPad * pad);
static gboolean gst_base_video_encoder_src_event (GstPad * pad, static gboolean gst_base_video_encoder_src_event (GstPad * pad,
GstEvent * event); GstEvent * event);
static gboolean gst_base_video_encoder_sink_event (GstPad * pad, static gboolean gst_base_video_encoder_sink_event (GstPad * pad,
@ -179,7 +180,6 @@ gst_base_video_encoder_reset (GstBaseVideoEncoder * base_video_encoder)
base_video_encoder->distance_from_sync = 0; base_video_encoder->distance_from_sync = 0;
base_video_encoder->force_keyframe = FALSE; base_video_encoder->force_keyframe = FALSE;
base_video_encoder->set_output_caps = FALSE;
base_video_encoder->drained = TRUE; base_video_encoder->drained = TRUE;
base_video_encoder->min_latency = 0; base_video_encoder->min_latency = 0;
base_video_encoder->max_latency = 0; base_video_encoder->max_latency = 0;
@ -211,6 +211,8 @@ gst_base_video_encoder_init (GstBaseVideoEncoder * base_video_encoder,
GST_DEBUG_FUNCPTR (gst_base_video_encoder_sink_event)); GST_DEBUG_FUNCPTR (gst_base_video_encoder_sink_event));
gst_pad_set_setcaps_function (pad, gst_pad_set_setcaps_function (pad,
GST_DEBUG_FUNCPTR (gst_base_video_encoder_sink_setcaps)); GST_DEBUG_FUNCPTR (gst_base_video_encoder_sink_setcaps));
gst_pad_set_getcaps_function (pad,
GST_DEBUG_FUNCPTR (gst_base_video_encoder_sink_getcaps));
pad = GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder); pad = GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder);
@ -359,6 +361,74 @@ exit:
return ret; return ret;
} }
static GstCaps *
gst_base_video_encoder_sink_getcaps (GstPad * pad)
{
GstBaseVideoEncoder *base_video_encoder;
const GstCaps *templ_caps;
GstCaps *allowed;
GstCaps *fcaps, *filter_caps;
gint i, j;
base_video_encoder = GST_BASE_VIDEO_ENCODER (gst_pad_get_parent (pad));
/* FIXME: Allow subclass to override this? */
/* Allow downstream to specify width/height/framerate/PAR constraints
* and forward them upstream for video converters to handle
*/
templ_caps =
gst_pad_get_pad_template_caps (GST_BASE_VIDEO_CODEC_SINK_PAD
(base_video_encoder));
allowed =
gst_pad_get_allowed_caps (GST_BASE_VIDEO_CODEC_SRC_PAD
(base_video_encoder));
if (!allowed || gst_caps_is_empty (allowed) || gst_caps_is_any (allowed)) {
fcaps = gst_caps_copy (templ_caps);
goto done;
}
GST_LOG_OBJECT (base_video_encoder, "template caps %" GST_PTR_FORMAT,
templ_caps);
GST_LOG_OBJECT (base_video_encoder, "allowed caps %" GST_PTR_FORMAT, allowed);
filter_caps = gst_caps_new_empty ();
for (i = 0; i < gst_caps_get_size (templ_caps); i++) {
GQuark q_name =
gst_structure_get_name_id (gst_caps_get_structure (templ_caps, i));
for (j = 0; j < gst_caps_get_size (allowed); j++) {
const GstStructure *allowed_s = gst_caps_get_structure (allowed, j);
const GValue *val;
GstStructure *s;
s = gst_structure_id_empty_new (q_name);
if ((val = gst_structure_get_value (allowed_s, "width")))
gst_structure_set_value (s, "width", val);
if ((val = gst_structure_get_value (allowed_s, "height")))
gst_structure_set_value (s, "height", val);
if ((val = gst_structure_get_value (allowed_s, "framerate")))
gst_structure_set_value (s, "framerate", val);
if ((val = gst_structure_get_value (allowed_s, "pixel-aspect-ratio")))
gst_structure_set_value (s, "pixel-aspect-ratio", val);
gst_caps_merge_structure (filter_caps, s);
}
}
fcaps = gst_caps_intersect (filter_caps, templ_caps);
gst_caps_unref (filter_caps);
done:
gst_caps_replace (&allowed, NULL);
GST_LOG_OBJECT (base_video_encoder, "Returning caps %" GST_PTR_FORMAT, fcaps);
return fcaps;
}
static void static void
gst_base_video_encoder_finalize (GObject * object) gst_base_video_encoder_finalize (GObject * object)
{ {
@ -761,27 +831,6 @@ gst_base_video_encoder_finish_frame (GstBaseVideoEncoder * base_video_encoder,
GST_LOG_OBJECT (base_video_encoder, GST_LOG_OBJECT (base_video_encoder,
"finish frame fpn %d", frame->presentation_frame_number); "finish frame fpn %d", frame->presentation_frame_number);
/* FIXME get rid of this ?
* seems a roundabout way that adds little benefit to simply get
* and subsequently set. subclass is adult enough to set_caps itself ...
* so simply check/ensure/assert that src pad caps are set by now */
if (!base_video_encoder->set_output_caps) {
if (!GST_PAD_CAPS (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder))) {
GstCaps *caps;
if (base_video_encoder_class->get_caps) {
caps = base_video_encoder_class->get_caps (base_video_encoder);
} else {
caps = gst_caps_new_simple ("video/unknown", NULL);
}
GST_DEBUG_OBJECT (base_video_encoder, "src caps %" GST_PTR_FORMAT, caps);
gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_encoder),
caps);
gst_caps_unref (caps);
}
base_video_encoder->set_output_caps = TRUE;
}
/* Push all pending events that arrived before this frame */ /* Push all pending events that arrived before this frame */
for (l = base_video_encoder->base_video_codec.frames; l; l = l->next) { for (l = base_video_encoder->base_video_codec.frames; l; l = l->next) {
GstVideoFrame *tmp = l->data; GstVideoFrame *tmp = l->data;

View file

@ -89,7 +89,6 @@ struct _GstBaseVideoEncoder
/*< private >*/ /*< private >*/
/* FIXME move to real private part ? /* FIXME move to real private part ?
* (and introduce a context ?) */ * (and introduce a context ?) */
gboolean set_output_caps;
gboolean drained; gboolean drained;
gint64 min_latency; gint64 min_latency;
@ -131,8 +130,6 @@ struct _GstBaseVideoEncoder
* Event handler on the sink pad. This function should return * Event handler on the sink pad. This function should return
* TRUE if the event was handled and should be discarded * TRUE if the event was handled and should be discarded
* (i.e. not unref'ed). * (i.e. not unref'ed).
* @getcaps: Optional, but recommended.
* Provides src pad caps to baseclass.
* *
* Subclasses can override any of the available virtual methods or not, as * Subclasses can override any of the available virtual methods or not, as
* needed. At minimum @handle_frame needs to be overridden, and @set_format * needed. At minimum @handle_frame needs to be overridden, and @set_format
@ -164,8 +161,6 @@ struct _GstBaseVideoEncoderClass
gboolean (*event) (GstBaseVideoEncoder *coder, gboolean (*event) (GstBaseVideoEncoder *coder,
GstEvent *event); GstEvent *event);
GstCaps * (*get_caps) (GstBaseVideoEncoder *coder);
/*< private >*/ /*< private >*/
/* FIXME before moving to base */ /* FIXME before moving to base */
gpointer _gst_reserved[GST_PADDING_LARGE]; gpointer _gst_reserved[GST_PADDING_LARGE];

View file

@ -130,6 +130,7 @@ gst_aiff_mux_change_state (GstElement * element, GstStateChange transition)
aiffmux->length = 0; aiffmux->length = 0;
aiffmux->rate = 0.0; aiffmux->rate = 0.0;
aiffmux->sent_header = FALSE; aiffmux->sent_header = FALSE;
aiffmux->overflow = FALSE;
break; break;
default: default:
break; break;
@ -160,7 +161,7 @@ gst_aiff_mux_class_init (GstAiffMuxClass * klass)
(AIFF_FORM_HEADER_LEN + AIFF_COMM_HEADER_LEN + AIFF_SSND_HEADER_LEN) (AIFF_FORM_HEADER_LEN + AIFF_COMM_HEADER_LEN + AIFF_SSND_HEADER_LEN)
static void static void
gst_aiff_mux_write_form_header (GstAiffMux * aiffmux, guint audio_data_size, gst_aiff_mux_write_form_header (GstAiffMux * aiffmux, guint32 audio_data_size,
GstByteWriter * writer) GstByteWriter * writer)
{ {
/* ckID == 'FORM' */ /* ckID == 'FORM' */
@ -228,7 +229,7 @@ gst_aiff_mux_write_ext (GstByteWriter * writer, double d)
*/ */
static void static void
gst_aiff_mux_write_comm_header (GstAiffMux * aiffmux, guint audio_data_size, gst_aiff_mux_write_comm_header (GstAiffMux * aiffmux, guint32 audio_data_size,
GstByteWriter * writer) GstByteWriter * writer)
{ {
gst_byte_writer_put_uint32_le (writer, GST_MAKE_FOURCC ('C', 'O', 'M', 'M')); gst_byte_writer_put_uint32_le (writer, GST_MAKE_FOURCC ('C', 'O', 'M', 'M'));
@ -236,13 +237,13 @@ gst_aiff_mux_write_comm_header (GstAiffMux * aiffmux, guint audio_data_size,
gst_byte_writer_put_uint16_be (writer, aiffmux->channels); gst_byte_writer_put_uint16_be (writer, aiffmux->channels);
/* numSampleFrames value will be overwritten when known */ /* numSampleFrames value will be overwritten when known */
gst_byte_writer_put_uint32_be (writer, gst_byte_writer_put_uint32_be (writer,
(audio_data_size * 8) / (aiffmux->width * aiffmux->channels)); audio_data_size / (aiffmux->width / 8 * aiffmux->channels));
gst_byte_writer_put_uint16_be (writer, aiffmux->depth); gst_byte_writer_put_uint16_be (writer, aiffmux->depth);
gst_aiff_mux_write_ext (writer, aiffmux->rate); gst_aiff_mux_write_ext (writer, aiffmux->rate);
} }
static void static void
gst_aiff_mux_write_ssnd_header (GstAiffMux * aiffmux, guint audio_data_size, gst_aiff_mux_write_ssnd_header (GstAiffMux * aiffmux, guint32 audio_data_size,
GstByteWriter * writer) GstByteWriter * writer)
{ {
gst_byte_writer_put_uint32_le (writer, GST_MAKE_FOURCC ('S', 'S', 'N', 'D')); gst_byte_writer_put_uint32_le (writer, GST_MAKE_FOURCC ('S', 'S', 'N', 'D'));
@ -255,7 +256,7 @@ gst_aiff_mux_write_ssnd_header (GstAiffMux * aiffmux, guint audio_data_size,
} }
static GstFlowReturn static GstFlowReturn
gst_aiff_mux_push_header (GstAiffMux * aiffmux, guint audio_data_size) gst_aiff_mux_push_header (GstAiffMux * aiffmux, guint32 audio_data_size)
{ {
GstFlowReturn ret; GstFlowReturn ret;
GstBuffer *outbuf; GstBuffer *outbuf;
@ -296,12 +297,16 @@ gst_aiff_mux_chain (GstPad * pad, GstBuffer * buf)
{ {
GstAiffMux *aiffmux = GST_AIFF_MUX (GST_PAD_PARENT (pad)); GstAiffMux *aiffmux = GST_AIFF_MUX (GST_PAD_PARENT (pad));
GstFlowReturn flow = GST_FLOW_OK; GstFlowReturn flow = GST_FLOW_OK;
guint64 cur_size;
if (!aiffmux->channels) { if (!aiffmux->channels) {
gst_buffer_unref (buf); gst_buffer_unref (buf);
return GST_FLOW_NOT_NEGOTIATED; return GST_FLOW_NOT_NEGOTIATED;
} }
if (G_UNLIKELY (aiffmux->overflow))
goto overflow;
if (!aiffmux->sent_header) { if (!aiffmux->sent_header) {
/* use bogus size initially, we'll write the real /* use bogus size initially, we'll write the real
* header when we get EOS and know the exact length */ * header when we get EOS and know the exact length */
@ -316,6 +321,20 @@ gst_aiff_mux_chain (GstPad * pad, GstBuffer * buf)
aiffmux->sent_header = TRUE; aiffmux->sent_header = TRUE;
} }
/* AIFF has an audio data size limit of slightly under 4 GB.
A value of audiosize + AIFF_HEADER_LEN - 8 is written, so
I'll error out if writing data that makes this overflow. */
cur_size = aiffmux->length + AIFF_HEADER_LEN - 8;
if (G_UNLIKELY (cur_size + GST_BUFFER_SIZE (buf) >= G_MAXUINT32)) {
GST_ERROR_OBJECT (aiffmux, "AIFF only supports about 4 GB worth of "
"audio data, dropping any further data on the floor");
GST_ELEMENT_WARNING (aiffmux, STREAM, MUX, ("AIFF has a 4GB size limit"),
("AIFF only supports about 4 GB worth of audio data, "
"dropping any further data on the floor"));
aiffmux->overflow = TRUE;
goto overflow;
}
GST_LOG_OBJECT (aiffmux, "pushing %u bytes raw audio, ts=%" GST_TIME_FORMAT, GST_LOG_OBJECT (aiffmux, "pushing %u bytes raw audio, ts=%" GST_TIME_FORMAT,
GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf))); GST_BUFFER_SIZE (buf), GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)));
@ -330,6 +349,13 @@ gst_aiff_mux_chain (GstPad * pad, GstBuffer * buf)
flow = gst_pad_push (aiffmux->srcpad, buf); flow = gst_pad_push (aiffmux->srcpad, buf);
return flow; return flow;
overflow:
{
GST_WARNING_OBJECT (aiffmux, "output file too large, dropping buffer");
gst_buffer_unref (buf);
return GST_FLOW_OK;
}
} }
static gboolean static gboolean

View file

@ -81,6 +81,7 @@ struct _GstAiffMux
gdouble rate; gdouble rate;
gboolean sent_header; gboolean sent_header;
gboolean overflow;
}; };
struct _GstAiffMuxClass struct _GstAiffMuxClass

View file

@ -20,10 +20,13 @@
/** /**
* SECTION:gstbaseaudiovisualizer * SECTION:gstbaseaudiovisualizer
* *
* A basclass for scopes. It takes care of re-fitting the audio-rate to * A basclass for scopes (visualizers). It takes care of re-fitting the
* video-rate. It also provides several background shading effects. These * audio-rate to video-rate and handles renegotiation (downstream video size
* effects are applied to a previous picture before the render() implementation * changes).
* can draw a new frame. *
* It also provides several background shading effects. These effects are
* applied to a previous picture before the render() implementation can draw a
* new frame.
*/ */
#ifdef HAVE_CONFIG_H #ifdef HAVE_CONFIG_H
@ -85,9 +88,19 @@ gst_base_audio_visualizer_shader_get_type (void)
"fade-and-move-up"}, "fade-and-move-up"},
{GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_DOWN, "Fade and move down", {GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_DOWN, "Fade and move down",
"fade-and-move-down"}, "fade-and-move-down"},
{GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_LEFT, "Fade and move left",
"fade-and-move-left"},
{GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_RIGHT,
"Fade and move right",
"fade-and-move-right"},
{GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_OUT, {GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_OUT,
"Fade and move horizontaly out", "Fade and move horizontally out", "fade-and-move-horiz-out"},
"fade-and-move-horiz-out"}, {GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_IN,
"Fade and move horizontally in", "fade-and-move-horiz-in"},
{GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_VERT_OUT,
"Fade and move vertically out", "fade-and-move-vert-out"},
{GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_VERT_IN,
"Fade and move vertically in", "fade-and-move-vert-in"},
{0, NULL, NULL}, {0, NULL, NULL},
}; };
@ -98,6 +111,59 @@ gst_base_audio_visualizer_shader_get_type (void)
return shader_type; return shader_type;
} }
/* we're only supporting GST_VIDEO_FORMAT_xRGB right now) */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
#define SHADE1(_d, _s, _i, _r, _g, _b) \
G_STMT_START { \
_d[_i] = (_s[_i] > _b) ? _s[_i] - _b : 0; \
_i++; \
_d[_i] = (_s[_i] > _g) ? _s[_i] - _g : 0; \
_i++; \
_d[_i] = (_s[_i] > _r) ? _s[_i] - _r : 0; \
_i++; \
_d[_i++] = 0; \
} G_STMT_END
#define SHADE2(_d, _s, _j, _i, _r, _g, _b) \
G_STMT_START { \
_d[_j++] = (_s[_i] > _b) ? _s[_i] - _b : 0; \
_i++; \
_d[_j++] = (_s[_i] > _g) ? _s[_i] - _g : 0; \
_i++; \
_d[_j++] = (_s[_i] > _r) ? _s[_i] - _r : 0; \
_i++; \
_d[_j++] = 0; \
_i++; \
} G_STMT_END
#else
#define SHADE1(_d, _s, _i, _r, _g, _b) \
G_STMT_START { \
_d[_i++] = 0; \
_d[_i] = (_s[_i] > _r) ? _s[_i] - _r : 0; \
_i++; \
_d[_i] = (_s[_i] > _g) ? _s[_i] - _g : 0; \
_i++; \
_d[_i] = (_s[_i] > _b) ? _s[_i] - _b : 0; \
_i++; \
} G_STMT_END
#define SHADE2(_d, _s, _j, _i, _r, _g, _b) \
G_STMT_START { \
_d[_j++] = 0; \
_i++; \
_d[_j++] = (_s[_i] > _r) ? _s[_i] - _r : 0; \
_i++; \
_d[_j++] = (_s[_i] > _g) ? _s[_i] - _g : 0; \
_i++; \
_d[_j++] = (_s[_i] > _b) ? _s[_i] - _b : 0; \
_i++; \
} G_STMT_END
#endif
static void static void
shader_fade (GstBaseAudioVisualizer * scope, const guint8 * s, guint8 * d) shader_fade (GstBaseAudioVisualizer * scope, const guint8 * s, guint8 * d)
{ {
@ -106,28 +172,9 @@ shader_fade (GstBaseAudioVisualizer * scope, const guint8 * s, guint8 * d)
guint g = (scope->shade_amount >> 8) & 0xff; guint g = (scope->shade_amount >> 8) & 0xff;
guint b = (scope->shade_amount >> 0) & 0xff; guint b = (scope->shade_amount >> 0) & 0xff;
/* we're only supporting GST_VIDEO_FORMAT_xRGB right now) */
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
for (i = 0; i < bpf;) { for (i = 0; i < bpf;) {
d[i] = (s[i] > b) ? s[i] - b : 0; SHADE1 (d, s, i, r, g, b);
i++;
d[i] = (s[i] > g) ? s[i] - g : 0;
i++;
d[i] = (s[i] > r) ? s[i] - r : 0;
i++;
d[i++] = 0;
} }
#else
for (i = 0; i < bpf;) {
d[i++] = 0;
d[i] = (s[i] > r) ? s[i] - r : 0;
i++;
d[i] = (s[i] > g) ? s[i] - g : 0;
i++;
d[i] = (s[i] > b) ? s[i] - b : 0;
i++;
}
#endif
} }
static void static void
@ -140,47 +187,9 @@ shader_fade_and_move_up (GstBaseAudioVisualizer * scope, const guint8 * s,
guint g = (scope->shade_amount >> 8) & 0xff; guint g = (scope->shade_amount >> 8) & 0xff;
guint b = (scope->shade_amount >> 0) & 0xff; guint b = (scope->shade_amount >> 0) & 0xff;
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
for (j = 0, i = bpl; i < bpf;) { for (j = 0, i = bpl; i < bpf;) {
d[j++] = (s[i] > b) ? s[i] - b : 0; SHADE2 (d, s, j, i, r, g, b);
i++;
d[j++] = (s[i] > g) ? s[i] - g : 0;
i++;
d[j++] = (s[i] > r) ? s[i] - r : 0;
i++;
d[j++] = 0;
i++;
} }
for (i = 0; i < bpl; i += 4) {
d[j] = (s[j] > b) ? s[j] - b : 0;
j++;
d[j] = (s[j] > g) ? s[j] - g : 0;
j++;
d[j] = (s[j] > r) ? s[j] - r : 0;
j++;
d[j++] = 0;
}
#else
for (j = 0, i = bpl; i < bpf;) {
d[j++] = 0;
i++;
d[j++] = (s[i] > r) ? s[i] - r : 0;
i++;
d[j++] = (s[i] > g) ? s[i] - g : 0;
i++;
d[j++] = (s[i] > b) ? s[i] - b : 0;
i++;
}
for (i = 0; i < bpl; i += 4) {
d[j++] = 0;
d[j] = (s[j] > r) ? s[j] - r : 0;
j++;
d[j] = (s[j] > g) ? s[j] - g : 0;
j++;
d[j] = (s[j] > b) ? s[j] - b : 0;
j++;
}
#endif
} }
static void static void
@ -193,47 +202,49 @@ shader_fade_and_move_down (GstBaseAudioVisualizer * scope, const guint8 * s,
guint g = (scope->shade_amount >> 8) & 0xff; guint g = (scope->shade_amount >> 8) & 0xff;
guint b = (scope->shade_amount >> 0) & 0xff; guint b = (scope->shade_amount >> 0) & 0xff;
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
for (i = 0; i < bpl;) {
d[i] = (s[i] > b) ? s[i] - b : 0;
i++;
d[i] = (s[i] > g) ? s[i] - g : 0;
i++;
d[i] = (s[i] > r) ? s[i] - r : 0;
i++;
d[i++] = 0;
}
for (j = bpl, i = 0; j < bpf;) { for (j = bpl, i = 0; j < bpf;) {
d[j++] = (s[i] > b) ? s[i] - b : 0; SHADE2 (d, s, j, i, r, g, b);
i++;
d[j++] = (s[i] > g) ? s[i] - g : 0;
i++;
d[j++] = (s[i] > r) ? s[i] - r : 0;
i++;
d[j++] = 0;
i++;
} }
#else }
for (i = 0; i < bpl;) {
d[i++] = 0; static void
d[i] = (s[i] > r) ? s[i] - r : 0; shader_fade_and_move_left (GstBaseAudioVisualizer * scope,
i++; const guint8 * s, guint8 * d)
d[i] = (s[i] > g) ? s[i] - g : 0; {
i++; guint i, j, k, bpf = scope->bpf;
d[i] = (s[i] > b) ? s[i] - b : 0; guint w = scope->width;
i++; guint r = (scope->shade_amount >> 16) & 0xff;
guint g = (scope->shade_amount >> 8) & 0xff;
guint b = (scope->shade_amount >> 0) & 0xff;
/* move to the left */
for (j = 0, i = 4; i < bpf;) {
for (k = 0; k < w - 1; k++) {
SHADE2 (d, s, j, i, r, g, b);
}
i += 4;
j += 4;
} }
for (j = bpl, i = 0; j < bpf;) { }
d[j++] = 0;
i++; static void
d[j++] = (s[i] > r) ? s[i] - r : 0; shader_fade_and_move_right (GstBaseAudioVisualizer * scope,
i++; const guint8 * s, guint8 * d)
d[j++] = (s[i] > g) ? s[i] - g : 0; {
i++; guint i, j, k, bpf = scope->bpf;
d[j++] = (s[i] > b) ? s[i] - b : 0; guint w = scope->width;
i++; guint r = (scope->shade_amount >> 16) & 0xff;
guint g = (scope->shade_amount >> 8) & 0xff;
guint b = (scope->shade_amount >> 0) & 0xff;
/* move to the left */
for (j = 4, i = 0; i < bpf;) {
for (k = 0; k < w - 1; k++) {
SHADE2 (d, s, j, i, r, g, b);
}
i += 4;
j += 4;
} }
#endif
} }
static void static void
@ -246,91 +257,91 @@ shader_fade_and_move_horiz_out (GstBaseAudioVisualizer * scope,
guint g = (scope->shade_amount >> 8) & 0xff; guint g = (scope->shade_amount >> 8) & 0xff;
guint b = (scope->shade_amount >> 0) & 0xff; guint b = (scope->shade_amount >> 0) & 0xff;
#if G_BYTE_ORDER == G_LITTLE_ENDIAN /* move upper half up */
/* middle up */
for (j = 0, i = bpl; i < bpf;) { for (j = 0, i = bpl; i < bpf;) {
d[j++] = (s[i] > b) ? s[i] - b : 0; SHADE2 (d, s, j, i, r, g, b);
i++;
d[j++] = (s[i] > g) ? s[i] - g : 0;
i++;
d[j++] = (s[i] > r) ? s[i] - r : 0;
i++;
d[j++] = 0;
i++;
}
for (i = 0; i < bpl; i += 4) {
d[j] = (s[j] > b) ? s[j] - b : 0;
j++;
d[j] = (s[j] > g) ? s[j] - g : 0;
j++;
d[j] = (s[j] > r) ? s[j] - r : 0;
j++;
d[j++] = 0;
}
/* middle down */
for (i = bpf; i < bpf + bpl;) {
d[i] = (s[i] > b) ? s[i] - b : 0;
i++;
d[i] = (s[i] > g) ? s[i] - g : 0;
i++;
d[i] = (s[i] > r) ? s[i] - r : 0;
i++;
d[i++] = 0;
} }
/* move lower half down */
for (j = bpf + bpl, i = bpf; j < bpf + bpf;) { for (j = bpf + bpl, i = bpf; j < bpf + bpf;) {
d[j++] = (s[i] > b) ? s[i] - b : 0; SHADE2 (d, s, j, i, r, g, b);
i++;
d[j++] = (s[i] > g) ? s[i] - g : 0;
i++;
d[j++] = (s[i] > r) ? s[i] - r : 0;
i++;
d[j++] = 0;
i++;
} }
#else
/* middle up */
for (j = 0, i = bpl; i < bpf;) {
d[j++] = 0;
i++;
d[j++] = (s[i] > r) ? s[i] - r : 0;
i++;
d[j++] = (s[i] > g) ? s[i] - g : 0;
i++;
d[j++] = (s[i] > b) ? s[i] - b : 0;
i++;
}
for (i = 0; i < bpl; i += 4) {
d[j++] = 0;
d[j] = (s[j] > r) ? s[j] - r : 0;
j++;
d[j] = (s[j] > g) ? s[j] - g : 0;
j++;
d[j] = (s[j] > b) ? s[j] - b : 0;
j++;
}
/* middle down */
for (i = bpf; i < bpf + bpl;) {
d[i++] = 0;
d[i] = (s[i] > r) ? s[i] - r : 0;
i++;
d[i] = (s[i] > g) ? s[i] - g : 0;
i++;
d[i] = (s[i] > b) ? s[i] - b : 0;
i++;
}
for (j = bpf + bpl, i = bpf; j < bpf + bpf;) {
d[j++] = 0;
i++;
d[j++] = (s[i] > r) ? s[i] - r : 0;
i++;
d[j++] = (s[i] > g) ? s[i] - g : 0;
i++;
d[j++] = (s[i] > b) ? s[i] - b : 0;
i++;
}
#endif
} }
static void
shader_fade_and_move_horiz_in (GstBaseAudioVisualizer * scope,
const guint8 * s, guint8 * d)
{
guint i, j, bpf = scope->bpf / 2;
guint bpl = 4 * scope->width;
guint r = (scope->shade_amount >> 16) & 0xff;
guint g = (scope->shade_amount >> 8) & 0xff;
guint b = (scope->shade_amount >> 0) & 0xff;
/* move upper half down */
for (i = 0, j = bpl; i < bpf;) {
SHADE2 (d, s, j, i, r, g, b);
}
/* move lower half up */
for (i = bpf + bpl, j = bpf; i < bpf + bpf;) {
SHADE2 (d, s, j, i, r, g, b);
}
}
static void
shader_fade_and_move_vert_out (GstBaseAudioVisualizer * scope,
const guint8 * s, guint8 * d)
{
guint i, j, k, bpf = scope->bpf;
guint m = scope->width / 2;
guint r = (scope->shade_amount >> 16) & 0xff;
guint g = (scope->shade_amount >> 8) & 0xff;
guint b = (scope->shade_amount >> 0) & 0xff;
/* move left half to the left */
for (j = 0, i = 4; i < bpf;) {
for (k = 0; k < m; k++) {
SHADE2 (d, s, j, i, r, g, b);
}
j += 4 * m;
i += 4 * m;
}
/* move right half to the right */
for (j = 4 * (m + 1), i = 4 * m; j < bpf;) {
for (k = 0; k < m; k++) {
SHADE2 (d, s, j, i, r, g, b);
}
j += 4 * m;
i += 4 * m;
}
}
static void
shader_fade_and_move_vert_in (GstBaseAudioVisualizer * scope,
const guint8 * s, guint8 * d)
{
guint i, j, k, bpf = scope->bpf;
guint m = scope->width / 2;
guint r = (scope->shade_amount >> 16) & 0xff;
guint g = (scope->shade_amount >> 8) & 0xff;
guint b = (scope->shade_amount >> 0) & 0xff;
/* move left half to the right */
for (j = 4, i = 0; j < bpf;) {
for (k = 0; k < m; k++) {
SHADE2 (d, s, j, i, r, g, b);
}
j += 4 * m;
i += 4 * m;
}
/* move right half to the left */
for (j = 4 * m, i = 4 * (m + 1); i < bpf;) {
for (k = 0; k < m; k++) {
SHADE2 (d, s, j, i, r, g, b);
}
j += 4 * m;
i += 4 * m;
}
}
static void static void
gst_base_audio_visualizer_change_shader (GstBaseAudioVisualizer * scope) gst_base_audio_visualizer_change_shader (GstBaseAudioVisualizer * scope)
@ -348,9 +359,24 @@ gst_base_audio_visualizer_change_shader (GstBaseAudioVisualizer * scope)
case GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_DOWN: case GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_DOWN:
scope->shader = shader_fade_and_move_down; scope->shader = shader_fade_and_move_down;
break; break;
case GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_LEFT:
scope->shader = shader_fade_and_move_left;
break;
case GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_RIGHT:
scope->shader = shader_fade_and_move_right;
break;
case GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_OUT: case GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_OUT:
scope->shader = shader_fade_and_move_horiz_out; scope->shader = shader_fade_and_move_horiz_out;
break; break;
case GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_IN:
scope->shader = shader_fade_and_move_horiz_in;
break;
case GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_VERT_OUT:
scope->shader = shader_fade_and_move_vert_out;
break;
case GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_VERT_IN:
scope->shader = shader_fade_and_move_vert_in;
break;
default: default:
GST_ERROR ("invalid shader function"); GST_ERROR ("invalid shader function");
scope->shader = NULL; scope->shader = NULL;
@ -463,6 +489,7 @@ gst_base_audio_visualizer_init (GstBaseAudioVisualizer * scope,
scope->next_ts = GST_CLOCK_TIME_NONE; scope->next_ts = GST_CLOCK_TIME_NONE;
scope->config_lock = g_mutex_new ();
} }
static void static void
@ -521,6 +548,10 @@ gst_base_audio_visualizer_dispose (GObject * object)
g_free (scope->pixelbuf); g_free (scope->pixelbuf);
scope->pixelbuf = NULL; scope->pixelbuf = NULL;
} }
if (scope->config_lock) {
g_mutex_free (scope->config_lock);
scope->config_lock = NULL;
}
G_OBJECT_CLASS (parent_class)->dispose (object); G_OBJECT_CLASS (parent_class)->dispose (object);
} }
@ -644,6 +675,8 @@ gst_base_audio_visualizer_src_setcaps (GstPad * pad, GstCaps * caps)
goto missing_caps_details; goto missing_caps_details;
} }
g_mutex_lock (scope->config_lock);
scope->width = w; scope->width = w;
scope->height = h; scope->height = h;
scope->fps_n = num; scope->fps_n = num;
@ -669,6 +702,9 @@ gst_base_audio_visualizer_src_setcaps (GstPad * pad, GstCaps * caps)
scope->width, scope->height, scope->fps_n, scope->fps_d); scope->width, scope->height, scope->fps_n, scope->fps_d);
GST_DEBUG_OBJECT (scope, "blocks: spf %u, req_spf %u", GST_DEBUG_OBJECT (scope, "blocks: spf %u, req_spf %u",
scope->spf, scope->req_spf); scope->spf, scope->req_spf);
g_mutex_unlock (scope->config_lock);
done: done:
gst_object_unref (scope); gst_object_unref (scope);
return res; return res;
@ -691,6 +727,7 @@ gst_base_audio_visualizer_chain (GstPad * pad, GstBuffer * buffer)
GstBaseAudioVisualizerClass *klass; GstBaseAudioVisualizerClass *klass;
GstBuffer *inbuf; GstBuffer *inbuf;
guint avail, sbpf; guint avail, sbpf;
guint8 *adata;
gboolean (*render) (GstBaseAudioVisualizer * scope, GstBuffer * audio, gboolean (*render) (GstBaseAudioVisualizer * scope, GstBuffer * audio,
GstBuffer * video); GstBuffer * video);
@ -718,6 +755,8 @@ gst_base_audio_visualizer_chain (GstPad * pad, GstBuffer * buffer)
gst_adapter_push (scope->adapter, buffer); gst_adapter_push (scope->adapter, buffer);
g_mutex_lock (scope->config_lock);
/* this is what we want */ /* this is what we want */
sbpf = scope->req_spf * scope->channels * sizeof (gint16); sbpf = scope->req_spf * scope->channels * sizeof (gint16);
@ -731,9 +770,13 @@ gst_base_audio_visualizer_chain (GstPad * pad, GstBuffer * buffer)
while (avail >= sbpf) { while (avail >= sbpf) {
GstBuffer *outbuf; GstBuffer *outbuf;
g_mutex_unlock (scope->config_lock);
ret = gst_pad_alloc_buffer_and_set_caps (scope->srcpad, ret = gst_pad_alloc_buffer_and_set_caps (scope->srcpad,
GST_BUFFER_OFFSET_NONE, GST_BUFFER_OFFSET_NONE,
scope->bpf, GST_PAD_CAPS (scope->srcpad), &outbuf); scope->bpf, GST_PAD_CAPS (scope->srcpad), &outbuf);
g_mutex_lock (scope->config_lock);
/* recheck as the value could have changed */
sbpf = scope->req_spf * scope->channels * sizeof (gint16);
/* no buffer allocated, we don't care why. */ /* no buffer allocated, we don't care why. */
if (ret != GST_FLOW_OK) if (ret != GST_FLOW_OK)
@ -750,8 +793,11 @@ gst_base_audio_visualizer_chain (GstPad * pad, GstBuffer * buffer)
memset (GST_BUFFER_DATA (outbuf), 0, scope->bpf); memset (GST_BUFFER_DATA (outbuf), 0, scope->bpf);
} }
GST_BUFFER_DATA (inbuf) = /* this can fail as the data size we need could have changed */
(guint8 *) gst_adapter_peek (scope->adapter, sbpf); if (!(adata = (guint8 *) gst_adapter_peek (scope->adapter, sbpf)))
break;
GST_BUFFER_DATA (inbuf) = adata;
GST_BUFFER_SIZE (inbuf) = sbpf; GST_BUFFER_SIZE (inbuf) = sbpf;
/* call class->render() vmethod */ /* call class->render() vmethod */
@ -766,9 +812,13 @@ gst_base_audio_visualizer_chain (GstPad * pad, GstBuffer * buffer)
} }
} }
g_mutex_unlock (scope->config_lock);
ret = gst_pad_push (scope->srcpad, outbuf); ret = gst_pad_push (scope->srcpad, outbuf);
outbuf = NULL; outbuf = NULL;
g_mutex_lock (scope->config_lock);
/* recheck as the value could have changed */
sbpf = scope->req_spf * scope->channels * sizeof (gint16);
GST_LOG_OBJECT (scope, "avail: %u, bpf: %u", avail, sbpf); GST_LOG_OBJECT (scope, "avail: %u, bpf: %u", avail, sbpf);
/* we want to take less or more, depending on spf : req_spf */ /* we want to take less or more, depending on spf : req_spf */
if (avail - sbpf >= sbpf) { if (avail - sbpf >= sbpf) {
@ -787,6 +837,8 @@ gst_base_audio_visualizer_chain (GstPad * pad, GstBuffer * buffer)
scope->next_ts += scope->frame_duration; scope->next_ts += scope->frame_duration;
} }
g_mutex_unlock (scope->config_lock);
gst_object_unref (scope); gst_object_unref (scope);
return ret; return ret;

View file

@ -45,7 +45,12 @@ typedef void (*GstBaseAudioVisualizerShaderFunc)(GstBaseAudioVisualizer *scope,
* @GST_BASE_AUDIO_VISUALIZER_SHADER_FADE: plain fading * @GST_BASE_AUDIO_VISUALIZER_SHADER_FADE: plain fading
* @GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_UP: fade and move up * @GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_UP: fade and move up
* @GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_DOWN: fade and move down * @GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_DOWN: fade and move down
* @GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_OUT: fade and move horizontaly out * @GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_LEFT: fade and move left
* @GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_RIGHT: fade and move right
* @GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_OUT: fade and move horizontally out
* @GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_IN: fade and move horizontally in
* @GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_VERT_OUT: fade and move vertically out
* @GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_VERT_IN: fade and move vertically in
* *
* Different types of supported background shading functions. * Different types of supported background shading functions.
*/ */
@ -54,7 +59,12 @@ typedef enum {
GST_BASE_AUDIO_VISUALIZER_SHADER_FADE, GST_BASE_AUDIO_VISUALIZER_SHADER_FADE,
GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_UP, GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_UP,
GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_DOWN, GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_DOWN,
GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_OUT GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_LEFT,
GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_RIGHT,
GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_OUT,
GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_HORIZ_IN,
GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_VERT_OUT,
GST_BASE_AUDIO_VISUALIZER_SHADER_FADE_AND_MOVE_VERT_IN
} GstBaseAudioVisualizerShader; } GstBaseAudioVisualizerShader;
struct _GstBaseAudioVisualizer struct _GstBaseAudioVisualizer
@ -89,6 +99,9 @@ struct _GstBaseAudioVisualizer
/* audio state */ /* audio state */
gint sample_rate; gint sample_rate;
gint rate; gint rate;
/* configuration mutex */
GMutex *config_lock;
}; };
struct _GstBaseAudioVisualizerClass struct _GstBaseAudioVisualizerClass

View file

@ -165,7 +165,8 @@ gst_spectra_scope_render (GstBaseAudioVisualizer * bscope, GstBuffer * audio,
{ {
GstSpectraScope *scope = GST_SPECTRA_SCOPE (bscope); GstSpectraScope *scope = GST_SPECTRA_SCOPE (bscope);
guint32 *vdata = (guint32 *) GST_BUFFER_DATA (video); guint32 *vdata = (guint32 *) GST_BUFFER_DATA (video);
gint16 *adata = (gint16 *) GST_BUFFER_DATA (audio); gint16 *adata = (gint16 *) g_memdup (GST_BUFFER_DATA (audio),
GST_BUFFER_SIZE (audio));
GstFFTS16Complex *fdata = scope->freq_data; GstFFTS16Complex *fdata = scope->freq_data;
guint x, y, off; guint x, y, off;
guint l, h = bscope->height - 1; guint l, h = bscope->height - 1;
@ -190,6 +191,7 @@ gst_spectra_scope_render (GstBaseAudioVisualizer * bscope, GstBuffer * audio,
/* run fft */ /* run fft */
gst_fft_s16_window (scope->fft_ctx, adata, GST_FFT_WINDOW_HAMMING); gst_fft_s16_window (scope->fft_ctx, adata, GST_FFT_WINDOW_HAMMING);
gst_fft_s16_fft (scope->fft_ctx, adata, fdata); gst_fft_s16_fft (scope->fft_ctx, adata, fdata);
g_free (adata);
/* draw lines */ /* draw lines */
for (x = 0; x < bscope->width; x++) { for (x = 0; x < bscope->width; x++) {

View file

@ -19,19 +19,115 @@
/** /**
* SECTION:element-camerabin2 * SECTION:element-camerabin2
* *
* GstCameraBin22 is a high-level camera object that encapsulates the gstreamer * CameraBin2 is a high-level camera object that encapsulates gstreamer
* internals and provides a task based API for the application. * elements, providing an API for controlling a digital camera.
* *
* <note> * <note>
* Note that camerabin2 is still UNSTABLE, EXPERIMENTAL and under heavy * Note that camerabin2 is still UNSTABLE, EXPERIMENTAL and under
* development. * development.
* </note> * </note>
* *
* CameraBin2 has the following main features:
* <itemizedlist>
* <listitem>
* Record videos
* </listitem>
* <listitem>
* Capture pictures
* </listitem>
* <listitem>
* Display a viewfinder
* </listitem>
* <listitem>
* Post preview images for each capture (video and image)
* </listitem>
* </itemizedlist>
*
* <refsect2>
* <title>Usage</title>
* <para>
* Camerabin2 can be created using gst_element_factory_make() just like
* any other element. Video or image capture mode can be selected using
* the #GstCameraBin2:mode property and the file to save the capture is
* selected using #GstCameraBin2:location property.
*
* After creating camerabin2, applications might want to do some
* customization (there's a section about this below), then select
* the desired mode and start capturing.
*
* In image capture mode, just send a #GstCameraBin:start-capture and a
* picture will be captured. When the picture is stored on the selected
* location, a %GST_MESSAGE_ELEMENT named 'image-done' will be posted on
* the #GstBus.
*
* In video capture mode, send a #GstCameraBin2:start-capture to start
* recording, then send a #GstCameraBin2:stop-capture to stop recording.
* Note that both signals are asynchronous, so, calling
* #GstCameraBin2:stop-capture doesn't guarantee that the video has been
* properly finished yet. Applications should wait for the 'video-done'
* message to be posted on the bus.
*
* In both modes, if #GstCameraBin2:post-previews is %TRUE, a #GstBuffer
* will be post to the #GstBus in a field named 'buffer', in a
* 'preview-image' message of type %GST_MESSAGE_ELEMENT.
* </para>
* </refsect2>
* <refsect2>
* <title>Customization</title>
* <para>
* Camerabin2 provides various customization properties, allowing the user
* to set custom filters, selecting the viewfinder sink and formats to
* use to encode the captured images/videos.
*
* #GstEncodingProfile<!-- -->s are used to tell camerabin2 which formats it
* should encode the captures to, those should be set to
* #GstCameraBin2:image-profile and #GstCameraBin2:video-profile. Default is
* jpeg for images, and ogg (theora and vorbis) for video. If a profile without
* an audio stream is set for video, audio will be disabled on recordings.
*
* #GstCameraBin2:preview-caps can be used to select which format preview
* images should be posted on the #GstBus. It has to be a raw video format.
*
* Camerabin2 has a #GstCameraBin2:camera-source property so applications can
* set their source that will provide buffers for the viewfinder and for
* captures. This camera source is a special type of source that has 3 pads.
* To use a 'regular' source with a single pad you should use
* #GstWrapperCameraBinSource, it will adapt your source and provide 3 pads.
*
* Applications can also select the desired viewfinder sink using
* #GstCameraBin2:viewfinder-sink, it is also possible to select the audio
* source using #GstCameraBin2:audio-source.
*
* The viewfinder resolution can be configured using
* #GstCameraBin2:viewfinder-caps, these #GstCaps should be a subset of
* #GstCameraBin2:viewfinder-supported-caps.
*
* To select the desired resolution for captures, camerabin2 provides
* #GstCameraBin2:image-capture-caps and #GstCameraBin2:video-capture-caps,
* these caps must be a subset of what the source can produce. The allowed
* caps can be probed using #GstCameraBin2:image-capture-supported-caps and
* #GstCameraBin2:video-capture-supported-caps. In an analogous way, there
* are #GstCameraBin2:audio-capture-caps and
* #GstCameraBin2:audio-capture-supported-caps.
*
* Camerabin2 also allows applications to insert custom #GstElements on any
* of its branches: video capture, image capture, viewfinder and preview.
* Check #GstCameraBin2:video-filter, #GstCameraBin2:image-filter,
* #GstCameraBin2:viewfinder-filter and #GstCameraBin2:preview-filter.
* </para>
* </refsect2>
*
* <refsect2> * <refsect2>
* <title>Example launch line</title> * <title>Example launch line</title>
* <para>
* Unfortunatelly, camerabin2 can't be really used from gst-launch, as you need
* to send signals to control it. The following pipeline might be able
* to show the viewfinder using all the default elements.
* |[ * |[
* gst-launch -v -m camerabin2 * gst-launch -v -m camerabin2
* ]| * ]|
* </para>
* </refsect2> * </refsect2>
*/ */
@ -75,7 +171,7 @@
gint bef = g_atomic_int_exchange_and_add (&c->processing_counter, 1); \ gint bef = g_atomic_int_exchange_and_add (&c->processing_counter, 1); \
if (bef == 0) \ if (bef == 0) \
g_object_notify (G_OBJECT (c), "idle"); \ g_object_notify (G_OBJECT (c), "idle"); \
GST_DEBUG_OBJECT ((c), "Processing counter increModemented to: %d", \ GST_DEBUG_OBJECT ((c), "Processing counter incremented to: %d", \
bef + 1); \ bef + 1); \
} }
@ -125,7 +221,8 @@ enum
PROP_MAX_ZOOM, PROP_MAX_ZOOM,
PROP_IMAGE_ENCODING_PROFILE, PROP_IMAGE_ENCODING_PROFILE,
PROP_IDLE, PROP_IDLE,
PROP_FLAGS PROP_FLAGS,
PROP_AUDIO_FILTER
}; };
enum enum
@ -449,9 +546,13 @@ gst_camera_bin_dispose (GObject * object)
gst_object_unref (camerabin->image_filter); gst_object_unref (camerabin->image_filter);
if (camerabin->viewfinder_filter) if (camerabin->viewfinder_filter)
gst_object_unref (camerabin->viewfinder_filter); gst_object_unref (camerabin->viewfinder_filter);
if (camerabin->audio_filter)
gst_object_unref (camerabin->audio_filter);
if (camerabin->user_video_filter) if (camerabin->user_video_filter)
gst_object_unref (camerabin->user_video_filter); gst_object_unref (camerabin->user_video_filter);
if (camerabin->user_audio_filter)
gst_object_unref (camerabin->user_audio_filter);
if (camerabin->user_image_filter) if (camerabin->user_image_filter)
gst_object_unref (camerabin->user_image_filter); gst_object_unref (camerabin->user_image_filter);
if (camerabin->user_viewfinder_filter) if (camerabin->user_viewfinder_filter)
@ -626,6 +727,12 @@ gst_camera_bin_class_init (GstCameraBin2Class * klass)
" (Should be set on NULL state)", " (Should be set on NULL state)",
GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_AUDIO_FILTER,
g_param_spec_object ("audio-filter", "Audio filter",
"The element that will process captured audio buffers when recording"
". (Should be set on NULL state)",
GST_TYPE_ELEMENT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
g_object_class_install_property (object_class, PROP_PREVIEW_FILTER, g_object_class_install_property (object_class, PROP_PREVIEW_FILTER,
g_param_spec_object ("preview-filter", "Preview filter", g_param_spec_object ("preview-filter", "Preview filter",
"The element that will process preview buffers." "The element that will process preview buffers."
@ -780,6 +887,18 @@ gst_image_capture_bin_post_image_done (GstCameraBin2 * camera,
GST_WARNING_OBJECT (camera, "Failed to post image-done message"); GST_WARNING_OBJECT (camera, "Failed to post image-done message");
} }
static void
gst_video_capture_bin_post_video_done (GstCameraBin2 * camera)
{
GstMessage *msg;
msg = gst_message_new_element (GST_OBJECT_CAST (camera),
gst_structure_new ("video-done", NULL));
if (!gst_element_post_message (GST_ELEMENT_CAST (camera), msg))
GST_WARNING_OBJECT (camera, "Failed to post video-done message");
}
static void static void
gst_camera_bin_handle_message (GstBin * bin, GstMessage * message) gst_camera_bin_handle_message (GstBin * bin, GstMessage * message)
{ {
@ -814,6 +933,7 @@ gst_camera_bin_handle_message (GstBin * bin, GstMessage * message)
if (src == GST_CAMERA_BIN2_CAST (bin)->videosink) { if (src == GST_CAMERA_BIN2_CAST (bin)->videosink) {
GST_DEBUG_OBJECT (bin, "EOS from video branch"); GST_DEBUG_OBJECT (bin, "EOS from video branch");
GST_CAMERA_BIN2_PROCESSING_DEC (GST_CAMERA_BIN2_CAST (bin)); GST_CAMERA_BIN2_PROCESSING_DEC (GST_CAMERA_BIN2_CAST (bin));
gst_video_capture_bin_post_video_done (GST_CAMERA_BIN2_CAST (bin));
} }
} }
break; break;
@ -1421,6 +1541,11 @@ gst_camera_bin_create_elements (GstCameraBin2 * camera)
gst_element_link_many (camera->audio_src, camera->audio_volume, gst_element_link_many (camera->audio_src, camera->audio_volume,
camera->audio_capsfilter, NULL); camera->audio_capsfilter, NULL);
} }
if (has_audio) {
gst_camera_bin_check_and_replace_filter (camera, &camera->audio_filter,
camera->user_audio_filter, camera->audio_src, camera->audio_volume,
"src");
}
if ((profile_switched && has_audio) || new_audio_src) { if ((profile_switched && has_audio) || new_audio_src) {
if (GST_PAD_LINK_FAILED (gst_camera_bin_link_encodebin (camera, if (GST_PAD_LINK_FAILED (gst_camera_bin_link_encodebin (camera,
@ -1734,6 +1859,12 @@ gst_camera_bin_set_property (GObject * object, guint prop_id,
g_object_set (camera->src, "preview-filter", camera->preview_filter, g_object_set (camera->src, "preview-filter", camera->preview_filter,
NULL); NULL);
break; break;
case PROP_AUDIO_FILTER:
if (camera->user_audio_filter)
g_object_unref (camera->user_audio_filter);
camera->user_audio_filter = g_value_dup_object (value);
break;
case PROP_VIEWFINDER_SINK: case PROP_VIEWFINDER_SINK:
g_object_set (camera->viewfinderbin, "video-sink", g_object_set (camera->viewfinderbin, "video-sink",
g_value_get_object (value), NULL); g_value_get_object (value), NULL);
@ -1890,6 +2021,10 @@ gst_camera_bin_get_property (GObject * object, guint prop_id,
if (camera->user_viewfinder_filter) if (camera->user_viewfinder_filter)
g_value_set_object (value, camera->user_viewfinder_filter); g_value_set_object (value, camera->user_viewfinder_filter);
break; break;
case PROP_AUDIO_FILTER:
if (camera->user_audio_filter)
g_value_set_object (value, camera->user_audio_filter);
break;
case PROP_PREVIEW_FILTER: case PROP_PREVIEW_FILTER:
if (camera->preview_filter) if (camera->preview_filter)
g_value_set_object (value, camera->preview_filter); g_value_set_object (value, camera->preview_filter);

View file

@ -68,9 +68,11 @@ struct _GstCameraBin2
GstElement *video_filter; GstElement *video_filter;
GstElement *image_filter; GstElement *image_filter;
GstElement *viewfinder_filter; GstElement *viewfinder_filter;
GstElement *audio_filter;
GstElement *user_video_filter; GstElement *user_video_filter;
GstElement *user_image_filter; GstElement *user_image_filter;
GstElement *user_viewfinder_filter; GstElement *user_viewfinder_filter;
GstElement *user_audio_filter;
GstElement *audio_src; GstElement *audio_src;
GstElement *user_audio_src; GstElement *user_audio_src;

View file

@ -140,7 +140,8 @@ gst_mpeg4_params_parse_vo (MPEG4Params * params, GstBitReader * br)
GET_BITS (br, 1, &bits); GET_BITS (br, 1, &bits);
if (bits) { if (bits) {
/* skip vbv_parameters */ /* skip vbv_parameters */
GET_BITS (br, 79, &bits); if (!gst_bit_reader_skip (br, 79))
goto failed;
} }
} }

View file

@ -6371,9 +6371,13 @@ mxf_descriptive_metadata_new (guint8 scheme, guint32 type,
_MXFDescriptiveMetadataScheme *s = NULL; _MXFDescriptiveMetadataScheme *s = NULL;
MXFDescriptiveMetadata *ret = NULL; MXFDescriptiveMetadata *ret = NULL;
g_return_val_if_fail (type != 0, NULL);
g_return_val_if_fail (primer != NULL, NULL); g_return_val_if_fail (primer != NULL, NULL);
if (G_UNLIKELY (type == 0)) {
GST_WARNING ("Type 0 is invalid");
return NULL;
}
for (i = 0; i < _dm_schemes->len; i++) { for (i = 0; i < _dm_schemes->len; i++) {
_MXFDescriptiveMetadataScheme *data = _MXFDescriptiveMetadataScheme *data =
&g_array_index (_dm_schemes, _MXFDescriptiveMetadataScheme, i); &g_array_index (_dm_schemes, _MXFDescriptiveMetadataScheme, i);

View file

@ -209,6 +209,10 @@ gst_mpeg_video_params_parse_sequence (MPEGVParams * params, GstBitReader * br)
params->bitrate *= 400; params->bitrate *= 400;
} }
/* skip 1 + VBV buffer size */
if (!gst_bit_reader_skip (br, 11))
goto failed;
/* constrained_parameters_flag */ /* constrained_parameters_flag */
GET_BITS (br, 1, &bits); GET_BITS (br, 1, &bits);

View file

@ -42,40 +42,35 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
"format = (fourcc) " DEVICE_YUV_FOURCC ", " "format = (fourcc) " DEVICE_YUV_FOURCC ", "
"width = (int) 640, " "width = (int) 640, "
"height = (int) 480, " "height = (int) 480, "
"framerate = (fraction) " G_STRINGIFY (DEVICE_FPS_N) "/" "framerate = [0/1, 100/1], "
G_STRINGIFY (DEVICE_FPS_D) ", "
"pixel-aspect-ratio = (fraction) 1/1" "pixel-aspect-ratio = (fraction) 1/1"
"; " "; "
"video/x-raw-yuv, " "video/x-raw-yuv, "
"format = (fourcc) " DEVICE_YUV_FOURCC ", " "format = (fourcc) " DEVICE_YUV_FOURCC ", "
"width = (int) 160, " "width = (int) 160, "
"height = (int) 120, " "height = (int) 120, "
"framerate = (fraction) " G_STRINGIFY (DEVICE_FPS_N) "/" "framerate = [0/1, 100/1], "
G_STRINGIFY (DEVICE_FPS_D) ", "
"pixel-aspect-ratio = (fraction) 1/1" "pixel-aspect-ratio = (fraction) 1/1"
"; " "; "
"video/x-raw-yuv, " "video/x-raw-yuv, "
"format = (fourcc) " DEVICE_YUV_FOURCC ", " "format = (fourcc) " DEVICE_YUV_FOURCC ", "
"width = (int) 176, " "width = (int) 176, "
"height = (int) 144, " "height = (int) 144, "
"framerate = (fraction) " G_STRINGIFY (DEVICE_FPS_N) "/" "framerate = [0/1, 100/1], "
G_STRINGIFY (DEVICE_FPS_D) ", "
"pixel-aspect-ratio = (fraction) 12/11" "pixel-aspect-ratio = (fraction) 12/11"
"; " "; "
"video/x-raw-yuv, " "video/x-raw-yuv, "
"format = (fourcc) " DEVICE_YUV_FOURCC ", " "format = (fourcc) " DEVICE_YUV_FOURCC ", "
"width = (int) 320, " "width = (int) 320, "
"height = (int) 240, " "height = (int) 240, "
"framerate = (fraction) " G_STRINGIFY (DEVICE_FPS_N) "/" "framerate = [0/1, 100/1], "
G_STRINGIFY (DEVICE_FPS_D) ", "
"pixel-aspect-ratio = (fraction) 1/1" "pixel-aspect-ratio = (fraction) 1/1"
"; " "; "
"video/x-raw-yuv, " "video/x-raw-yuv, "
"format = (fourcc) " DEVICE_YUV_FOURCC ", " "format = (fourcc) " DEVICE_YUV_FOURCC ", "
"width = (int) 352, " "width = (int) 352, "
"height = (int) 288, " "height = (int) 288, "
"framerate = (fraction) " G_STRINGIFY (DEVICE_FPS_N) "/" "framerate = [0/1, 100/1], "
G_STRINGIFY (DEVICE_FPS_D) ", "
"pixel-aspect-ratio = (fraction) 12/11" "pixel-aspect-ratio = (fraction) 12/11"
";" ";"
) )
@ -107,6 +102,7 @@ GST_BOILERPLATE (GstQTKitVideoSrc, gst_qtkit_video_src, GstPushSrc,
BOOL stopRequest; BOOL stopRequest;
gint width, height; gint width, height;
gint fps_n, fps_d;
GstClockTime duration; GstClockTime duration;
guint64 offset; guint64 offset;
} }
@ -123,6 +119,7 @@ GST_BOILERPLATE (GstQTKitVideoSrc, gst_qtkit_video_src, GstPushSrc,
- (BOOL)stop; - (BOOL)stop;
- (BOOL)unlock; - (BOOL)unlock;
- (BOOL)unlockStop; - (BOOL)unlockStop;
- (void)fixate:(GstCaps *)caps;
- (BOOL)query:(GstQuery *)query; - (BOOL)query:(GstQuery *)query;
- (GstStateChangeReturn)changeState:(GstStateChange)transition; - (GstStateChangeReturn)changeState:(GstStateChange)transition;
- (GstFlowReturn)create:(GstBuffer **)buf; - (GstFlowReturn)create:(GstBuffer **)buf;
@ -243,6 +240,7 @@ openFailed:
NSDictionary *outputAttrs; NSDictionary *outputAttrs;
BOOL success; BOOL success;
NSRunLoop *mainRunLoop; NSRunLoop *mainRunLoop;
NSTimeInterval interval;
g_assert (device != nil); g_assert (device != nil);
@ -251,7 +249,12 @@ openFailed:
s = gst_caps_get_structure (caps, 0); s = gst_caps_get_structure (caps, 0);
gst_structure_get_int (s, "width", &width); gst_structure_get_int (s, "width", &width);
gst_structure_get_int (s, "height", &height); gst_structure_get_int (s, "height", &height);
if (!gst_structure_get_fraction (s, "framerate", &fps_n, &fps_d)) {
fps_n = DEVICE_FPS_N;
fps_d = DEVICE_FPS_D;
}
GST_INFO ("got caps %dx%d %d/%d", width, height, fps_n, fps_d);
input = [[QTCaptureDeviceInput alloc] initWithDevice:device]; input = [[QTCaptureDeviceInput alloc] initWithDevice:device];
output = [[QTCaptureDecompressedVideoOutput alloc] init]; output = [[QTCaptureDecompressedVideoOutput alloc] init];
@ -269,6 +272,16 @@ openFailed:
]; ];
[output setPixelBufferAttributes:outputAttrs]; [output setPixelBufferAttributes:outputAttrs];
if (fps_n != 0) {
duration = gst_util_uint64_scale (GST_SECOND, fps_d, fps_n);
gst_util_fraction_to_double (fps_d, fps_n, (gdouble *) &interval);
} else {
duration = GST_CLOCK_TIME_NONE;
interval = 0;
}
[output setMinimumVideoFrameInterval:interval];
session = [[QTCaptureSession alloc] init]; session = [[QTCaptureSession alloc] init];
success = [session addInput:input success = [session addInput:input
error:nil]; error:nil];
@ -299,8 +312,11 @@ openFailed:
queue = [[NSMutableArray alloc] initWithCapacity:FRAME_QUEUE_SIZE]; queue = [[NSMutableArray alloc] initWithCapacity:FRAME_QUEUE_SIZE];
stopRequest = NO; stopRequest = NO;
duration = gst_util_uint64_scale (GST_SECOND, DEVICE_FPS_D, DEVICE_FPS_N);
offset = 0; offset = 0;
width = height = 0;
fps_n = 0;
fps_d = 1;
duration = GST_CLOCK_TIME_NONE;
return YES; return YES;
} }
@ -359,6 +375,18 @@ openFailed:
return YES; return YES;
} }
- (void)fixate:(GstCaps *)caps
{
GstStructure *structure;
gst_caps_truncate (caps);
structure = gst_caps_get_structure (caps, 0);
if (gst_structure_has_field (structure, "framerate")) {
gst_structure_fixate_field_nearest_fraction (structure, "framerate",
DEVICE_FPS_N, DEVICE_FPS_D);
}
}
- (GstStateChangeReturn)changeState:(GstStateChange)transition - (GstStateChangeReturn)changeState:(GstStateChange)transition
{ {
GstStateChangeReturn ret; GstStateChangeReturn ret;
@ -484,6 +512,7 @@ static gboolean gst_qtkit_video_src_unlock (GstBaseSrc * basesrc);
static gboolean gst_qtkit_video_src_unlock_stop (GstBaseSrc * basesrc); static gboolean gst_qtkit_video_src_unlock_stop (GstBaseSrc * basesrc);
static GstFlowReturn gst_qtkit_video_src_create (GstPushSrc * pushsrc, static GstFlowReturn gst_qtkit_video_src_create (GstPushSrc * pushsrc,
GstBuffer ** buf); GstBuffer ** buf);
static void gst_qtkit_video_src_fixate (GstBaseSrc * basesrc, GstCaps * caps);
static void static void
gst_qtkit_video_src_base_init (gpointer gclass) gst_qtkit_video_src_base_init (gpointer gclass)
@ -519,6 +548,7 @@ gst_qtkit_video_src_class_init (GstQTKitVideoSrcClass * klass)
gstbasesrc_class->query = gst_qtkit_video_src_query; gstbasesrc_class->query = gst_qtkit_video_src_query;
gstbasesrc_class->unlock = gst_qtkit_video_src_unlock; gstbasesrc_class->unlock = gst_qtkit_video_src_unlock;
gstbasesrc_class->unlock_stop = gst_qtkit_video_src_unlock_stop; gstbasesrc_class->unlock_stop = gst_qtkit_video_src_unlock_stop;
gstbasesrc_class->fixate = gst_qtkit_video_src_fixate;
gstpushsrc_class->create = gst_qtkit_video_src_create; gstpushsrc_class->create = gst_qtkit_video_src_create;
@ -684,3 +714,11 @@ gst_qtkit_video_src_create (GstPushSrc * pushsrc, GstBuffer ** buf)
return ret; return ret;
} }
static void
gst_qtkit_video_src_fixate (GstBaseSrc * basesrc, GstCaps * caps)
{
OBJC_CALLOUT_BEGIN ();
[GST_QTKIT_VIDEO_SRC_IMPL (basesrc) fixate: caps];
OBJC_CALLOUT_END ();
}

View file

@ -20,6 +20,7 @@ libgstdecklink_la_SOURCES = \
DeckLinkAPIDispatch.cpp DeckLinkAPIDispatch.cpp
noinst_HEADERS = \ noinst_HEADERS = \
gstdecklink.h \
gstdecklinksrc.h \ gstdecklinksrc.h \
gstdecklinksink.h \ gstdecklinksink.h \
capture.h \ capture.h \

View file

@ -1162,10 +1162,12 @@ GST_START_TEST (test_video_custom_filter)
GstElement *vf_filter; GstElement *vf_filter;
GstElement *video_filter; GstElement *video_filter;
GstElement *preview_filter; GstElement *preview_filter;
GstElement *audio_filter;
GstPad *pad; GstPad *pad;
gint vf_probe_counter = 0; gint vf_probe_counter = 0;
gint video_probe_counter = 0; gint video_probe_counter = 0;
gint preview_probe_counter = 0; gint preview_probe_counter = 0;
gint audio_probe_counter = 0;
if (!camera) if (!camera)
return; return;
@ -1173,6 +1175,7 @@ GST_START_TEST (test_video_custom_filter)
vf_filter = gst_element_factory_make ("identity", "vf-filter"); vf_filter = gst_element_factory_make ("identity", "vf-filter");
video_filter = gst_element_factory_make ("identity", "video-filter"); video_filter = gst_element_factory_make ("identity", "video-filter");
preview_filter = gst_element_factory_make ("identity", "preview-filter"); preview_filter = gst_element_factory_make ("identity", "preview-filter");
audio_filter = gst_element_factory_make ("identity", "audio-filter");
pad = gst_element_get_static_pad (vf_filter, "src"); pad = gst_element_get_static_pad (vf_filter, "src");
gst_pad_add_buffer_probe (pad, (GCallback) filter_buffer_count, gst_pad_add_buffer_probe (pad, (GCallback) filter_buffer_count,
@ -1184,6 +1187,11 @@ GST_START_TEST (test_video_custom_filter)
&video_probe_counter); &video_probe_counter);
gst_object_unref (pad); gst_object_unref (pad);
pad = gst_element_get_static_pad (audio_filter, "src");
gst_pad_add_buffer_probe (pad, (GCallback) filter_buffer_count,
&audio_probe_counter);
gst_object_unref (pad);
pad = gst_element_get_static_pad (preview_filter, "src"); pad = gst_element_get_static_pad (preview_filter, "src");
gst_pad_add_buffer_probe (pad, (GCallback) filter_buffer_count, gst_pad_add_buffer_probe (pad, (GCallback) filter_buffer_count,
&preview_probe_counter); &preview_probe_counter);
@ -1193,11 +1201,12 @@ GST_START_TEST (test_video_custom_filter)
g_object_set (camera, "mode", 2, g_object_set (camera, "mode", 2,
"location", make_test_file_name (VIDEO_FILENAME, -1), "location", make_test_file_name (VIDEO_FILENAME, -1),
"viewfinder-filter", vf_filter, "video-filter", video_filter, "viewfinder-filter", vf_filter, "video-filter", video_filter,
"preview-filter", preview_filter, NULL); "preview-filter", preview_filter, "audio-filter", audio_filter, NULL);
gst_object_unref (vf_filter); gst_object_unref (vf_filter);
gst_object_unref (preview_filter); gst_object_unref (preview_filter);
gst_object_unref (video_filter); gst_object_unref (video_filter);
gst_object_unref (audio_filter);
if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) == if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
GST_STATE_CHANGE_FAILURE) { GST_STATE_CHANGE_FAILURE) {
@ -1223,6 +1232,7 @@ GST_START_TEST (test_video_custom_filter)
fail_unless (vf_probe_counter > 0); fail_unless (vf_probe_counter > 0);
fail_unless (video_probe_counter > 0); fail_unless (video_probe_counter > 0);
fail_unless (audio_probe_counter > 0);
fail_unless (preview_probe_counter == 1); fail_unless (preview_probe_counter == 1);
} }

View file

@ -1,7 +1,11 @@
noinst_PROGRAMS = gstmotioncells_dynamic_test noinst_PROGRAMS = gstmotioncells_dynamic_test
gstmotioncells_dynamic_test_SOURCES = gstmotioncells_dynamic_test.c gst_element_print_properties.c gstmotioncells_dynamic_test_SOURCES = \
gstmotioncells_dynamic_test.c \
gst_element_print_properties.c
gstmotioncells_dynamic_test_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) gstmotioncells_dynamic_test_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS)
gstmotioncells_dynamic_test_LDFLAGS = $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) $(GSTPB_BASE_LIBS) gstmotioncells_dynamic_test_LDFLAGS = $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) $(GSTPB_BASE_LIBS)
noinst_HEADERS = gst_element_print_properties.h noinst_HEADERS = \
gstmotioncells_dynamic_test.h \
gst_element_print_properties.h