#define GST_RIFF_LIST_INFO GST_MAKE_FOURCC ('I','N','F','O')
#define GST_RIFF_LIST_AVIX GST_MAKE_FOURCC ('A','V','I','X')
#define GST_RIFF_LIST_adtl GST_MAKE_FOURCC ('a','d','t','l')
+#define GST_RIFF_LIST_ncdt GST_MAKE_FOURCC ('n','c','d','t')
/* fcc types */
#define GST_RIFF_FCC_vids GST_MAKE_FOURCC ('v','i','d','s')
#define GST_RIFF_INFO_IAAR GST_MAKE_FOURCC ('I','A','A','R') /* album artist */
#define GST_RIFF_INFO_ITRK GST_MAKE_FOURCC ('I','T','R','K') /* track number */
+/* ncdt types - see http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCDT */
+#define GST_RIFF_LIST_nctg GST_MAKE_FOURCC ('n','c','t','g')
+
/*********Chunk Names***************/
#define GST_RIFF_FF00 GST_MAKE_FOURCC (0xFF,0xFF,0x00,0x00)
#define GST_RIFF_00 GST_MAKE_FOURCC ('0', '0',0x00,0x00)
}
}
+static void
+parse_tag_value (GstElement * element, GstTagList * taglist, const gchar * type,
+ guint8 * ptr, guint tsize)
+{
+ static const gchar *env_vars[] = { "GST_AVI_TAG_ENCODING",
+ "GST_RIFF_TAG_ENCODING", "GST_TAG_ENCODING", NULL
+ };
+ GType tag_type;
+ gchar *val;
+
+ tag_type = gst_tag_get_type (type);
+ val = gst_tag_freeform_string_to_utf8 ((gchar *) ptr, tsize, env_vars);
+
+ if (val != NULL) {
+ if (tag_type == G_TYPE_STRING) {
+ gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, type, val, NULL);
+ } else {
+ GValue tag_val = { 0, };
+
+ g_value_init (&tag_val, tag_type);
+ if (gst_value_deserialize (&tag_val, val)) {
+ gst_tag_list_add_value (taglist, GST_TAG_MERGE_APPEND, type, &tag_val);
+ } else {
+ GST_WARNING_OBJECT (element, "could not deserialize '%s' into a "
+ "tag %s of type %s", val, type, g_type_name (tag_type));
+ }
+ g_value_unset (&tag_val);
+ }
+ g_free (val);
+ } else {
+ GST_WARNING_OBJECT (element, "could not extract %s tag", type);
+ }
+}
+
/**
* gst_riff_parse_info:
* @element: caller element (used for debugging/error).
}
if (type != NULL && ptr[0] != '\0') {
- static const gchar *env_vars[] = { "GST_AVI_TAG_ENCODING",
- "GST_RIFF_TAG_ENCODING", "GST_TAG_ENCODING", NULL
- };
- GType tag_type;
- gchar *val;
-
GST_DEBUG_OBJECT (element, "mapped tag %" GST_FOURCC_FORMAT " to tag %s",
GST_FOURCC_ARGS (tag), type);
- tag_type = gst_tag_get_type (type);
- val = gst_tag_freeform_string_to_utf8 ((gchar *) ptr, tsize, env_vars);
-
- if (val != NULL) {
- if (tag_type == G_TYPE_STRING) {
- gst_tag_list_add (taglist, GST_TAG_MERGE_APPEND, type, val, NULL);
- } else {
- GValue tag_val = { 0, };
-
- g_value_init (&tag_val, tag_type);
- if (gst_value_deserialize (&tag_val, val)) {
- gst_tag_list_add_value (taglist, GST_TAG_MERGE_APPEND, type,
- &tag_val);
- } else {
- GST_WARNING_OBJECT (element, "could not deserialize '%s' into a "
- "tag %s of type %s", val, type, g_type_name (tag_type));
- }
- g_value_unset (&tag_val);
- }
- g_free (val);
- } else {
- GST_WARNING_OBJECT (element, "could not extract %s tag", type);
- }
+ parse_tag_value (element, taglist, type, ptr, tsize);
}
if (tsize & 1) {
return;
}
+
+/**
+ * gst_riff_parse_ncdt:
+ * @element: caller element (used for debugging/error).
+ * @buf: input data to be used for parsing, stripped from header.
+ * @taglist: a pointer to a taglist (returned by this function)
+ * containing information about this stream. May be
+ * NULL if no supported tags were found.
+ *
+ * Parses Nikon metadata from input data.
+ *
+ * Since: 1.4
+ */
+void
+gst_riff_parse_ncdt (GstElement * element,
+ GstBuffer * buf, GstTagList ** _taglist)
+{
+ GstMapInfo info;
+ guint8 *ptr;
+ gsize left;
+ guint tsize;
+ guint32 tag;
+ const gchar *type;
+ GstTagList *taglist;
+
+ g_return_if_fail (_taglist != NULL);
+
+ if (!buf) {
+ *_taglist = NULL;
+ return;
+ }
+ gst_buffer_map (buf, &info, GST_MAP_READ);
+
+ taglist = gst_tag_list_new_empty ();
+
+ ptr = info.data;
+ left = info.size;
+
+ while (left > 8) {
+ tag = GST_READ_UINT32_LE (ptr);
+ tsize = GST_READ_UINT32_LE (ptr + 4);
+
+ GST_MEMDUMP_OBJECT (element, "tag chunk", ptr, MIN (tsize + 8, left));
+
+ left -= 8;
+ ptr += 8;
+
+ GST_DEBUG ("tag %" GST_FOURCC_FORMAT ", size %u",
+ GST_FOURCC_ARGS (tag), tsize);
+
+ if (tsize > left) {
+ GST_WARNING_OBJECT (element,
+ "Tagsize %d is larger than available data %" G_GSIZE_FORMAT,
+ tsize, left);
+ tsize = left;
+ }
+
+ /* find out the type of metadata */
+ switch (tag) {
+ case GST_RIFF_LIST_nctg:{
+ while (tsize > 4) {
+ guint16 sub_tag = GST_READ_UINT16_LE (ptr);
+ guint16 sub_size = GST_READ_UINT16_LE (ptr + 2);
+
+ tsize -= 4;
+ ptr += 4;
+
+ GST_DEBUG ("sub-tag %u, size %u", sub_tag, sub_size);
+ /* http://www.sno.phy.queensu.ca/~phil/exiftool/TagNames/Nikon.html#NCTG
+ * for some reason the sub_tag has a +2 offset
+ */
+ switch (sub_tag) {
+ case 0x03: /* Make */
+ type = GST_TAG_DEVICE_MANUFACTURER;
+ break;
+ case 0x04: /* Model */
+ type = GST_TAG_DEVICE_MODEL;
+ break;
+ /* TODO: 0x05: is software version, like V1.0 */
+ case 0x06: /* Software */
+ type = GST_TAG_ENCODER;
+ break;
+ case 0x13: /* CreationDate */
+ type = GST_TAG_DATE_TIME;
+ if (ptr[4] == ':')
+ ptr[4] = '-';
+ if (ptr[7] == ':')
+ ptr[7] = '-';
+ break;
+ default:
+ type = NULL;
+ break;
+ }
+ if (type != NULL && ptr[0] != '\0') {
+ GST_DEBUG_OBJECT (element, "mapped tag %u to tag %s", sub_tag,
+ type);
+
+ parse_tag_value (element, taglist, type, ptr, sub_size);
+ }
+
+ ptr += sub_size;
+ tsize -= sub_size;
+ }
+ break;
+ default:
+ type = NULL;
+ GST_WARNING_OBJECT (element,
+ "Unknown ncdt (metadata) tag entry %" GST_FOURCC_FORMAT,
+ GST_FOURCC_ARGS (tag));
+ break;
+ }
+
+ if (tsize & 1) {
+ tsize++;
+ if (tsize > left)
+ tsize = left;
+ }
+
+ ptr += tsize;
+ left -= tsize;
+ }
+
+ if (!gst_tag_list_is_empty (taglist)) {
+ GST_INFO_OBJECT (element, "extracted tags: %" GST_PTR_FORMAT, taglist);
+ *_taglist = taglist;
+ } else {
+ *_taglist = NULL;
+ gst_tag_list_unref (taglist);
+ }
+ gst_buffer_unmap (buf, &info);
+
+ return;
+ }