From abcc8554971b964ee697a158043afe213798af71 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Sun, 7 Dec 2008 17:16:29 +0000 Subject: [PATCH] gst/mxf/: Add initial support for uncompressed video essence (SMPTE S384M). Original commit message from CVS: * gst/mxf/Makefile.am: * gst/mxf/mxfdemux.c: (gst_mxf_demux_handle_header_metadata_update_streams): * gst/mxf/mxftypes.h: * gst/mxf/mxfup.c: (mxf_is_up_essence_track), (mxf_up_handle_essence_element), (mxf_up_rgba_create_caps), (mxf_up_create_caps): * gst/mxf/mxfup.h: Add initial support for uncompressed video essence (SMPTE S384M). * gst/mxf/mxfparse.c: (mxf_metadata_rgba_picture_essence_descriptor_handle_tag), (mxf_metadata_rgba_picture_essence_descriptor_reset): Fix parsing of the RGBA descriptor and add support for parsing the pixel layout. --- ChangeLog | 18 ++++ gst/mxf/Makefile.am | 9 +- gst/mxf/mxfdemux.c | 10 +- gst/mxf/mxfparse.c | 38 +++++++- gst/mxf/mxftypes.h | 5 +- gst/mxf/mxfup.c | 216 ++++++++++++++++++++++++++++++++++++++++++++ gst/mxf/mxfup.h | 36 ++++++++ 7 files changed, 325 insertions(+), 7 deletions(-) create mode 100644 gst/mxf/mxfup.c create mode 100644 gst/mxf/mxfup.h diff --git a/ChangeLog b/ChangeLog index 199c8b880e..a66bf9e419 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,21 @@ +2008-12-07 Sebastian Dröge + + * gst/mxf/Makefile.am: + * gst/mxf/mxfdemux.c: + (gst_mxf_demux_handle_header_metadata_update_streams): + * gst/mxf/mxftypes.h: + * gst/mxf/mxfup.c: (mxf_is_up_essence_track), + (mxf_up_handle_essence_element), (mxf_up_rgba_create_caps), + (mxf_up_create_caps): + * gst/mxf/mxfup.h: + Add initial support for uncompressed video essence (SMPTE S384M). + + * gst/mxf/mxfparse.c: + (mxf_metadata_rgba_picture_essence_descriptor_handle_tag), + (mxf_metadata_rgba_picture_essence_descriptor_reset): + Fix parsing of the RGBA descriptor and add support for parsing + the pixel layout. + 2008-12-06 Sebastian Dröge * gst/mxf/mxfdemux.c: (gst_mxf_demux_parse_footer_metadata): diff --git a/gst/mxf/Makefile.am b/gst/mxf/Makefile.am index 4b164c0765..16e2e85812 100644 --- a/gst/mxf/Makefile.am +++ b/gst/mxf/Makefile.am @@ -9,10 +9,12 @@ libgstmxf_la_SOURCES = \ mxfdv-dif.c \ mxfalaw.c \ mxfjpeg2000.c \ - mxfd10.c + mxfd10.c \ + mxfup.c -libgstmxf_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) -libgstmxf_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) +libgstmxf_la_CFLAGS = $(GST_CFLAGS) $(GST_BASE_CFLAGS) $(GST_PLUGINS_BASE_CFLAGS) +libgstmxf_la_LIBADD = $(GST_LIBS) $(GST_BASE_LIBS) $(GST_PLUGINS_BASE_LIBS) \ + -lgstvideo-@GST_MAJORMINOR@ libgstmxf_la_LDFLAGS = $(GST_PLUGIN_LDFLAGS) noinst_HEADERS = \ @@ -24,5 +26,6 @@ noinst_HEADERS = \ mxfalaw.h \ mxfjpeg2000.h \ mxfd10.h \ + mxfup.h \ mxftypes.h diff --git a/gst/mxf/mxfdemux.c b/gst/mxf/mxfdemux.c index e991011678..de3259d330 100644 --- a/gst/mxf/mxfdemux.c +++ b/gst/mxf/mxfdemux.c @@ -37,6 +37,7 @@ #include "mxfalaw.h" #include "mxfjpeg2000.h" #include "mxfd10.h" +#include "mxfup.h" #include @@ -1323,8 +1324,9 @@ gst_mxf_demux_handle_header_metadata_resolve_references (GstMXFDemux * demux) MXFMetadataEssenceContainerData, i); for (j = 0; j < demux->content_storage.n_essence_container_data; j++) { - if (mxf_ul_is_equal (&demux->content_storage. - essence_container_data_uids[j], &data->instance_uid)) { + if (mxf_ul_is_equal (&demux-> + content_storage.essence_container_data_uids[j], + &data->instance_uid)) { demux->content_storage.essence_container_data[j] = data; break; } @@ -1887,6 +1889,10 @@ gst_mxf_demux_handle_header_metadata_update_streams (GstMXFDemux * demux) caps = mxf_d10_create_caps (source_package, source_track, &pad->tags, &pad->handle_essence_element, &pad->mapping_data); + else if (mxf_is_up_essence_track (source_track)) + caps = + mxf_up_create_caps (source_package, source_track, + &pad->tags, &pad->handle_essence_element, &pad->mapping_data); break; case MXF_METADATA_TRACK_SOUND_ESSENCE: if (mxf_is_aes_bwf_essence_track (source_track)) diff --git a/gst/mxf/mxfparse.c b/gst/mxf/mxfparse.c index 212c694238..e2ff891ef6 100644 --- a/gst/mxf/mxfparse.c +++ b/gst/mxf/mxfparse.c @@ -2774,36 +2774,70 @@ gboolean goto error; descriptor->component_max_ref = GST_READ_UINT32_BE (tag_data); GST_DEBUG (" component max ref = %u", descriptor->component_max_ref); + ret = TRUE; break; case 0x3407: if (tag_size != 4) goto error; descriptor->component_min_ref = GST_READ_UINT32_BE (tag_data); GST_DEBUG (" component min ref = %u", descriptor->component_min_ref); + ret = TRUE; break; case 0x3408: if (tag_size != 4) goto error; descriptor->alpha_max_ref = GST_READ_UINT32_BE (tag_data); GST_DEBUG (" alpha max ref = %u", descriptor->alpha_max_ref); + ret = TRUE; break; case 0x3409: if (tag_size != 4) goto error; descriptor->alpha_min_ref = GST_READ_UINT32_BE (tag_data); GST_DEBUG (" alpha min ref = %u", descriptor->alpha_min_ref); + ret = TRUE; break; case 0x3405: if (tag_size != 1) goto error; descriptor->scanning_direction = GST_READ_UINT8 (tag_data); GST_DEBUG (" scanning direction = %u", descriptor->scanning_direction); + ret = TRUE; break; - case 0x3401: + case 0x3401:{ + guint i, len; + + if (tag_size % 2 != 0) + goto error; + + i = 0; + while (tag_data[i] != 0 && tag_data[i + 1] != 0 && i + 2 <= tag_size) + i += 2; + len = i / 2; + + descriptor->n_pixel_layout = len; + GST_DEBUG (" number of pixel layouts = %u", len); + if (len == 0) + return TRUE; + + descriptor->pixel_layout = g_malloc0 (2 * len); + + for (i = 0; i < len; i++) { + descriptor->pixel_layout[2 * i] = tag_data[2 * i]; + descriptor->pixel_layout[2 * i + 1] = tag_data[2 * i + 1]; + GST_DEBUG (" pixel layout %u = %c : %u", i, + (gchar) descriptor->pixel_layout[2 * i], + descriptor->pixel_layout[2 * i + 1]); + } + + ret = TRUE; + break; + } case 0x3403: case 0x3404: /* TODO: handle this */ GST_WARNING (" tag 0x%04x not implemented yet", tag); + ret = TRUE; break; default: ret = @@ -2829,6 +2863,8 @@ void mxf_metadata_rgba_picture_essence_descriptor_reset mxf_metadata_generic_picture_essence_descriptor_reset ( (MXFMetadataGenericPictureEssenceDescriptor *) descriptor); + g_free (descriptor->pixel_layout); + MXF_METADATA_DESCRIPTOR_CLEAR (descriptor, MXFMetadataRGBAPictureEssenceDescriptor, MXFMetadataGenericPictureEssenceDescriptor); diff --git a/gst/mxf/mxftypes.h b/gst/mxf/mxftypes.h index aaa3ec5c17..b66e0cc6ca 100644 --- a/gst/mxf/mxftypes.h +++ b/gst/mxf/mxftypes.h @@ -477,7 +477,10 @@ struct _MXFMetadataRGBAPictureEssenceDescriptor { guint32 alpha_min_ref; guint8 scanning_direction; - /* TODO: pixel layout, palette & palette layout */ + guint32 n_pixel_layout; + guint8 *pixel_layout; + + /* TODO: palette & palette layout */ }; struct _MXFMetadataGenericSoundEssenceDescriptor { diff --git a/gst/mxf/mxfup.c b/gst/mxf/mxfup.c new file mode 100644 index 0000000000..2d4017557c --- /dev/null +++ b/gst/mxf/mxfup.c @@ -0,0 +1,216 @@ +/* GStreamer + * Copyright (C) 2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* Implementation of SMPTE 384M - Mapping of Uncompressed Pictures into the MXF + * Generic Container + */ + +/* TODO: + * - Handle CDCI essence + * - Correctly transform for the GStreamer strides + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif + +#include +#include + +#include + +#include "mxfup.h" + +GST_DEBUG_CATEGORY_EXTERN (mxf_debug); +#define GST_CAT_DEFAULT mxf_debug + +gboolean +mxf_is_up_essence_track (const MXFMetadataTrack * track) +{ + guint i; + + g_return_val_if_fail (track != NULL, FALSE); + + if (track->descriptor == NULL) + return FALSE; + + for (i = 0; i < track->n_descriptor; i++) { + MXFMetadataFileDescriptor *d = track->descriptor[i]; + MXFUL *key = &d->essence_container; + /* SMPTE 384M 8 */ + if (mxf_is_generic_container_essence_container_label (key) && + key->u[12] == 0x02 && key->u[13] == 0x05 && key->u[15] <= 0x03) + return TRUE; + } + + return FALSE; +} + +static GstFlowReturn +mxf_up_handle_essence_element (const MXFUL * key, GstBuffer * buffer, + GstCaps * caps, MXFMetadataGenericPackage * package, + MXFMetadataTrack * track, MXFMetadataStructuralComponent * component, + gpointer mapping_data, GstBuffer ** outbuf) +{ + *outbuf = buffer; + + /* SMPTE 384M 7.1 */ + if (key->u[12] != 0x15 || (key->u[14] != 0x01 && key->u[14] != 0x02 + && key->u[14] != 0x03 && key->u[14] != 0x04)) { + GST_ERROR ("Invalid uncompressed picture essence element"); + return GST_FLOW_ERROR; + } + + return GST_FLOW_OK; +} + +static GstCaps * +mxf_up_rgba_create_caps (MXFMetadataGenericPackage * package, + MXFMetadataTrack * track, MXFMetadataRGBAPictureEssenceDescriptor * d, + GstTagList ** tags, + MXFEssenceElementHandler * handler, gpointer * mapping_data) +{ + GstCaps *caps = NULL; + + 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 { + 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 { + GST_ERROR ("Unsupport 4 component pixel layout"); + return NULL; + } + } else { + GST_ERROR ("Pixel layouts with %u components not supported yet", + d->n_pixel_layout); + return NULL; + } + + return caps; +} + +GstCaps * +mxf_up_create_caps (MXFMetadataGenericPackage * package, + MXFMetadataTrack * track, GstTagList ** tags, + MXFEssenceElementHandler * handler, gpointer * mapping_data) +{ + MXFMetadataGenericPictureEssenceDescriptor *p = NULL; + MXFMetadataCDCIPictureEssenceDescriptor *c = NULL; + MXFMetadataRGBAPictureEssenceDescriptor *r = NULL; + guint i; + GstCaps *caps = NULL; + + g_return_val_if_fail (package != NULL, NULL); + g_return_val_if_fail (track != NULL, NULL); + + if (track->descriptor == NULL) { + GST_ERROR ("No descriptor found for this track"); + return NULL; + } + + for (i = 0; i < track->n_descriptor; i++) { + if (((MXFMetadataGenericDescriptor *) track->descriptor[i])->type == + MXF_METADATA_RGBA_PICTURE_ESSENCE_DESCRIPTOR) { + p = (MXFMetadataGenericPictureEssenceDescriptor *) track->descriptor[i]; + r = (MXFMetadataRGBAPictureEssenceDescriptor *) track->descriptor[i]; + break; + } else if (((MXFMetadataGenericDescriptor *) track->descriptor[i])->type == + MXF_METADATA_CDCI_PICTURE_ESSENCE_DESCRIPTOR) { + p = (MXFMetadataGenericPictureEssenceDescriptor *) track->descriptor[i]; + c = (MXFMetadataCDCIPictureEssenceDescriptor *) track->descriptor[i]; + } + } + + if (!p) { + GST_ERROR ("No picture essence descriptor found for this track"); + return NULL; + } + + *handler = mxf_up_handle_essence_element; + + if (r) { + caps = + mxf_up_rgba_create_caps (package, track, r, tags, handler, + mapping_data); + } else { + GST_ERROR ("CDCI uncompressed picture essence not supported yet"); + return NULL; + } + + if (caps) { + mxf_metadata_generic_picture_essence_descriptor_set_caps (p, caps); + } + + return caps; +} diff --git a/gst/mxf/mxfup.h b/gst/mxf/mxfup.h new file mode 100644 index 0000000000..66fc849df0 --- /dev/null +++ b/gst/mxf/mxfup.h @@ -0,0 +1,36 @@ +/* GStreamer + * Copyright (C) 2008 Sebastian Dröge + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Library General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Library General Public License for more details. + * + * You should have received a copy of the GNU Library General Public + * License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +/* Implementation of SMPTE 384M - Mapping of Uncompressed Pictures into the MXF + * Generic Container + */ + +#ifndef __MXF_UP_H__ +#define __MXF_UP_H__ + +#include + +#include "mxfparse.h" + +gboolean mxf_is_up_essence_track (const MXFMetadataTrack *track); + +GstCaps * +mxf_up_create_caps (MXFMetadataGenericPackage *package, MXFMetadataTrack *track, GstTagList **tags, MXFEssenceElementHandler *handler, gpointer *mapping_data); + +#endif /* __MXF_UP_H__ */