ypos, ypos + overlay->image_height);
break;
case GST_VIDEO_FORMAT_xRGB:
- gst_text_overlay_shade_xRGB (overlay,
- GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
+ gst_text_overlay_shade_xRGB (overlay, data,
+ xpos, xpos + overlay->image_width,
ypos, ypos + overlay->image_height);
break;
+ case GST_VIDEO_FORMAT_xBGR:
+ gst_text_overlay_shade_xBGR (overlay,
+ GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
+ ypos, ypos + overlay->image_height);
+ break;
case GST_VIDEO_FORMAT_BGRx:
- gst_text_overlay_shade_BGRx (overlay,
- GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
+ gst_text_overlay_shade_BGRx (overlay, data,
+ xpos, xpos + overlay->image_width,
ypos, ypos + overlay->image_height);
break;
+ case GST_VIDEO_FORMAT_RGBx:
+ gst_text_overlay_shade_RGBx (overlay,
+ GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
+ ypos, ypos + overlay->image_height);
+ break;
+ case GST_VIDEO_FORMAT_ARGB:
+ gst_text_overlay_shade_ARGB (overlay,
+ GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
+ ypos, ypos + overlay->image_height);
+ break;
+ case GST_VIDEO_FORMAT_ABGR:
+ gst_text_overlay_shade_ABGR (overlay,
+ GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
+ ypos, ypos + overlay->image_height);
+ break;
+ case GST_VIDEO_FORMAT_RGBA:
+ gst_text_overlay_shade_RGBA (overlay,
+ GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
+ ypos, ypos + overlay->image_height);
+ break;
+ case GST_VIDEO_FORMAT_BGRA:
+ gst_text_overlay_shade_BGRA (overlay,
+ GST_BUFFER_DATA (video_frame), xpos, xpos + overlay->image_width,
+ ypos, ypos + overlay->image_height);
+ break;
default:
g_assert_not_reached ();
}
break;
case GST_VIDEO_FORMAT_NV12:
case GST_VIDEO_FORMAT_NV21:
- gst_text_overlay_blit_NV12_NV21 (overlay,
- GST_BUFFER_DATA (video_frame), xpos, ypos);
+ gst_text_overlay_blit_NV12_NV21 (overlay, data, xpos, ypos);
break;
case GST_VIDEO_FORMAT_UYVY:
- gst_text_overlay_blit_UYVY (overlay,
- GST_BUFFER_DATA (video_frame), xpos, ypos);
+ gst_text_overlay_blit_UYVY (overlay, data, xpos, ypos);
break;
case GST_VIDEO_FORMAT_AYUV:
- gst_text_overlay_blit_AYUV (overlay,
- GST_BUFFER_DATA (video_frame), xpos, ypos);
+ gst_text_overlay_blit_AYUV (overlay, data, xpos, ypos);
break;
case GST_VIDEO_FORMAT_BGRx:
- gst_text_overlay_blit_BGRx (overlay,
- GST_BUFFER_DATA (video_frame), xpos, ypos);
+ gst_text_overlay_blit_BGRx (overlay, data, xpos, ypos);
break;
case GST_VIDEO_FORMAT_xRGB:
- gst_text_overlay_blit_xRGB (overlay,
- GST_BUFFER_DATA (video_frame), xpos, ypos);
+ gst_text_overlay_blit_xRGB (overlay, data, xpos, ypos);
break;
+ case GST_VIDEO_FORMAT_RGBx:
+ gst_text_overlay_blit_RGBx (overlay,
+ GST_BUFFER_DATA (video_frame), xpos, ypos);
+ break;
+ case GST_VIDEO_FORMAT_xBGR:
+ gst_text_overlay_blit_xBGR (overlay,
+ GST_BUFFER_DATA (video_frame), xpos, ypos);
+ break;
+ case GST_VIDEO_FORMAT_ARGB:
+ gst_text_overlay_blit_ARGB (overlay,
+ GST_BUFFER_DATA (video_frame), xpos, ypos);
+ break;
+ case GST_VIDEO_FORMAT_ABGR:
+ gst_text_overlay_blit_ABGR (overlay,
+ GST_BUFFER_DATA (video_frame), xpos, ypos);
+ break;
+ case GST_VIDEO_FORMAT_RGBA:
+ gst_text_overlay_blit_RGBA (overlay,
+ GST_BUFFER_DATA (video_frame), xpos, ypos);
+ break;
+ case GST_VIDEO_FORMAT_BGRA:
+ gst_text_overlay_blit_BGRA (overlay,
+ GST_BUFFER_DATA (video_frame), xpos, ypos);
+ break;
default:
g_assert_not_reached ();
}
}
}
-gst_base_audio_sink_get_alignment (GstBaseAudioSink * sink, GstClockTime sample_offset)
+ static gint64
- gint64 diff_s = gst_util_uint64_scale_int (diff, GST_SECOND, ringbuf->spec.rate);
++gst_base_audio_sink_get_alignment (GstBaseAudioSink * sink,
++ GstClockTime sample_offset)
+ {
+ GstRingBuffer *ringbuf = sink->ringbuffer;
+ gint64 align;
+ gint64 diff;
+ gint64 maxdrift;
+ gint segdone = g_atomic_int_get (&ringbuf->segdone) - ringbuf->segbase;
+ gint64 samples_done = segdone * ringbuf->samples_per_seg;
+ gint64 headroom = sample_offset - samples_done;
+ gboolean allow_align = TRUE;
+
+ /* now try to align the sample to the previous one, first see how big the
+ * difference is. */
+ if (sample_offset >= sink->next_sample)
+ diff = sample_offset - sink->next_sample;
+ else
+ diff = sink->next_sample - sample_offset;
+
+ /* calculate the max allowed drift in units of samples. By default this is
+ * 20ms and should be anough to compensate for timestamp rounding errors. */
+ maxdrift = (ringbuf->spec.rate * sink->priv->drift_tolerance) / GST_MSECOND;
+
+ /* calc align with previous sample */
+ align = sink->next_sample - sample_offset;
+
+ /* don't align if it means writing behind the read-segment */
+ if (diff > headroom && align < 0)
+ allow_align = FALSE;
+
+ if (G_LIKELY (diff < maxdrift && allow_align)) {
+ GST_DEBUG_OBJECT (sink,
+ "align with prev sample, ABS (%" G_GINT64_FORMAT ") < %"
+ G_GINT64_FORMAT, align, maxdrift);
+ } else {
+ /* calculate sample diff in seconds for error message */
- sample_offset > sink->next_sample ? "+" : "-",
- GST_TIME_ARGS (diff_s));
++ gint64 diff_s =
++ gst_util_uint64_scale_int (diff, GST_SECOND, ringbuf->spec.rate);
+ /* timestamps drifted apart from previous samples too much, we need to
+ * resync. We log this as an element warning. */
+ GST_WARNING_OBJECT (sink,
+ "Unexpected discontinuity in audio timestamps of "
+ "%s%" GST_TIME_FORMAT ", resyncing",
++ sample_offset > sink->next_sample ? "+" : "-", GST_TIME_ARGS (diff_s));
+ align = 0;
+ }
+
+ return align;
+ }
+
static GstFlowReturn
gst_base_audio_sink_render (GstBaseSink * bsink, GstBuffer * buf)
{
spec->buffer_time = src->buffer_time;
spec->latency_time = src->latency_time;
- if (!gst_ring_buffer_parse_caps (spec, caps))
+ GST_OBJECT_LOCK (src);
- if (!gst_ring_buffer_parse_caps (spec, caps))
- {
++ if (!gst_ring_buffer_parse_caps (spec, caps)) {
+ GST_OBJECT_UNLOCK (src);
goto parse_error;
+ }
/* calculate suggested segsize and segtotal */
spec->segsize =
}
}
+ /* Standardized way of adding pictures to vorbiscomments:
+ * http://wiki.xiph.org/VorbisComment#METADATA_BLOCK_PICTURE
+ */
+ static void
+ gst_vorbis_tag_add_metadata_block_picture (GstTagList * tags,
+ gchar * value, gint value_len)
+ {
+ GstByteReader reader;
+ guint32 img_len = 0, img_type = 0;
+ guint32 img_mimetype_len = 0, img_description_len = 0;
+ gsize decoded_len;
+ const guint8 *data;
+
+ /* img_data_base64 points to a temporary copy of the base64 encoded data, so
+ * it's safe to do inpace decoding here
+ */
+ g_base64_decode_inplace (value, &decoded_len);
+ if (decoded_len == 0)
+ goto decode_failed;
+
+ gst_byte_reader_init (&reader, (guint8 *) value, decoded_len);
+
+ if (!gst_byte_reader_get_uint32_be (&reader, &img_type))
+ goto error;
+
+ if (!gst_byte_reader_get_uint32_be (&reader, &img_mimetype_len))
+ goto error;
+ if (!gst_byte_reader_skip (&reader, img_mimetype_len))
+ goto error;
+
+ if (!gst_byte_reader_get_uint32_be (&reader, &img_description_len))
+ goto error;
+ if (!gst_byte_reader_skip (&reader, img_description_len))
+ goto error;
+
+ /* Skip width, height, color depth and number of colors for
+ * indexed formats */
+ if (!gst_byte_reader_skip (&reader, 4 * 4))
+ goto error;
+
+ if (!gst_byte_reader_get_uint32_be (&reader, &img_len))
+ goto error;
+
+ if (!gst_byte_reader_get_data (&reader, img_len, &data))
+ goto error;
+
+ gst_tag_list_add_id3_image (tags, data, img_len, img_type);
+
+ return;
+
+ error:
+ GST_WARNING
+ ("Couldn't extract image or image type from METADATA_BLOCK_PICTURE tag");
+ return;
+ decode_failed:
+ GST_WARNING ("Failed to decode Base64 data from METADATA_BLOCK_PICTURE tag");
+ return;
+ }
+
/**
- * gst_tag_list_from_vorbiscomment_buffer:
- * @buffer: buffer to convert
+ * gst_tag_list_from_vorbiscomment:
+ * @data: data to convert
+ * @size: size of @data
* @id_data: identification data at start of stream
* @id_data_length: length of identification data
* @vendor_string: pointer to a string that should take the vendor string
GstStructure *mime_struct;
GstBuffer *buffer;
GList *l = NULL;
+ guint8 *data;
+ gsize size;
+ GstByteWriter writer;
+ GstTagImageType image_type = GST_TAG_IMAGE_TYPE_NONE;
+ gint width = 0, height = 0;
+ guint8 *metadata_block;
+ guint metadata_block_len;
g_return_val_if_fail (image_value != NULL, NULL);
buffer = gst_value_get_buffer (image_value);
g_return_val_if_fail (gst_caps_is_fixed (buffer->caps), NULL);
mime_struct = gst_caps_get_structure (buffer->caps, 0);
+
mime_type = gst_structure_get_name (mime_struct);
+ if (strcmp (mime_type, "text/uri-list") == 0)
+ mime_type = "-->";
+ mime_type_len = strlen (mime_type);
- data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
- if (strcmp (mime_type, "text/uri-list") == 0) {
- /* URI reference */
- coverart_data = g_strndup ((gchar *) data, size);
+ gst_structure_get (mime_struct, "image-type", GST_TYPE_TAG_IMAGE_TYPE,
+ &image_type, "width", G_TYPE_INT, &width, "height", G_TYPE_INT, &height,
+ NULL);
+
+ metadata_block_len = 32 + mime_type_len + GST_BUFFER_SIZE (buffer);
+ gst_byte_writer_init_with_size (&writer, metadata_block_len, TRUE);
+
+ if (image_type == GST_TAG_IMAGE_TYPE_NONE
+ && strcmp (tag, GST_TAG_PREVIEW_IMAGE) == 0) {
+ gst_byte_writer_put_uint32_be_unchecked (&writer, 0x01);
} else {
- coverart_data = g_base64_encode (data, size);
+ /* Convert to ID3v2 APIC image type */
+ if (image_type == GST_TAG_IMAGE_TYPE_NONE)
+ image_type = GST_TAG_IMAGE_TYPE_UNDEFINED;
+ else
+ image_type = image_type + 2;
+ gst_byte_writer_put_uint32_be_unchecked (&writer, image_type);
}
- gst_byte_writer_put_uint32_be_unchecked (&writer, GST_BUFFER_SIZE (buffer));
- gst_byte_writer_put_data_unchecked (&writer, GST_BUFFER_DATA (buffer),
- GST_BUFFER_SIZE (buffer));
+
+ gst_byte_writer_put_uint32_be_unchecked (&writer, mime_type_len);
+ gst_byte_writer_put_data_unchecked (&writer, (guint8 *) mime_type,
+ mime_type_len);
+ /* description length */
+ gst_byte_writer_put_uint32_be_unchecked (&writer, 0);
+ gst_byte_writer_put_uint32_be_unchecked (&writer, width);
+ gst_byte_writer_put_uint32_be_unchecked (&writer, height);
+ /* color depth */
+ gst_byte_writer_put_uint32_be_unchecked (&writer, 0);
+ /* for indexed formats the number of colors */
+ gst_byte_writer_put_uint32_be_unchecked (&writer, 0);
- data_result = g_strdup_printf ("COVERART=%s", coverart_data);
- mime_result = g_strdup_printf ("COVERARTMIME=%s", mime_type);
- g_free (coverart_data);
++
++ data = gst_buffer_map (buffer, &size, NULL, GST_MAP_READ);
++ gst_byte_writer_put_uint32_be_unchecked (&writer, size);
++ gst_byte_writer_put_data_unchecked (&writer, data, size);
+ gst_buffer_unmap (buffer, data, size);
+
+ g_assert (gst_byte_writer_get_pos (&writer) == metadata_block_len);
+
+ metadata_block = gst_byte_writer_reset_and_get_data (&writer);
+ comment_data = g_base64_encode (metadata_block, metadata_block_len);
+ g_free (metadata_block);
+ data_result = g_strdup_printf ("METADATA_BLOCK_PICTURE=%s", comment_data);
+ g_free (comment_data);
l = g_list_append (l, data_result);
- l = g_list_append (l, mime_result);
return l;
}