mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-23 18:21:04 +00:00
Merge branch 'master' into 0.11
This commit is contained in:
commit
52d48bb142
25 changed files with 747 additions and 484 deletions
|
@ -734,7 +734,12 @@ celt_dec_chain_parse_data (GstCeltDec * dec, GstBuffer * buf,
|
|||
}
|
||||
|
||||
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);
|
||||
#endif
|
||||
}
|
||||
|
||||
res = gst_pad_alloc_buffer_and_set_caps (dec->srcpad,
|
||||
|
|
|
@ -145,8 +145,6 @@ static GstFlowReturn gst_dirac_enc_handle_frame (GstBaseVideoEncoder *
|
|||
base_video_encoder, GstVideoFrame * frame);
|
||||
static GstFlowReturn gst_dirac_enc_shape_output (GstBaseVideoEncoder *
|
||||
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,
|
||||
GstBuffer * seq_header);
|
||||
|
||||
|
@ -314,7 +312,6 @@ gst_dirac_enc_class_init (GstDiracEncClass * klass)
|
|||
GST_DEBUG_FUNCPTR (gst_dirac_enc_handle_frame);
|
||||
basevideoencoder_class->shape_output =
|
||||
GST_DEBUG_FUNCPTR (gst_dirac_enc_shape_output);
|
||||
basevideoencoder_class->get_caps = GST_DEBUG_FUNCPTR (gst_dirac_enc_get_caps);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -331,29 +328,10 @@ gst_dirac_enc_set_format (GstBaseVideoEncoder * base_video_encoder,
|
|||
{
|
||||
GstDiracEnc *dirac_enc = GST_DIRAC_ENC (base_video_encoder);
|
||||
GstCaps *caps;
|
||||
GstStructure *structure;
|
||||
gboolean ret;
|
||||
|
||||
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);
|
||||
|
||||
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);
|
||||
|
||||
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
|
||||
|
@ -1112,7 +1101,7 @@ static GstFlowReturn
|
|||
gst_dirac_enc_process (GstDiracEnc * dirac_enc, gboolean end_sequence)
|
||||
{
|
||||
GstBuffer *outbuf;
|
||||
GstFlowReturn ret;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
int parse_code;
|
||||
int state;
|
||||
GstVideoFrame *frame;
|
||||
|
@ -1174,7 +1163,28 @@ gst_dirac_enc_process (GstDiracEnc * dirac_enc, gboolean end_sequence)
|
|||
}
|
||||
|
||||
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);
|
||||
|
||||
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;
|
||||
|
@ -1245,10 +1255,6 @@ static GstFlowReturn
|
|||
gst_dirac_enc_shape_output (GstBaseVideoEncoder * base_video_encoder,
|
||||
GstVideoFrame * frame)
|
||||
{
|
||||
GstDiracEnc *dirac_enc;
|
||||
|
||||
dirac_enc = GST_DIRAC_ENC (base_video_encoder);
|
||||
|
||||
gst_dirac_enc_shape_output_ogg (base_video_encoder, frame);
|
||||
|
||||
return GST_FLOW_ERROR;
|
||||
|
@ -1286,25 +1292,4 @@ gst_dirac_enc_create_codec_data (GstDiracEnc * dirac_enc,
|
|||
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;
|
||||
}
|
||||
|
|
|
@ -117,16 +117,27 @@ create_fingerprint (GstOFA * ofa)
|
|||
GstBuffer *buf;
|
||||
gint rate = GST_AUDIO_FILTER (ofa)->format.rate;
|
||||
gint channels = GST_AUDIO_FILTER (ofa)->format.channels;
|
||||
gint endianness =
|
||||
(GST_AUDIO_FILTER (ofa)->format.
|
||||
bigend) ? OFA_BIG_ENDIAN : OFA_LITTLE_ENDIAN;
|
||||
gint endianness;
|
||||
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");
|
||||
|
||||
buf =
|
||||
gst_adapter_take_buffer (ofa->adapter,
|
||||
gst_adapter_available (ofa->adapter));
|
||||
buf = gst_adapter_take_buffer (ofa->adapter, available);
|
||||
|
||||
ofa->fingerprint = g_strdup (ofa_create_print (GST_BUFFER_DATA (buf),
|
||||
endianness, GST_BUFFER_SIZE (buf) / 2, rate,
|
||||
|
|
|
@ -105,9 +105,6 @@ GST_DEBUG_CATEGORY_STATIC (gst_motion_cells_debug);
|
|||
POINTER = NULL;\
|
||||
}
|
||||
|
||||
int instanceCounter = 0;
|
||||
gboolean element_id_was_max = false;
|
||||
|
||||
/* Filter signals and args */
|
||||
enum
|
||||
{
|
||||
|
@ -396,8 +393,7 @@ gst_motion_cells_init (GstMotioncells * filter, GstMotioncellsClass * gclass)
|
|||
|
||||
filter->datafileidx = 0;
|
||||
g_mutex_lock (filter->propset_mutex);
|
||||
filter->id = instanceCounter;
|
||||
motion_cells_init ();
|
||||
filter->id = motion_cells_init ();
|
||||
g_mutex_unlock (filter->propset_mutex);
|
||||
|
||||
}
|
||||
|
|
|
@ -46,12 +46,13 @@
|
|||
#include <limits.h>
|
||||
#include "motioncells_wrapper.h"
|
||||
|
||||
extern int instanceCounter;
|
||||
extern bool element_id_was_max;
|
||||
static int instanceCounter = 0;
|
||||
static gboolean element_id_was_max = false;
|
||||
|
||||
MotionCells *mc;
|
||||
char p_str[] = "idx failed";
|
||||
|
||||
void
|
||||
int
|
||||
motion_cells_init ()
|
||||
{
|
||||
mc = new MotionCells ();
|
||||
|
@ -67,6 +68,7 @@ motion_cells_init ()
|
|||
instanceCounter = motioncellsfreeids.back ();
|
||||
motioncellsfreeids.pop_back ();
|
||||
}
|
||||
return tmpmc.id;
|
||||
}
|
||||
|
||||
int
|
||||
|
|
|
@ -62,7 +62,7 @@ extern "C"
|
|||
{
|
||||
#endif
|
||||
|
||||
void motion_cells_init ();
|
||||
int motion_cells_init ();
|
||||
int perform_detection_motion_cells (IplImage * p_image, double p_sensitivity,
|
||||
double p_framerate, int p_gridx, int p_gridy,
|
||||
long int p_timestamp_millisec, bool p_isVisible, bool p_useAlpha,
|
||||
|
|
|
@ -60,7 +60,6 @@ struct _GstSchroEnc
|
|||
/* state */
|
||||
SchroEncoder *encoder;
|
||||
SchroVideoFormat *video_format;
|
||||
GstBuffer *seq_header_buffer;
|
||||
|
||||
guint64 last_granulepos;
|
||||
guint64 granule_offset;
|
||||
|
@ -102,8 +101,6 @@ static GstFlowReturn gst_schro_enc_handle_frame (GstBaseVideoEncoder *
|
|||
base_video_encoder, GstVideoFrame * frame);
|
||||
static GstFlowReturn gst_schro_enc_shape_output (GstBaseVideoEncoder *
|
||||
base_video_encoder, GstVideoFrame * frame);
|
||||
static GstCaps *gst_schro_enc_get_caps (GstBaseVideoEncoder *
|
||||
base_video_encoder);
|
||||
|
||||
static GstStaticPadTemplate gst_schro_enc_sink_template =
|
||||
GST_STATIC_PAD_TEMPLATE ("sink",
|
||||
|
@ -219,7 +216,6 @@ gst_schro_enc_class_init (GstSchroEncClass * klass)
|
|||
GST_DEBUG_FUNCPTR (gst_schro_enc_handle_frame);
|
||||
basevideocoder_class->shape_output =
|
||||
GST_DEBUG_FUNCPTR (gst_schro_enc_shape_output);
|
||||
basevideocoder_class->get_caps = GST_DEBUG_FUNCPTR (gst_schro_enc_get_caps);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -241,28 +237,12 @@ static gboolean
|
|||
gst_schro_enc_set_format (GstBaseVideoEncoder * base_video_encoder,
|
||||
GstVideoState * state)
|
||||
{
|
||||
GstCaps *caps;
|
||||
GstStructure *structure;
|
||||
GstSchroEnc *schro_enc = GST_SCHRO_ENC (base_video_encoder);
|
||||
GstCaps *caps;
|
||||
GstBuffer *seq_header_buffer;
|
||||
gboolean ret;
|
||||
|
||||
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,
|
||||
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_start (schro_enc->encoder);
|
||||
|
||||
schro_enc->seq_header_buffer =
|
||||
seq_header_buffer =
|
||||
gst_schro_wrap_schro_buffer (schro_encoder_encode_sequence_header
|
||||
(schro_enc->encoder));
|
||||
|
||||
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
|
||||
|
@ -404,10 +429,6 @@ gst_schro_enc_stop (GstBaseVideoEncoder * base_video_encoder)
|
|||
schro_encoder_free (schro_enc->encoder);
|
||||
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) {
|
||||
g_free (schro_enc->video_format);
|
||||
schro_enc->video_format = NULL;
|
||||
|
@ -458,91 +479,6 @@ gst_schro_enc_handle_frame (GstBaseVideoEncoder * base_video_encoder,
|
|||
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
|
||||
gst_schro_enc_shape_output (GstBaseVideoEncoder * base_video_encoder,
|
||||
GstVideoFrame * frame)
|
||||
|
|
|
@ -220,7 +220,6 @@ static GstFlowReturn gst_vp8_enc_shape_output (GstBaseVideoEncoder * encoder,
|
|||
GstVideoFrame * frame);
|
||||
static gboolean gst_vp8_enc_sink_event (GstBaseVideoEncoder *
|
||||
base_video_encoder, GstEvent * event);
|
||||
static GstCaps *gst_vp8_enc_get_caps (GstBaseVideoEncoder * base_video_encoder);
|
||||
|
||||
static GstStaticPadTemplate gst_vp8_enc_sink_template =
|
||||
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->shape_output = gst_vp8_enc_shape_output;
|
||||
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_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_image_t *image;
|
||||
guint8 *data = NULL;
|
||||
GstCaps *caps;
|
||||
gboolean ret;
|
||||
|
||||
encoder = GST_VP8_ENC (base_video_encoder);
|
||||
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,
|
||||
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",
|
||||
"width", G_TYPE_INT, state->width,
|
||||
|
@ -870,56 +853,66 @@ gst_vp8_enc_get_caps (GstBaseVideoEncoder * base_video_encoder)
|
|||
state->fps_d,
|
||||
"pixel-aspect-ratio", GST_TYPE_FRACTION, state->par_n,
|
||||
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);
|
||||
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);
|
||||
|
||||
/* put buffers in a fixed list */
|
||||
g_value_init (&array, GST_TYPE_ARRAY);
|
||||
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);
|
||||
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);
|
||||
g_value_unset (&array);
|
||||
ret = gst_pad_set_caps (GST_BASE_VIDEO_CODEC_SRC_PAD (encoder), caps);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
return caps;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
|
|
|
@ -1917,11 +1917,9 @@ gst_base_video_decoder_alloc_src_buffer (GstBaseVideoDecoder *
|
|||
{
|
||||
GstBuffer *buffer;
|
||||
GstFlowReturn flow_ret;
|
||||
int num_bytes;
|
||||
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_PAD_CAPS (GST_BASE_VIDEO_CODEC_SRC_PAD (base_video_decoder)));
|
||||
flow_ret =
|
||||
|
|
|
@ -91,7 +91,7 @@
|
|||
* <itemizedlist>
|
||||
* <listitem><para>Provide pad templates</para></listitem>
|
||||
* <listitem><para>
|
||||
* Provide source pad caps in @get_caps.
|
||||
* Provide source pad caps before pushing the first buffer
|
||||
* </para></listitem>
|
||||
* <listitem><para>
|
||||
* 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,
|
||||
GstCaps * caps);
|
||||
static GstCaps *gst_base_video_encoder_sink_getcaps (GstPad * pad);
|
||||
static gboolean gst_base_video_encoder_src_event (GstPad * pad,
|
||||
GstEvent * event);
|
||||
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->force_keyframe = FALSE;
|
||||
|
||||
base_video_encoder->set_output_caps = FALSE;
|
||||
base_video_encoder->drained = TRUE;
|
||||
base_video_encoder->min_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_pad_set_setcaps_function (pad,
|
||||
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);
|
||||
|
||||
|
@ -359,6 +361,74 @@ exit:
|
|||
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
|
||||
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,
|
||||
"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 */
|
||||
for (l = base_video_encoder->base_video_codec.frames; l; l = l->next) {
|
||||
GstVideoFrame *tmp = l->data;
|
||||
|
|
|
@ -89,7 +89,6 @@ struct _GstBaseVideoEncoder
|
|||
/*< private >*/
|
||||
/* FIXME move to real private part ?
|
||||
* (and introduce a context ?) */
|
||||
gboolean set_output_caps;
|
||||
gboolean drained;
|
||||
|
||||
gint64 min_latency;
|
||||
|
@ -131,8 +130,6 @@ struct _GstBaseVideoEncoder
|
|||
* Event handler on the sink pad. This function should return
|
||||
* TRUE if the event was handled and should be discarded
|
||||
* (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
|
||||
* needed. At minimum @handle_frame needs to be overridden, and @set_format
|
||||
|
@ -164,8 +161,6 @@ struct _GstBaseVideoEncoderClass
|
|||
gboolean (*event) (GstBaseVideoEncoder *coder,
|
||||
GstEvent *event);
|
||||
|
||||
GstCaps * (*get_caps) (GstBaseVideoEncoder *coder);
|
||||
|
||||
/*< private >*/
|
||||
/* FIXME before moving to base */
|
||||
gpointer _gst_reserved[GST_PADDING_LARGE];
|
||||
|
|
|
@ -130,6 +130,7 @@ gst_aiff_mux_change_state (GstElement * element, GstStateChange transition)
|
|||
aiffmux->length = 0;
|
||||
aiffmux->rate = 0.0;
|
||||
aiffmux->sent_header = FALSE;
|
||||
aiffmux->overflow = FALSE;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
@ -160,7 +161,7 @@ gst_aiff_mux_class_init (GstAiffMuxClass * klass)
|
|||
(AIFF_FORM_HEADER_LEN + AIFF_COMM_HEADER_LEN + AIFF_SSND_HEADER_LEN)
|
||||
|
||||
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)
|
||||
{
|
||||
/* ckID == 'FORM' */
|
||||
|
@ -228,7 +229,7 @@ gst_aiff_mux_write_ext (GstByteWriter * writer, double d)
|
|||
*/
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
/* numSampleFrames value will be overwritten when known */
|
||||
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_aiff_mux_write_ext (writer, aiffmux->rate);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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
|
||||
gst_aiff_mux_push_header (GstAiffMux * aiffmux, guint audio_data_size)
|
||||
gst_aiff_mux_push_header (GstAiffMux * aiffmux, guint32 audio_data_size)
|
||||
{
|
||||
GstFlowReturn ret;
|
||||
GstBuffer *outbuf;
|
||||
|
@ -296,12 +297,16 @@ gst_aiff_mux_chain (GstPad * pad, GstBuffer * buf)
|
|||
{
|
||||
GstAiffMux *aiffmux = GST_AIFF_MUX (GST_PAD_PARENT (pad));
|
||||
GstFlowReturn flow = GST_FLOW_OK;
|
||||
guint64 cur_size;
|
||||
|
||||
if (!aiffmux->channels) {
|
||||
gst_buffer_unref (buf);
|
||||
return GST_FLOW_NOT_NEGOTIATED;
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (aiffmux->overflow))
|
||||
goto overflow;
|
||||
|
||||
if (!aiffmux->sent_header) {
|
||||
/* use bogus size initially, we'll write the real
|
||||
* 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;
|
||||
}
|
||||
|
||||
/* 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_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);
|
||||
|
||||
return flow;
|
||||
|
||||
overflow:
|
||||
{
|
||||
GST_WARNING_OBJECT (aiffmux, "output file too large, dropping buffer");
|
||||
gst_buffer_unref (buf);
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
@ -81,6 +81,7 @@ struct _GstAiffMux
|
|||
gdouble rate;
|
||||
|
||||
gboolean sent_header;
|
||||
gboolean overflow;
|
||||
};
|
||||
|
||||
struct _GstAiffMuxClass
|
||||
|
|
|
@ -20,10 +20,13 @@
|
|||
/**
|
||||
* SECTION:gstbaseaudiovisualizer
|
||||
*
|
||||
* A basclass for scopes. It takes care of re-fitting the audio-rate to
|
||||
* video-rate. It also provides several background shading effects. These
|
||||
* effects are applied to a previous picture before the render() implementation
|
||||
* can draw a new frame.
|
||||
* A basclass for scopes (visualizers). It takes care of re-fitting the
|
||||
* audio-rate to video-rate and handles renegotiation (downstream video size
|
||||
* changes).
|
||||
*
|
||||
* 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
|
||||
|
@ -85,9 +88,19 @@ gst_base_audio_visualizer_shader_get_type (void)
|
|||
"fade-and-move-up"},
|
||||
{GST_BASE_AUDIO_VISUALIZER_SHADER_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,
|
||||
"Fade and move horizontaly out",
|
||||
"fade-and-move-horiz-out"},
|
||||
"Fade and move horizontally 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},
|
||||
};
|
||||
|
||||
|
@ -98,6 +111,59 @@ gst_base_audio_visualizer_shader_get_type (void)
|
|||
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
|
||||
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 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;) {
|
||||
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;
|
||||
SHADE1 (d, s, i, r, g, b);
|
||||
}
|
||||
#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
|
||||
|
@ -140,47 +187,9 @@ shader_fade_and_move_up (GstBaseAudioVisualizer * scope, const guint8 * s,
|
|||
guint g = (scope->shade_amount >> 8) & 0xff;
|
||||
guint b = (scope->shade_amount >> 0) & 0xff;
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
for (j = 0, i = bpl; i < bpf;) {
|
||||
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++;
|
||||
SHADE2 (d, s, j, i, r, g, b);
|
||||
}
|
||||
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
|
||||
|
@ -193,47 +202,49 @@ shader_fade_and_move_down (GstBaseAudioVisualizer * scope, const guint8 * s,
|
|||
guint g = (scope->shade_amount >> 8) & 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;) {
|
||||
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++;
|
||||
SHADE2 (d, s, j, i, r, g, b);
|
||||
}
|
||||
#else
|
||||
for (i = 0; i < 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++;
|
||||
}
|
||||
|
||||
static void
|
||||
shader_fade_and_move_left (GstBaseAudioVisualizer * scope,
|
||||
const guint8 * s, guint8 * d)
|
||||
{
|
||||
guint i, j, k, bpf = scope->bpf;
|
||||
guint w = scope->width;
|
||||
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++;
|
||||
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++;
|
||||
}
|
||||
|
||||
static void
|
||||
shader_fade_and_move_right (GstBaseAudioVisualizer * scope,
|
||||
const guint8 * s, guint8 * d)
|
||||
{
|
||||
guint i, j, k, bpf = scope->bpf;
|
||||
guint w = scope->width;
|
||||
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
|
||||
|
@ -246,91 +257,91 @@ shader_fade_and_move_horiz_out (GstBaseAudioVisualizer * scope,
|
|||
guint g = (scope->shade_amount >> 8) & 0xff;
|
||||
guint b = (scope->shade_amount >> 0) & 0xff;
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
/* middle up */
|
||||
/* move upper half up */
|
||||
for (j = 0, i = bpl; i < bpf;) {
|
||||
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++;
|
||||
}
|
||||
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;
|
||||
SHADE2 (d, s, j, i, r, g, b);
|
||||
}
|
||||
/* move lower half down */
|
||||
for (j = bpf + bpl, i = bpf; j < bpf + bpf;) {
|
||||
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++;
|
||||
SHADE2 (d, s, j, i, r, g, b);
|
||||
}
|
||||
#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
|
||||
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:
|
||||
scope->shader = shader_fade_and_move_down;
|
||||
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:
|
||||
scope->shader = shader_fade_and_move_horiz_out;
|
||||
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:
|
||||
GST_ERROR ("invalid shader function");
|
||||
scope->shader = NULL;
|
||||
|
@ -463,6 +489,7 @@ gst_base_audio_visualizer_init (GstBaseAudioVisualizer * scope,
|
|||
|
||||
scope->next_ts = GST_CLOCK_TIME_NONE;
|
||||
|
||||
scope->config_lock = g_mutex_new ();
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -521,6 +548,10 @@ gst_base_audio_visualizer_dispose (GObject * object)
|
|||
g_free (scope->pixelbuf);
|
||||
scope->pixelbuf = NULL;
|
||||
}
|
||||
if (scope->config_lock) {
|
||||
g_mutex_free (scope->config_lock);
|
||||
scope->config_lock = NULL;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
g_mutex_lock (scope->config_lock);
|
||||
|
||||
scope->width = w;
|
||||
scope->height = h;
|
||||
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);
|
||||
GST_DEBUG_OBJECT (scope, "blocks: spf %u, req_spf %u",
|
||||
scope->spf, scope->req_spf);
|
||||
|
||||
g_mutex_unlock (scope->config_lock);
|
||||
|
||||
done:
|
||||
gst_object_unref (scope);
|
||||
return res;
|
||||
|
@ -691,6 +727,7 @@ gst_base_audio_visualizer_chain (GstPad * pad, GstBuffer * buffer)
|
|||
GstBaseAudioVisualizerClass *klass;
|
||||
GstBuffer *inbuf;
|
||||
guint avail, sbpf;
|
||||
guint8 *adata;
|
||||
gboolean (*render) (GstBaseAudioVisualizer * scope, GstBuffer * audio,
|
||||
GstBuffer * video);
|
||||
|
||||
|
@ -718,6 +755,8 @@ gst_base_audio_visualizer_chain (GstPad * pad, GstBuffer * buffer)
|
|||
|
||||
gst_adapter_push (scope->adapter, buffer);
|
||||
|
||||
g_mutex_lock (scope->config_lock);
|
||||
|
||||
/* this is what we want */
|
||||
sbpf = scope->req_spf * scope->channels * sizeof (gint16);
|
||||
|
||||
|
@ -731,9 +770,13 @@ gst_base_audio_visualizer_chain (GstPad * pad, GstBuffer * buffer)
|
|||
while (avail >= sbpf) {
|
||||
GstBuffer *outbuf;
|
||||
|
||||
g_mutex_unlock (scope->config_lock);
|
||||
ret = gst_pad_alloc_buffer_and_set_caps (scope->srcpad,
|
||||
GST_BUFFER_OFFSET_NONE,
|
||||
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. */
|
||||
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);
|
||||
}
|
||||
|
||||
GST_BUFFER_DATA (inbuf) =
|
||||
(guint8 *) gst_adapter_peek (scope->adapter, sbpf);
|
||||
/* this can fail as the data size we need could have changed */
|
||||
if (!(adata = (guint8 *) gst_adapter_peek (scope->adapter, sbpf)))
|
||||
break;
|
||||
|
||||
GST_BUFFER_DATA (inbuf) = adata;
|
||||
GST_BUFFER_SIZE (inbuf) = sbpf;
|
||||
|
||||
/* 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);
|
||||
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);
|
||||
/* we want to take less or more, depending on spf : req_spf */
|
||||
if (avail - sbpf >= sbpf) {
|
||||
|
@ -787,6 +837,8 @@ gst_base_audio_visualizer_chain (GstPad * pad, GstBuffer * buffer)
|
|||
scope->next_ts += scope->frame_duration;
|
||||
}
|
||||
|
||||
g_mutex_unlock (scope->config_lock);
|
||||
|
||||
gst_object_unref (scope);
|
||||
|
||||
return ret;
|
||||
|
|
|
@ -45,7 +45,12 @@ typedef void (*GstBaseAudioVisualizerShaderFunc)(GstBaseAudioVisualizer *scope,
|
|||
* @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_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.
|
||||
*/
|
||||
|
@ -54,7 +59,12 @@ typedef enum {
|
|||
GST_BASE_AUDIO_VISUALIZER_SHADER_FADE,
|
||||
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_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;
|
||||
|
||||
struct _GstBaseAudioVisualizer
|
||||
|
@ -89,6 +99,9 @@ struct _GstBaseAudioVisualizer
|
|||
/* audio state */
|
||||
gint sample_rate;
|
||||
gint rate;
|
||||
|
||||
/* configuration mutex */
|
||||
GMutex *config_lock;
|
||||
};
|
||||
|
||||
struct _GstBaseAudioVisualizerClass
|
||||
|
|
|
@ -165,7 +165,8 @@ gst_spectra_scope_render (GstBaseAudioVisualizer * bscope, GstBuffer * audio,
|
|||
{
|
||||
GstSpectraScope *scope = GST_SPECTRA_SCOPE (bscope);
|
||||
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;
|
||||
guint x, y, off;
|
||||
guint l, h = bscope->height - 1;
|
||||
|
@ -190,6 +191,7 @@ gst_spectra_scope_render (GstBaseAudioVisualizer * bscope, GstBuffer * audio,
|
|||
/* run fft */
|
||||
gst_fft_s16_window (scope->fft_ctx, adata, GST_FFT_WINDOW_HAMMING);
|
||||
gst_fft_s16_fft (scope->fft_ctx, adata, fdata);
|
||||
g_free (adata);
|
||||
|
||||
/* draw lines */
|
||||
for (x = 0; x < bscope->width; x++) {
|
||||
|
|
|
@ -19,19 +19,115 @@
|
|||
/**
|
||||
* SECTION:element-camerabin2
|
||||
*
|
||||
* GstCameraBin22 is a high-level camera object that encapsulates the gstreamer
|
||||
* internals and provides a task based API for the application.
|
||||
* CameraBin2 is a high-level camera object that encapsulates gstreamer
|
||||
* elements, providing an API for controlling a digital camera.
|
||||
*
|
||||
* <note>
|
||||
* Note that camerabin2 is still UNSTABLE, EXPERIMENTAL and under heavy
|
||||
* Note that camerabin2 is still UNSTABLE, EXPERIMENTAL and under
|
||||
* development.
|
||||
* </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>
|
||||
* <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
|
||||
* ]|
|
||||
* </para>
|
||||
* </refsect2>
|
||||
|
||||
*/
|
||||
|
@ -75,7 +171,7 @@
|
|||
gint bef = g_atomic_int_exchange_and_add (&c->processing_counter, 1); \
|
||||
if (bef == 0) \
|
||||
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); \
|
||||
}
|
||||
|
||||
|
@ -125,7 +221,8 @@ enum
|
|||
PROP_MAX_ZOOM,
|
||||
PROP_IMAGE_ENCODING_PROFILE,
|
||||
PROP_IDLE,
|
||||
PROP_FLAGS
|
||||
PROP_FLAGS,
|
||||
PROP_AUDIO_FILTER
|
||||
};
|
||||
|
||||
enum
|
||||
|
@ -449,9 +546,13 @@ gst_camera_bin_dispose (GObject * object)
|
|||
gst_object_unref (camerabin->image_filter);
|
||||
if (camerabin->viewfinder_filter)
|
||||
gst_object_unref (camerabin->viewfinder_filter);
|
||||
if (camerabin->audio_filter)
|
||||
gst_object_unref (camerabin->audio_filter);
|
||||
|
||||
if (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)
|
||||
gst_object_unref (camerabin->user_image_filter);
|
||||
if (camerabin->user_viewfinder_filter)
|
||||
|
@ -626,6 +727,12 @@ gst_camera_bin_class_init (GstCameraBin2Class * klass)
|
|||
" (Should be set on NULL state)",
|
||||
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_param_spec_object ("preview-filter", "Preview filter",
|
||||
"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");
|
||||
}
|
||||
|
||||
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
|
||||
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) {
|
||||
GST_DEBUG_OBJECT (bin, "EOS from video branch");
|
||||
GST_CAMERA_BIN2_PROCESSING_DEC (GST_CAMERA_BIN2_CAST (bin));
|
||||
gst_video_capture_bin_post_video_done (GST_CAMERA_BIN2_CAST (bin));
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -1421,6 +1541,11 @@ gst_camera_bin_create_elements (GstCameraBin2 * camera)
|
|||
gst_element_link_many (camera->audio_src, camera->audio_volume,
|
||||
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 (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,
|
||||
NULL);
|
||||
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:
|
||||
g_object_set (camera->viewfinderbin, "video-sink",
|
||||
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)
|
||||
g_value_set_object (value, camera->user_viewfinder_filter);
|
||||
break;
|
||||
case PROP_AUDIO_FILTER:
|
||||
if (camera->user_audio_filter)
|
||||
g_value_set_object (value, camera->user_audio_filter);
|
||||
break;
|
||||
case PROP_PREVIEW_FILTER:
|
||||
if (camera->preview_filter)
|
||||
g_value_set_object (value, camera->preview_filter);
|
||||
|
|
|
@ -68,9 +68,11 @@ struct _GstCameraBin2
|
|||
GstElement *video_filter;
|
||||
GstElement *image_filter;
|
||||
GstElement *viewfinder_filter;
|
||||
GstElement *audio_filter;
|
||||
GstElement *user_video_filter;
|
||||
GstElement *user_image_filter;
|
||||
GstElement *user_viewfinder_filter;
|
||||
GstElement *user_audio_filter;
|
||||
|
||||
GstElement *audio_src;
|
||||
GstElement *user_audio_src;
|
||||
|
|
|
@ -140,7 +140,8 @@ gst_mpeg4_params_parse_vo (MPEG4Params * params, GstBitReader * br)
|
|||
GET_BITS (br, 1, &bits);
|
||||
if (bits) {
|
||||
/* skip vbv_parameters */
|
||||
GET_BITS (br, 79, &bits);
|
||||
if (!gst_bit_reader_skip (br, 79))
|
||||
goto failed;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -6371,9 +6371,13 @@ mxf_descriptive_metadata_new (guint8 scheme, guint32 type,
|
|||
_MXFDescriptiveMetadataScheme *s = NULL;
|
||||
MXFDescriptiveMetadata *ret = NULL;
|
||||
|
||||
g_return_val_if_fail (type != 0, 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++) {
|
||||
_MXFDescriptiveMetadataScheme *data =
|
||||
&g_array_index (_dm_schemes, _MXFDescriptiveMetadataScheme, i);
|
||||
|
|
|
@ -209,6 +209,10 @@ gst_mpeg_video_params_parse_sequence (MPEGVParams * params, GstBitReader * br)
|
|||
params->bitrate *= 400;
|
||||
}
|
||||
|
||||
/* skip 1 + VBV buffer size */
|
||||
if (!gst_bit_reader_skip (br, 11))
|
||||
goto failed;
|
||||
|
||||
/* constrained_parameters_flag */
|
||||
GET_BITS (br, 1, &bits);
|
||||
|
||||
|
|
|
@ -42,40 +42,35 @@ static GstStaticPadTemplate src_template = GST_STATIC_PAD_TEMPLATE ("src",
|
|||
"format = (fourcc) " DEVICE_YUV_FOURCC ", "
|
||||
"width = (int) 640, "
|
||||
"height = (int) 480, "
|
||||
"framerate = (fraction) " G_STRINGIFY (DEVICE_FPS_N) "/"
|
||||
G_STRINGIFY (DEVICE_FPS_D) ", "
|
||||
"framerate = [0/1, 100/1], "
|
||||
"pixel-aspect-ratio = (fraction) 1/1"
|
||||
"; "
|
||||
"video/x-raw-yuv, "
|
||||
"format = (fourcc) " DEVICE_YUV_FOURCC ", "
|
||||
"width = (int) 160, "
|
||||
"height = (int) 120, "
|
||||
"framerate = (fraction) " G_STRINGIFY (DEVICE_FPS_N) "/"
|
||||
G_STRINGIFY (DEVICE_FPS_D) ", "
|
||||
"framerate = [0/1, 100/1], "
|
||||
"pixel-aspect-ratio = (fraction) 1/1"
|
||||
"; "
|
||||
"video/x-raw-yuv, "
|
||||
"format = (fourcc) " DEVICE_YUV_FOURCC ", "
|
||||
"width = (int) 176, "
|
||||
"height = (int) 144, "
|
||||
"framerate = (fraction) " G_STRINGIFY (DEVICE_FPS_N) "/"
|
||||
G_STRINGIFY (DEVICE_FPS_D) ", "
|
||||
"framerate = [0/1, 100/1], "
|
||||
"pixel-aspect-ratio = (fraction) 12/11"
|
||||
"; "
|
||||
"video/x-raw-yuv, "
|
||||
"format = (fourcc) " DEVICE_YUV_FOURCC ", "
|
||||
"width = (int) 320, "
|
||||
"height = (int) 240, "
|
||||
"framerate = (fraction) " G_STRINGIFY (DEVICE_FPS_N) "/"
|
||||
G_STRINGIFY (DEVICE_FPS_D) ", "
|
||||
"framerate = [0/1, 100/1], "
|
||||
"pixel-aspect-ratio = (fraction) 1/1"
|
||||
"; "
|
||||
"video/x-raw-yuv, "
|
||||
"format = (fourcc) " DEVICE_YUV_FOURCC ", "
|
||||
"width = (int) 352, "
|
||||
"height = (int) 288, "
|
||||
"framerate = (fraction) " G_STRINGIFY (DEVICE_FPS_N) "/"
|
||||
G_STRINGIFY (DEVICE_FPS_D) ", "
|
||||
"framerate = [0/1, 100/1], "
|
||||
"pixel-aspect-ratio = (fraction) 12/11"
|
||||
";"
|
||||
)
|
||||
|
@ -107,6 +102,7 @@ GST_BOILERPLATE (GstQTKitVideoSrc, gst_qtkit_video_src, GstPushSrc,
|
|||
BOOL stopRequest;
|
||||
|
||||
gint width, height;
|
||||
gint fps_n, fps_d;
|
||||
GstClockTime duration;
|
||||
guint64 offset;
|
||||
}
|
||||
|
@ -123,6 +119,7 @@ GST_BOILERPLATE (GstQTKitVideoSrc, gst_qtkit_video_src, GstPushSrc,
|
|||
- (BOOL)stop;
|
||||
- (BOOL)unlock;
|
||||
- (BOOL)unlockStop;
|
||||
- (void)fixate:(GstCaps *)caps;
|
||||
- (BOOL)query:(GstQuery *)query;
|
||||
- (GstStateChangeReturn)changeState:(GstStateChange)transition;
|
||||
- (GstFlowReturn)create:(GstBuffer **)buf;
|
||||
|
@ -243,6 +240,7 @@ openFailed:
|
|||
NSDictionary *outputAttrs;
|
||||
BOOL success;
|
||||
NSRunLoop *mainRunLoop;
|
||||
NSTimeInterval interval;
|
||||
|
||||
g_assert (device != nil);
|
||||
|
||||
|
@ -251,7 +249,12 @@ openFailed:
|
|||
s = gst_caps_get_structure (caps, 0);
|
||||
gst_structure_get_int (s, "width", &width);
|
||||
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];
|
||||
|
||||
output = [[QTCaptureDecompressedVideoOutput alloc] init];
|
||||
|
@ -269,6 +272,16 @@ openFailed:
|
|||
];
|
||||
[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];
|
||||
success = [session addInput:input
|
||||
error:nil];
|
||||
|
@ -299,8 +312,11 @@ openFailed:
|
|||
queue = [[NSMutableArray alloc] initWithCapacity:FRAME_QUEUE_SIZE];
|
||||
stopRequest = NO;
|
||||
|
||||
duration = gst_util_uint64_scale (GST_SECOND, DEVICE_FPS_D, DEVICE_FPS_N);
|
||||
offset = 0;
|
||||
width = height = 0;
|
||||
fps_n = 0;
|
||||
fps_d = 1;
|
||||
duration = GST_CLOCK_TIME_NONE;
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
@ -359,6 +375,18 @@ openFailed:
|
|||
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 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 GstFlowReturn gst_qtkit_video_src_create (GstPushSrc * pushsrc,
|
||||
GstBuffer ** buf);
|
||||
static void gst_qtkit_video_src_fixate (GstBaseSrc * basesrc, GstCaps * caps);
|
||||
|
||||
static void
|
||||
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->unlock = gst_qtkit_video_src_unlock;
|
||||
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;
|
||||
|
||||
|
@ -684,3 +714,11 @@ gst_qtkit_video_src_create (GstPushSrc * pushsrc, GstBuffer ** buf)
|
|||
|
||||
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 ();
|
||||
}
|
||||
|
|
|
@ -20,6 +20,7 @@ libgstdecklink_la_SOURCES = \
|
|||
DeckLinkAPIDispatch.cpp
|
||||
|
||||
noinst_HEADERS = \
|
||||
gstdecklink.h \
|
||||
gstdecklinksrc.h \
|
||||
gstdecklinksink.h \
|
||||
capture.h \
|
||||
|
|
|
@ -1162,10 +1162,12 @@ GST_START_TEST (test_video_custom_filter)
|
|||
GstElement *vf_filter;
|
||||
GstElement *video_filter;
|
||||
GstElement *preview_filter;
|
||||
GstElement *audio_filter;
|
||||
GstPad *pad;
|
||||
gint vf_probe_counter = 0;
|
||||
gint video_probe_counter = 0;
|
||||
gint preview_probe_counter = 0;
|
||||
gint audio_probe_counter = 0;
|
||||
|
||||
if (!camera)
|
||||
return;
|
||||
|
@ -1173,6 +1175,7 @@ GST_START_TEST (test_video_custom_filter)
|
|||
vf_filter = gst_element_factory_make ("identity", "vf-filter");
|
||||
video_filter = gst_element_factory_make ("identity", "video-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");
|
||||
gst_pad_add_buffer_probe (pad, (GCallback) filter_buffer_count,
|
||||
|
@ -1184,6 +1187,11 @@ GST_START_TEST (test_video_custom_filter)
|
|||
&video_probe_counter);
|
||||
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");
|
||||
gst_pad_add_buffer_probe (pad, (GCallback) filter_buffer_count,
|
||||
&preview_probe_counter);
|
||||
|
@ -1193,11 +1201,12 @@ GST_START_TEST (test_video_custom_filter)
|
|||
g_object_set (camera, "mode", 2,
|
||||
"location", make_test_file_name (VIDEO_FILENAME, -1),
|
||||
"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 (preview_filter);
|
||||
gst_object_unref (video_filter);
|
||||
gst_object_unref (audio_filter);
|
||||
|
||||
if (gst_element_set_state (GST_ELEMENT (camera), GST_STATE_PLAYING) ==
|
||||
GST_STATE_CHANGE_FAILURE) {
|
||||
|
@ -1223,6 +1232,7 @@ GST_START_TEST (test_video_custom_filter)
|
|||
|
||||
fail_unless (vf_probe_counter > 0);
|
||||
fail_unless (video_probe_counter > 0);
|
||||
fail_unless (audio_probe_counter > 0);
|
||||
fail_unless (preview_probe_counter == 1);
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,11 @@
|
|||
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_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
|
||||
|
|
Loading…
Reference in a new issue