diff --git a/gst/isomp4/qtdemux.c b/gst/isomp4/qtdemux.c index b66c34cc35..15ac144da2 100644 --- a/gst/isomp4/qtdemux.c +++ b/gst/isomp4/qtdemux.c @@ -298,6 +298,8 @@ struct _QtDemuxStream GstAllocator *allocator; GstAllocationParams params; + gsize alignment; + /* when a discontinuity is pending */ gboolean discont; @@ -1848,6 +1850,7 @@ _create_stream (void) stream->n_samples_moof = 0; stream->duration_moof = 0; stream->duration_last_moof = 0; + stream->alignment = 1; g_queue_init (&stream->protection_scheme_event_queue); return stream; } @@ -5127,6 +5130,44 @@ clipped: } } +static GstBuffer * +gst_qtdemux_align_buffer (GstQTDemux * demux, + GstBuffer * buffer, gsize alignment) +{ + GstMapInfo map; + + gst_buffer_map (buffer, &map, GST_MAP_READ); + + if (map.size < sizeof (guintptr)) { + gst_buffer_unmap (buffer, &map); + return buffer; + } + + if (((guintptr) map.data) & (alignment - 1)) { + GstBuffer *new_buffer; + GstAllocationParams params = { 0, alignment - 1, 0, 0, }; + + new_buffer = gst_buffer_new_allocate (NULL, + gst_buffer_get_size (buffer), ¶ms); + + /* Copy data "by hand", so ensure alignment is kept: */ + gst_buffer_fill (new_buffer, 0, map.data, map.size); + + gst_buffer_copy_into (new_buffer, buffer, GST_BUFFER_COPY_METADATA, 0, -1); + GST_DEBUG_OBJECT (demux, + "We want output aligned on %" G_GSIZE_FORMAT ", reallocated", + alignment); + + gst_buffer_unmap (buffer, &map); + gst_buffer_unref (buffer); + + return new_buffer; + } + + gst_buffer_unmap (buffer, &map); + return buffer; +} + /* the input buffer metadata must be writable, * but time/duration etc not yet set and need not be preserved */ static GstBuffer * @@ -5248,6 +5289,8 @@ gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux, GST_BUFFER_FLAG_UNSET (buf, GST_BUFFER_FLAG_DISCONT); } + if (stream->alignment > 1) + buffer = gst_qtdemux_align_buffer (qtdemux, buffer, stream->alignment); gst_pad_push (stream->pad, buffer); stream->buffers = g_slist_delete_link (stream->buffers, stream->buffers); @@ -5351,6 +5394,9 @@ gst_qtdemux_decorate_and_push_buffer (GstQTDemux * qtdemux, } } + if (stream->alignment > 1) + buf = gst_qtdemux_align_buffer (qtdemux, buf, stream->alignment); + ret = gst_pad_push (stream->pad, buf); if (GST_CLOCK_TIME_IS_VALID (pts) && GST_CLOCK_TIME_IS_VALID (duration)) { @@ -13137,6 +13183,7 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream, caps = gst_caps_new_empty_simple ("video/x-raw"); gst_caps_set_simple (caps, "format", G_TYPE_STRING, "RGB8P", NULL); _codec ("Windows Raw RGB"); + stream->alignment = 32; break; case FOURCC_raw_: { @@ -13500,11 +13547,24 @@ qtdemux_video_caps (GstQTDemux * qtdemux, QtDemuxStream * stream, /* enable clipping for raw video streams */ stream->need_clip = TRUE; + stream->alignment = 32; } return caps; } +static guint +round_up_pow2 (guint n) +{ + n = n - 1; + n = n | (n >> 1); + n = n | (n >> 2); + n = n | (n >> 4); + n = n | (n >> 8); + n = n | (n >> 16); + return n + 1; +} + static GstCaps * qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream, guint32 fourcc, const guint8 * data, int len, gchar ** codec_name) @@ -13547,6 +13607,8 @@ qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream, caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, gst_audio_format_to_string (format), "layout", G_TYPE_STRING, "interleaved", NULL); + stream->alignment = GST_ROUND_UP_8 (depth); + stream->alignment = round_up_pow2 (stream->alignment); break; } case GST_MAKE_FOURCC ('f', 'l', '6', '4'): @@ -13554,12 +13616,14 @@ qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream, caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "F64BE", "layout", G_TYPE_STRING, "interleaved", NULL); + stream->alignment = 8; break; case GST_MAKE_FOURCC ('f', 'l', '3', '2'): _codec ("Raw 32-bit floating-point audio"); caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "F32BE", "layout", G_TYPE_STRING, "interleaved", NULL); + stream->alignment = 4; break; case FOURCC_in24: _codec ("Raw 24-bit PCM audio"); @@ -13568,12 +13632,14 @@ qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream, caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "S24BE", "layout", G_TYPE_STRING, "interleaved", NULL); + stream->alignment = 4; break; case GST_MAKE_FOURCC ('i', 'n', '3', '2'): _codec ("Raw 32-bit PCM audio"); caps = gst_caps_new_simple ("audio/x-raw", "format", G_TYPE_STRING, "S32BE", "layout", G_TYPE_STRING, "interleaved", NULL); + stream->alignment = 4; break; case FOURCC_ulaw: _codec ("Mu-law audio"); @@ -13753,6 +13819,8 @@ qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream, "format", G_TYPE_STRING, gst_audio_format_to_string (format), "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" : "interleaved", NULL); + stream->alignment = GST_ROUND_UP_8 (depth); + stream->alignment = round_up_pow2 (stream->alignment); } else { if (width == 0) width = 32; @@ -13771,6 +13839,7 @@ qtdemux_audio_caps (GstQTDemux * qtdemux, QtDemuxStream * stream, "format", G_TYPE_STRING, gst_audio_format_to_string (format), "layout", G_TYPE_STRING, (flags & FLAG_IS_NON_INTERLEAVED) ? "non-interleaved" : "interleaved", NULL); + stream->alignment = width / 8; } break; }