[vlc-devel] [PATCH 4/5] jpeg: read panoramic metadata from the XMP EXIF data

Steve Lhomme robux4 at videolabs.io
Thu Nov 10 15:19:59 CET 2016


---
 modules/codec/jpeg.c | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 83 insertions(+), 1 deletion(-)

diff --git a/modules/codec/jpeg.c b/modules/codec/jpeg.c
index 30e095e..dbe3e94 100644
--- a/modules/codec/jpeg.c
+++ b/modules/codec/jpeg.c
@@ -247,6 +247,88 @@ de_get32( void * ptr, uint endian ) {
     return val;
 }
 
+static bool getRDFFloat(const char *psz_rdf, const char *psz_var, float *out)
+{
+    size_t varlen = strlen(psz_var);
+    char *p_start = strcasestr( psz_rdf, psz_var );
+    if (p_start == NULL)
+        return false;
+
+    char *p_end = strchr( p_start + varlen, '"');
+    if (unlikely(p_end == NULL))
+        return false;
+
+    char pose[p_end - p_start + 1];
+    memcpy(pose, p_start + varlen, p_end - p_start - varlen);
+    pose[p_end - p_start - varlen] = 0;
+    if (sscanf(pose, "%f", out) != 1)
+        return false;
+
+    return true;
+}
+
+#define EXIF_JPEG_MARKER    0xE1
+#define EXIF_XMP_STRING     "http://ns.adobe.com/xap/1.0/\000"
+
+/* read XMP metadata for projection according to
+ * https://developers.google.com/streetview/spherical-metadata */
+static void jpeg_GetProjection( j_decompress_ptr cinfo, video_format_t *fmt )
+{
+    jpeg_saved_marker_ptr xmp_marker = NULL;
+    jpeg_saved_marker_ptr cmarker = cinfo->marker_list;
+
+    while ( cmarker )
+    {
+        if ( cmarker->marker == EXIF_JPEG_MARKER )
+        {
+            if ( !memcmp( cmarker->data, EXIF_XMP_STRING, 29 ) )
+            {
+                xmp_marker = cmarker;
+                break;
+            }
+        }
+        cmarker = cmarker->next;
+    }
+
+    if (xmp_marker == NULL || xmp_marker->data_length < 32)
+        return;
+    char *psz_rdf = malloc(xmp_marker->data_length - 29);
+    if (unlikely(psz_rdf == NULL))
+        return;
+    memcpy(psz_rdf, xmp_marker->data + 29, xmp_marker->data_length - 29);
+
+    /* Try to find the string "GSpherical:Spherical" because the v1
+        spherical video spec says the tag must be there. */
+    if ( strcasestr( psz_rdf, "ProjectionType=\"equirectangular\"" ) )
+        fmt->projection_mode = PROJECTION_MODE_EQUIRECTANGULAR;
+
+    /* pose handling */
+    float value;
+    if (getRDFFloat( psz_rdf, "PoseHeadingDegrees=\"", &value))
+        fmt->f_pose_yaw_degrees = value;
+
+    if (getRDFFloat( psz_rdf, "PosePitchDegrees=\"", &value))
+        fmt->f_pose_pitch_degrees = value;
+
+    if (getRDFFloat( psz_rdf, "PoseRollDegrees=\"", &value))
+        fmt->f_pose_roll_degrees = value;
+
+    /* initial view */
+    if (getRDFFloat( psz_rdf, "InitialViewHeadingDegrees=\"", &value))
+        fmt->f_pose_yaw_degrees = value;
+
+    if (getRDFFloat( psz_rdf, "InitialViewPitchDegrees=\"", &value))
+        fmt->f_pose_pitch_degrees = value;
+
+    if (getRDFFloat( psz_rdf, "InitialViewRollDegrees=\"", &value))
+        fmt->f_pose_roll_degrees = value;
+
+    if (getRDFFloat( psz_rdf, "InitialHorizontalFOVDegrees=\"", &value))
+        fmt->f_pose_fov_degrees = value;
+
+    free(psz_rdf);
+}
+
 /*
  * Look through the meta data in the libjpeg decompress structure to determine
  * if an EXIF Orientation tag is present. If so return its value (1-8),
@@ -276,7 +358,6 @@ jpeg_GetOrientation( j_decompress_ptr cinfo )
     const char leth[] = { 0x49, 0x49, 0x2a, 0x00 }; /* Little endian TIFF header */
     const char beth[] = { 0x4d, 0x4d, 0x00, 0x2a }; /* Big endian TIFF header */
 
-    #define EXIF_JPEG_MARKER    0xE1
     #define EXIF_IDENT_STRING   "Exif\000\000"
     #define EXIF_ORIENT_TAGID   0x112
 
@@ -453,6 +534,7 @@ static picture_t *DecodeBlock(decoder_t *p_dec, block_t **pp_block)
         msg_Dbg( p_dec, "Jpeg orientation is %d", i_otag );
         p_dec->fmt_out.video.orientation = ORIENT_FROM_EXIF( i_otag );
     }
+    jpeg_GetProjection( &p_sys->p_jpeg, &p_dec->fmt_out.video );
 
     /* Get a new picture */
     if (decoder_UpdateVideoFormat(p_dec))
-- 
2.10.1



More information about the vlc-devel mailing list