matroska-demux: Play ProRes video streams
authorJan Schmidt <jan@centricular.com>
Wed, 18 Nov 2015 05:20:38 +0000 (16:20 +1100)
committerJan Schmidt <jan@centricular.com>
Fri, 18 Dec 2015 16:47:49 +0000 (03:47 +1100)
Generate video/x-prores caps for ProRes video streams.
Every frame needs an 8 byte header prepended, as described in
http://wiki.multimedia.cx/index.php?title=Apple_ProRes#Frame_layout
so do that in a post-processing callback.

https://bugzilla.gnome.org/show_bug.cgi?id=758258

gst/matroska/matroska-demux.c
gst/matroska/matroska-ids.h

index 85fd3ad31cf938f9e16829013eb8680a86db2c42..1cd0f15ba65491dadb35f6f2b3acf994647d33b4 100644 (file)
@@ -2971,6 +2971,33 @@ gst_matroska_demux_add_wvpk_header (GstElement * element,
   return GST_FLOW_OK;
 }
 
+static GstFlowReturn
+gst_matroska_demux_add_prores_header (GstElement * element,
+    GstMatroskaTrackContext * stream, GstBuffer ** buf)
+{
+  GstBuffer *newbuf = gst_buffer_new_allocate (NULL, 8, NULL);
+  GstMapInfo map;
+  guint32 frame_size;
+
+  if (!gst_buffer_map (newbuf, &map, GST_MAP_WRITE)) {
+    GST_ERROR ("Failed to map newly allocated buffer");
+    return GST_FLOW_ERROR;
+  }
+
+  frame_size = gst_buffer_get_size (*buf);
+
+  GST_WRITE_UINT32_BE (map.data, frame_size);
+  map.data[4] = 'i';
+  map.data[5] = 'c';
+  map.data[6] = 'p';
+  map.data[7] = 'f';
+
+  gst_buffer_unmap (newbuf, &map);
+  *buf = gst_buffer_append (newbuf, *buf);
+
+  return GST_FLOW_OK;
+}
+
 /* @text must be null-terminated */
 static gboolean
 gst_matroska_demux_subtitle_chunk_has_tag (GstElement * element,
@@ -5228,6 +5255,48 @@ gst_matroska_demux_video_caps (GstMatroskaTrackVideoContext *
   } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_VP9)) {
     caps = gst_caps_new_empty_simple ("video/x-vp9");
     *codec_name = g_strdup_printf ("On2 VP9");
+  } else if (!strcmp (codec_id, GST_MATROSKA_CODEC_ID_VIDEO_PRORES)) {
+    guint32 fourcc;
+    const gchar *variant, *variant_descr = "";
+
+    /* Expect a fourcc in the codec private data */
+    if (size < 4) {
+      GST_WARNING ("Too small PRORESS fourcc (%d bytes)", size);
+      return NULL;
+    }
+
+    fourcc = GST_STR_FOURCC (data);
+    switch (fourcc) {
+      case GST_MAKE_FOURCC ('a', 'p', 'c', 's'):
+        variant_descr = " 4:2:2 LT";
+        variant = "lt";
+        break;
+      case GST_MAKE_FOURCC ('a', 'p', 'c', 'h'):
+        variant = "hq";
+        variant_descr = " 4:2:2 HQ";
+        break;
+      case GST_MAKE_FOURCC ('a', 'p', '4', 'h'):
+        variant = "4444";
+        variant_descr = " 4:4:4:4";
+        break;
+      case GST_MAKE_FOURCC ('a', 'p', 'c', 'o'):
+        variant = "proxy";
+        variant_descr = " 4:2:2 Proxy";
+        break;
+      case GST_MAKE_FOURCC ('a', 'p', 'c', 'n'):
+      default:
+        variant = "standard";
+        variant_descr = " 4:2:2 SD";
+        break;
+    }
+
+    GST_LOG ("Prores video, codec fourcc %" GST_FOURCC_FORMAT,
+        GST_FOURCC_ARGS (fourcc));
+
+    caps = gst_caps_new_simple ("video/x-prores",
+        "format", G_TYPE_STRING, variant, NULL);
+    *codec_name = g_strdup_printf ("Apple ProRes%s", variant_descr);
+    context->postprocess_frame = gst_matroska_demux_add_prores_header;
   } else {
     GST_WARNING ("Unknown codec '%s', cannot build Caps", codec_id);
     return NULL;
index f3063b81d588dd663508e6c75cd35db61c569851..c4419c29113ff97134496ecf2279cbc3cf7df360 100644 (file)
 #define GST_MATROSKA_CODEC_ID_VIDEO_VP8          "V_VP8"
 #define GST_MATROSKA_CODEC_ID_VIDEO_VP9          "V_VP9"
 #define GST_MATROSKA_CODEC_ID_VIDEO_MPEGH_HEVC   "V_MPEGH/ISO/HEVC"
+#define GST_MATROSKA_CODEC_ID_VIDEO_PRORES       "V_PRORES"
 
 #define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L1       "A_MPEG/L1"
 #define GST_MATROSKA_CODEC_ID_AUDIO_MPEG1_L2       "A_MPEG/L2"