static inline gboolean gst_jpeg_parse_remove_marker (GstJpegParse * parse, GstByteReader * reader, guint8 marker, GstBuffer * buffer) { guint16 size = 0; guint pos = gst_byte_reader_get_pos (reader); guint8 *data; gsize bsize; if (!gst_byte_reader_peek_uint16_be (reader, &size)) return FALSE; if (gst_byte_reader_get_remaining (reader) < size) return FALSE; GST_LOG_OBJECT (parse, "unhandled marker %x removing %u bytes", marker, size); data = gst_buffer_map (buffer, &bsize, NULL, GST_MAP_READWRITE); memmove (&data[pos], &data[pos + size], bsize - (pos + size)); gst_buffer_unmap (buffer, data, bsize - size); if (!gst_byte_reader_set_pos (reader, pos - size)) return FALSE; return TRUE; }
static inline gboolean gst_jpeg_parse_remove_marker (GstJpegParse * parse, GstByteReader * reader, guint8 marker, GstBuffer * buffer) { guint16 size = 0; guint pos = gst_byte_reader_get_pos (reader); guint8 *data = GST_BUFFER_DATA (buffer); if (!gst_byte_reader_peek_uint16_be (reader, &size)) return FALSE; if (gst_byte_reader_get_remaining (reader) < size) return FALSE; GST_LOG_OBJECT (parse, "unhandled marker %x removing %u bytes", marker, size); memmove (&data[pos], &data[pos + size], GST_BUFFER_SIZE (buffer) - (pos + size)); GST_BUFFER_SIZE (buffer) -= size; if (!gst_byte_reader_set_pos (reader, pos - size)) return FALSE; return TRUE; }
static gint deserialize_speed (GstExifReader * exif_reader, GstByteReader * reader, const GstExifTagMatch * exiftag, GstExifTagData * tagdata) { GstExifTagData next_tagdata = { 0, }; gdouble multiplier = 1; gint ret = 0; GST_LOG ("Starting to parse %s tag in exif 0x%x", exiftag->gst_tag, exiftag->exif_tag); if (exiftag->complementary_tag == tagdata->tag) { if (tagdata->offset_as_data[0] == 'K') { multiplier = KILOMETERS_PER_HOUR_TO_METERS_PER_SECOND; } else if (tagdata->offset_as_data[0] == 'M') { multiplier = MILES_PER_HOUR_TO_METERS_PER_SECOND; } else if (tagdata->offset_as_data[0] == 'N') { multiplier = KNOTS_TO_METERS_PER_SECOND; } else { GST_WARNING ("Invalid GPSSpeedRed %c", tagdata->offset_as_data[0]); return ret; } } else { GST_DEBUG ("No GPSSpeedRef, using default=K"); multiplier = KILOMETERS_PER_HOUR_TO_METERS_PER_SECOND; if (tagdata->tag == exiftag->exif_tag) { tagdata_copy (&next_tagdata, tagdata); } } /* now read the following tag that must be the exif_tag */ if (next_tagdata.tag == 0) { if (exif_reader->byte_order == G_LITTLE_ENDIAN) { if (!gst_byte_reader_peek_uint16_le (reader, &next_tagdata.tag)) goto reader_fail; } else { if (!gst_byte_reader_peek_uint16_be (reader, &next_tagdata.tag)) goto reader_fail; } if (exiftag->exif_tag != next_tagdata.tag) { GST_WARNING ("Unexpected tag"); return ret; } /* read the remaining tag entry data */ if (!parse_exif_tag_header (reader, exif_reader->byte_order, &next_tagdata)) { ret = -1; goto reader_fail; } ret = 1; } /* some checking */ if (next_tagdata.tag_type != EXIF_TYPE_RATIONAL) { GST_WARNING ("Invalid type %d for 0x%x", next_tagdata.tag_type, next_tagdata.tag); return ret; } if (next_tagdata.count != 1) { GST_WARNING ("0x%x tag must have a single fraction, we have %u", next_tagdata.tag_type, next_tagdata.count); return ret; } parse_exif_rational_tag (exif_reader, exiftag->gst_tag, next_tagdata.count, next_tagdata.offset, multiplier); return ret; reader_fail: GST_WARNING ("Failed to read fields from buffer (too short?)"); return ret; }
static gint deserialize_geo_direction (GstExifReader * exif_reader, GstByteReader * reader, const GstExifTagMatch * exiftag, GstExifTagData * tagdata) { GstExifTagData next_tagdata = { 0, }; gint ret = 0; GST_LOG ("Starting to parse %s tag in exif 0x%x", exiftag->gst_tag, exiftag->exif_tag); if (exiftag->complementary_tag == tagdata->tag) { /* First should come the 'Ref' tags */ if (tagdata->offset_as_data[0] == 'M') { GST_WARNING ("Magnetic direction is not supported"); return ret; } else if (tagdata->offset_as_data[0] == 'T') { /* nop */ } else { GST_WARNING ("Invalid Ref for direction or track %c", tagdata->offset_as_data[0]); return ret; } } else { GST_DEBUG ("No Direction Ref, using default=T"); if (tagdata->tag == exiftag->exif_tag) { /* this is the main tag */ tagdata_copy (&next_tagdata, tagdata); } } if (next_tagdata.tag == 0) { /* now read the following tag that must be the exif_tag */ if (exif_reader->byte_order == G_LITTLE_ENDIAN) { if (!gst_byte_reader_peek_uint16_le (reader, &next_tagdata.tag)) goto reader_fail; } else { if (!gst_byte_reader_peek_uint16_be (reader, &next_tagdata.tag)) goto reader_fail; } if (exiftag->exif_tag != next_tagdata.tag) { GST_WARNING ("Unexpected tag"); return ret; } /* read the remaining tag entry data */ if (!parse_exif_tag_header (reader, exif_reader->byte_order, &next_tagdata)) { ret = -1; goto reader_fail; } ret = 1; } /* some checking */ if (next_tagdata.tag_type != EXIF_TYPE_RATIONAL) { GST_WARNING ("Invalid type %d for 0x%x", next_tagdata.tag_type, next_tagdata.tag); return ret; } if (next_tagdata.count != 1) { GST_WARNING ("0x%x tag must have a single fraction, we have %u", next_tagdata.tag_type, next_tagdata.count); return ret; } parse_exif_rational_tag (exif_reader, exiftag->gst_tag, next_tagdata.count, next_tagdata.offset, 1); return ret; reader_fail: GST_WARNING ("Failed to read fields from buffer (too short?)"); return ret; }
static gint deserialize_geo_coordinate (GstExifReader * exif_reader, GstByteReader * reader, const GstExifTagMatch * exiftag, GstExifTagData * tagdata) { GstByteReader fractions_reader; gint multiplier; GstExifTagData next_tagdata; gint ret = 0; /* for the conversion */ guint32 degrees_n = 0; guint32 degrees_d = 1; guint32 minutes_n = 0; guint32 minutes_d = 1; guint32 seconds_n = 0; guint32 seconds_d = 1; gdouble degrees; gdouble minutes; gdouble seconds; GST_LOG ("Starting to parse %s tag in exif 0x%x", exiftag->gst_tag, exiftag->exif_tag); if (exiftag->complementary_tag != tagdata->tag) { /* First should come the 'Ref' tags */ GST_WARNING ("Tag %d is not the 'Ref' tag for latitude nor longitude", tagdata->tag); return ret; } if (tagdata->offset_as_data[0] == 'N' || tagdata->offset_as_data[0] == 'E') { multiplier = 1; } else if (tagdata->offset_as_data[0] == 'S' || tagdata->offset_as_data[0] == 'W') { multiplier = -1; } else { GST_WARNING ("Invalid LatitudeRef or LongitudeRef %c", tagdata->offset_as_data[0]); return ret; } /* now read the following tag that must be the latitude or longitude */ if (exif_reader->byte_order == G_LITTLE_ENDIAN) { if (!gst_byte_reader_peek_uint16_le (reader, &next_tagdata.tag)) goto reader_fail; } else { if (!gst_byte_reader_peek_uint16_be (reader, &next_tagdata.tag)) goto reader_fail; } if (exiftag->exif_tag != next_tagdata.tag) { GST_WARNING ("This is not a geo cordinate tag"); return ret; } /* read the remaining tag entry data */ if (!parse_exif_tag_header (reader, exif_reader->byte_order, &next_tagdata)) { ret = -1; goto reader_fail; } ret = 1; /* some checking */ if (next_tagdata.tag_type != EXIF_TYPE_RATIONAL) { GST_WARNING ("Invalid type %d for geo coordinate (latitude/longitude)", next_tagdata.tag_type); return ret; } if (next_tagdata.count != 3) { GST_WARNING ("Geo coordinate should use 3 fractions, we have %u", next_tagdata.count); return ret; } /* now parse the fractions */ gst_byte_reader_init_from_buffer (&fractions_reader, exif_reader->buffer); if (!gst_byte_reader_set_pos (&fractions_reader, next_tagdata.offset - exif_reader->base_offset)) goto reader_fail; if (exif_reader->byte_order == G_LITTLE_ENDIAN) { if (!gst_byte_reader_get_uint32_le (&fractions_reader, °rees_n) || !gst_byte_reader_get_uint32_le (&fractions_reader, °rees_d) || !gst_byte_reader_get_uint32_le (&fractions_reader, &minutes_n) || !gst_byte_reader_get_uint32_le (&fractions_reader, &minutes_d) || !gst_byte_reader_get_uint32_le (&fractions_reader, &seconds_n) || !gst_byte_reader_get_uint32_le (&fractions_reader, &seconds_d)) goto reader_fail; } else { if (!gst_byte_reader_get_uint32_be (&fractions_reader, °rees_n) || !gst_byte_reader_get_uint32_be (&fractions_reader, °rees_d) || !gst_byte_reader_get_uint32_be (&fractions_reader, &minutes_n) || !gst_byte_reader_get_uint32_be (&fractions_reader, &minutes_d) || !gst_byte_reader_get_uint32_be (&fractions_reader, &seconds_n) || !gst_byte_reader_get_uint32_be (&fractions_reader, &seconds_d)) goto reader_fail; } GST_DEBUG ("Read degrees fraction for tag %s: %u/%u %u/%u %u/%u", exiftag->gst_tag, degrees_n, degrees_d, minutes_n, minutes_d, seconds_n, seconds_d); gst_util_fraction_to_double (degrees_n, degrees_d, °rees); gst_util_fraction_to_double (minutes_n, minutes_d, &minutes); gst_util_fraction_to_double (seconds_n, seconds_d, &seconds); minutes += seconds / 60; degrees += minutes / 60; degrees *= multiplier; GST_DEBUG ("Adding %s tag: %lf", exiftag->gst_tag, degrees); gst_tag_list_add (exif_reader->taglist, GST_TAG_MERGE_REPLACE, exiftag->gst_tag, degrees, NULL); return ret; reader_fail: GST_WARNING ("Failed to read fields from buffer (too short?)"); return ret; }