Merge branch 'master' into 0.11
authorWim Taymans <wim.taymans@collabora.co.uk>
Wed, 17 Aug 2011 17:01:39 +0000 (19:01 +0200)
committerWim Taymans <wim.taymans@collabora.co.uk>
Wed, 17 Aug 2011 17:01:39 +0000 (19:01 +0200)
25 files changed:
ext/celt/gstceltdec.c
ext/dirac/gstdiracenc.cc
ext/ofa/gstofa.c
ext/opencv/gstmotioncells.c
ext/opencv/motioncells_wrapper.cpp
ext/opencv/motioncells_wrapper.h
ext/schroedinger/gstschroenc.c
ext/vp8/gstvp8enc.c
gst-libs/gst/video/gstbasevideodecoder.c
gst-libs/gst/video/gstbasevideoencoder.c
gst-libs/gst/video/gstbasevideoencoder.h
gst/aiff/aiffmux.c
gst/aiff/aiffmux.h
gst/audiovisualizers/gstbaseaudiovisualizer.c
gst/audiovisualizers/gstbaseaudiovisualizer.h
gst/audiovisualizers/gstspectrascope.c
gst/camerabin2/gstcamerabin2.c
gst/camerabin2/gstcamerabin2.h
gst/mpeg4videoparse/mpeg4parse.c
gst/mxf/mxfmetadata.c
gst/videoparsers/mpegvideoparse.c
sys/applemedia/qtkitvideosrc.m
sys/decklink/Makefile.am
tests/check/elements/camerabin2.c
tests/examples/opencv/Makefile.am

index e27c6a52c843c50554d54965279e7b51b8abbd0a..f80e5cdb18beadaa071485e7dfe32364f88a31cf 100644 (file)
@@ -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,
index 118a315279fb687f0df345df458e93ba56e3f96b..eb19d780718d9fe9b85192854c69757d12d901e8 100644 (file)
@@ -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;
-}
index d1be48635e14ba524cd9fe7533dc6e0c84a3dc78..a18d7e352e7e32e27dbdb2993843b21dc3d38841 100644 (file)
@@ -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,
index a349bcac1d562af28df7565624b636053c5ddafb..71b41c350a744035a740a023e440fc77951ae85d 100644 (file)
@@ -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);
 
 }
index b768f9ece98727af8ed1ade90c7f03d55b6580aa..d50968677415dd7d72307ae5da1a9b1425bcb4c8 100644 (file)
 #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
index 0feaafa8bdc5b08ac05bacd3f76d9f65cc3778d7..470bcfbe42478922446c89bf5d7636e72f1b9c65 100644 (file)
@@ -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,
index ffb4bdb8d73f81fd84d7e3599b3dfc5e8f026e58..beda4eac9626d1c102be136e4d35d2e03bbf16ab 100644 (file)
@@ -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)
index 26f79fadc6781041419922eb3a7e6a5153faf35b..78325265adc90e2d67bfd61cb6cb866d00cb9cd7 100644 (file)
@@ -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);
-
-  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);
-
+  {
+    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);
+
+    /* 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
index 0278abc83e1189a79ea659b55bfb0f53772b698e..5392d44866e4831b40d41a83198e7f5f52bff499 100644 (file)
@@ -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 =
index e4efe6d39f1467967a6245fdd1e8434a1dd06af0..88d8c72dc830cae523a2d229ee2ec34530899685 100644 (file)
@@ -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;
index e1dd03be13fc652cc2e9b6150051fc0921d84cae..c712fe86e50b4d5630338144ea2d3e61a6f429c8 100644 (file)
@@ -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];
index 39770cf2e38e9751b927e2db2586d4ec5dd00ff5..a2d99f587cfcdd7f8798127233b1c7d6841124e0 100644 (file)
@@ -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
index 73c1d89d3aa638db52f9022601d3a88300bf0e9a..9c0954f58968cb54f5996b6d0c898615c633213a 100644 (file)
@@ -81,6 +81,7 @@ struct _GstAiffMux
   gdouble rate;
 
   gboolean sent_header;
+  gboolean overflow;
 };
 
 struct _GstAiffMuxClass
index 52fe5acd425eb3fd098fafdb23a8c41842e58950..6d42b7dc58dab8cf2c44193bf4a3cdfc9cc87019 100644 (file)
 /**
  * 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;
-  }
-#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++;
+    SHADE1 (d, s, i, r, g, b);
   }
-#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++;
-  }
-  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++;
+    SHADE2 (d, s, j, i, r, g, b);
   }
-#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++;
+}
+
+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);
   }
-  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++;
+  /* 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;
   }
-#endif
 }
 
+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;
index e2119b611497052fd867f7f29f723f582f9925ac..42a4c073399c6ba4d759dda6a3e1d7f04b043638 100644 (file)
@@ -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
index 9ab5419833f45836a2367f309c22d2f3a637af30..4ebc7a15b2eb59bb687238c5205fb5fa5b471adb 100644 (file)
@@ -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++) {
index 8d799277bff8844d90dcee7e381ed6bbd3d3b373..fc517e1219d1b1cf6585b02e8a3528da6c0cb4c1 100644 (file)
 /**
  * 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>
 
  */
   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);
index 3276429ca7134051eb35c4472dd31812d92ad25f..e8611a8774257bcf8c2f997bb2ef52831b208af8 100644 (file)
@@ -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;
index 50fd3c7482be33ea1666c78d2ce83badd165f0f8..c00c85a6c26749c245162e74b5c4b2d8a50c5115 100644 (file)
@@ -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;
     }
   }
 
index ed05703ee3b75ade8cca7399ca01eb090a459c92..cf3ccb65552ddd15c8ac1deca4f19add860469bc 100644 (file)
@@ -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);
index 45f8dd306ceb8de195f9f49ae3c21ce41851c24c..e85d77bdbb443f5895dfa2c3479a0d54acc7cecc 100644 (file)
@@ -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);
 
index 67388f051a5d7c0034efb429d85017299215ff1a..c228692ddba6e149190ac4cd215c014d75f72834 100644 (file)
@@ -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 ();
+}
index ffa4ac25cc182c905c774fe3a7846c1e1e3fdb24..c84d871264443feb4aa3309dafc29de4298ac773 100644 (file)
@@ -20,6 +20,7 @@ libgstdecklink_la_SOURCES = \
        DeckLinkAPIDispatch.cpp
 
 noinst_HEADERS = \
+       gstdecklink.h \
        gstdecklinksrc.h \
        gstdecklinksink.h \
        capture.h \
index 5277b619a668cb1a4db7abda28730c3e026f1f0d..6638ccf767083b1927c6c2bd9755c5ac14392b12 100644 (file)
@@ -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);
 }
 
index 16af077a2968d6d0f1ae69e026bd0e204d6c748f..4241e9e579fa679ef057da1b0454a1f605171153 100644 (file)
@@ -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