+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):
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;
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);
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);
"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)
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 =
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 FALSE;
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 FALSE;
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);