mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-23 08:46:40 +00:00
qtmux: Write additional atoms for prores video
These required atoms are: colorimetry, field information, spatial/temporal quality, and vendor. https://bugzilla.gnome.org/show_bug.cgi?id=769048
This commit is contained in:
parent
cbd13883a8
commit
fe38414412
4 changed files with 141 additions and 6 deletions
|
@ -3915,6 +3915,106 @@ build_pasp_extension (gint par_width, gint par_height)
|
|||
atom_data_free);
|
||||
}
|
||||
|
||||
AtomInfo *
|
||||
build_fiel_extension_prores (const gchar * interlace_mode, gboolean tff)
|
||||
{
|
||||
AtomData *atom_data = atom_data_new (FOURCC_fiel);
|
||||
guint8 *data;
|
||||
gint field_order;
|
||||
gint interlace;
|
||||
|
||||
atom_data_alloc_mem (atom_data, 2);
|
||||
data = atom_data->data;
|
||||
|
||||
if (!g_strcmp0 (interlace_mode, "progressive")) {
|
||||
interlace = 1;
|
||||
field_order = 0;
|
||||
} else {
|
||||
interlace = 2;
|
||||
if (!g_strcmp0 (interlace_mode, "interleaved"))
|
||||
field_order = tff ? 9 : 14;
|
||||
else if (!g_strcmp0 (interlace_mode, "mixed"))
|
||||
field_order = tff ? 1 : 6;
|
||||
else
|
||||
g_assert_not_reached ();
|
||||
}
|
||||
|
||||
GST_WRITE_UINT8 (data, interlace);
|
||||
GST_WRITE_UINT8 (data + 1, field_order);
|
||||
|
||||
return build_atom_info_wrapper ((Atom *) atom_data, atom_data_copy_data,
|
||||
atom_data_free);
|
||||
}
|
||||
|
||||
AtomInfo *
|
||||
build_colr_extension (GstVideoColorimetry colorimetry)
|
||||
{
|
||||
AtomData *atom_data = atom_data_new (FOURCC_colr);
|
||||
guint8 *data;
|
||||
guint16 primaries;
|
||||
guint16 transfer_function;
|
||||
guint16 matrix;
|
||||
|
||||
switch (colorimetry.primaries) {
|
||||
case GST_VIDEO_COLOR_PRIMARIES_BT709:
|
||||
primaries = 1;
|
||||
break;
|
||||
case GST_VIDEO_COLOR_PRIMARIES_BT470BG:
|
||||
primaries = 5;
|
||||
break;
|
||||
case GST_VIDEO_COLOR_PRIMARIES_SMPTE170M:
|
||||
case GST_VIDEO_COLOR_PRIMARIES_SMPTE240M:
|
||||
primaries = 6;
|
||||
break;
|
||||
case GST_VIDEO_COLOR_PRIMARIES_UNKNOWN:
|
||||
default:
|
||||
primaries = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (colorimetry.transfer) {
|
||||
case GST_VIDEO_TRANSFER_BT709:
|
||||
transfer_function = 1;
|
||||
break;
|
||||
case GST_VIDEO_TRANSFER_SMPTE240M:
|
||||
transfer_function = 7;
|
||||
break;
|
||||
case GST_VIDEO_TRANSFER_UNKNOWN:
|
||||
default:
|
||||
transfer_function = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
switch (colorimetry.matrix) {
|
||||
case GST_VIDEO_COLOR_MATRIX_BT709:
|
||||
matrix = 1;
|
||||
break;
|
||||
case GST_VIDEO_COLOR_MATRIX_BT601:
|
||||
matrix = 6;
|
||||
break;
|
||||
case GST_VIDEO_COLOR_MATRIX_SMPTE240M:
|
||||
matrix = 7;
|
||||
break;
|
||||
case GST_VIDEO_COLOR_MATRIX_UNKNOWN:
|
||||
default:
|
||||
matrix = 2;
|
||||
break;
|
||||
}
|
||||
|
||||
atom_data_alloc_mem (atom_data, 10);
|
||||
data = atom_data->data;
|
||||
|
||||
/* colour specification box */
|
||||
GST_WRITE_UINT32_LE (data, FOURCC_nclc);
|
||||
|
||||
GST_WRITE_UINT16_BE (data + 4, primaries);
|
||||
GST_WRITE_UINT16_BE (data + 6, transfer_function); /* transfer function */
|
||||
GST_WRITE_UINT16_BE (data + 8, matrix);
|
||||
|
||||
return build_atom_info_wrapper ((Atom *) atom_data, atom_data_copy_data,
|
||||
atom_data_free);
|
||||
}
|
||||
|
||||
SampleTableEntryMP4V *
|
||||
atom_trak_set_video_type (AtomTRAK * trak, AtomsContext * context,
|
||||
VisualSampleEntry * entry, guint32 scale, GList * ext_atoms_list)
|
||||
|
@ -3923,11 +4023,8 @@ atom_trak_set_video_type (AtomTRAK * trak, AtomsContext * context,
|
|||
guint dwidth, dheight;
|
||||
gint par_n = 0, par_d = 0;
|
||||
|
||||
if ((entry->par_n != 1 || entry->par_d != 1) &&
|
||||
(entry->par_n != entry->par_d)) {
|
||||
par_n = entry->par_n;
|
||||
par_d = entry->par_d;
|
||||
}
|
||||
|
||||
dwidth = entry->width;
|
||||
dheight = entry->height;
|
||||
|
@ -3960,7 +4057,7 @@ atom_trak_set_video_type (AtomTRAK * trak, AtomsContext * context,
|
|||
ste->extension_atoms = g_list_concat (ste->extension_atoms, ext_atoms_list);
|
||||
|
||||
/* QT spec has a pasp extension atom in stsd that can hold PAR */
|
||||
if (par_n && (context->flavor == ATOMS_TREE_FLAVOR_MOV)) {
|
||||
if (context->flavor == ATOMS_TREE_FLAVOR_MOV) {
|
||||
ste->extension_atoms = g_list_append (ste->extension_atoms,
|
||||
build_pasp_extension (par_n, par_d));
|
||||
}
|
||||
|
|
|
@ -1044,6 +1044,8 @@ AtomInfo * build_jp2h_extension (gint width, gint height, const gchar *
|
|||
|
||||
AtomInfo * build_jp2x_extension (const GstBuffer * prefix);
|
||||
AtomInfo * build_fiel_extension (gint fields);
|
||||
AtomInfo * build_fiel_extension_prores (const gchar * interlace_mode, gboolean tff);
|
||||
AtomInfo * build_colr_extension (GstVideoColorimetry colorimetry);
|
||||
AtomInfo * build_ac3_extension (guint8 fscod, guint8 bsid,
|
||||
guint8 bsmod, guint8 acmod,
|
||||
guint8 lfe_on, guint8 bitrate_code);
|
||||
|
|
|
@ -169,6 +169,7 @@ G_BEGIN_DECLS
|
|||
#define FOURCC_mp4s GST_MAKE_FOURCC('m','p','4','s')
|
||||
#define FOURCC_mp4v GST_MAKE_FOURCC('m','p','4','v')
|
||||
#define FOURCC_name GST_MAKE_FOURCC('n','a','m','e')
|
||||
#define FOURCC_nclc GST_MAKE_FOURCC('n','c','l','c')
|
||||
#define FOURCC_opus GST_MAKE_FOURCC('O','p','u','s')
|
||||
#define FOURCC_dops GST_MAKE_FOURCC('d','O','p','s')
|
||||
#define FOURCC_pasp GST_MAKE_FOURCC('p','a','s','p')
|
||||
|
|
|
@ -4246,8 +4246,14 @@ gst_qt_mux_video_sink_set_caps (GstQTPad * qtpad, GstCaps * caps)
|
|||
entry.fourcc = fourcc;
|
||||
} else if (strcmp (mimetype, "video/x-prores") == 0) {
|
||||
const gchar *variant;
|
||||
const gchar *colorimetry_str;
|
||||
const gchar *interlace_mode;
|
||||
gboolean tff = TRUE;
|
||||
GstVideoColorimetry colorimetry;
|
||||
|
||||
variant = gst_structure_get_string (structure, "variant");
|
||||
colorimetry_str = gst_structure_get_string (structure, "colorimetry");
|
||||
interlace_mode = gst_structure_get_string (structure, "interlace-mode");
|
||||
if (!variant || !g_strcmp0 (variant, "standard"))
|
||||
entry.fourcc = FOURCC_apcn;
|
||||
else if (!g_strcmp0 (variant, "lt"))
|
||||
|
@ -4256,6 +4262,29 @@ gst_qt_mux_video_sink_set_caps (GstQTPad * qtpad, GstCaps * caps)
|
|||
entry.fourcc = FOURCC_apch;
|
||||
else if (!g_strcmp0 (variant, "proxy"))
|
||||
entry.fourcc = FOURCC_apco;
|
||||
if (!g_strcmp0 (interlace_mode, "interleaved") ||
|
||||
!g_strcmp0 (interlace_mode, "mixed")) {
|
||||
/* Assume top-fields-first if unspecified */
|
||||
gst_structure_get_boolean (structure, "top-field-first", &tff);
|
||||
}
|
||||
|
||||
if (gst_video_colorimetry_from_string (&colorimetry, colorimetry_str)) {
|
||||
ext_atom = build_colr_extension (colorimetry);
|
||||
if (ext_atom)
|
||||
ext_atom_list = g_list_append (ext_atom_list, ext_atom);
|
||||
}
|
||||
|
||||
ext_atom = build_fiel_extension_prores (interlace_mode, tff);
|
||||
if (ext_atom)
|
||||
ext_atom_list = g_list_append (ext_atom_list, ext_atom);
|
||||
|
||||
if (colorimetry_str == NULL) {
|
||||
/* TODO: Maybe implement better heuristics */
|
||||
GST_WARNING_OBJECT (qtmux,
|
||||
"Colorimetry information not found in caps. The resulting file's "
|
||||
"color information might be wrong");
|
||||
colorimetry_str = height < 720 ? "bt601" : "bt709";
|
||||
}
|
||||
}
|
||||
|
||||
if (!entry.fourcc)
|
||||
|
@ -4267,6 +4296,12 @@ gst_qt_mux_video_sink_set_caps (GstQTPad * qtpad, GstCaps * caps)
|
|||
qtpad->trak_ste =
|
||||
(SampleTableEntry *) atom_trak_set_video_type (qtpad->trak,
|
||||
qtmux->context, &entry, rate, ext_atom_list);
|
||||
if (strcmp (mimetype, "video/x-prores") == 0) {
|
||||
SampleTableEntryMP4V *mp4v = (SampleTableEntryMP4V *) qtpad->trak_ste;
|
||||
mp4v->spatial_quality = 0x3FF;
|
||||
mp4v->temporal_quality = 0;
|
||||
mp4v->vendor = FOURCC_appl;
|
||||
}
|
||||
|
||||
gst_object_unref (qtmux);
|
||||
return TRUE;
|
||||
|
|
Loading…
Reference in a new issue