gst/matroska/: Add Real[Audio|Video] support to Matroska containers.

Original commit message from CVS:
* gst/matroska/matroska-demux.c: (gst_matroska_demux_send_event),
(gst_matroska_demux_video_caps), (gst_matroska_demux_audio_caps):
* gst/matroska/matroska-mux.c:
(gst_matroska_mux_video_pad_setcaps),
(gst_matroska_mux_audio_pad_setcaps), (gst_matroska_mux_finish):
Add Real[Audio|Video] support to Matroska containers.
It works fine for:
* decoding real audio/video streams contained in mkv
* 'transmuxing' real (.rm) files into .mkv files
It will not work though for encoding real[audio/video] streams that
don't contain the 'mdpr_data' extra data on the caps.
The reason why this will not work is because I never intended to
duplicate virtually all the 'mdpr' block creation into mkvmux.
Fixes #536067
This commit is contained in:
Edward Hervey 2008-08-25 14:15:43 +00:00
parent c0826dc21d
commit dbea08db34
3 changed files with 164 additions and 1 deletions

View file

@ -1,3 +1,20 @@
2008-08-25 Edward Hervey <edward.hervey@collabora.co.uk>
* gst/matroska/matroska-demux.c: (gst_matroska_demux_send_event),
(gst_matroska_demux_video_caps), (gst_matroska_demux_audio_caps):
* gst/matroska/matroska-mux.c:
(gst_matroska_mux_video_pad_setcaps),
(gst_matroska_mux_audio_pad_setcaps), (gst_matroska_mux_finish):
Add Real[Audio|Video] support to Matroska containers.
It works fine for:
* decoding real audio/video streams contained in mkv
* 'transmuxing' real (.rm) files into .mkv files
It will not work though for encoding real[audio/video] streams that
don't contain the 'mdpr_data' extra data on the caps.
The reason why this will not work is because I never intended to
duplicate virtually all the 'mdpr' block creation into mkvmux.
Fixes #536067
2008-08-25 Wim Taymans <wim.taymans@collabora.co.uk>
* gst/law/alaw-encode.c: (gst_alaw_enc_init), (gst_alaw_enc_chain):

View file

