Commit 7378f1b4 authored by Edward Hervey's avatar Edward Hervey 🤘 Committed by Edward Hervey

isomp4: qtmux: Add Closed Caption support

Supports CEA 608 and CEA 708 CC streams

Also supports usage in "Robust Prefill" mode if the incoming caption
stream is constant (i.e. there is one incoming CC buffer for each
video frame).

https://bugzilla.gnome.org/show_bug.cgi?id=606643
parent 76e32ef4
......@@ -692,6 +692,7 @@ atom_stsd_remove_entries (AtomSTSD * stsd)
case TIMECODE:
sample_entry_tmcd_free ((SampleTableEntryTMCD *) se);
break;
case CLOSEDCAPTION:
default:
/* best possible cleanup */
atom_sample_entry_free (se);
......@@ -2229,6 +2230,20 @@ sample_entry_tmcd_copy_data (SampleTableEntryTMCD * tmcd, guint8 ** buffer,
return *offset - original_offset;
}
static guint64
sample_entry_generic_copy_data (SampleTableEntry * entry, guint8 ** buffer,
guint64 * size, guint64 * offset)
{
guint64 original_offset = *offset;
if (!atom_sample_entry_copy_data (entry, buffer, size, offset)) {
return 0;
}
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)
......@@ -2462,6 +2477,11 @@ atom_stsd_copy_data (AtomSTSD * stsd, guint8 ** buffer, guint64 * size,
walker->data, buffer, size, offset)) {
return 0;
}
} else if (se->kind == CLOSEDCAPTION) {
if (!sample_entry_generic_copy_data ((SampleTableEntry *)
walker->data, buffer, size, offset)) {
return 0;
}
} else {
if (!atom_hint_sample_entry_copy_data (
(AtomHintSampleEntry *) walker->data, buffer, size, offset)) {
......@@ -4082,6 +4102,44 @@ atom_trak_set_timecode_type (AtomTRAK * trak, AtomsContext * context,
return ste;
}
SampleTableEntry *
atom_trak_set_caption_type (AtomTRAK * trak, AtomsContext * context,
guint32 trak_timescale, guint32 caption_type)
{
SampleTableEntry *ste;
AtomGMHD *gmhd = trak->mdia.minf.gmhd;
AtomSTSD *stsd = &trak->mdia.minf.stbl.stsd;
if (context->flavor != ATOMS_TREE_FLAVOR_MOV) {
return NULL;
}
trak->mdia.mdhd.time_info.timescale = trak_timescale;
trak->mdia.hdlr.component_type = FOURCC_mhlr;
trak->mdia.hdlr.handler_type = FOURCC_clcp;
g_free (trak->mdia.hdlr.name);
trak->mdia.hdlr.name = g_strdup ("Closed Caption Media Handler");
ste = g_new0 (SampleTableEntry, 1);
atom_sample_entry_init (ste, caption_type);
ste->kind = CLOSEDCAPTION;
ste->data_reference_index = 1;
stsd->entries = g_list_prepend (stsd->entries, ste);
stsd->n_entries++;
gmhd = atom_gmhd_new ();
gmhd->gmin.graphics_mode = 0x0040;
gmhd->gmin.opcolor[0] = 0x8000;
gmhd->gmin.opcolor[1] = 0x8000;
gmhd->gmin.opcolor[2] = 0x8000;
trak->mdia.minf.gmhd = gmhd;
trak->is_video = FALSE;
trak->is_h264 = FALSE;
return ste;
}
static AtomInfo *
build_pasp_extension (gint par_width, gint par_height)
{
......
......@@ -386,7 +386,8 @@ typedef enum _SampleEntryKind
AUDIO,
VIDEO,
SUBTITLE,
TIMECODE
TIMECODE,
CLOSEDCAPTION
} SampleEntryKind;
typedef struct _SampleTableEntry
......@@ -999,7 +1000,6 @@ guint64 atom_mfra_copy_data (AtomMFRA *mfra, guint8 **buffer, guint64
/* media sample description related helpers */
typedef struct
{
guint16 version;
......@@ -1056,6 +1056,9 @@ SampleTableEntryTX3G * atom_trak_set_subtitle_type (AtomTRAK * trak, AtomsContex
SampleTableEntryTMCD *
atom_trak_set_timecode_type (AtomTRAK * trak, AtomsContext * context, guint trak_timescale, GstVideoTimeCode * tc);
SampleTableEntry * atom_trak_set_caption_type (AtomTRAK *trak, AtomsContext *context,
guint32 trak_timescale, guint32 caption_type);
void atom_trak_update_bitrates (AtomTRAK * trak, guint32 avg_bitrate,
guint32 max_bitrate);
......
This diff is collapsed.
......@@ -290,7 +290,7 @@ struct _GstQTMux
gboolean reserved_prefill;
/* for request pad naming */
guint video_pads, audio_pads, subtitle_pads;
guint video_pads, audio_pads, subtitle_pads, caption_pads;
};
struct _GstQTMuxClass
......@@ -308,6 +308,7 @@ typedef struct _GstQTMuxClassParams
GstCaps *video_sink_caps;
GstCaps *audio_sink_caps;
GstCaps *subtitle_sink_caps;
GstCaps *caption_sink_caps;
} GstQTMuxClassParams;
#define GST_QT_MUX_PARAMS_QDATA g_quark_from_static_string("qt-mux-params")
......
......@@ -166,6 +166,11 @@
"text/x-raw, " \
"format=(string)utf8"
#define CEA608_CAPS \
"closedcaption/x-cea-608, format=(string)cc_data"
#define CEA708_CAPS \
"closedcaption/x-cea-708, format=(string)cdp"
/* FIXME 0.11 - take a look at bugs #580005 and #340375 */
GstQTMuxFormatProp gst_qt_mux_format_list[] = {
/* original QuickTime format; see Apple site (e.g. qtff.pdf) */
......@@ -209,7 +214,8 @@ GstQTMuxFormatProp gst_qt_mux_format_list[] = {
"audio/x-alaw, " COMMON_AUDIO_CAPS (2, MAX) "; "
"audio/x-mulaw, " COMMON_AUDIO_CAPS (2, MAX) "; "
AMR_CAPS " ; " ALAC_CAPS " ; " OPUS_CAPS),
GST_STATIC_CAPS (TEXT_UTF8)}
GST_STATIC_CAPS (TEXT_UTF8),
GST_STATIC_CAPS (CEA608_CAPS "; " CEA708_CAPS)}
,
/* ISO 14496-14: mp42 as ISO base media extension
* (supersedes original ISO 144996-1 mp41) */
......@@ -224,7 +230,8 @@ GstQTMuxFormatProp gst_qt_mux_format_list[] = {
"video/x-mp4-part," COMMON_VIDEO_CAPS),
GST_STATIC_CAPS (MP123_CAPS "; "
AAC_CAPS " ; " AC3_CAPS " ; " ALAC_CAPS " ; " OPUS_CAPS),
GST_STATIC_CAPS (TEXT_UTF8)}
GST_STATIC_CAPS (TEXT_UTF8),
GST_STATIC_CAPS_NONE}
,
/* Microsoft Smooth Streaming fmp4/isml */
/* TODO add WMV/WMA support */
......@@ -237,6 +244,7 @@ GstQTMuxFormatProp gst_qt_mux_format_list[] = {
GST_STATIC_CAPS ("video/quicktime, variant = (string) iso-fragmented"),
GST_STATIC_CAPS (MPEG4V_CAPS "; " H264_CAPS),
GST_STATIC_CAPS (MP3_CAPS "; " AAC_CAPS),
GST_STATIC_CAPS_NONE,
GST_STATIC_CAPS_NONE}
,
/* 3GPP Technical Specification 26.244 V7.3.0
......@@ -250,7 +258,8 @@ GstQTMuxFormatProp gst_qt_mux_format_list[] = {
GST_STATIC_CAPS ("video/quicktime, variant = (string) 3gpp"),
GST_STATIC_CAPS (H263_CAPS "; " MPEG4V_CAPS "; " H264_CAPS),
GST_STATIC_CAPS (AMR_CAPS "; " MP3_CAPS "; " AAC_CAPS "; " AC3_CAPS),
GST_STATIC_CAPS (TEXT_UTF8)}
GST_STATIC_CAPS (TEXT_UTF8),
GST_STATIC_CAPS_NONE}
,
/* ISO 15444-3: Motion-JPEG-2000 (also ISO base media extension) */
{
......@@ -263,6 +272,7 @@ GstQTMuxFormatProp gst_qt_mux_format_list[] = {
GST_STATIC_CAPS ("image/x-j2c, " COMMON_VIDEO_CAPS "; "
"image/x-jpc, " COMMON_VIDEO_CAPS),
GST_STATIC_CAPS (PCM_CAPS),
GST_STATIC_CAPS_NONE,
GST_STATIC_CAPS_NONE}
,
{
......
......@@ -70,6 +70,7 @@ typedef struct _GstQTMuxFormatProp
GstStaticCaps video_sink_caps;
GstStaticCaps audio_sink_caps;
GstStaticCaps subtitle_sink_caps;
GstStaticCaps caption_sink_caps;
} GstQTMuxFormatProp;
extern GstQTMuxFormatProp gst_qt_mux_format_list[];
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment