From 1925b8e9f78e8deb89d451e67b6edb8ca9d7b61f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 16 Mar 2009 12:07:20 +0100 Subject: mxfdemux: Add support for AYUV and v308 YUV colorspaces --- gst/mxf/mxfup.c | 9 +++++++++ 1 file changed, 9 insertions(+) (limited to 'gst/mxf/mxfup.c') diff --git a/gst/mxf/mxfup.c b/gst/mxf/mxfup.c index ccc34ffd..d76690bd 100644 --- a/gst/mxf/mxfup.c +++ b/gst/mxf/mxfup.c @@ -132,6 +132,10 @@ mxf_up_rgba_create_caps (MXFMetadataTimelineTrack * track, && d->pixel_layout[4] == 'R' && d->pixel_layout[1] == 8 && d->pixel_layout[3] == 8 && d->pixel_layout[5] == 8) { caps = gst_caps_from_string (GST_VIDEO_CAPS_BGR); + } else if (d->pixel_layout[0] == 'Y' && d->pixel_layout[2] == 'U' + && d->pixel_layout[4] == 'V' && d->pixel_layout[1] == 8 + && d->pixel_layout[3] == 8 && d->pixel_layout[5] == 8) { + caps = gst_caps_from_string (GST_VIDEO_CAPS_YUV ("v308")); } else { GST_ERROR ("Unsupport 3 component pixel layout"); return NULL; @@ -177,6 +181,11 @@ mxf_up_rgba_create_caps (MXFMetadataTimelineTrack * track, && d->pixel_layout[1] == 8 && d->pixel_layout[3] == 8 && d->pixel_layout[5] == 8 && d->pixel_layout[7] == 8) { caps = gst_caps_from_string (GST_VIDEO_CAPS_BGRA); + } else if (d->pixel_layout[0] == 'A' && d->pixel_layout[2] == 'Y' + && d->pixel_layout[4] == 'U' && d->pixel_layout[6] == 'V' + && d->pixel_layout[1] == 8 && d->pixel_layout[3] == 8 + && d->pixel_layout[5] == 8 && d->pixel_layout[7] == 8) { + caps = gst_caps_from_string (GST_VIDEO_CAPS_YUV ("AYUV")); } else { GST_ERROR ("Unsupport 4 component pixel layout"); return NULL; -- cgit v1.2.1 From 9aa16c2ea5bdbf5052998f53d0f7ed0e2b9481e1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 16 Mar 2009 12:48:31 +0100 Subject: mxfmux: Add initial support for muxing raw picture essence --- gst/mxf/mxfup.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 168 insertions(+) (limited to 'gst/mxf/mxfup.c') diff --git a/gst/mxf/mxfup.c b/gst/mxf/mxfup.c index d76690bd..bce9a19e 100644 --- a/gst/mxf/mxfup.c +++ b/gst/mxf/mxfup.c @@ -40,6 +40,7 @@ #include #include "mxfup.h" +#include "mxfwrite.h" GST_DEBUG_CATEGORY_EXTERN (mxf_debug); #define GST_CAT_DEFAULT mxf_debug @@ -273,8 +274,175 @@ static const MXFEssenceElementHandler mxf_up_essence_element_handler = { mxf_up_create_caps }; +static GstFlowReturn +mxf_up_write_func (GstBuffer * buffer, GstCaps * caps, gpointer mapping_data, + GstAdapter * adapter, GstBuffer ** outbuf, gboolean flush) +{ + *outbuf = buffer; + return GST_FLOW_OK; +} + +static const guint8 up_essence_container_ul[] = { + 0x06, 0x0e, 0x2b, 0x34, 0x04, 0x01, 0x01, 0x01, + 0x0D, 0x01, 0x03, 0x01, 0x02, 0x05, 0x7F, 0x01 +}; + +static const struct +{ + const gchar *caps; + guint32 n_pixel_layout; + guint8 pixel_layout[10]; +} _rgba_mapping_table[] = { + { + GST_VIDEO_CAPS_RGB, 3, { + 'R', 8, 'G', 8, 'B', 8}}, { + GST_VIDEO_CAPS_BGR, 3, { + 'B', 8, 'G', 8, 'R', 8}}, { + GST_VIDEO_CAPS_YUV ("v308"), 3, { + 'Y', 8, 'U', 8, 'V', 8}}, { + GST_VIDEO_CAPS_xRGB, 4, { + 'F', 8, 'R', 8, 'G', 8, 'B', 8}}, { + GST_VIDEO_CAPS_RGBx, 4, { + 'R', 8, 'G', 8, 'B', 8, 'F', 8}}, { + GST_VIDEO_CAPS_xBGR, 4, { + 'F', 8, 'B', 8, 'G', 8, 'R', 8}}, { + GST_VIDEO_CAPS_BGRx, 4, { + 'B', 8, 'G', 8, 'R', 8, 'F', 8}}, { + GST_VIDEO_CAPS_RGBA, 4, { + 'R', 8, 'G', 8, 'B', 8, 'A', 8}}, { + GST_VIDEO_CAPS_ARGB, 4, { + 'A', 8, 'R', 8, 'G', 8, 'B', 8}}, { + GST_VIDEO_CAPS_BGRA, 4, { + 'B', 8, 'G', 8, 'R', 8, 'A', 8}}, { + GST_VIDEO_CAPS_ABGR, 4, { + 'A', 8, 'B', 8, 'G', 8, 'R', 8}}, { + GST_VIDEO_CAPS_YUV ("AYUV"), 4, { + 'A', 8, 'Y', 8, 'U', 8, 'V', 8}} +}; + +static MXFMetadataFileDescriptor * +mxf_up_get_rgba_descriptor (GstPadTemplate * tmpl, GstCaps * caps, + MXFEssenceElementWriteFunc * handler, gpointer * mapping_data) +{ + MXFMetadataRGBAPictureEssenceDescriptor *ret; + guint i; + GstCaps *tmp, *intersection; + + ret = (MXFMetadataRGBAPictureEssenceDescriptor *) + gst_mini_object_new (MXF_TYPE_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR); + + for (i = 0; i < G_N_ELEMENTS (_rgba_mapping_table); i++) { + tmp = gst_caps_from_string (_rgba_mapping_table[i].caps); + intersection = gst_caps_intersect (caps, tmp); + gst_caps_unref (tmp); + + if (!gst_caps_is_empty (intersection)) { + gst_caps_unref (intersection); + ret->n_pixel_layout = _rgba_mapping_table[i].n_pixel_layout; + ret->pixel_layout = g_new0 (guint8, ret->n_pixel_layout * 2); + memcpy (ret->pixel_layout, _rgba_mapping_table[i].pixel_layout, + ret->n_pixel_layout * 2); + break; + } + gst_caps_unref (intersection); + } + + memcpy (&ret->parent.parent.essence_container, &up_essence_container_ul, 16); + + mxf_metadata_generic_picture_essence_descriptor_from_caps (&ret->parent, + caps); + + *handler = mxf_up_write_func; + + return (MXFMetadataFileDescriptor *) ret; +} + +static MXFMetadataFileDescriptor * +mxf_up_get_cdci_descriptor (GstPadTemplate * tmpl, GstCaps * caps, + MXFEssenceElementWriteFunc * handler, gpointer * mapping_data) +{ + g_assert_not_reached (); + return NULL; +} + +static MXFMetadataFileDescriptor * +mxf_up_get_descriptor (GstPadTemplate * tmpl, GstCaps * caps, + MXFEssenceElementWriteFunc * handler, gpointer * mapping_data) +{ + GstStructure *s; + + s = gst_caps_get_structure (caps, 0); + if (strcmp (gst_structure_get_name (s), "video/x-raw-rgb") == 0) { + return mxf_up_get_rgba_descriptor (tmpl, caps, handler, mapping_data); + } else if (strcmp (gst_structure_get_name (s), "video/x-raw-yuv") == 0) { + guint32 fourcc; + + if (!gst_structure_get_fourcc (s, "format", &fourcc)) + return NULL; + + if (fourcc == GST_MAKE_FOURCC ('A', 'Y', 'U', 'V') || + fourcc == GST_MAKE_FOURCC ('v', '3', '0', '8')) + return mxf_up_get_rgba_descriptor (tmpl, caps, handler, mapping_data); + + return mxf_up_get_cdci_descriptor (tmpl, caps, handler, mapping_data); + } + + g_assert_not_reached (); +} + +static void +mxf_up_update_descriptor (MXFMetadataFileDescriptor * d, GstCaps * caps, + gpointer mapping_data, GstBuffer * buf) +{ + return; +} + +static void +mxf_up_get_edit_rate (MXFMetadataFileDescriptor * a, GstCaps * caps, + gpointer mapping_data, GstBuffer * buf, MXFMetadataSourcePackage * package, + MXFMetadataTimelineTrack * track, MXFFraction * edit_rate) +{ + edit_rate->n = a->sample_rate.n; + edit_rate->d = a->sample_rate.d; +} + +static guint32 +mxf_up_get_track_number_template (MXFMetadataFileDescriptor * a, + GstCaps * caps, gpointer mapping_data) +{ + return (0x15 << 24) | (0x02 << 8); +} + +static MXFEssenceElementWriter mxf_up_essence_element_writer = { + mxf_up_get_descriptor, + mxf_up_update_descriptor, + mxf_up_get_edit_rate, + mxf_up_get_track_number_template, + NULL, + {{0,}} +}; + void mxf_up_init (void) { mxf_essence_element_handler_register (&mxf_up_essence_element_handler); + + mxf_up_essence_element_writer.pad_template = + gst_pad_template_new ("up_video_sink_%u", GST_PAD_SINK, GST_PAD_REQUEST, + gst_caps_from_string (GST_VIDEO_CAPS_RGB "; " + GST_VIDEO_CAPS_BGR "; " + GST_VIDEO_CAPS_RGBx "; " + GST_VIDEO_CAPS_xRGB "; " + GST_VIDEO_CAPS_BGRx "; " + GST_VIDEO_CAPS_xBGR "; " + GST_VIDEO_CAPS_ARGB "; " + GST_VIDEO_CAPS_RGBA "; " + GST_VIDEO_CAPS_ABGR "; " + GST_VIDEO_CAPS_BGRA "; " + GST_VIDEO_CAPS_YUV ("AYUV") "; " GST_VIDEO_CAPS_YUV ("v308"))); + + memcpy (&mxf_up_essence_element_writer.data_definition, + mxf_metadata_track_identifier_get (MXF_METADATA_TRACK_PICTURE_ESSENCE), + 16); + mxf_essence_element_writer_register (&mxf_up_essence_element_writer); } -- cgit v1.2.1 From b6bac882f9e49e7cc33fb78f27b2d7190824bdb4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 16 Mar 2009 15:37:25 +0100 Subject: mxfdemux: Simplify caps selection by using a lookup table --- gst/mxf/mxfup.c | 147 +++++++++++++++++--------------------------------------- 1 file changed, 44 insertions(+), 103 deletions(-) (limited to 'gst/mxf/mxfup.c') diff --git a/gst/mxf/mxfup.c b/gst/mxf/mxfup.c index bce9a19e..2a06a89c 100644 --- a/gst/mxf/mxfup.c +++ b/gst/mxf/mxfup.c @@ -45,6 +45,39 @@ GST_DEBUG_CATEGORY_EXTERN (mxf_debug); #define GST_CAT_DEFAULT mxf_debug +static const struct +{ + const gchar *caps; + guint32 n_pixel_layout; + guint8 pixel_layout[10]; +} _rgba_mapping_table[] = { + { + GST_VIDEO_CAPS_RGB, 3, { + 'R', 8, 'G', 8, 'B', 8}}, { + GST_VIDEO_CAPS_BGR, 3, { + 'B', 8, 'G', 8, 'R', 8}}, { + GST_VIDEO_CAPS_YUV ("v308"), 3, { + 'Y', 8, 'U', 8, 'V', 8}}, { + GST_VIDEO_CAPS_xRGB, 4, { + 'F', 8, 'R', 8, 'G', 8, 'B', 8}}, { + GST_VIDEO_CAPS_RGBx, 4, { + 'R', 8, 'G', 8, 'B', 8, 'F', 8}}, { + GST_VIDEO_CAPS_xBGR, 4, { + 'F', 8, 'B', 8, 'G', 8, 'R', 8}}, { + GST_VIDEO_CAPS_BGRx, 4, { + 'B', 8, 'G', 8, 'R', 8, 'F', 8}}, { + GST_VIDEO_CAPS_RGBA, 4, { + 'R', 8, 'G', 8, 'B', 8, 'A', 8}}, { + GST_VIDEO_CAPS_ARGB, 4, { + 'A', 8, 'R', 8, 'G', 8, 'B', 8}}, { + GST_VIDEO_CAPS_BGRA, 4, { + 'B', 8, 'G', 8, 'R', 8, 'A', 8}}, { + GST_VIDEO_CAPS_ABGR, 4, { + 'A', 8, 'B', 8, 'G', 8, 'R', 8}}, { + GST_VIDEO_CAPS_YUV ("AYUV"), 4, { + 'A', 8, 'Y', 8, 'U', 8, 'V', 8}} +}; + typedef struct { guint32 image_start_offset; @@ -118,83 +151,22 @@ mxf_up_rgba_create_caps (MXFMetadataTimelineTrack * track, MXFEssenceElementHandleFunc * handler, gpointer * mapping_data) { GstCaps *caps = NULL; + guint i; if (!d->pixel_layout) { GST_ERROR ("No pixel layout"); return NULL; } - if (d->n_pixel_layout == 3) { - if (d->pixel_layout[0] == 'R' && d->pixel_layout[2] == 'G' - && d->pixel_layout[4] == 'B' && d->pixel_layout[1] == 8 - && d->pixel_layout[3] == 8 && d->pixel_layout[5] == 8) { - caps = gst_caps_from_string (GST_VIDEO_CAPS_RGB); - } else if (d->pixel_layout[0] == 'B' && d->pixel_layout[2] == 'G' - && d->pixel_layout[4] == 'R' && d->pixel_layout[1] == 8 - && d->pixel_layout[3] == 8 && d->pixel_layout[5] == 8) { - caps = gst_caps_from_string (GST_VIDEO_CAPS_BGR); - } else if (d->pixel_layout[0] == 'Y' && d->pixel_layout[2] == 'U' - && d->pixel_layout[4] == 'V' && d->pixel_layout[1] == 8 - && d->pixel_layout[3] == 8 && d->pixel_layout[5] == 8) { - caps = gst_caps_from_string (GST_VIDEO_CAPS_YUV ("v308")); - } else { - GST_ERROR ("Unsupport 3 component pixel layout"); - return NULL; - } - } else if (d->n_pixel_layout == 4) { - if (d->pixel_layout[0] == 'R' && d->pixel_layout[2] == 'G' - && d->pixel_layout[4] == 'B' && d->pixel_layout[6] == 'F' - && d->pixel_layout[1] == 8 && d->pixel_layout[3] == 8 - && d->pixel_layout[5] == 8 && d->pixel_layout[7] == 8) { - caps = gst_caps_from_string (GST_VIDEO_CAPS_RGBx); - } else if (d->pixel_layout[0] == 'B' && d->pixel_layout[2] == 'G' - && d->pixel_layout[4] == 'R' && d->pixel_layout[6] == 'F' - && d->pixel_layout[1] == 8 && d->pixel_layout[3] == 8 - && d->pixel_layout[5] == 8 && d->pixel_layout[7] == 8) { - caps = gst_caps_from_string (GST_VIDEO_CAPS_BGRx); - } else if (d->pixel_layout[0] == 'F' && d->pixel_layout[2] == 'R' - && d->pixel_layout[4] == 'G' && d->pixel_layout[6] == 'B' - && d->pixel_layout[1] == 8 && d->pixel_layout[3] == 8 - && d->pixel_layout[5] == 8 && d->pixel_layout[7] == 8) { - caps = gst_caps_from_string (GST_VIDEO_CAPS_xRGB); - } else if (d->pixel_layout[0] == 'F' && d->pixel_layout[2] == 'B' - && d->pixel_layout[4] == 'G' && d->pixel_layout[6] == 'R' - && d->pixel_layout[1] == 8 && d->pixel_layout[3] == 8 - && d->pixel_layout[5] == 8 && d->pixel_layout[7] == 8) { - caps = gst_caps_from_string (GST_VIDEO_CAPS_xBGR); - } else if (d->pixel_layout[0] == 'A' && d->pixel_layout[2] == 'R' - && d->pixel_layout[4] == 'G' && d->pixel_layout[6] == 'B' - && d->pixel_layout[1] == 8 && d->pixel_layout[3] == 8 - && d->pixel_layout[5] == 8 && d->pixel_layout[7] == 8) { - caps = gst_caps_from_string (GST_VIDEO_CAPS_ARGB); - } else if (d->pixel_layout[0] == 'A' && d->pixel_layout[2] == 'B' - && d->pixel_layout[4] == 'G' && d->pixel_layout[6] == 'R' - && d->pixel_layout[1] == 8 && d->pixel_layout[3] == 8 - && d->pixel_layout[5] == 8 && d->pixel_layout[7] == 8) { - caps = gst_caps_from_string (GST_VIDEO_CAPS_ABGR); - } else if (d->pixel_layout[0] == 'R' && d->pixel_layout[2] == 'G' - && d->pixel_layout[4] == 'B' && d->pixel_layout[6] == 'A' - && d->pixel_layout[1] == 8 && d->pixel_layout[3] == 8 - && d->pixel_layout[5] == 8 && d->pixel_layout[7] == 8) { - caps = gst_caps_from_string (GST_VIDEO_CAPS_RGBA); - } else if (d->pixel_layout[0] == 'B' && d->pixel_layout[2] == 'G' - && d->pixel_layout[4] == 'R' && d->pixel_layout[6] == 'A' - && d->pixel_layout[1] == 8 && d->pixel_layout[3] == 8 - && d->pixel_layout[5] == 8 && d->pixel_layout[7] == 8) { - caps = gst_caps_from_string (GST_VIDEO_CAPS_BGRA); - } else if (d->pixel_layout[0] == 'A' && d->pixel_layout[2] == 'Y' - && d->pixel_layout[4] == 'U' && d->pixel_layout[6] == 'V' - && d->pixel_layout[1] == 8 && d->pixel_layout[3] == 8 - && d->pixel_layout[5] == 8 && d->pixel_layout[7] == 8) { - caps = gst_caps_from_string (GST_VIDEO_CAPS_YUV ("AYUV")); - } else { - GST_ERROR ("Unsupport 4 component pixel layout"); - return NULL; + for (i = 0; i < G_N_ELEMENTS (_rgba_mapping_table); i++) { + if (d->n_pixel_layout != _rgba_mapping_table[i].n_pixel_layout) + continue; + + if (memcmp (d->pixel_layout, &_rgba_mapping_table[i].pixel_layout, + _rgba_mapping_table[i].n_pixel_layout * 2) == 0) { + caps = gst_caps_from_string (_rgba_mapping_table[i].caps); + break; } - } else { - GST_ERROR ("Pixel layouts with %u components not supported yet", - d->n_pixel_layout); - return NULL; } if (caps) { @@ -206,6 +178,8 @@ mxf_up_rgba_create_caps (MXFMetadataTimelineTrack * track, ((MXFMetadataGenericPictureEssenceDescriptor *) d)->image_end_offset; *mapping_data = data; + } else { + GST_WARNING ("Unsupported pixel layout"); } return caps; @@ -287,39 +261,6 @@ static const guint8 up_essence_container_ul[] = { 0x0D, 0x01, 0x03, 0x01, 0x02, 0x05, 0x7F, 0x01 }; -static const struct -{ - const gchar *caps; - guint32 n_pixel_layout; - guint8 pixel_layout[10]; -} _rgba_mapping_table[] = { - { - GST_VIDEO_CAPS_RGB, 3, { - 'R', 8, 'G', 8, 'B', 8}}, { - GST_VIDEO_CAPS_BGR, 3, { - 'B', 8, 'G', 8, 'R', 8}}, { - GST_VIDEO_CAPS_YUV ("v308"), 3, { - 'Y', 8, 'U', 8, 'V', 8}}, { - GST_VIDEO_CAPS_xRGB, 4, { - 'F', 8, 'R', 8, 'G', 8, 'B', 8}}, { - GST_VIDEO_CAPS_RGBx, 4, { - 'R', 8, 'G', 8, 'B', 8, 'F', 8}}, { - GST_VIDEO_CAPS_xBGR, 4, { - 'F', 8, 'B', 8, 'G', 8, 'R', 8}}, { - GST_VIDEO_CAPS_BGRx, 4, { - 'B', 8, 'G', 8, 'R', 8, 'F', 8}}, { - GST_VIDEO_CAPS_RGBA, 4, { - 'R', 8, 'G', 8, 'B', 8, 'A', 8}}, { - GST_VIDEO_CAPS_ARGB, 4, { - 'A', 8, 'R', 8, 'G', 8, 'B', 8}}, { - GST_VIDEO_CAPS_BGRA, 4, { - 'B', 8, 'G', 8, 'R', 8, 'A', 8}}, { - GST_VIDEO_CAPS_ABGR, 4, { - 'A', 8, 'B', 8, 'G', 8, 'R', 8}}, { - GST_VIDEO_CAPS_YUV ("AYUV"), 4, { - 'A', 8, 'Y', 8, 'U', 8, 'V', 8}} -}; - static MXFMetadataFileDescriptor * mxf_up_get_rgba_descriptor (GstPadTemplate * tmpl, GstCaps * caps, MXFEssenceElementWriteFunc * handler, gpointer * mapping_data) -- cgit v1.2.1 From a31498d8d48a6cb5a4ee38253c825391ff39bd7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 16 Mar 2009 17:18:17 +0100 Subject: mxf: Implement stride transformations for raw video content for muxing and demuxing --- gst/mxf/mxfup.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 100 insertions(+), 20 deletions(-) (limited to 'gst/mxf/mxfup.c') diff --git a/gst/mxf/mxfup.c b/gst/mxf/mxfup.c index 2a06a89c..35ad6221 100644 --- a/gst/mxf/mxfup.c +++ b/gst/mxf/mxfup.c @@ -24,7 +24,6 @@ /* TODO: * - Handle CDCI essence * - Handle more formats with RGBA descriptor (4:4:4 / 4:4:4:4 YUV, RGB656, ...) - * - Correctly transform for the GStreamer strides * - Handle all the dimensions and other properties in the picture * essence descriptors correctly according to S377M Annex E * - Handle interlaced correctly, i.e. weave until we support one-field-per-buffer @@ -50,36 +49,40 @@ static const struct const gchar *caps; guint32 n_pixel_layout; guint8 pixel_layout[10]; + guint32 fourcc; } _rgba_mapping_table[] = { { GST_VIDEO_CAPS_RGB, 3, { - 'R', 8, 'G', 8, 'B', 8}}, { + 'R', 8, 'G', 8, 'B', 8}, GST_MAKE_FOURCC ('R', 'G', 'B', ' ')}, { GST_VIDEO_CAPS_BGR, 3, { - 'B', 8, 'G', 8, 'R', 8}}, { + 'B', 8, 'G', 8, 'R', 8}, GST_MAKE_FOURCC ('B', 'G', 'R', ' ')}, { GST_VIDEO_CAPS_YUV ("v308"), 3, { - 'Y', 8, 'U', 8, 'V', 8}}, { + 'Y', 8, 'U', 8, 'V', 8}, GST_MAKE_FOURCC ('v', '3', '0', '8')}, { GST_VIDEO_CAPS_xRGB, 4, { - 'F', 8, 'R', 8, 'G', 8, 'B', 8}}, { + 'F', 8, 'R', 8, 'G', 8, 'B', 8}, GST_MAKE_FOURCC ('x', 'R', 'G', 'B')}, { GST_VIDEO_CAPS_RGBx, 4, { - 'R', 8, 'G', 8, 'B', 8, 'F', 8}}, { + 'R', 8, 'G', 8, 'B', 8, 'F', 8}, GST_MAKE_FOURCC ('R', 'G', 'B', 'x')}, { GST_VIDEO_CAPS_xBGR, 4, { - 'F', 8, 'B', 8, 'G', 8, 'R', 8}}, { + 'F', 8, 'B', 8, 'G', 8, 'R', 8}, GST_MAKE_FOURCC ('x', 'B', 'G', 'R')}, { GST_VIDEO_CAPS_BGRx, 4, { - 'B', 8, 'G', 8, 'R', 8, 'F', 8}}, { + 'B', 8, 'G', 8, 'R', 8, 'F', 8}, GST_MAKE_FOURCC ('B', 'G', 'R', 'x')}, { GST_VIDEO_CAPS_RGBA, 4, { - 'R', 8, 'G', 8, 'B', 8, 'A', 8}}, { + 'R', 8, 'G', 8, 'B', 8, 'A', 8}, GST_MAKE_FOURCC ('R', 'G', 'B', 'A')}, { GST_VIDEO_CAPS_ARGB, 4, { - 'A', 8, 'R', 8, 'G', 8, 'B', 8}}, { + 'A', 8, 'R', 8, 'G', 8, 'B', 8}, GST_MAKE_FOURCC ('A', 'R', 'G', 'B')}, { GST_VIDEO_CAPS_BGRA, 4, { - 'B', 8, 'G', 8, 'R', 8, 'A', 8}}, { + 'B', 8, 'G', 8, 'R', 8, 'A', 8}, GST_MAKE_FOURCC ('B', 'G', 'R', 'A')}, { GST_VIDEO_CAPS_ABGR, 4, { - 'A', 8, 'B', 8, 'G', 8, 'R', 8}}, { + 'A', 8, 'B', 8, 'G', 8, 'R', 8}, GST_MAKE_FOURCC ('A', 'B', 'G', 'R')}, { GST_VIDEO_CAPS_YUV ("AYUV"), 4, { - 'A', 8, 'Y', 8, 'U', 8, 'V', 8}} + 'A', 8, 'Y', 8, 'U', 8, 'V', 8}, GST_MAKE_FOURCC ('A', 'Y', 'U', 'V')} }; typedef struct { + guint32 fourcc; /* fourcc or RGB format specifier */ + gint width, height; + guint bpp; guint32 image_start_offset; guint32 image_end_offset; } MXFUPMappingData; @@ -127,7 +130,6 @@ mxf_up_handle_essence_element (const MXFUL * key, GstBuffer * buffer, } if (!data || (data->image_start_offset == 0 && data->image_end_offset == 0)) { - *outbuf = buffer; } else { if (data->image_start_offset + data->image_end_offset > GST_BUFFER_SIZE (buffer)) { @@ -138,10 +140,38 @@ mxf_up_handle_essence_element (const MXFUL * key, GstBuffer * buffer, GST_BUFFER_DATA (buffer) += data->image_start_offset; GST_BUFFER_SIZE (buffer) -= data->image_start_offset; GST_BUFFER_SIZE (buffer) -= data->image_end_offset; - *outbuf = buffer; } } + if (GST_BUFFER_SIZE (buffer) != data->bpp * data->width * data->height) { + GST_ERROR ("Invalid buffer size"); + return GST_FLOW_ERROR; + } + + if (data->bpp != 4 + || GST_ROUND_UP_4 (data->width * data->bpp) != data->width * data->bpp) { + guint y; + GstBuffer *ret; + guint8 *indata, *outdata; + + ret = + gst_buffer_new_and_alloc (GST_ROUND_UP_4 (data->width * data->bpp) * + data->height); + indata = GST_BUFFER_DATA (buffer); + outdata = GST_BUFFER_DATA (ret); + + for (y = 0; y < data->height; y++) { + memcpy (outdata, indata, data->width * data->bpp); + outdata += GST_ROUND_UP_4 (data->width * data->bpp); + indata += data->width * data->bpp; + } + + gst_buffer_unref (buffer); + *outbuf = ret; + } else { + *outbuf = buffer; + } + return GST_FLOW_OK; } @@ -152,6 +182,8 @@ mxf_up_rgba_create_caps (MXFMetadataTimelineTrack * track, { GstCaps *caps = NULL; guint i; + guint32 fourcc; + guint bpp; if (!d->pixel_layout) { GST_ERROR ("No pixel layout"); @@ -165,13 +197,24 @@ mxf_up_rgba_create_caps (MXFMetadataTimelineTrack * track, if (memcmp (d->pixel_layout, &_rgba_mapping_table[i].pixel_layout, _rgba_mapping_table[i].n_pixel_layout * 2) == 0) { caps = gst_caps_from_string (_rgba_mapping_table[i].caps); + fourcc = _rgba_mapping_table[i].fourcc; + bpp = _rgba_mapping_table[i].n_pixel_layout; break; } } if (caps) { MXFUPMappingData *data = g_new0 (MXFUPMappingData, 1); + GstStructure *s; + + mxf_metadata_generic_picture_essence_descriptor_set_caps (&d->parent, caps); + + s = gst_caps_get_structure (caps, 0); + gst_structure_get_int (s, "width", &data->width); + gst_structure_get_int (s, "height", &data->height); + data->fourcc = fourcc; + data->bpp = bpp; data->image_start_offset = ((MXFMetadataGenericPictureEssenceDescriptor *) d)->image_start_offset; data->image_end_offset = @@ -236,10 +279,6 @@ mxf_up_create_caps (MXFMetadataTimelineTrack * track, GstTagList ** tags, return NULL; } - if (caps) { - mxf_metadata_generic_picture_essence_descriptor_set_caps (p, caps); - } - return caps; } @@ -252,7 +291,40 @@ static GstFlowReturn mxf_up_write_func (GstBuffer * buffer, GstCaps * caps, gpointer mapping_data, GstAdapter * adapter, GstBuffer ** outbuf, gboolean flush) { - *outbuf = buffer; + MXFUPMappingData *data = mapping_data; + + if (!buffer) + return GST_FLOW_OK; + + if (GST_BUFFER_SIZE (buffer) != + GST_ROUND_UP_4 (data->bpp * data->width) * data->height) { + GST_ERROR ("Invalid buffer size"); + return GST_FLOW_ERROR; + } + + if (data->bpp != 4 + || GST_ROUND_UP_4 (data->width * data->bpp) != data->width * data->bpp) { + guint y; + GstBuffer *ret; + guint8 *indata, *outdata; + + ret = gst_buffer_new_and_alloc (data->width * data->bpp * data->height); + indata = GST_BUFFER_DATA (buffer); + outdata = GST_BUFFER_DATA (ret); + + for (y = 0; y < data->height; y++) { + memcpy (outdata, indata, data->width * data->bpp); + indata += GST_ROUND_UP_4 (data->width * data->bpp); + outdata += data->width * data->bpp; + } + + gst_buffer_unref (buffer); + + *outbuf = ret; + } else { + *outbuf = buffer; + } + return GST_FLOW_OK; } @@ -268,6 +340,9 @@ mxf_up_get_rgba_descriptor (GstPadTemplate * tmpl, GstCaps * caps, MXFMetadataRGBAPictureEssenceDescriptor *ret; guint i; GstCaps *tmp, *intersection; + MXFUPMappingData *md = g_new0 (MXFUPMappingData, 1); + + *mapping_data = md; ret = (MXFMetadataRGBAPictureEssenceDescriptor *) gst_mini_object_new (MXF_TYPE_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR); @@ -281,6 +356,8 @@ mxf_up_get_rgba_descriptor (GstPadTemplate * tmpl, GstCaps * caps, gst_caps_unref (intersection); ret->n_pixel_layout = _rgba_mapping_table[i].n_pixel_layout; ret->pixel_layout = g_new0 (guint8, ret->n_pixel_layout * 2); + md->fourcc = _rgba_mapping_table[i].fourcc; + md->bpp = _rgba_mapping_table[i].n_pixel_layout; memcpy (ret->pixel_layout, _rgba_mapping_table[i].pixel_layout, ret->n_pixel_layout * 2); break; @@ -293,6 +370,9 @@ mxf_up_get_rgba_descriptor (GstPadTemplate * tmpl, GstCaps * caps, mxf_metadata_generic_picture_essence_descriptor_from_caps (&ret->parent, caps); + md->width = ret->parent.stored_width; + md->height = ret->parent.stored_height; + *handler = mxf_up_write_func; return (MXFMetadataFileDescriptor *) ret; -- cgit v1.2.1 From c95ba980b2511c9bfc95ed2970c3d8b817e57aeb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 16 Mar 2009 17:22:22 +0100 Subject: mxfdemux: Use correct width/height for stride conversions --- gst/mxf/mxfup.c | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'gst/mxf/mxfup.c') diff --git a/gst/mxf/mxfup.c b/gst/mxf/mxfup.c index 35ad6221..3770c7da 100644 --- a/gst/mxf/mxfup.c +++ b/gst/mxf/mxfup.c @@ -205,14 +205,11 @@ mxf_up_rgba_create_caps (MXFMetadataTimelineTrack * track, if (caps) { MXFUPMappingData *data = g_new0 (MXFUPMappingData, 1); - GstStructure *s; mxf_metadata_generic_picture_essence_descriptor_set_caps (&d->parent, caps); - s = gst_caps_get_structure (caps, 0); - gst_structure_get_int (s, "width", &data->width); - gst_structure_get_int (s, "height", &data->height); - + data->width = d->parent.stored_width; + data->height = d->parent.stored_height; data->fourcc = fourcc; data->bpp = bpp; data->image_start_offset = -- cgit v1.2.1 From c6730cd2233bece0c4491873d322c1dfb1055bca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 16 Mar 2009 17:49:40 +0100 Subject: mxf: Add support for muxing/demuxing subsampled YUV formats --- gst/mxf/mxfup.c | 109 +++++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 105 insertions(+), 4 deletions(-) (limited to 'gst/mxf/mxfup.c') diff --git a/gst/mxf/mxfup.c b/gst/mxf/mxfup.c index 3770c7da..412a6622 100644 --- a/gst/mxf/mxfup.c +++ b/gst/mxf/mxfup.c @@ -78,6 +78,21 @@ static const struct 'A', 8, 'Y', 8, 'U', 8, 'V', 8}, GST_MAKE_FOURCC ('A', 'Y', 'U', 'V')} }; +static const struct +{ + const gchar *caps; + guint bpp; + guint horizontal_subsampling; + guint vertical_subsampling; + gboolean reversed_byte_order; + guint32 fourcc; +} _cdci_mapping_table[] = { + { + GST_VIDEO_CAPS_YUV ("YUY2"), 2, 1, 0, TRUE, GST_MAKE_FOURCC ('Y', 'U', 'Y', + '2')}, { +GST_VIDEO_CAPS_YUV ("UYVY"), 2, 1, 0, FALSE, GST_MAKE_FOURCC ('U', 'Y', 'V', + 'Y')},}; + typedef struct { guint32 fourcc; /* fourcc or RGB format specifier */ @@ -225,6 +240,52 @@ mxf_up_rgba_create_caps (MXFMetadataTimelineTrack * track, return caps; } +static GstCaps * +mxf_up_cdci_create_caps (MXFMetadataTimelineTrack * track, + MXFMetadataCDCIPictureEssenceDescriptor * d, GstTagList ** tags, + MXFEssenceElementHandleFunc * handler, gpointer * mapping_data) +{ + GstCaps *caps = NULL; + guint i; + guint32 fourcc; + guint bpp; + + for (i = 0; i < G_N_ELEMENTS (_cdci_mapping_table); i++) { + if (_cdci_mapping_table[i].horizontal_subsampling == + d->horizontal_subsampling + && _cdci_mapping_table[i].vertical_subsampling == + d->vertical_subsampling + && _cdci_mapping_table[i].reversed_byte_order == + d->reversed_byte_order) { + caps = gst_caps_from_string (_cdci_mapping_table[i].caps); + fourcc = _cdci_mapping_table[i].fourcc; + bpp = _cdci_mapping_table[i].bpp; + break; + } + } + + if (caps) { + MXFUPMappingData *data = g_new0 (MXFUPMappingData, 1); + + mxf_metadata_generic_picture_essence_descriptor_set_caps (&d->parent, caps); + + data->width = d->parent.stored_width; + data->height = d->parent.stored_height; + data->fourcc = fourcc; + data->bpp = bpp; + data->image_start_offset = + ((MXFMetadataGenericPictureEssenceDescriptor *) d)->image_start_offset; + data->image_end_offset = + ((MXFMetadataGenericPictureEssenceDescriptor *) d)->image_end_offset; + + *mapping_data = data; + } else { + GST_WARNING ("Unsupported CDCI format"); + } + + return caps; +} + static GstCaps * mxf_up_create_caps (MXFMetadataTimelineTrack * track, GstTagList ** tags, MXFEssenceElementHandleFunc * handler, gpointer * mapping_data) @@ -271,8 +332,9 @@ mxf_up_create_caps (MXFMetadataTimelineTrack * track, GstTagList ** tags, if (r) { caps = mxf_up_rgba_create_caps (track, r, tags, handler, mapping_data); + } else if (c) { + caps = mxf_up_cdci_create_caps (track, c, tags, handler, mapping_data); } else { - GST_ERROR ("CDCI uncompressed picture essence not supported yet"); return NULL; } @@ -379,8 +441,45 @@ static MXFMetadataFileDescriptor * mxf_up_get_cdci_descriptor (GstPadTemplate * tmpl, GstCaps * caps, MXFEssenceElementWriteFunc * handler, gpointer * mapping_data) { - g_assert_not_reached (); - return NULL; + MXFMetadataCDCIPictureEssenceDescriptor *ret; + guint i; + GstCaps *tmp, *intersection; + MXFUPMappingData *md = g_new0 (MXFUPMappingData, 1); + + *mapping_data = md; + + ret = (MXFMetadataCDCIPictureEssenceDescriptor *) + gst_mini_object_new (MXF_TYPE_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR); + + for (i = 0; i < G_N_ELEMENTS (_cdci_mapping_table); i++) { + tmp = gst_caps_from_string (_cdci_mapping_table[i].caps); + intersection = gst_caps_intersect (caps, tmp); + gst_caps_unref (tmp); + + if (!gst_caps_is_empty (intersection)) { + gst_caps_unref (intersection); + ret->horizontal_subsampling = + _cdci_mapping_table[i].horizontal_subsampling; + ret->vertical_subsampling = _cdci_mapping_table[i].vertical_subsampling; + ret->reversed_byte_order = _cdci_mapping_table[i].reversed_byte_order; + md->fourcc = _cdci_mapping_table[i].fourcc; + md->bpp = _cdci_mapping_table[i].bpp; + break; + } + gst_caps_unref (intersection); + } + + memcpy (&ret->parent.parent.essence_container, &up_essence_container_ul, 16); + + mxf_metadata_generic_picture_essence_descriptor_from_caps (&ret->parent, + caps); + + md->width = ret->parent.stored_width; + md->height = ret->parent.stored_height; + + *handler = mxf_up_write_func; + + return (MXFMetadataFileDescriptor *) ret; } static MXFMetadataFileDescriptor * @@ -457,7 +556,9 @@ mxf_up_init (void) GST_VIDEO_CAPS_RGBA "; " GST_VIDEO_CAPS_ABGR "; " GST_VIDEO_CAPS_BGRA "; " - GST_VIDEO_CAPS_YUV ("AYUV") "; " GST_VIDEO_CAPS_YUV ("v308"))); + GST_VIDEO_CAPS_YUV ("AYUV") "; " + GST_VIDEO_CAPS_YUV ("v308") "; " + GST_VIDEO_CAPS_YUV ("UYVY") "; " GST_VIDEO_CAPS_YUV ("YUY2"))); memcpy (&mxf_up_essence_element_writer.data_definition, mxf_metadata_track_identifier_get (MXF_METADATA_TRACK_PICTURE_ESSENCE), -- cgit v1.2.1 From effb5786da04e28effadc0602ef1ec5465458801 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 22 Mar 2009 15:51:37 +0100 Subject: mxfmux: Fix some memory leaks, improve debugging and handle errors better --- gst/mxf/mxfup.c | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) (limited to 'gst/mxf/mxfup.c') diff --git a/gst/mxf/mxfup.c b/gst/mxf/mxfup.c index 412a6622..a86a2c19 100644 --- a/gst/mxf/mxfup.c +++ b/gst/mxf/mxfup.c @@ -424,10 +424,20 @@ mxf_up_get_rgba_descriptor (GstPadTemplate * tmpl, GstCaps * caps, gst_caps_unref (intersection); } + if (md->fourcc == 0) { + GST_ERROR ("Invalid caps %" GST_PTR_FORMAT, caps); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (ret)); + return NULL; + } + + memcpy (&ret->parent.parent.essence_container, &up_essence_container_ul, 16); - mxf_metadata_generic_picture_essence_descriptor_from_caps (&ret->parent, - caps); + if (!mxf_metadata_generic_picture_essence_descriptor_from_caps (&ret->parent, + caps)) { + gst_mini_object_unref (GST_MINI_OBJECT_CAST (ret)); + return NULL; + } md->width = ret->parent.stored_width; md->height = ret->parent.stored_height; @@ -469,10 +479,19 @@ mxf_up_get_cdci_descriptor (GstPadTemplate * tmpl, GstCaps * caps, gst_caps_unref (intersection); } + if (md->fourcc == 0) { + GST_ERROR ("Invalid caps %" GST_PTR_FORMAT, caps); + gst_mini_object_unref (GST_MINI_OBJECT_CAST (ret)); + return NULL; + } + memcpy (&ret->parent.parent.essence_container, &up_essence_container_ul, 16); - mxf_metadata_generic_picture_essence_descriptor_from_caps (&ret->parent, - caps); + if (!mxf_metadata_generic_picture_essence_descriptor_from_caps (&ret->parent, + caps)) { + gst_mini_object_unref (GST_MINI_OBJECT_CAST (ret)); + return NULL; + } md->width = ret->parent.stored_width; md->height = ret->parent.stored_height; -- cgit v1.2.1