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") "; " 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), 16); mxf_essence_element_writer_register (&mxf_up_essence_element_writer); }
void mxf_alaw_init (void) { mxf_essence_element_handler_register (&mxf_alaw_essence_element_handler); mxf_alaw_essence_element_writer.pad_template = gst_pad_template_new ("alaw_audio_sink_%u", GST_PAD_SINK, GST_PAD_REQUEST, gst_caps_from_string (ALAW_CAPS)); memcpy (&mxf_alaw_essence_element_writer.data_definition, mxf_metadata_track_identifier_get (MXF_METADATA_TRACK_SOUND_ESSENCE), 16); mxf_essence_element_writer_register (&mxf_alaw_essence_element_writer); }
void mxf_vc3_init (void) { mxf_essence_element_handler_register (&mxf_vc3_essence_element_handler); mxf_vc3_essence_element_writer.pad_template = gst_pad_template_new ("vc3_video_sink_%u", GST_PAD_SINK, GST_PAD_REQUEST, gst_caps_from_string ("video/x-dnxhd, width = " GST_VIDEO_SIZE_RANGE ", height = " GST_VIDEO_SIZE_RANGE ", framerate = " GST_VIDEO_FPS_RANGE)); memcpy (&mxf_vc3_essence_element_writer.data_definition, mxf_metadata_track_identifier_get (MXF_METADATA_TRACK_PICTURE_ESSENCE), 16); mxf_essence_element_writer_register (&mxf_vc3_essence_element_writer); }
void mxf_jpeg2000_init (void) { mxf_essence_element_handler_register (&mxf_jpeg2000_essence_element_handler); mxf_jpeg2000_essence_element_writer.pad_template = gst_pad_template_new ("jpeg2000_video_sink_%u", GST_PAD_SINK, GST_PAD_REQUEST, gst_caps_from_string ("image/x-jpc, fields = 1, width = " GST_VIDEO_SIZE_RANGE ", height = " GST_VIDEO_SIZE_RANGE ", framerate = " GST_VIDEO_FPS_RANGE ", fourcc = (GstFourcc) { sRGB, sYUV }")); memcpy (&mxf_jpeg2000_essence_element_writer.data_definition, mxf_metadata_track_identifier_get (MXF_METADATA_TRACK_PICTURE_ESSENCE), 16); mxf_essence_element_writer_register (&mxf_jpeg2000_essence_element_writer); }
static GstFlowReturn gst_mxf_mux_create_metadata (GstMXFMux * mux) { GstFlowReturn ret = GST_FLOW_OK; GSList *l; GArray *tmp; GST_DEBUG_OBJECT (mux, "Creating MXF metadata"); for (l = mux->collect->data; l; l = l->next) { GstMXFMuxPad *cpad = l->data; if (!cpad || !cpad->descriptor || !GST_PAD_CAPS (cpad->collect.pad)) return GST_FLOW_ERROR; if (cpad->writer->update_descriptor) cpad->writer->update_descriptor (cpad->descriptor, GST_PAD_CAPS (cpad->collect.pad), cpad->mapping_data, cpad->collect.buffer); } /* Preface */ mux->preface = (MXFMetadataPreface *) gst_mini_object_new (MXF_TYPE_METADATA_PREFACE); mxf_uuid_init (&MXF_METADATA_BASE (mux->preface)->instance_uid, mux->metadata); g_hash_table_insert (mux->metadata, &MXF_METADATA_BASE (mux->preface)->instance_uid, mux->preface); mux->metadata_list = g_list_prepend (mux->metadata_list, mux->preface); mxf_timestamp_set_now (&mux->preface->last_modified_date); mux->preface->version = 258; mux->preface->object_model_version = 1; mxf_op_set_generalized (&mux->preface->operational_pattern, MXF_OP_1a, TRUE, TRUE, FALSE); tmp = g_array_new (FALSE, FALSE, sizeof (MXFUL)); for (l = mux->collect->data; l; l = l->next) { GstMXFMuxPad *cpad = l->data; guint i; gboolean found = FALSE; if (!cpad || !cpad->descriptor || mxf_ul_is_zero (&cpad->descriptor->essence_container)) return GST_FLOW_ERROR; for (i = 0; i < tmp->len; i++) { if (mxf_ul_is_equal (&cpad->descriptor->essence_container, &g_array_index (tmp, MXFUL, i))) { found = TRUE; break; } } if (found) continue; g_array_append_val (tmp, cpad->descriptor->essence_container); } mux->preface->n_essence_containers = tmp->len; mux->preface->essence_containers = (MXFUL *) g_array_free (tmp, FALSE); /* This will later be used as UID for the material package */ mxf_uuid_init (&mux->preface->primary_package_uid, mux->metadata); /* Identifications */ { MXFMetadataIdentification *identification; static const guint8 gst_uid[] = { 0xe5, 0xde, 0xcd, 0x04, 0x24, 0x90, 0x69, 0x18, 0x8a, 0xc9, 0xb5, 0xd7, 0x02, 0x58, 0x46, 0x78 }; guint major, minor, micro, nano; mux->preface->n_identifications = 1; mux->preface->identifications = g_new0 (MXFMetadataIdentification *, 1); identification = mux->preface->identifications[0] = (MXFMetadataIdentification *) gst_mini_object_new (MXF_TYPE_METADATA_IDENTIFICATION); mxf_uuid_init (&MXF_METADATA_BASE (identification)->instance_uid, mux->metadata); g_hash_table_insert (mux->metadata, &MXF_METADATA_BASE (identification)->instance_uid, identification); mux->metadata_list = g_list_prepend (mux->metadata_list, identification); mxf_uuid_init (&identification->this_generation_uid, NULL); identification->company_name = g_strdup ("GStreamer"); identification->product_name = g_strdup ("GStreamer Multimedia Framework"); gst_version (&major, &minor, µ, &nano); identification->product_version.major = major; identification->product_version.minor = minor; identification->product_version.patch = micro; identification->product_version.build = nano; identification->product_version.release = (nano == 0) ? 1 : (nano == 1) ? 2 : 4; identification->version_string = g_strdup_printf ("%u.%u.%u.%u", major, minor, micro, nano); memcpy (&identification->product_uid, &gst_uid, 16); memcpy (&identification->modification_date, &mux->preface->last_modified_date, sizeof (MXFTimestamp)); memcpy (&identification->toolkit_version, &identification->product_version, sizeof (MXFProductVersion)); #ifdef HAVE_SYS_UTSNAME_H { struct utsname sys_details; if (uname (&sys_details) == 0) { identification->platform = g_strdup_printf ("%s %s %s", sys_details.sysname, sys_details.release, sys_details.machine); } } #endif #if defined(G_OS_WIN32) if (identification->platform == NULL) identification->platform = g_strdup ("Microsoft Windows"); #elif defined(G_OS_BEOS) if (identification->platform == NULL) identification->platform = g_strdup ("BEOS"); #elif defined(G_OS_UNIX) if (identification->platform == NULL) identification->platform = g_strdup ("Unix"); #endif } /* Content storage */ { MXFMetadataContentStorage *cstorage; guint i; cstorage = mux->preface->content_storage = (MXFMetadataContentStorage *) gst_mini_object_new (MXF_TYPE_METADATA_CONTENT_STORAGE); mxf_uuid_init (&MXF_METADATA_BASE (cstorage)->instance_uid, mux->metadata); g_hash_table_insert (mux->metadata, &MXF_METADATA_BASE (cstorage)->instance_uid, cstorage); mux->metadata_list = g_list_prepend (mux->metadata_list, cstorage); cstorage->n_packages = 2; cstorage->packages = g_new0 (MXFMetadataGenericPackage *, 2); /* Source package */ { MXFMetadataSourcePackage *p; cstorage->packages[1] = (MXFMetadataGenericPackage *) gst_mini_object_new (MXF_TYPE_METADATA_SOURCE_PACKAGE); mxf_uuid_init (&MXF_METADATA_BASE (cstorage->packages[1])->instance_uid, mux->metadata); g_hash_table_insert (mux->metadata, &MXF_METADATA_BASE (cstorage->packages[1])->instance_uid, cstorage->packages[1]); mux->metadata_list = g_list_prepend (mux->metadata_list, cstorage->packages[1]); p = (MXFMetadataSourcePackage *) cstorage->packages[1]; mxf_umid_init (&p->parent.package_uid); p->parent.name = g_strdup ("Source package"); memcpy (&p->parent.package_creation_date, &mux->preface->last_modified_date, sizeof (MXFTimestamp)); memcpy (&p->parent.package_modified_date, &mux->preface->last_modified_date, sizeof (MXFTimestamp)); p->parent.n_tracks = g_slist_length (mux->collect->data); p->parent.tracks = g_new0 (MXFMetadataTrack *, p->parent.n_tracks); if (p->parent.n_tracks > 1) { MXFMetadataMultipleDescriptor *d; p->descriptor = (MXFMetadataGenericDescriptor *) gst_mini_object_new (MXF_TYPE_METADATA_MULTIPLE_DESCRIPTOR); d = (MXFMetadataMultipleDescriptor *) p->descriptor; d->n_sub_descriptors = p->parent.n_tracks; d->sub_descriptors = g_new0 (MXFMetadataGenericDescriptor *, p->parent.n_tracks); mxf_uuid_init (&MXF_METADATA_BASE (d)->instance_uid, mux->metadata); g_hash_table_insert (mux->metadata, &MXF_METADATA_BASE (d)->instance_uid, d); mux->metadata_list = g_list_prepend (mux->metadata_list, d); } /* Tracks */ { guint n = 0; /* Essence tracks */ for (l = mux->collect->data; l; l = l->next) { GstMXFMuxPad *cpad = l->data; MXFMetadataTimelineTrack *track; MXFMetadataSequence *sequence; MXFMetadataSourceClip *clip; p->parent.tracks[n] = (MXFMetadataTrack *) gst_mini_object_new (MXF_TYPE_METADATA_TIMELINE_TRACK); track = (MXFMetadataTimelineTrack *) p->parent.tracks[n]; mxf_uuid_init (&MXF_METADATA_BASE (track)->instance_uid, mux->metadata); g_hash_table_insert (mux->metadata, &MXF_METADATA_BASE (track)->instance_uid, track); mux->metadata_list = g_list_prepend (mux->metadata_list, track); track->parent.track_id = n + 1; track->parent.track_number = cpad->writer->get_track_number_template (cpad->descriptor, GST_PAD_CAPS (cpad->collect.pad), cpad->mapping_data); cpad->writer->get_edit_rate (cpad->descriptor, GST_PAD_CAPS (cpad->collect.pad), cpad->mapping_data, cpad->collect.buffer, p, track, &track->edit_rate); sequence = track->parent.sequence = (MXFMetadataSequence *) gst_mini_object_new (MXF_TYPE_METADATA_SEQUENCE); mxf_uuid_init (&MXF_METADATA_BASE (sequence)->instance_uid, mux->metadata); g_hash_table_insert (mux->metadata, &MXF_METADATA_BASE (sequence)->instance_uid, sequence); mux->metadata_list = g_list_prepend (mux->metadata_list, sequence); memcpy (&sequence->data_definition, &cpad->writer->data_definition, 16); sequence->n_structural_components = 1; sequence->structural_components = g_new0 (MXFMetadataStructuralComponent *, 1); clip = (MXFMetadataSourceClip *) gst_mini_object_new (MXF_TYPE_METADATA_SOURCE_CLIP); sequence->structural_components[0] = (MXFMetadataStructuralComponent *) clip; mxf_uuid_init (&MXF_METADATA_BASE (clip)->instance_uid, mux->metadata); g_hash_table_insert (mux->metadata, &MXF_METADATA_BASE (clip)->instance_uid, clip); mux->metadata_list = g_list_prepend (mux->metadata_list, clip); memcpy (&clip->parent.data_definition, &sequence->data_definition, 16); clip->start_position = 0; cpad->source_package = p; cpad->source_track = track; cpad->descriptor->linked_track_id = n + 1; if (p->parent.n_tracks == 1) { p->descriptor = (MXFMetadataGenericDescriptor *) cpad->descriptor; } else { MXF_METADATA_MULTIPLE_DESCRIPTOR (p->descriptor)-> sub_descriptors[n] = (MXFMetadataGenericDescriptor *) cpad->descriptor; } n++; } } } /* Material package */ { MXFMetadataMaterialPackage *p; MXFFraction min_edit_rate = { 0, 0 }; gdouble min_edit_rate_d = G_MAXDOUBLE; cstorage->packages[0] = (MXFMetadataGenericPackage *) gst_mini_object_new (MXF_TYPE_METADATA_MATERIAL_PACKAGE); memcpy (&MXF_METADATA_BASE (cstorage->packages[0])->instance_uid, &mux->preface->primary_package_uid, 16); g_hash_table_insert (mux->metadata, &MXF_METADATA_BASE (cstorage->packages[0])->instance_uid, cstorage->packages[0]); mux->metadata_list = g_list_prepend (mux->metadata_list, cstorage->packages[0]); p = (MXFMetadataMaterialPackage *) cstorage->packages[0]; mxf_umid_init (&p->package_uid); p->name = g_strdup ("Material package"); memcpy (&p->package_creation_date, &mux->preface->last_modified_date, sizeof (MXFTimestamp)); memcpy (&p->package_modified_date, &mux->preface->last_modified_date, sizeof (MXFTimestamp)); p->n_tracks = g_slist_length (mux->collect->data) + 1; p->tracks = g_new0 (MXFMetadataTrack *, p->n_tracks); /* Tracks */ { guint n; n = 1; /* Essence tracks */ for (l = mux->collect->data; l; l = l->next) { GstMXFMuxPad *cpad = l->data; MXFMetadataSourcePackage *source_package; MXFMetadataTimelineTrack *track, *source_track; MXFMetadataSequence *sequence; MXFMetadataSourceClip *clip; source_package = MXF_METADATA_SOURCE_PACKAGE (cstorage->packages[1]); source_track = MXF_METADATA_TIMELINE_TRACK (source_package->parent.tracks[n - 1]); p->tracks[n] = (MXFMetadataTrack *) gst_mini_object_new (MXF_TYPE_METADATA_TIMELINE_TRACK); track = (MXFMetadataTimelineTrack *) p->tracks[n]; mxf_uuid_init (&MXF_METADATA_BASE (track)->instance_uid, mux->metadata); g_hash_table_insert (mux->metadata, &MXF_METADATA_BASE (track)->instance_uid, track); mux->metadata_list = g_list_prepend (mux->metadata_list, track); track->parent.track_id = n + 1; track->parent.track_number = 0; cpad->writer->get_edit_rate (cpad->descriptor, GST_PAD_CAPS (cpad->collect.pad), cpad->mapping_data, cpad->collect.buffer, source_package, source_track, &track->edit_rate); if (track->edit_rate.n != source_track->edit_rate.n || track->edit_rate.d != source_track->edit_rate.d) { memcpy (&source_track->edit_rate, &track->edit_rate, sizeof (MXFFraction)); } if (track->edit_rate.d <= 0 || track->edit_rate.n <= 0) { GST_ERROR_OBJECT (mux, "Invalid edit rate"); return GST_FLOW_ERROR; } if (min_edit_rate_d > ((gdouble) track->edit_rate.n) / ((gdouble) track->edit_rate.d)) { min_edit_rate_d = ((gdouble) track->edit_rate.n) / ((gdouble) track->edit_rate.d); memcpy (&min_edit_rate, &track->edit_rate, sizeof (MXFFraction)); } sequence = track->parent.sequence = (MXFMetadataSequence *) gst_mini_object_new (MXF_TYPE_METADATA_SEQUENCE); mxf_uuid_init (&MXF_METADATA_BASE (sequence)->instance_uid, mux->metadata); g_hash_table_insert (mux->metadata, &MXF_METADATA_BASE (sequence)->instance_uid, sequence); mux->metadata_list = g_list_prepend (mux->metadata_list, sequence); memcpy (&sequence->data_definition, &cpad->writer->data_definition, 16); sequence->n_structural_components = 1; sequence->structural_components = g_new0 (MXFMetadataStructuralComponent *, 1); clip = (MXFMetadataSourceClip *) gst_mini_object_new (MXF_TYPE_METADATA_SOURCE_CLIP); sequence->structural_components[0] = (MXFMetadataStructuralComponent *) clip; mxf_uuid_init (&MXF_METADATA_BASE (clip)->instance_uid, mux->metadata); g_hash_table_insert (mux->metadata, &MXF_METADATA_BASE (clip)->instance_uid, clip); mux->metadata_list = g_list_prepend (mux->metadata_list, clip); memcpy (&clip->parent.data_definition, &sequence->data_definition, 16); clip->start_position = 0; memcpy (&clip->source_package_id, &cstorage->packages[1]->package_uid, 32); clip->source_track_id = n; n++; } n = 0; /* Timecode track */ { MXFMetadataTimelineTrack *track; MXFMetadataSequence *sequence; MXFMetadataTimecodeComponent *component; p->tracks[n] = (MXFMetadataTrack *) gst_mini_object_new (MXF_TYPE_METADATA_TIMELINE_TRACK); track = (MXFMetadataTimelineTrack *) p->tracks[n]; mxf_uuid_init (&MXF_METADATA_BASE (track)->instance_uid, mux->metadata); g_hash_table_insert (mux->metadata, &MXF_METADATA_BASE (track)->instance_uid, track); mux->metadata_list = g_list_prepend (mux->metadata_list, track); track->parent.track_id = n + 1; track->parent.track_number = 0; track->parent.track_name = g_strdup ("Timecode track"); /* FIXME: Is this correct? */ memcpy (&track->edit_rate, &min_edit_rate, sizeof (MXFFraction)); sequence = track->parent.sequence = (MXFMetadataSequence *) gst_mini_object_new (MXF_TYPE_METADATA_SEQUENCE); mxf_uuid_init (&MXF_METADATA_BASE (sequence)->instance_uid, mux->metadata); g_hash_table_insert (mux->metadata, &MXF_METADATA_BASE (sequence)->instance_uid, sequence); mux->metadata_list = g_list_prepend (mux->metadata_list, sequence); memcpy (&sequence->data_definition, mxf_metadata_track_identifier_get (MXF_METADATA_TRACK_TIMECODE_12M_INACTIVE), 16); sequence->n_structural_components = 1; sequence->structural_components = g_new0 (MXFMetadataStructuralComponent *, 1); component = (MXFMetadataTimecodeComponent *) gst_mini_object_new (MXF_TYPE_METADATA_TIMECODE_COMPONENT); sequence->structural_components[0] = (MXFMetadataStructuralComponent *) component; mxf_uuid_init (&MXF_METADATA_BASE (component)->instance_uid, mux->metadata); g_hash_table_insert (mux->metadata, &MXF_METADATA_BASE (component)->instance_uid, component); mux->metadata_list = g_list_prepend (mux->metadata_list, component); memcpy (&component->parent.data_definition, &sequence->data_definition, 16); component->start_timecode = 0; component->rounded_timecode_base = (((gdouble) track->edit_rate.n) / ((gdouble) track->edit_rate.d) + 0.5); /* TODO: drop frame */ } memcpy (&mux->min_edit_rate, &min_edit_rate, sizeof (MXFFraction)); } } for (i = 0; i < cstorage->packages[1]->n_tracks; i++) { MXFMetadataTrack *track = cstorage->packages[1]->tracks[i]; guint j; guint32 templ; guint8 n_type, n; if ((track->track_number & 0x00ff00ff) != 0) continue; templ = track->track_number; n_type = 0; for (j = 0; j < cstorage->packages[1]->n_tracks; j++) { MXFMetadataTrack *tmp = cstorage->packages[1]->tracks[j]; if (tmp->track_number == templ) { n_type++; } } n = 0; for (j = 0; j < cstorage->packages[1]->n_tracks; j++) { MXFMetadataTrack *tmp = cstorage->packages[1]->tracks[j]; if (tmp->track_number == templ) { n++; tmp->track_number |= (n_type << 16) | (n); } } } cstorage->n_essence_container_data = 1; cstorage->essence_container_data = g_new0 (MXFMetadataEssenceContainerData *, 1); cstorage->essence_container_data[0] = (MXFMetadataEssenceContainerData *) gst_mini_object_new (MXF_TYPE_METADATA_ESSENCE_CONTAINER_DATA); mxf_uuid_init (&MXF_METADATA_BASE (cstorage->essence_container_data[0])-> instance_uid, mux->metadata); g_hash_table_insert (mux->metadata, &MXF_METADATA_BASE (cstorage->essence_container_data[0])->instance_uid, cstorage->essence_container_data[0]); mux->metadata_list = g_list_prepend (mux->metadata_list, cstorage->essence_container_data[0]); cstorage->essence_container_data[0]->linked_package = MXF_METADATA_SOURCE_PACKAGE (cstorage->packages[1]); cstorage->essence_container_data[0]->index_sid = 0; cstorage->essence_container_data[0]->body_sid = 1; }