@ -1995,6 +1995,8 @@ gst_matroska_demux_send_event (GstMatroskaDemux * demux, GstEvent * event)
gst_pad_push_event (stream->pad, event);
if (stream->pending_tags) {
GST_DEBUG_OBJECT (demux, "Sending pending_tags %p for pad %s:%s",
stream->pending_tags, GST_DEBUG_PAD_NAME (stream->pad));
gst_element_found_tags_for_pad (GST_ELEMENT (demux), stream->pad,
stream->pending_tags);
stream->pending_tags = NULL;
@ -5091,6 +5093,29 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
caps = gst_caps_new_simple ("video/x-pn-realvideo",
"rmversion", G_TYPE_INT, rmversion, NULL);
GST_DEBUG ("data:%p, size:0x%x", data, size);
/* We need to extract the extradata ! */
if (data && (size >= 0x22)) {
GstBuffer *priv;
guint rformat;
guint subformat;
gst_util_dump_mem (data, size);
gst_util_dump_mem (data + 0x1a, size - 0x1a);
subformat = GST_READ_UINT32_BE (data + 0x1a);
rformat = GST_READ_UINT32_BE (data + 0x1e);
priv = gst_buffer_new_and_alloc (size - 0x1a);
memcpy (GST_BUFFER_DATA (priv), data + 0x1a, size - 0x1a);
gst_caps_set_simple (caps,
"codec_data", GST_TYPE_BUFFER, priv,
"format", G_TYPE_INT, rformat,
"subformat", G_TYPE_INT, subformat, NULL);
gst_buffer_unref (priv);
}
*codec_name = g_strdup_printf ("RealVideo %d.0", rmversion);
} else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_THEORA)) {
caps = gst_caps_new_simple ("video/x-theora", NULL);
@ -5425,8 +5450,47 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *
raversion = 8;
else
raversion = 2;
caps = gst_caps_new_simple ("audio/x-pn-realaudio",
"raversion", G_TYPE_INT, raversion, NULL);
/* Extract extra information from caps, mapping varies based on codec */
if (data && (size >= 0x50)) {
GstBuffer *priv;
guint flavor;
guint packet_size;
guint height;
guint leaf_size;
guint sample_width;
guint extra_data_size;
GST_ERROR ("real audio raversion:%d", raversion);
gst_util_dump_mem (data, size);
if (raversion == 8) {
/* COOK */
flavor = GST_READ_UINT16_BE (data + 22);
packet_size = GST_READ_UINT32_BE (data + 24);
height = GST_READ_UINT16_BE (data + 40);
leaf_size = GST_READ_UINT16_BE (data + 44);
sample_width = GST_READ_UINT16_BE (data + 58);
extra_data_size = GST_READ_UINT32_BE (data + 74);
GST_ERROR
("flavor:%d, packet_size:%d, height:%d, leaf_size:%d, sample_width:%d, extra_data_size:%d",
flavor, packet_size, height, leaf_size, sample_width,
extra_data_size);
gst_caps_set_simple (caps, "flavor", G_TYPE_INT, flavor, "packet_size",
G_TYPE_INT, packet_size, "height", G_TYPE_INT, height, "leaf_size",
G_TYPE_INT, leaf_size, "width", G_TYPE_INT, sample_width, NULL);
if ((size - 78) >= extra_data_size) {
priv = gst_buffer_new_and_alloc (extra_data_size);
memcpy (GST_BUFFER_DATA (priv), data + 78, extra_data_size);
gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, priv, NULL);
gst_buffer_unref (priv);
}
}
}
*codec_name = g_strdup_printf ("RealAudio %d.0", raversion);
} else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_SIPR)) {
caps = gst_caps_new_simple ("audio/x-sipro", NULL);

View file

@ -91,6 +91,9 @@ static GstStaticPadTemplate videosink_templ =
"video/x-theora; "
"video/x-dirac, "
COMMON_VIDEO_CAPS "; "
"video/x-pn-realvideo, "
"rmversion = (int) [1, 4], "
COMMON_VIDEO_CAPS "; "
"video/x-raw-yuv, "
"format = (fourcc) { YUY2, I420, YV12, UYVY, AYUV }, "
COMMON_VIDEO_CAPS)
@ -149,7 +152,9 @@ static GstStaticPadTemplate audiosink_templ =
COMMON_AUDIO_CAPS ";"
"audio/x-tta, "
"width = (int) { 8, 16, 24 }, "
"channels = (int) { 1, 2 }, " "rate = (int) [ 8000, 96000 ]")
"channels = (int) { 1, 2 }, " "rate = (int) [ 8000, 96000 ]; "
"audio/x-pn-realaudio, "
"raversion = (int) { 1, 2, 8 }, " COMMON_AUDIO_CAPS ";")
);
static GstStaticPadTemplate subtitlesink_templ =
@ -751,6 +756,45 @@ skip_details:
} else if (!strcmp (mimetype, "video/x-msmpeg")) {
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3);
return TRUE;
} else if (!strcmp (mimetype, "video/x-pn-realvideo")) {
gint rmversion;
const GValue *mdpr_data;
gst_structure_get_int (structure, "rmversion", &rmversion);
switch (rmversion) {
case 1:
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO1);
break;
case 2:
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO2);
break;
case 3:
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO3);
break;
case 4:
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_REALVIDEO4);
break;
default:
return FALSE;
}
mdpr_data = gst_structure_get_value (structure, "mdpr_data");
if (mdpr_data != NULL) {
guint8 *priv_data = NULL;
guint priv_data_size = 0;
GstBuffer *codec_data_buf = g_value_peek_pointer (mdpr_data);
priv_data_size = GST_BUFFER_SIZE (codec_data_buf);
priv_data = g_malloc0 (priv_data_size);
memcpy (priv_data, GST_BUFFER_DATA (codec_data_buf), priv_data_size);
context->codec_priv = priv_data;
context->codec_priv_size = priv_data_size;
}
return TRUE;
}
@ -1203,6 +1247,42 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
audiocontext->bitdepth = width;
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_TTA);
return TRUE;
} else if (!strcmp (mimetype, "audio/x-pn-realaudio")) {
gint raversion;
const GValue *mdpr_data;
gst_structure_get_int (structure, "raversion", &raversion);
switch (raversion) {
case 1:
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_REAL_14_4);
break;
case 2:
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_REAL_28_8);
break;
case 8:
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_REAL_COOK);
break;
default:
return FALSE;
}
mdpr_data = gst_structure_get_value (structure, "mdpr_data");
if (mdpr_data != NULL) {
guint8 *priv_data = NULL;
guint priv_data_size = 0;
GstBuffer *codec_data_buf = g_value_peek_pointer (mdpr_data);
priv_data_size = GST_BUFFER_SIZE (codec_data_buf);
priv_data = g_malloc0 (priv_data_size);
memcpy (priv_data, GST_BUFFER_DATA (codec_data_buf), priv_data_size);
context->codec_priv = priv_data;
context->codec_priv_size = priv_data_size;
}
return TRUE;
}
@ -1687,6 +1767,8 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
if (tags != NULL) {
guint64 master_tags, master_tag;
GST_DEBUG ("Writing tags");
/* TODO: maybe limit via the TARGETS id by looking at the source pad */
mux->tags_pos = ebml->pos;
master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);