mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-04-26 06:54:49 +00:00
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:
parent
c0826dc21d
commit
dbea08db34
3 changed files with 164 additions and 1 deletions
17
ChangeLog
17
ChangeLog
|
@ -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>
|
2008-08-25 Wim Taymans <wim.taymans@collabora.co.uk>
|
||||||
|
|
||||||
* gst/law/alaw-encode.c: (gst_alaw_enc_init), (gst_alaw_enc_chain):
|
* gst/law/alaw-encode.c: (gst_alaw_enc_init), (gst_alaw_enc_chain):
|
||||||
|
|
|
@ -1995,6 +1995,8 @@ gst_matroska_demux_send_event (GstMatroskaDemux * demux, GstEvent * event)
|
||||||
gst_pad_push_event (stream->pad, event);
|
gst_pad_push_event (stream->pad, event);
|
||||||
|
|
||||||
if (stream->pending_tags) {
|
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,
|
gst_element_found_tags_for_pad (GST_ELEMENT (demux), stream->pad,
|
||||||
stream->pending_tags);
|
stream->pending_tags);
|
||||||
stream->pending_tags = NULL;
|
stream->pending_tags = NULL;
|
||||||
|
@ -5091,6 +5093,29 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
|
||||||
|
|
||||||
caps = gst_caps_new_simple ("video/x-pn-realvideo",
|
caps = gst_caps_new_simple ("video/x-pn-realvideo",
|
||||||
"rmversion", G_TYPE_INT, rmversion, NULL);
|
"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);
|
*codec_name = g_strdup_printf ("RealVideo %d.0", rmversion);
|
||||||
} else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_THEORA)) {
|
} else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_THEORA)) {
|
||||||
caps = gst_caps_new_simple ("video/x-theora", NULL);
|
caps = gst_caps_new_simple ("video/x-theora", NULL);
|
||||||
|
@ -5425,8 +5450,47 @@ gst_matroska_demux_audio_caps (GstMatroskaTrackAudioContext *
|
||||||
raversion = 8;
|
raversion = 8;
|
||||||
else
|
else
|
||||||
raversion = 2;
|
raversion = 2;
|
||||||
|
|
||||||
caps = gst_caps_new_simple ("audio/x-pn-realaudio",
|
caps = gst_caps_new_simple ("audio/x-pn-realaudio",
|
||||||
"raversion", G_TYPE_INT, raversion, NULL);
|
"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);
|
*codec_name = g_strdup_printf ("RealAudio %d.0", raversion);
|
||||||
} else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_SIPR)) {
|
} else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_AUDIO_REAL_SIPR)) {
|
||||||
caps = gst_caps_new_simple ("audio/x-sipro", NULL);
|
caps = gst_caps_new_simple ("audio/x-sipro", NULL);
|
||||||
|
|
|
@ -91,6 +91,9 @@ static GstStaticPadTemplate videosink_templ =
|
||||||
"video/x-theora; "
|
"video/x-theora; "
|
||||||
"video/x-dirac, "
|
"video/x-dirac, "
|
||||||
COMMON_VIDEO_CAPS "; "
|
COMMON_VIDEO_CAPS "; "
|
||||||
|
"video/x-pn-realvideo, "
|
||||||
|
"rmversion = (int) [1, 4], "
|
||||||
|
COMMON_VIDEO_CAPS "; "
|
||||||
"video/x-raw-yuv, "
|
"video/x-raw-yuv, "
|
||||||
"format = (fourcc) { YUY2, I420, YV12, UYVY, AYUV }, "
|
"format = (fourcc) { YUY2, I420, YV12, UYVY, AYUV }, "
|
||||||
COMMON_VIDEO_CAPS)
|
COMMON_VIDEO_CAPS)
|
||||||
|
@ -149,7 +152,9 @@ static GstStaticPadTemplate audiosink_templ =
|
||||||
COMMON_AUDIO_CAPS ";"
|
COMMON_AUDIO_CAPS ";"
|
||||||
"audio/x-tta, "
|
"audio/x-tta, "
|
||||||
"width = (int) { 8, 16, 24 }, "
|
"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 =
|
static GstStaticPadTemplate subtitlesink_templ =
|
||||||
|
@ -751,6 +756,45 @@ skip_details:
|
||||||
} else if (!strcmp (mimetype, "video/x-msmpeg")) {
|
} else if (!strcmp (mimetype, "video/x-msmpeg")) {
|
||||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_VIDEO_MSMPEG4V3);
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1203,6 +1247,42 @@ gst_matroska_mux_audio_pad_setcaps (GstPad * pad, GstCaps * caps)
|
||||||
audiocontext->bitdepth = width;
|
audiocontext->bitdepth = width;
|
||||||
context->codec_id = g_strdup (GST_MATROSKA_CODEC_ID_AUDIO_TTA);
|
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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1687,6 +1767,8 @@ gst_matroska_mux_finish (GstMatroskaMux * mux)
|
||||||
if (tags != NULL) {
|
if (tags != NULL) {
|
||||||
guint64 master_tags, master_tag;
|
guint64 master_tags, master_tag;
|
||||||
|
|
||||||
|
GST_DEBUG ("Writing tags");
|
||||||
|
|
||||||
/* TODO: maybe limit via the TARGETS id by looking at the source pad */
|
/* TODO: maybe limit via the TARGETS id by looking at the source pad */
|
||||||
mux->tags_pos = ebml->pos;
|
mux->tags_pos = ebml->pos;
|
||||||
master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
|
master_tags = gst_ebml_write_master_start (ebml, GST_MATROSKA_ID_TAGS);
|
||||||
|
|
Loading…
Reference in a new issue