diff --git a/ext/ogg/gstoggdemux.c b/ext/ogg/gstoggdemux.c index 56e2551692..28cb6bc3bd 100644 --- a/ext/ogg/gstoggdemux.c +++ b/ext/ogg/gstoggdemux.c @@ -524,6 +524,8 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet, GST_DEBUG_OBJECT (ogg, "%p streaming to peer serial %08x", pad, pad->map.serialno); + gst_ogg_stream_update_stats (&pad->map, packet); + if (pad->map.is_ogm) { const guint8 *data; long bytes; diff --git a/ext/ogg/gstoggmux.c b/ext/ogg/gstoggmux.c index 4f12ed70c6..a540420bb0 100644 --- a/ext/ogg/gstoggmux.c +++ b/ext/ogg/gstoggmux.c @@ -847,7 +847,11 @@ gst_ogg_mux_decorate_buffer (GstOggMux * ogg_mux, GstOggPadData * pad, gst_buffer_map (buf, &map, GST_MAP_READ); packet.packet = map.data; packet.bytes = map.size; + + gst_ogg_stream_update_stats (&pad->map, &packet); + duration = gst_ogg_stream_get_packet_duration (&pad->map, &packet); + gst_buffer_unmap (buf, &map); /* give up if no duration can be determined, relying on upstream */ diff --git a/ext/ogg/gstoggstream.c b/ext/ogg/gstoggstream.c index 145fabc187..d467c73944 100644 --- a/ext/ogg/gstoggstream.c +++ b/ext/ogg/gstoggstream.c @@ -69,6 +69,8 @@ typedef gint64 (*GstOggMapGranuleposToKeyGranuleFunc) (GstOggStream * pad, gint64 granulepos); typedef GstBuffer *(*GstOggMapGetHeadersFunc) (GstOggStream * pad); +typedef void (*GstOggMapUpdateStatsFunc) (GstOggStream * pad, + ogg_packet * packet); #define SKELETON_FISBONE_MIN_SIZE 52 #define SKELETON_FISHEAD_3_3_MIN_SIZE 112 @@ -91,6 +93,7 @@ struct _GstOggMap GstOggMapGranuleposToKeyGranuleFunc granulepos_to_key_granule_func; GstOggMapExtractTagsFunc extract_tags_func; GstOggMapGetHeadersFunc get_headers_func; + GstOggMapUpdateStatsFunc update_stats_func; }; extern const GstOggMap mappers[]; @@ -280,6 +283,15 @@ gst_ogg_stream_get_headers (GstOggStream * pad) return mappers[pad->map].get_headers_func (pad); } +void +gst_ogg_stream_update_stats (GstOggStream * pad, ogg_packet * packet) +{ + if (!mappers[pad->map].get_headers_func) + return; + + return mappers[pad->map].update_stats_func (pad, packet); +} + /* some generic functions */ static gboolean @@ -742,11 +754,14 @@ static gint64 granule_to_granulepos_vp8 (GstOggStream * pad, gint64 granule, gint64 keyframe_granule) { - /* FIXME: This requires to look into the content of the packets - * because the simple granule counter doesn't know about invisible - * frames... - */ - return -1; + guint inv; + gint64 granulepos; + + inv = (pad->invisible_count <= 0) ? 0x3 : pad->invisible_count - 1; + + granulepos = + (granule << 32) | (inv << 30) | ((granule - keyframe_granule) << 3); + return granulepos; } /* Check if this packet contains an invisible frame or not */ @@ -813,6 +828,18 @@ get_headers_vp8 (GstOggStream * pad) return NULL; } +static void +update_stats_vp8 (GstOggStream * pad, ogg_packet * packet) +{ + if (packet_duration_vp8 (pad, packet)) { + /* set to -1 as when we get thefirst invisible it should be + * set to 0 */ + pad->invisible_count = -1; + } else { + pad->invisible_count++; + } +} + /* vorbis */ static gboolean @@ -2221,6 +2248,7 @@ const GstOggMap mappers[] = { packet_duration_constant, NULL, extract_tags_theora, + NULL, NULL }, { @@ -2236,6 +2264,7 @@ const GstOggMap mappers[] = { packet_duration_vorbis, NULL, extract_tags_vorbis, + NULL, NULL }, { @@ -2251,6 +2280,7 @@ const GstOggMap mappers[] = { packet_duration_constant, NULL, extract_tags_count, + NULL, NULL }, { @@ -2266,6 +2296,7 @@ const GstOggMap mappers[] = { NULL, NULL, NULL, + NULL, NULL }, { @@ -2281,6 +2312,7 @@ const GstOggMap mappers[] = { NULL, NULL, NULL, + NULL, NULL }, { @@ -2296,6 +2328,7 @@ const GstOggMap mappers[] = { NULL, NULL, NULL, + NULL, NULL }, { @@ -2311,6 +2344,7 @@ const GstOggMap mappers[] = { NULL, NULL, NULL, + NULL, NULL }, { @@ -2326,6 +2360,7 @@ const GstOggMap mappers[] = { packet_duration_flac, NULL, NULL, + NULL, NULL }, { @@ -2341,6 +2376,7 @@ const GstOggMap mappers[] = { packet_duration_flac, NULL, extract_tags_flac, + NULL, NULL }, { @@ -2355,6 +2391,7 @@ const GstOggMap mappers[] = { NULL, NULL, NULL, + NULL, NULL }, { @@ -2370,6 +2407,7 @@ const GstOggMap mappers[] = { packet_duration_constant, NULL, extract_tags_count, + NULL, NULL }, { @@ -2385,6 +2423,7 @@ const GstOggMap mappers[] = { packet_duration_kate, NULL, extract_tags_kate, + NULL, NULL }, { @@ -2400,6 +2439,7 @@ const GstOggMap mappers[] = { packet_duration_constant, granulepos_to_key_granule_dirac, NULL, + NULL, NULL }, { @@ -2415,7 +2455,8 @@ const GstOggMap mappers[] = { packet_duration_vp8, granulepos_to_key_granule_vp8, extract_tags_vp8, - get_headers_vp8 + get_headers_vp8, + update_stats_vp8 }, { "OpusHead", 8, 0, @@ -2430,6 +2471,7 @@ const GstOggMap mappers[] = { packet_duration_opus, NULL, extract_tags_opus, + NULL, NULL }, { @@ -2445,6 +2487,7 @@ const GstOggMap mappers[] = { packet_duration_ogm, NULL, NULL, + NULL, NULL }, { @@ -2460,6 +2503,7 @@ const GstOggMap mappers[] = { packet_duration_constant, NULL, NULL, + NULL, NULL }, { @@ -2475,6 +2519,7 @@ const GstOggMap mappers[] = { packet_duration_ogm, NULL, extract_tags_ogm, + NULL, NULL }, { @@ -2490,6 +2535,7 @@ const GstOggMap mappers[] = { packet_duration_constant, NULL, extract_tags_daala, + NULL, NULL }, diff --git a/ext/ogg/gstoggstream.h b/ext/ogg/gstoggstream.h index a6da79e21b..06e2907351 100644 --- a/ext/ogg/gstoggstream.h +++ b/ext/ogg/gstoggstream.h @@ -94,6 +94,7 @@ struct _GstOggStream gboolean theora_has_zero_keyoffset; /* VP8 stuff */ gboolean is_vp8; + gint64 invisible_count; /* opus stuff */ gint64 first_granpos; /* OGM stuff */ @@ -136,6 +137,7 @@ gint64 gst_ogg_stream_get_packet_duration (GstOggStream * pad, ogg_packet *packe void gst_ogg_stream_extract_tags (GstOggStream * pad, ogg_packet * packet); const char *gst_ogg_stream_get_media_type (GstOggStream * pad); GstBuffer *gst_ogg_stream_get_headers (GstOggStream *pad); +void gst_ogg_stream_update_stats (GstOggStream * pad, ogg_packet * packet); gboolean gst_ogg_map_parse_fisbone (GstOggStream * pad, const guint8 * data, guint size, guint32 * serialno, GstOggSkeleton *type);