From: Sebastian Dröge Date: Thu, 19 Jun 2008 10:48:57 +0000 (+0000) Subject: gst/matroska/: Fix demuxing of WavPack files. Muxing is still broken. X-Git-Tag: RELEASE-0_10_9~57 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=96da52009539004821fdce2b1c8fba549798e648;p=platform%2Fupstream%2Fgst-plugins-good.git gst/matroska/: Fix demuxing of WavPack files. Muxing is still broken. Original commit message from CVS: * gst/matroska/matroska-demux.c: (gst_matroska_demux_add_wvpk_header), (gst_matroska_demux_audio_caps): * gst/matroska/matroska-ids.h: Fix demuxing of WavPack files. Muxing is still broken. --- diff --git a/ChangeLog b/ChangeLog index 37066f96c..d68074760 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,11 @@ +2008-06-19 Sebastian Dröge + + * gst/matroska/matroska-demux.c: + (gst_matroska_demux_add_wvpk_header), + (gst_matroska_demux_audio_caps): + * gst/matroska/matroska-ids.h: + Fix demuxing of WavPack files. Muxing is still broken. + 2008-06-19 Sebastian Dröge * gst/matroska/matroska-demux.c: (gst_matroska_track_free), diff --git a/gst/matroska/matroska-demux.c b/gst/matroska/matroska-demux.c index a09dc89cf..d18a3594b 100644 --- a/gst/matroska/matroska-demux.c +++ b/gst/matroska/matroska-demux.c @@ -3315,61 +3315,148 @@ gst_matroska_demux_add_wvpk_header (GstElement * element, { GstMatroskaDemux *demux = GST_MATROSKA_DEMUX (element); - GstBuffer *newbuf; + GstMatroskaTrackAudioContext *audiocontext = + (GstMatroskaTrackAudioContext *) stream; + GstBuffer *newbuf = NULL; guint8 *data; guint newlen; - GstFlowReturn ret, cret; + GstFlowReturn ret, cret = GST_FLOW_OK; - /* we need to reconstruct the header of the wavpack block */ Wavpack4Header wvh; - /* FIXME: broken for > 2 channels and hybrid files - http://www.matroska.org/technical/specs/codecid/wavpack.html */ - wvh.ck_id[0] = 'w'; wvh.ck_id[1] = 'v'; wvh.ck_id[2] = 'p'; wvh.ck_id[3] = 'k'; - /* -20 because ck_size is the size of the wavpack block -8 - * and lace_size is the size of the wavpack block + 12 - * (the three guint32 of the header that already are in the buffer) */ - wvh.ck_size = GST_BUFFER_SIZE (*buf) + sizeof (Wavpack4Header) - 20; + wvh.version = GST_READ_UINT16_LE (stream->codec_priv); wvh.track_no = 0; wvh.index_no = 0; wvh.total_samples = -1; - wvh.block_index = 0; + wvh.block_index = audiocontext->wvpk_block_index; - /* block_samples, flags and crc are already in the buffer */ - newlen = GST_BUFFER_SIZE (*buf) + sizeof (Wavpack4Header) - 12; - ret = gst_pad_alloc_buffer_and_set_caps (stream->pad, GST_BUFFER_OFFSET_NONE, - newlen, stream->caps, &newbuf); - cret = gst_matroska_demux_combine_flows (demux, stream, ret); - if (ret != GST_FLOW_OK) { - GST_DEBUG_OBJECT (demux, "pad_alloc failed %s, combined %s", - gst_flow_get_name (ret), gst_flow_get_name (cret)); - return cret; - } + if (audiocontext->channels <= 2) { + guint32 block_samples; - data = GST_BUFFER_DATA (newbuf); - data[0] = 'w'; - data[1] = 'v'; - data[2] = 'p'; - data[3] = 'k'; - GST_WRITE_UINT32_LE (data + 4, wvh.ck_size); - GST_WRITE_UINT16_LE (data + 8, wvh.version); - GST_WRITE_UINT8 (data + 10, wvh.track_no); - GST_WRITE_UINT8 (data + 11, wvh.index_no); - GST_WRITE_UINT32_LE (data + 12, wvh.total_samples); - GST_WRITE_UINT32_LE (data + 16, wvh.block_index); - g_memmove (data + 20, GST_BUFFER_DATA (*buf), GST_BUFFER_SIZE (*buf)); - gst_buffer_copy_metadata (newbuf, *buf, - GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS); - gst_buffer_unref (*buf); - *buf = newbuf; + block_samples = GST_READ_UINT32_LE (GST_BUFFER_DATA (*buf)); + /* we need to reconstruct the header of the wavpack block */ + + /* -20 because ck_size is the size of the wavpack block -8 + * and lace_size is the size of the wavpack block + 12 + * (the three guint32 of the header that already are in the buffer) */ + wvh.ck_size = GST_BUFFER_SIZE (*buf) + sizeof (Wavpack4Header) - 20; + + /* block_samples, flags and crc are already in the buffer */ + newlen = GST_BUFFER_SIZE (*buf) + sizeof (Wavpack4Header) - 12; + ret = + gst_pad_alloc_buffer_and_set_caps (stream->pad, GST_BUFFER_OFFSET_NONE, + newlen, stream->caps, &newbuf); + cret = gst_matroska_demux_combine_flows (demux, stream, ret); + if (ret != GST_FLOW_OK) { + GST_DEBUG_OBJECT (demux, "pad_alloc failed %s, combined %s", + gst_flow_get_name (ret), gst_flow_get_name (cret)); + return cret; + } + + data = GST_BUFFER_DATA (newbuf); + data[0] = 'w'; + data[1] = 'v'; + data[2] = 'p'; + data[3] = 'k'; + GST_WRITE_UINT32_LE (data + 4, wvh.ck_size); + GST_WRITE_UINT16_LE (data + 8, wvh.version); + GST_WRITE_UINT8 (data + 10, wvh.track_no); + GST_WRITE_UINT8 (data + 11, wvh.index_no); + GST_WRITE_UINT32_LE (data + 12, wvh.total_samples); + GST_WRITE_UINT32_LE (data + 16, wvh.block_index); + g_memmove (data + 20, GST_BUFFER_DATA (*buf), GST_BUFFER_SIZE (*buf)); + gst_buffer_copy_metadata (newbuf, *buf, + GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS); + gst_buffer_unref (*buf); + *buf = newbuf; + audiocontext->wvpk_block_index += block_samples; + } else { + guint8 *outdata; + + guint outpos = 0; + + guint size; + + guint32 block_samples, flags, crc, blocksize; + + data = GST_BUFFER_DATA (*buf); + size = GST_BUFFER_SIZE (*buf); + + if (size < 4) { + GST_ERROR_OBJECT (demux, "Too small wavpack buffer"); + return GST_FLOW_ERROR; + } + + block_samples = GST_READ_UINT32_LE (data); + data += 4; + size -= 4; + + while (size > 12) { + flags = GST_READ_UINT32_LE (data); + data += 4; + size -= 4; + crc = GST_READ_UINT32_LE (data); + data += 4; + size -= 4; + blocksize = GST_READ_UINT32_LE (data); + data += 4; + size -= 4; + + if (blocksize == 0 || size < blocksize) + break; + + if (newbuf == NULL) { + newbuf = gst_buffer_new_and_alloc (sizeof (Wavpack4Header) + blocksize); + gst_buffer_set_caps (newbuf, stream->caps); + + gst_buffer_copy_metadata (newbuf, *buf, + GST_BUFFER_COPY_TIMESTAMPS | GST_BUFFER_COPY_FLAGS); + + outpos = 0; + outdata = GST_BUFFER_DATA (newbuf); + } else { + GST_BUFFER_SIZE (newbuf) += sizeof (Wavpack4Header) + blocksize; + GST_BUFFER_DATA (newbuf) = + g_realloc (GST_BUFFER_DATA (newbuf), GST_BUFFER_SIZE (newbuf)); + GST_BUFFER_MALLOCDATA (newbuf) = GST_BUFFER_DATA (newbuf); + outdata = GST_BUFFER_DATA (newbuf); + } + + outdata[outpos] = 'w'; + outdata[outpos + 1] = 'v'; + outdata[outpos + 2] = 'p'; + outdata[outpos + 3] = 'k'; + outpos += 4; + + GST_WRITE_UINT32_LE (outdata + outpos, + blocksize + sizeof (Wavpack4Header) - 8); + GST_WRITE_UINT16_LE (outdata + outpos + 4, wvh.version); + GST_WRITE_UINT8 (outdata + outpos + 6, wvh.track_no); + GST_WRITE_UINT8 (outdata + outpos + 7, wvh.index_no); + GST_WRITE_UINT32_LE (outdata + outpos + 8, wvh.total_samples); + GST_WRITE_UINT32_LE (outdata + outpos + 12, wvh.block_index); + GST_WRITE_UINT32_LE (outdata + outpos + 16, block_samples); + GST_WRITE_UINT32_LE (outdata + outpos + 20, flags); + GST_WRITE_UINT32_LE (outdata + outpos + 24, crc); + outpos += 28; + + g_memmove (outdata + outpos, data, blocksize); + outpos += blocksize; + data += blocksize; + size -= blocksize; + } + gst_buffer_unref (*buf); + *buf = newbuf; + audiocontext->wvpk_block_index += block_samples; + } return cret; } @@ -5066,6 +5153,7 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext * "framed", G_TYPE_BOOLEAN, TRUE, NULL); *codec_name = g_strdup ("Wavpack audio"); context->postprocess_frame = gst_matroska_demux_add_wvpk_header; + audiocontext->wvpk_block_index = 0; } else if ((!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4)) || (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4)) || (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_COOK))) { diff --git a/gst/matroska/matroska-ids.h b/gst/matroska/matroska-ids.h index fcf6e60dc..c6c1852a1 100644 --- a/gst/matroska/matroska-ids.h +++ b/gst/matroska/matroska-ids.h @@ -523,6 +523,8 @@ typedef struct _GstMatroskaTrackAudioContext { GstMatroskaTrackContext parent; guint samplerate, channels, bitdepth; + + guint32 wvpk_block_index; } GstMatroskaTrackAudioContext; typedef struct _GstMatroskaTrackSubtitleContext {