mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 01:30:38 +00:00
qtmux: add support for text/x-raw subtitles
Adds it to mp4mux, qtmux and gppmux. Buffers need to be prefixed with 2 bytes for the text length before being muxed. https://bugzilla.gnome.org/show_bug.cgi?id=581295
This commit is contained in:
parent
d644cda79b
commit
99e966e2e1
2 changed files with 94 additions and 6 deletions
|
@ -550,6 +550,39 @@ gst_qt_mux_prepare_jpc_buffer (GstQTPad * qtpad, GstBuffer * buf,
|
||||||
return newbuf;
|
return newbuf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static GstBuffer *
|
||||||
|
gst_qt_mux_prepare_tx3g_buffer (GstQTPad * qtpad, GstBuffer * buf,
|
||||||
|
GstQTMux * qtmux)
|
||||||
|
{
|
||||||
|
GstBuffer *newbuf;
|
||||||
|
GstMapInfo frommap;
|
||||||
|
GstMapInfo tomap;
|
||||||
|
gsize size;
|
||||||
|
|
||||||
|
GST_LOG_OBJECT (qtmux, "Preparing tx3g buffer %" GST_PTR_FORMAT, buf);
|
||||||
|
|
||||||
|
if (buf == NULL)
|
||||||
|
return NULL;
|
||||||
|
|
||||||
|
size = gst_buffer_get_size (buf);
|
||||||
|
newbuf = gst_buffer_new_and_alloc (size + 2);
|
||||||
|
|
||||||
|
gst_buffer_map (buf, &frommap, GST_MAP_READ);
|
||||||
|
gst_buffer_map (newbuf, &tomap, GST_MAP_WRITE);
|
||||||
|
|
||||||
|
GST_WRITE_UINT16_BE (tomap.data, size);
|
||||||
|
memcpy (tomap.data + 2, frommap.data, size);
|
||||||
|
|
||||||
|
gst_buffer_unmap (newbuf, &tomap);
|
||||||
|
gst_buffer_unmap (buf, &frommap);
|
||||||
|
|
||||||
|
gst_buffer_copy_into (newbuf, buf, GST_BUFFER_COPY_METADATA, 0, size);
|
||||||
|
|
||||||
|
gst_buffer_unref (buf);
|
||||||
|
|
||||||
|
return newbuf;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_qt_mux_add_mp4_tag (GstQTMux * qtmux, const GstTagList * list,
|
gst_qt_mux_add_mp4_tag (GstQTMux * qtmux, const GstTagList * list,
|
||||||
const char *tag, const char *tag2, guint32 fourcc)
|
const char *tag, const char *tag2, guint32 fourcc)
|
||||||
|
@ -1806,6 +1839,10 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
|
||||||
guint32 timescale;
|
guint32 timescale;
|
||||||
GstClockTime first_ts = GST_CLOCK_TIME_NONE;
|
GstClockTime first_ts = GST_CLOCK_TIME_NONE;
|
||||||
|
|
||||||
|
/* for setting some subtitles fields */
|
||||||
|
guint max_width = 0;
|
||||||
|
guint max_height = 0;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (qtmux, "Updating remaining values and sending last data");
|
GST_DEBUG_OBJECT (qtmux, "Updating remaining values and sending last data");
|
||||||
|
|
||||||
/* pushing last buffers for each pad */
|
/* pushing last buffers for each pad */
|
||||||
|
@ -1845,6 +1882,12 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
|
||||||
first_ts = qtpad->last_dts;
|
first_ts = qtpad->last_dts;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* subtitles need to know the video width/height,
|
||||||
|
* it is stored shifted 16 bits to the left according to the
|
||||||
|
* spec */
|
||||||
|
max_width = MAX (max_width, (qtpad->trak->tkhd.width >> 16));
|
||||||
|
max_height = MAX (max_height, (qtpad->trak->tkhd.height >> 16));
|
||||||
|
|
||||||
/* update average bitrate of streams if needed */
|
/* update average bitrate of streams if needed */
|
||||||
{
|
{
|
||||||
guint32 avgbitrate = 0;
|
guint32 avgbitrate = 0;
|
||||||
|
@ -1860,6 +1903,23 @@ gst_qt_mux_stop_file (GstQTMux * qtmux)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* need to update values on subtitle traks now that we know the
|
||||||
|
* max width and height */
|
||||||
|
for (walk = qtmux->collect->data; walk; walk = g_slist_next (walk)) {
|
||||||
|
GstCollectData *cdata = (GstCollectData *) walk->data;
|
||||||
|
GstQTPad *qtpad = (GstQTPad *) cdata;
|
||||||
|
|
||||||
|
if (!qtpad->fourcc) {
|
||||||
|
GST_DEBUG_OBJECT (qtmux, "Pad %s has never had buffers",
|
||||||
|
GST_PAD_NAME (qtpad->collect.pad));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (qtpad->fourcc == FOURCC_tx3g) {
|
||||||
|
atom_trak_tx3g_update_dimension (qtpad->trak, max_width, max_height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (qtmux->fragment_sequence) {
|
if (qtmux->fragment_sequence) {
|
||||||
GstSegment segment;
|
GstSegment segment;
|
||||||
|
|
||||||
|
@ -3142,6 +3202,8 @@ gst_qt_mux_subtitle_sink_set_caps (GstQTPad * qtpad, GstCaps * caps)
|
||||||
{
|
{
|
||||||
GstPad *pad = qtpad->collect.pad;
|
GstPad *pad = qtpad->collect.pad;
|
||||||
GstQTMux *qtmux = GST_QT_MUX_CAST (gst_pad_get_parent (pad));
|
GstQTMux *qtmux = GST_QT_MUX_CAST (gst_pad_get_parent (pad));
|
||||||
|
GstStructure *structure;
|
||||||
|
SubtitleSampleEntry entry = { 0, };
|
||||||
|
|
||||||
qtpad->prepare_buf_func = NULL;
|
qtpad->prepare_buf_func = NULL;
|
||||||
|
|
||||||
|
@ -3168,16 +3230,38 @@ gst_qt_mux_subtitle_sink_set_caps (GstQTPad * qtpad, GstCaps * caps)
|
||||||
GST_DEBUG_PAD_NAME (pad), caps);
|
GST_DEBUG_PAD_NAME (pad), caps);
|
||||||
|
|
||||||
/* subtitles default */
|
/* subtitles default */
|
||||||
|
subtitle_sample_entry_init (&entry);
|
||||||
qtpad->is_out_of_order = FALSE;
|
qtpad->is_out_of_order = FALSE;
|
||||||
qtpad->sync = FALSE;
|
qtpad->sync = FALSE;
|
||||||
|
qtpad->prepare_buf_func = NULL;
|
||||||
|
|
||||||
/* TODO fill me */
|
structure = gst_caps_get_structure (caps, 0);
|
||||||
|
|
||||||
|
if (gst_structure_has_name (structure, "text/x-raw")) {
|
||||||
|
const gchar *format = gst_structure_get_string (structure, "format");
|
||||||
|
if (format && strcmp (format, "utf8") == 0) {
|
||||||
|
entry.fourcc = FOURCC_tx3g;
|
||||||
|
qtpad->prepare_buf_func = gst_qt_mux_prepare_tx3g_buffer;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!entry.fourcc)
|
||||||
|
goto refuse_caps;
|
||||||
|
|
||||||
|
qtpad->fourcc = entry.fourcc;
|
||||||
|
atom_trak_set_subtitle_type (qtpad->trak, qtmux->context, &entry);
|
||||||
|
|
||||||
gst_object_unref (qtmux);
|
gst_object_unref (qtmux);
|
||||||
/* not implemented */
|
return TRUE;
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
/* ERRORS */
|
/* ERRORS */
|
||||||
|
refuse_caps:
|
||||||
|
{
|
||||||
|
GST_WARNING_OBJECT (qtmux, "pad %s refused caps %" GST_PTR_FORMAT,
|
||||||
|
GST_PAD_NAME (pad), caps);
|
||||||
|
gst_object_unref (qtmux);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
refuse_renegotiation:
|
refuse_renegotiation:
|
||||||
{
|
{
|
||||||
GST_WARNING_OBJECT (qtmux,
|
GST_WARNING_OBJECT (qtmux,
|
||||||
|
|
|
@ -133,6 +133,10 @@
|
||||||
"audio/x-alac, " \
|
"audio/x-alac, " \
|
||||||
COMMON_AUDIO_CAPS(2, MAX)
|
COMMON_AUDIO_CAPS(2, MAX)
|
||||||
|
|
||||||
|
#define TEXT_UTF8 \
|
||||||
|
"text/x-raw, " \
|
||||||
|
"format=(string)utf8"
|
||||||
|
|
||||||
/* FIXME 0.11 - take a look at bugs #580005 and #340375 */
|
/* FIXME 0.11 - take a look at bugs #580005 and #340375 */
|
||||||
GstQTMuxFormatProp gst_qt_mux_format_list[] = {
|
GstQTMuxFormatProp gst_qt_mux_format_list[] = {
|
||||||
/* original QuickTime format; see Apple site (e.g. qtff.pdf) */
|
/* original QuickTime format; see Apple site (e.g. qtff.pdf) */
|
||||||
|
@ -167,7 +171,7 @@ GstQTMuxFormatProp gst_qt_mux_format_list[] = {
|
||||||
"audio/x-alaw, " COMMON_AUDIO_CAPS (2, MAX) "; "
|
"audio/x-alaw, " COMMON_AUDIO_CAPS (2, MAX) "; "
|
||||||
"audio/x-mulaw, " COMMON_AUDIO_CAPS (2, MAX) "; "
|
"audio/x-mulaw, " COMMON_AUDIO_CAPS (2, MAX) "; "
|
||||||
AMR_CAPS " ; " ALAC_CAPS),
|
AMR_CAPS " ; " ALAC_CAPS),
|
||||||
GST_STATIC_CAPS_NONE}
|
GST_STATIC_CAPS (TEXT_UTF8)}
|
||||||
,
|
,
|
||||||
/* ISO 14496-14: mp42 as ISO base media extension
|
/* ISO 14496-14: mp42 as ISO base media extension
|
||||||
* (supersedes original ISO 144996-1 mp41) */
|
* (supersedes original ISO 144996-1 mp41) */
|
||||||
|
@ -181,7 +185,7 @@ GstQTMuxFormatProp gst_qt_mux_format_list[] = {
|
||||||
GST_STATIC_CAPS (MPEG4V_CAPS "; " H264_CAPS ";"
|
GST_STATIC_CAPS (MPEG4V_CAPS "; " H264_CAPS ";"
|
||||||
"video/x-mp4-part," COMMON_VIDEO_CAPS),
|
"video/x-mp4-part," COMMON_VIDEO_CAPS),
|
||||||
GST_STATIC_CAPS (MP3_CAPS "; " AAC_CAPS " ; " ALAC_CAPS),
|
GST_STATIC_CAPS (MP3_CAPS "; " AAC_CAPS " ; " ALAC_CAPS),
|
||||||
GST_STATIC_CAPS_NONE}
|
GST_STATIC_CAPS (TEXT_UTF8)}
|
||||||
,
|
,
|
||||||
/* Microsoft Smooth Streaming fmp4/isml */
|
/* Microsoft Smooth Streaming fmp4/isml */
|
||||||
/* TODO add WMV/WMA support */
|
/* TODO add WMV/WMA support */
|
||||||
|
@ -207,7 +211,7 @@ GstQTMuxFormatProp gst_qt_mux_format_list[] = {
|
||||||
GST_STATIC_CAPS ("video/quicktime, variant = (string) 3gpp"),
|
GST_STATIC_CAPS ("video/quicktime, variant = (string) 3gpp"),
|
||||||
GST_STATIC_CAPS (H263_CAPS "; " MPEG4V_CAPS "; " H264_CAPS),
|
GST_STATIC_CAPS (H263_CAPS "; " MPEG4V_CAPS "; " H264_CAPS),
|
||||||
GST_STATIC_CAPS (AMR_CAPS "; " MP3_CAPS "; " AAC_CAPS),
|
GST_STATIC_CAPS (AMR_CAPS "; " MP3_CAPS "; " AAC_CAPS),
|
||||||
GST_STATIC_CAPS_NONE}
|
GST_STATIC_CAPS (TEXT_UTF8)}
|
||||||
,
|
,
|
||||||
/* ISO 15444-3: Motion-JPEG-2000 (also ISO base media extension) */
|
/* ISO 15444-3: Motion-JPEG-2000 (also ISO base media extension) */
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in a new issue