mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-10 17:35:59 +00:00
qtmux: add support for the TX3G atoms
Adds functions for creating and setting values related to the tx3g atom for raw text subtitle support. QTFF spec has information on those atoms https://bugzilla.gnome.org/show_bug.cgi?id=581295
This commit is contained in:
parent
2ae1897273
commit
d644cda79b
3 changed files with 241 additions and 2 deletions
|
@ -486,6 +486,38 @@ sample_entry_mp4v_new (AtomsContext * context)
|
|||
return mp4v;
|
||||
}
|
||||
|
||||
static void
|
||||
sample_entry_tx3g_init (SampleTableEntryTX3G * tx3g)
|
||||
{
|
||||
atom_sample_entry_init (&tx3g->se, FOURCC_tx3g);
|
||||
|
||||
tx3g->display_flags = 0;
|
||||
tx3g->font_id = 1; /* must be 1 as there is a single font */
|
||||
tx3g->font_face = 0;
|
||||
tx3g->foreground_color_rgba = 0xFFFFFFFF; /* white, opaque */
|
||||
|
||||
/* can't set this now */
|
||||
tx3g->default_text_box = 0;
|
||||
tx3g->font_size = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
sample_entry_tx3g_free (SampleTableEntryTX3G * tx3g)
|
||||
{
|
||||
atom_sample_entry_free (&tx3g->se);
|
||||
g_free (tx3g);
|
||||
}
|
||||
|
||||
static SampleTableEntryTX3G *
|
||||
sample_entry_tx3g_new (void)
|
||||
{
|
||||
SampleTableEntryTX3G *tx3g = g_new0 (SampleTableEntryTX3G, 1);
|
||||
|
||||
sample_entry_tx3g_init (tx3g);
|
||||
return tx3g;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
atom_stsd_init (AtomSTSD * stsd)
|
||||
{
|
||||
|
@ -516,6 +548,9 @@ atom_stsd_remove_entries (AtomSTSD * stsd)
|
|||
case VIDEO:
|
||||
sample_entry_mp4v_free ((SampleTableEntryMP4V *) se);
|
||||
break;
|
||||
case SUBTITLE:
|
||||
sample_entry_tx3g_free ((SampleTableEntryTX3G *) se);
|
||||
break;
|
||||
default:
|
||||
/* best possible cleanup */
|
||||
atom_sample_entry_free (se);
|
||||
|
@ -1795,6 +1830,48 @@ sample_entry_mp4v_copy_data (SampleTableEntryMP4V * mp4v, guint8 ** buffer,
|
|||
return *offset - original_offset;
|
||||
}
|
||||
|
||||
static guint64
|
||||
sample_entry_tx3g_copy_data (SampleTableEntryTX3G * tx3g, guint8 ** buffer,
|
||||
guint64 * size, guint64 * offset)
|
||||
{
|
||||
guint64 original_offset = *offset;
|
||||
|
||||
if (!atom_sample_entry_copy_data (&tx3g->se, buffer, size, offset)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
prop_copy_uint32 (tx3g->display_flags, buffer, size, offset);
|
||||
|
||||
/* reserved */
|
||||
prop_copy_uint8 (1, buffer, size, offset);
|
||||
prop_copy_uint8 (-1, buffer, size, offset);
|
||||
prop_copy_uint32 (0, buffer, size, offset);
|
||||
|
||||
prop_copy_uint64 (tx3g->default_text_box, buffer, size, offset);
|
||||
|
||||
/* reserved */
|
||||
prop_copy_uint32 (0, buffer, size, offset);
|
||||
|
||||
prop_copy_uint16 (tx3g->font_id, buffer, size, offset);
|
||||
prop_copy_uint8 (tx3g->font_face, buffer, size, offset);
|
||||
prop_copy_uint8 (tx3g->font_size, buffer, size, offset);
|
||||
prop_copy_uint32 (tx3g->foreground_color_rgba, buffer, size, offset);
|
||||
|
||||
/* it must have a fonttable atom */
|
||||
{
|
||||
Atom atom;
|
||||
|
||||
atom_header_set (&atom, FOURCC_ftab, 18, 0);
|
||||
atom_copy_data (&atom, buffer, size, offset);
|
||||
prop_copy_uint16 (1, buffer, size, offset); /* Count must be 1 */
|
||||
prop_copy_uint16 (1, buffer, size, offset); /* Font id: 1 */
|
||||
prop_copy_size_string ((guint8 *) "Serif", 5, buffer, size, offset);
|
||||
}
|
||||
|
||||
atom_write_size (buffer, size, offset, original_offset);
|
||||
return *offset - original_offset;
|
||||
}
|
||||
|
||||
guint64
|
||||
atom_stsz_copy_data (AtomSTSZ * stsz, guint8 ** buffer, guint64 * size,
|
||||
guint64 * offset)
|
||||
|
@ -1985,6 +2062,11 @@ atom_stsd_copy_data (AtomSTSD * stsd, guint8 ** buffer, guint64 * size,
|
|||
walker->data, buffer, size, offset)) {
|
||||
return 0;
|
||||
}
|
||||
} else if (se->kind == SUBTITLE) {
|
||||
if (!sample_entry_tx3g_copy_data ((SampleTableEntryTX3G *)
|
||||
walker->data, buffer, size, offset)) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
if (!atom_hint_sample_entry_copy_data (
|
||||
(AtomHintSampleEntry *) walker->data, buffer, size, offset)) {
|
||||
|
@ -2826,6 +2908,40 @@ atom_trak_update_bitrates (AtomTRAK * trak, guint32 avg_bitrate,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
atom_trak_tx3g_update_dimension (AtomTRAK * trak, guint32 width, guint32 height)
|
||||
{
|
||||
AtomSTSD *stsd;
|
||||
GList *iter;
|
||||
SampleTableEntryTX3G *tx3g = NULL;
|
||||
|
||||
stsd = &trak->mdia.minf.stbl.stsd;
|
||||
for (iter = stsd->entries; iter && tx3g == NULL; iter = g_list_next (iter)) {
|
||||
SampleTableEntry *entry = iter->data;
|
||||
|
||||
switch (entry->kind) {
|
||||
case SUBTITLE:{
|
||||
tx3g = (SampleTableEntryTX3G *) entry;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Currently we never set the vertical placement flag, so we don't
|
||||
* check for it to set the dimensions differently as the spec says.
|
||||
* Always do it for the not set case */
|
||||
if (tx3g) {
|
||||
tx3g->font_size = 0.05 * height;
|
||||
|
||||
height = 0.15 * height;
|
||||
trak->tkhd.width = width << 16;
|
||||
trak->tkhd.height = height << 16;
|
||||
tx3g->default_text_box = width | (height << 16);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Meta tags functions
|
||||
*/
|
||||
|
@ -3067,6 +3183,12 @@ atom_minf_set_video (AtomMINF * minf, AtomsContext * context)
|
|||
minf->vmhd = atom_vmhd_new (context);
|
||||
}
|
||||
|
||||
static void
|
||||
atom_minf_set_subtitle (AtomMINF * minf)
|
||||
{
|
||||
atom_minf_clear_handlers (minf);
|
||||
}
|
||||
|
||||
static void
|
||||
atom_hdlr_set_type (AtomHDLR * hdlr, AtomsContext * context, guint32 comp_type,
|
||||
guint32 hdlr_type)
|
||||
|
@ -3103,6 +3225,15 @@ atom_mdia_set_hdlr_type_video (AtomMDIA * mdia, AtomsContext * context)
|
|||
atom_hdlr_set_name (&mdia->hdlr, "VideoHandler");
|
||||
}
|
||||
|
||||
static void
|
||||
atom_mdia_set_hdlr_type_subtitle (AtomMDIA * mdia, AtomsContext * context)
|
||||
{
|
||||
atom_hdlr_set_type (&mdia->hdlr, context, FOURCC_mhlr, FOURCC_sbtl);
|
||||
|
||||
/* Just follows the pattern from video and audio above */
|
||||
atom_hdlr_set_name (&mdia->hdlr, "SubtitleHandler");
|
||||
}
|
||||
|
||||
static void
|
||||
atom_mdia_set_audio (AtomMDIA * mdia, AtomsContext * context)
|
||||
{
|
||||
|
@ -3117,6 +3248,13 @@ atom_mdia_set_video (AtomMDIA * mdia, AtomsContext * context)
|
|||
atom_minf_set_video (&mdia->minf, context);
|
||||
}
|
||||
|
||||
static void
|
||||
atom_mdia_set_subtitle (AtomMDIA * mdia, AtomsContext * context)
|
||||
{
|
||||
atom_mdia_set_hdlr_type_subtitle (mdia, context);
|
||||
atom_minf_set_subtitle (&mdia->minf);
|
||||
}
|
||||
|
||||
static void
|
||||
atom_tkhd_set_audio (AtomTKHD * tkhd)
|
||||
{
|
||||
|
@ -3135,6 +3273,18 @@ atom_tkhd_set_video (AtomTKHD * tkhd, AtomsContext * context, guint32 width,
|
|||
tkhd->height = height;
|
||||
}
|
||||
|
||||
static void
|
||||
atom_tkhd_set_subtitle (AtomTKHD * tkhd, AtomsContext * context, guint32 width,
|
||||
guint32 height)
|
||||
{
|
||||
tkhd->volume = 0;
|
||||
|
||||
/* qt and ISO base media do not contradict, and examples agree */
|
||||
tkhd->width = width;
|
||||
tkhd->height = height;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
atom_edts_add_entry (AtomEDTS * edts, EditListEntry * entry)
|
||||
{
|
||||
|
@ -3205,6 +3355,23 @@ atom_trak_add_video_entry (AtomTRAK * trak, AtomsContext * context,
|
|||
return mp4v;
|
||||
}
|
||||
|
||||
static SampleTableEntryTX3G *
|
||||
atom_trak_add_subtitle_entry (AtomTRAK * trak, AtomsContext * context,
|
||||
guint32 type)
|
||||
{
|
||||
SampleTableEntryTX3G *tx3g = sample_entry_tx3g_new ();
|
||||
AtomSTSD *stsd = &trak->mdia.minf.stbl.stsd;
|
||||
|
||||
tx3g->se.header.type = type;
|
||||
tx3g->se.kind = SUBTITLE;
|
||||
tx3g->se.data_reference_index = 1;
|
||||
|
||||
stsd->entries = g_list_prepend (stsd->entries, tx3g);
|
||||
stsd->n_entries++;
|
||||
return tx3g;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
atom_trak_set_constant_size_samples (AtomTRAK * trak, guint32 sample_size)
|
||||
{
|
||||
|
@ -3226,6 +3393,13 @@ atom_trak_set_video (AtomTRAK * trak, AtomsContext * context, guint32 width,
|
|||
atom_mdia_set_video (&trak->mdia, context);
|
||||
}
|
||||
|
||||
static void
|
||||
atom_trak_set_subtitle (AtomTRAK * trak, AtomsContext * context)
|
||||
{
|
||||
atom_tkhd_set_subtitle (&trak->tkhd, context, 0, 0);
|
||||
atom_mdia_set_subtitle (&trak->mdia, context);
|
||||
}
|
||||
|
||||
static void
|
||||
atom_trak_set_audio_commons (AtomTRAK * trak, AtomsContext * context,
|
||||
guint32 rate)
|
||||
|
@ -3244,6 +3418,13 @@ atom_trak_set_video_commons (AtomTRAK * trak, AtomsContext * context,
|
|||
trak->tkhd.height = height << 16;
|
||||
}
|
||||
|
||||
static void
|
||||
atom_trak_set_subtitle_commons (AtomTRAK * trak, AtomsContext * context)
|
||||
{
|
||||
atom_trak_set_subtitle (trak, context);
|
||||
trak->mdia.mdhd.time_info.timescale = 1000;
|
||||
}
|
||||
|
||||
void
|
||||
atom_trak_set_audio_type (AtomTRAK * trak, AtomsContext * context,
|
||||
AudioSampleEntry * entry, guint32 scale, AtomInfo * ext, gint sample_size)
|
||||
|
@ -3348,6 +3529,32 @@ atom_trak_set_video_type (AtomTRAK * trak, AtomsContext * context,
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
subtitle_sample_entry_init (SubtitleSampleEntry * entry)
|
||||
{
|
||||
entry->font_size = 0;
|
||||
entry->font_face = 0;
|
||||
entry->foreground_color_rgba = 0xFFFFFFFF; /* all white, opaque */
|
||||
}
|
||||
|
||||
void
|
||||
atom_trak_set_subtitle_type (AtomTRAK * trak, AtomsContext * context,
|
||||
SubtitleSampleEntry * entry)
|
||||
{
|
||||
SampleTableEntryTX3G *tx3g;
|
||||
|
||||
atom_trak_set_subtitle_commons (trak, context);
|
||||
atom_stsd_remove_entries (&trak->mdia.minf.stbl.stsd);
|
||||
tx3g = atom_trak_add_subtitle_entry (trak, context, entry->fourcc);
|
||||
|
||||
tx3g->font_face = entry->font_face;
|
||||
tx3g->font_size = entry->font_size;
|
||||
tx3g->foreground_color_rgba = entry->foreground_color_rgba;
|
||||
|
||||
trak->is_video = FALSE;
|
||||
trak->is_h264 = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
atom_mfhd_init (AtomMFHD * mfhd, guint32 sequence_number)
|
||||
{
|
||||
|
|
|
@ -340,7 +340,8 @@ typedef enum _SampleEntryKind
|
|||
{
|
||||
UNKNOWN,
|
||||
AUDIO,
|
||||
VIDEO
|
||||
VIDEO,
|
||||
SUBTITLE,
|
||||
} SampleEntryKind;
|
||||
|
||||
typedef struct _SampleTableEntry
|
||||
|
@ -350,7 +351,7 @@ typedef struct _SampleTableEntry
|
|||
guint8 reserved[6];
|
||||
guint16 data_reference_index;
|
||||
|
||||
/* sort of entry */
|
||||
/* type of entry */
|
||||
SampleEntryKind kind;
|
||||
} SampleTableEntry;
|
||||
|
||||
|
@ -421,6 +422,19 @@ typedef struct _SampleTableEntryMP4S
|
|||
AtomESDS es;
|
||||
} SampleTableEntryMP4S;
|
||||
|
||||
typedef struct _SampleTableEntryTX3G
|
||||
{
|
||||
SampleTableEntry se;
|
||||
|
||||
guint32 display_flags;
|
||||
guint64 default_text_box;
|
||||
guint16 font_id;
|
||||
guint8 font_face; /* bold=0x1, italic=0x2, underline=0x4 */
|
||||
guint8 font_size; /* should always be 0.05 multiplied by the video track header height */
|
||||
guint32 foreground_color_rgba;
|
||||
|
||||
} SampleTableEntryTX3G;
|
||||
|
||||
typedef struct _AtomSTSD
|
||||
{
|
||||
AtomFull header;
|
||||
|
@ -899,6 +913,17 @@ typedef struct
|
|||
GstBuffer *codec_data;
|
||||
} AudioSampleEntry;
|
||||
|
||||
typedef struct
|
||||
{
|
||||
guint32 fourcc;
|
||||
|
||||
guint8 font_face; /* bold=0x1, italic=0x2, underline=0x4 */
|
||||
guint8 font_size;
|
||||
guint32 foreground_color_rgba;
|
||||
} SubtitleSampleEntry;
|
||||
|
||||
void subtitle_sample_entry_init (SubtitleSampleEntry * entry);
|
||||
|
||||
void atom_trak_set_audio_type (AtomTRAK * trak, AtomsContext * context,
|
||||
AudioSampleEntry * entry, guint32 scale,
|
||||
AtomInfo * ext, gint sample_size);
|
||||
|
@ -907,9 +932,15 @@ void atom_trak_set_video_type (AtomTRAK * trak, AtomsContext * context,
|
|||
VisualSampleEntry * entry, guint32 rate,
|
||||
GList * ext_atoms_list);
|
||||
|
||||
void atom_trak_set_subtitle_type (AtomTRAK * trak, AtomsContext * context,
|
||||
SubtitleSampleEntry * entry);
|
||||
|
||||
void atom_trak_update_bitrates (AtomTRAK * trak, guint32 avg_bitrate,
|
||||
guint32 max_bitrate);
|
||||
|
||||
void atom_trak_tx3g_update_dimension (AtomTRAK * trak, guint32 width,
|
||||
guint32 height);
|
||||
|
||||
AtomInfo * build_codec_data_extension (guint32 fourcc, const GstBuffer * codec_data);
|
||||
AtomInfo * build_mov_aac_extension (AtomTRAK * trak, const GstBuffer * codec_data,
|
||||
guint32 avg_bitrate, guint32 max_bitrate);
|
||||
|
|
|
@ -120,6 +120,7 @@ G_BEGIN_DECLS
|
|||
#define FOURCC_free GST_MAKE_FOURCC('f','r','e','e')
|
||||
#define FOURCC_frma GST_MAKE_FOURCC('f','r','m','a')
|
||||
#define FOURCC_ftyp GST_MAKE_FOURCC('f','t','y','p')
|
||||
#define FOURCC_ftab GST_MAKE_FOURCC('f','t','a','b')
|
||||
#define FOURCC_gama GST_MAKE_FOURCC('g','a','m','a')
|
||||
#define FOURCC_glbl GST_MAKE_FOURCC('g','l','b','l')
|
||||
#define FOURCC_gmhd GST_MAKE_FOURCC('g','m','h','d')
|
||||
|
|
Loading…
Reference in a new issue