summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSebastian Dröge <sebastian@centricular.com>2018-02-02 13:51:49 +0200
committerSebastian Dröge <sebastian@centricular.com>2018-02-09 11:05:02 +0200
commite7177059e91ec5c2b9f1b67e0ed2ed09493ffb83 (patch)
treeeabd04affb5a20acf6cb5c667956f364945890e3
parent4fd8635983f1f9c6124ed148a5e145fc966b4584 (diff)
qtmux: Add support for muxing svmi atom for stereoscopic video information
https://bugzilla.gnome.org/show_bug.cgi?id=793120
-rw-r--r--gst/isomp4/atoms.c55
-rw-r--r--gst/isomp4/atoms.h13
-rw-r--r--gst/isomp4/gstqtmux.c31
3 files changed, 99 insertions, 0 deletions
diff --git a/gst/isomp4/atoms.c b/gst/isomp4/atoms.c
index eb90b7929..4ca69274b 100644
--- a/gst/isomp4/atoms.c
+++ b/gst/isomp4/atoms.c
@@ -729,6 +729,33 @@ atom_ctts_free (AtomCTTS * ctts)
}
static void
+atom_svmi_init (AtomSVMI * svmi)
+{
+ guint8 flags[3] = { 0, 0, 0 };
+
+ atom_full_init (&svmi->header, FOURCC_svmi, 0, 0, 0, flags);
+ svmi->stereoscopic_composition_type = 0x00;
+ svmi->is_left_first = FALSE;
+}
+
+AtomSVMI *
+atom_svmi_new (guint8 stereoscopic_composition_type, gboolean is_left_first)
+{
+ AtomSVMI *svmi = g_new0 (AtomSVMI, 1);
+
+ atom_svmi_init (svmi);
+ svmi->stereoscopic_composition_type = stereoscopic_composition_type;
+ svmi->is_left_first = is_left_first;
+ return svmi;
+}
+
+static void
+atom_svmi_free (AtomSVMI * svmi)
+{
+ g_free (svmi);
+}
+
+static void
atom_stts_init (AtomSTTS * stts)
{
guint8 flags[3] = { 0, 0, 0 };
@@ -822,6 +849,7 @@ atom_stbl_init (AtomSTBL * stbl)
atom_stsz_init (&stbl->stsz);
atom_stsc_init (&stbl->stsc);
stbl->ctts = NULL;
+ stbl->svmi = NULL;
atom_co64_init (&stbl->stco64);
}
@@ -838,6 +866,9 @@ atom_stbl_clear (AtomSTBL * stbl)
if (stbl->ctts) {
atom_ctts_free (stbl->ctts);
}
+ if (stbl->svmi) {
+ atom_svmi_free (stbl->svmi);
+ }
atom_stco64_clear (&stbl->stco64);
}
@@ -2293,6 +2324,25 @@ atom_ctts_copy_data (AtomCTTS * ctts, guint8 ** buffer, guint64 * size,
}
guint64
+atom_svmi_copy_data (AtomSVMI * svmi, guint8 ** buffer, guint64 * size,
+ guint64 * offset)
+{
+ guint64 original_offset = *offset;
+
+ if (!atom_full_copy_data (&svmi->header, buffer, size, offset)) {
+ return 0;
+ }
+
+ prop_copy_uint8 (svmi->stereoscopic_composition_type, buffer, size, offset);
+ prop_copy_uint8 (svmi->is_left_first ? 1 : 0, buffer, size, offset);
+ /* stereo-mono change count */
+ prop_copy_uint32 (0, buffer, size, offset);
+
+ atom_write_size (buffer, size, offset, original_offset);
+ return *offset - original_offset;
+}
+
+guint64
atom_stco64_copy_data (AtomSTCO64 * stco64, guint8 ** buffer, guint64 * size,
guint64 * offset)
{
@@ -2454,6 +2504,11 @@ atom_stbl_copy_data (AtomSTBL * stbl, guint8 ** buffer, guint64 * size,
return 0;
}
}
+ if (stbl->svmi) {
+ if (!atom_svmi_copy_data (stbl->svmi, buffer, size, offset)) {
+ return 0;
+ }
+ }
if (!atom_stco64_copy_data (&stbl->stco64, buffer, size, offset)) {
return 0;
}
diff --git a/gst/isomp4/atoms.h b/gst/isomp4/atoms.h
index f73cb9f05..27d249431 100644
--- a/gst/isomp4/atoms.h
+++ b/gst/isomp4/atoms.h
@@ -563,6 +563,14 @@ typedef struct _AtomCTTS
gboolean do_pts;
} AtomCTTS;
+typedef struct _AtomSVMI
+{
+ AtomFull header;
+
+ guint8 stereoscopic_composition_type;
+ gboolean is_left_first;
+} AtomSVMI;
+
typedef struct _AtomSTBL
{
Atom header;
@@ -574,6 +582,8 @@ typedef struct _AtomSTBL
AtomSTSZ stsz;
/* NULL if not present */
AtomCTTS *ctts;
+ /* NULL if not present */
+ AtomSVMI *svmi;
AtomSTCO64 stco64;
} AtomSTBL;
@@ -960,6 +970,9 @@ guint64 atom_stsz_copy_data (AtomSTSZ *atom, guint8 **buffer,
guint64 *size, guint64* offset);
guint64 atom_ctts_copy_data (AtomCTTS *atom, guint8 **buffer,
guint64 *size, guint64* offset);
+guint64 atom_svmi_copy_data (AtomSVMI *atom, guint8 **buffer,
+ guint64 *size, guint64* offset);
+AtomSVMI * atom_svmi_new (guint8 stereoscopic_composition_type, gboolean is_left_first);
guint64 atom_stco64_copy_data (AtomSTCO64 *atom, guint8 **buffer,
guint64 *size, guint64* offset);
AtomMOOF* atom_moof_new (AtomsContext *context, guint32 sequence_number);
diff --git a/gst/isomp4/gstqtmux.c b/gst/isomp4/gstqtmux.c
index 09357be1b..74e177c3d 100644
--- a/gst/isomp4/gstqtmux.c
+++ b/gst/isomp4/gstqtmux.c
@@ -5189,6 +5189,7 @@ gst_qt_mux_video_sink_set_caps (GstQTPad * qtpad, GstCaps * caps)
GList *ext_atom_list = NULL;
gboolean sync = FALSE;
int par_num, par_den;
+ const gchar *multiview_mode;
/* does not go well to renegotiate stream mid-way, unless
* the old caps are a subset of the new one (this means upstream
@@ -5258,6 +5259,36 @@ gst_qt_mux_video_sink_set_caps (GstQTPad * qtpad, GstCaps * caps)
GST_DEBUG_OBJECT (qtmux, "Rate of video track selected: %" G_GUINT32_FORMAT,
rate);
+ multiview_mode = gst_structure_get_string (structure, "multiview-mode");
+ if (multiview_mode && !qtpad->trak->mdia.minf.stbl.svmi) {
+ GstVideoMultiviewMode mode;
+ GstVideoMultiviewFlags flags = 0;
+
+ mode = gst_video_multiview_mode_from_caps_string (multiview_mode);
+ gst_structure_get_flagset (structure, "multiview-flags", &flags, NULL);
+ switch (mode) {
+ case GST_VIDEO_MULTIVIEW_MODE_SIDE_BY_SIDE:
+ qtpad->trak->mdia.minf.stbl.svmi =
+ atom_svmi_new (0,
+ flags & GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST);
+ break;
+ case GST_VIDEO_MULTIVIEW_MODE_ROW_INTERLEAVED:
+ qtpad->trak->mdia.minf.stbl.svmi =
+ atom_svmi_new (1,
+ flags & GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST);
+ break;
+ case GST_VIDEO_MULTIVIEW_MODE_FRAME_BY_FRAME:
+ qtpad->trak->mdia.minf.stbl.svmi =
+ atom_svmi_new (2,
+ flags & GST_VIDEO_MULTIVIEW_FLAGS_RIGHT_VIEW_FIRST);
+ break;
+ default:
+ GST_DEBUG_OBJECT (qtmux, "Unsupported multiview-mode %s",
+ multiview_mode);
+ break;
+ }
+ }
+
/* set common properties */
entry.width = width;
entry.height = height;