mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-25 17:50:36 +00:00
Merge branch 'master' into 0.11
Conflicts: ext/ogg/gstoggmux.c
This commit is contained in:
commit
7b45a7367b
5 changed files with 130 additions and 4 deletions
|
@ -891,9 +891,12 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
|
||||||
pad->start_time = gst_ogg_stream_granule_to_time (&pad->map,
|
pad->start_time = gst_ogg_stream_granule_to_time (&pad->map,
|
||||||
start_granule);
|
start_granule);
|
||||||
GST_DEBUG_OBJECT (ogg,
|
GST_DEBUG_OBJECT (ogg,
|
||||||
"start time %" GST_TIME_FORMAT " (%" GST_TIME_FORMAT ") for %s",
|
"start time %" GST_TIME_FORMAT " (%" GST_TIME_FORMAT ") for %s "
|
||||||
|
"from granpos %" G_GINT64_FORMAT " (granule %" G_GINT64_FORMAT ", "
|
||||||
|
"accumulated granule %" G_GINT64_FORMAT,
|
||||||
GST_TIME_ARGS (pad->start_time), GST_TIME_ARGS (pad->start_time),
|
GST_TIME_ARGS (pad->start_time), GST_TIME_ARGS (pad->start_time),
|
||||||
gst_ogg_stream_get_media_type (&pad->map));
|
gst_ogg_stream_get_media_type (&pad->map), packet->granulepos,
|
||||||
|
granule, pad->map.accumulated_granule);
|
||||||
} else {
|
} else {
|
||||||
packet->granulepos = gst_ogg_stream_granule_to_granulepos (&pad->map,
|
packet->granulepos = gst_ogg_stream_granule_to_granulepos (&pad->map,
|
||||||
pad->map.accumulated_granule, pad->keyframe_granule);
|
pad->map.accumulated_granule, pad->keyframe_granule);
|
||||||
|
|
|
@ -115,7 +115,7 @@ static GstStaticPadTemplate audio_sink_factory =
|
||||||
GST_PAD_REQUEST,
|
GST_PAD_REQUEST,
|
||||||
GST_STATIC_CAPS
|
GST_STATIC_CAPS
|
||||||
("audio/x-vorbis; audio/x-flac; audio/x-speex; audio/x-celt; "
|
("audio/x-vorbis; audio/x-flac; audio/x-speex; audio/x-celt; "
|
||||||
"application/x-ogm-audio; ")
|
"application/x-ogm-audio; audio/x-opus")
|
||||||
);
|
);
|
||||||
|
|
||||||
static GstStaticPadTemplate subtitle_sink_factory =
|
static GstStaticPadTemplate subtitle_sink_factory =
|
||||||
|
|
|
@ -127,6 +127,10 @@ gst_ogg_stream_granule_to_time (GstOggStream * pad, gint64 granule)
|
||||||
if (granule == 0 || pad->granulerate_n == 0 || pad->granulerate_d == 0)
|
if (granule == 0 || pad->granulerate_n == 0 || pad->granulerate_d == 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
granule += pad->granule_offset;
|
||||||
|
if (granule < 0)
|
||||||
|
return 0;
|
||||||
|
|
||||||
return gst_util_uint64_scale (granule, GST_SECOND * pad->granulerate_d,
|
return gst_util_uint64_scale (granule, GST_SECOND * pad->granulerate_d,
|
||||||
pad->granulerate_n);
|
pad->granulerate_n);
|
||||||
}
|
}
|
||||||
|
@ -1820,6 +1824,103 @@ extract_tags_kate (GstOggStream * pad, ogg_packet * packet)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* opus */
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
setup_opus_mapper (GstOggStream * pad, ogg_packet * packet)
|
||||||
|
{
|
||||||
|
if (packet->bytes < 19)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
pad->granulerate_n = 48000;
|
||||||
|
pad->granulerate_d = 1;
|
||||||
|
pad->granuleshift = 0;
|
||||||
|
pad->n_header_packets = 2;
|
||||||
|
|
||||||
|
/* pre-skip is in samples at 48000 Hz, which matches granule one for one */
|
||||||
|
pad->granule_offset = -GST_READ_UINT16_LE (packet->packet + 10);
|
||||||
|
GST_INFO ("Opus has a pre-skip of %" G_GINT64_FORMAT " samples",
|
||||||
|
-pad->granule_offset);
|
||||||
|
|
||||||
|
pad->caps = gst_caps_new_simple ("audio/x-opus", NULL);
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
is_header_opus (GstOggStream * pad, ogg_packet * packet)
|
||||||
|
{
|
||||||
|
return packet->bytes >= 8 && !memcmp (packet->packet, "Opus", 4);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gint64
|
||||||
|
packet_duration_opus (GstOggStream * pad, ogg_packet * packet)
|
||||||
|
{
|
||||||
|
static const guint64 durations[32] = {
|
||||||
|
480, 960, 1920, 2880, /* Silk NB */
|
||||||
|
480, 960, 1920, 2880, /* Silk MB */
|
||||||
|
480, 960, 1920, 2880, /* Silk WB */
|
||||||
|
480, 960, /* Hybrid SWB */
|
||||||
|
480, 960, /* Hybrid FB */
|
||||||
|
120, 240, 480, 960, /* CELT NB */
|
||||||
|
120, 240, 480, 960, /* CELT NB */
|
||||||
|
120, 240, 480, 960, /* CELT NB */
|
||||||
|
120, 240, 480, 960, /* CELT NB */
|
||||||
|
};
|
||||||
|
|
||||||
|
gint64 duration;
|
||||||
|
gint64 frame_duration;
|
||||||
|
gint nframes;
|
||||||
|
guint8 toc;
|
||||||
|
|
||||||
|
if (packet->bytes < 1)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
/* headers */
|
||||||
|
if (is_header_opus (pad, packet))
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
toc = packet->packet[0];
|
||||||
|
|
||||||
|
frame_duration = durations[toc >> 3];
|
||||||
|
switch (toc & 3) {
|
||||||
|
case 0:
|
||||||
|
nframes = 1;
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
nframes = 2;
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
nframes = 2;
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (packet->bytes < 2) {
|
||||||
|
GST_WARNING ("Code 3 Opus packet has less than 2 bytes");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
nframes = packet->packet[1] & 63;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
duration = nframes * frame_duration;
|
||||||
|
if (duration > 5760) {
|
||||||
|
GST_WARNING ("Opus packet duration > 120 ms, invalid");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
GST_LOG ("Opus packet: frame size %.1f ms, %d frames, duration %.1f ms",
|
||||||
|
frame_duration / 48.f, nframes, duration / 48.f);
|
||||||
|
return duration;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
extract_tags_opus (GstOggStream * pad, ogg_packet * packet)
|
||||||
|
{
|
||||||
|
if (packet->bytes >= 8 && memcmp (packet->packet, "OpusTags", 8) == 0) {
|
||||||
|
tag_list_from_vorbiscomment_packet (packet,
|
||||||
|
(const guint8 *) "OpusTags", 8, &pad->taglist);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* *INDENT-OFF* */
|
/* *INDENT-OFF* */
|
||||||
/* indent hates our freedoms */
|
/* indent hates our freedoms */
|
||||||
|
@ -1991,6 +2092,18 @@ const GstOggMap mappers[] = {
|
||||||
granulepos_to_key_granule_vp8,
|
granulepos_to_key_granule_vp8,
|
||||||
extract_tags_vp8
|
extract_tags_vp8
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"OpusHead", 8, 0,
|
||||||
|
"audio/x-opus",
|
||||||
|
setup_opus_mapper,
|
||||||
|
granulepos_to_granule_default,
|
||||||
|
granule_to_granulepos_default,
|
||||||
|
NULL,
|
||||||
|
is_header_opus,
|
||||||
|
packet_duration_opus,
|
||||||
|
NULL,
|
||||||
|
extract_tags_opus
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"\001audio\0\0\0", 9, 53,
|
"\001audio\0\0\0", 9, 53,
|
||||||
"application/x-ogm-audio",
|
"application/x-ogm-audio",
|
||||||
|
|
|
@ -60,6 +60,7 @@ struct _GstOggStream
|
||||||
gboolean have_fisbone;
|
gboolean have_fisbone;
|
||||||
gint granulerate_n;
|
gint granulerate_n;
|
||||||
gint granulerate_d;
|
gint granulerate_d;
|
||||||
|
gint64 granule_offset;
|
||||||
guint32 preroll;
|
guint32 preroll;
|
||||||
guint granuleshift;
|
guint granuleshift;
|
||||||
gint n_header_packets;
|
gint n_header_packets;
|
||||||
|
|
|
@ -446,12 +446,20 @@ gst_play_sink_convert_bin_remove_elements (GstPlaySinkConvertBin * self)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_play_sink_convert_bin_finalize (GObject * object)
|
gst_play_sink_convert_bin_dispose (GObject * object)
|
||||||
{
|
{
|
||||||
GstPlaySinkConvertBin *self = GST_PLAY_SINK_CONVERT_BIN_CAST (object);
|
GstPlaySinkConvertBin *self = GST_PLAY_SINK_CONVERT_BIN_CAST (object);
|
||||||
|
|
||||||
gst_play_sink_convert_bin_remove_elements (self);
|
gst_play_sink_convert_bin_remove_elements (self);
|
||||||
|
|
||||||
|
G_OBJECT_CLASS (parent_class)->dispose (object);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
gst_play_sink_convert_bin_finalize (GObject * object)
|
||||||
|
{
|
||||||
|
GstPlaySinkConvertBin *self = GST_PLAY_SINK_CONVERT_BIN_CAST (object);
|
||||||
|
|
||||||
gst_object_unref (self->sink_proxypad);
|
gst_object_unref (self->sink_proxypad);
|
||||||
g_mutex_free (self->lock);
|
g_mutex_free (self->lock);
|
||||||
|
|
||||||
|
@ -548,6 +556,7 @@ gst_play_sink_convert_bin_class_init (GstPlaySinkConvertBinClass * klass)
|
||||||
gobject_class = (GObjectClass *) klass;
|
gobject_class = (GObjectClass *) klass;
|
||||||
gstelement_class = (GstElementClass *) klass;
|
gstelement_class = (GstElementClass *) klass;
|
||||||
|
|
||||||
|
gobject_class->dispose = gst_play_sink_convert_bin_dispose;
|
||||||
gobject_class->finalize = gst_play_sink_convert_bin_finalize;
|
gobject_class->finalize = gst_play_sink_convert_bin_finalize;
|
||||||
|
|
||||||
gst_element_class_add_pad_template (gstelement_class,
|
gst_element_class_add_pad_template (gstelement_class,
|
||||||
|
|
Loading…
Reference in a new issue