oggmux: implement vp8 granulepos function

Add an extra function to the oggstream map to inform it about
the incoming buffers. This way oggmux can keep a count on the
vp8 invisible frames and calculate the granulepos correctly.

https://bugzilla.gnome.org/show_bug.cgi?id=722682
This commit is contained in:
Thiago Santos 2014-03-06 12:59:08 -03:00
parent e00c306571
commit a2633b7cf1
4 changed files with 60 additions and 6 deletions

View file

@ -524,6 +524,8 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet,
GST_DEBUG_OBJECT (ogg, GST_DEBUG_OBJECT (ogg,
"%p streaming to peer serial %08x", pad, pad->map.serialno); "%p streaming to peer serial %08x", pad, pad->map.serialno);
gst_ogg_stream_update_stats (&pad->map, packet);
if (pad->map.is_ogm) { if (pad->map.is_ogm) {
const guint8 *data; const guint8 *data;
long bytes; long bytes;

View file

@ -847,7 +847,11 @@ gst_ogg_mux_decorate_buffer (GstOggMux * ogg_mux, GstOggPadData * pad,
gst_buffer_map (buf, &map, GST_MAP_READ); gst_buffer_map (buf, &map, GST_MAP_READ);
packet.packet = map.data; packet.packet = map.data;
packet.bytes = map.size; packet.bytes = map.size;
gst_ogg_stream_update_stats (&pad->map, &packet);
duration = gst_ogg_stream_get_packet_duration (&pad->map, &packet); duration = gst_ogg_stream_get_packet_duration (&pad->map, &packet);
gst_buffer_unmap (buf, &map); gst_buffer_unmap (buf, &map);
/* give up if no duration can be determined, relying on upstream */ /* give up if no duration can be determined, relying on upstream */

View file

@ -69,6 +69,8 @@ typedef gint64 (*GstOggMapGranuleposToKeyGranuleFunc) (GstOggStream * pad,
gint64 granulepos); gint64 granulepos);
typedef GstBuffer *(*GstOggMapGetHeadersFunc) (GstOggStream * pad); typedef GstBuffer *(*GstOggMapGetHeadersFunc) (GstOggStream * pad);
typedef void (*GstOggMapUpdateStatsFunc) (GstOggStream * pad,
ogg_packet * packet);
#define SKELETON_FISBONE_MIN_SIZE 52 #define SKELETON_FISBONE_MIN_SIZE 52
#define SKELETON_FISHEAD_3_3_MIN_SIZE 112 #define SKELETON_FISHEAD_3_3_MIN_SIZE 112
@ -91,6 +93,7 @@ struct _GstOggMap
GstOggMapGranuleposToKeyGranuleFunc granulepos_to_key_granule_func; GstOggMapGranuleposToKeyGranuleFunc granulepos_to_key_granule_func;
GstOggMapExtractTagsFunc extract_tags_func; GstOggMapExtractTagsFunc extract_tags_func;
GstOggMapGetHeadersFunc get_headers_func; GstOggMapGetHeadersFunc get_headers_func;
GstOggMapUpdateStatsFunc update_stats_func;
}; };
extern const GstOggMap mappers[]; extern const GstOggMap mappers[];
@ -280,6 +283,15 @@ gst_ogg_stream_get_headers (GstOggStream * pad)
return mappers[pad->map].get_headers_func (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 */ /* some generic functions */
static gboolean static gboolean
@ -742,11 +754,14 @@ static gint64
granule_to_granulepos_vp8 (GstOggStream * pad, gint64 granule, granule_to_granulepos_vp8 (GstOggStream * pad, gint64 granule,
gint64 keyframe_granule) gint64 keyframe_granule)
{ {
/* FIXME: This requires to look into the content of the packets guint inv;
* because the simple granule counter doesn't know about invisible gint64 granulepos;
* frames...
*/ inv = (pad->invisible_count <= 0) ? 0x3 : pad->invisible_count - 1;
return -1;
granulepos =
(granule << 32) | (inv << 30) | ((granule - keyframe_granule) << 3);
return granulepos;
} }
/* Check if this packet contains an invisible frame or not */ /* Check if this packet contains an invisible frame or not */
@ -813,6 +828,18 @@ get_headers_vp8 (GstOggStream * pad)
return NULL; 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 */ /* vorbis */
static gboolean static gboolean
@ -2221,6 +2248,7 @@ const GstOggMap mappers[] = {
packet_duration_constant, packet_duration_constant,
NULL, NULL,
extract_tags_theora, extract_tags_theora,
NULL,
NULL NULL
}, },
{ {
@ -2236,6 +2264,7 @@ const GstOggMap mappers[] = {
packet_duration_vorbis, packet_duration_vorbis,
NULL, NULL,
extract_tags_vorbis, extract_tags_vorbis,
NULL,
NULL NULL
}, },
{ {
@ -2251,6 +2280,7 @@ const GstOggMap mappers[] = {
packet_duration_constant, packet_duration_constant,
NULL, NULL,
extract_tags_count, extract_tags_count,
NULL,
NULL NULL
}, },
{ {
@ -2266,6 +2296,7 @@ const GstOggMap mappers[] = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
NULL NULL
}, },
{ {
@ -2281,6 +2312,7 @@ const GstOggMap mappers[] = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
NULL NULL
}, },
{ {
@ -2296,6 +2328,7 @@ const GstOggMap mappers[] = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
NULL NULL
}, },
{ {
@ -2311,6 +2344,7 @@ const GstOggMap mappers[] = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
NULL NULL
}, },
{ {
@ -2326,6 +2360,7 @@ const GstOggMap mappers[] = {
packet_duration_flac, packet_duration_flac,
NULL, NULL,
NULL, NULL,
NULL,
NULL NULL
}, },
{ {
@ -2341,6 +2376,7 @@ const GstOggMap mappers[] = {
packet_duration_flac, packet_duration_flac,
NULL, NULL,
extract_tags_flac, extract_tags_flac,
NULL,
NULL NULL
}, },
{ {
@ -2355,6 +2391,7 @@ const GstOggMap mappers[] = {
NULL, NULL,
NULL, NULL,
NULL, NULL,
NULL,
NULL NULL
}, },
{ {
@ -2370,6 +2407,7 @@ const GstOggMap mappers[] = {
packet_duration_constant, packet_duration_constant,
NULL, NULL,
extract_tags_count, extract_tags_count,
NULL,
NULL NULL
}, },
{ {
@ -2385,6 +2423,7 @@ const GstOggMap mappers[] = {
packet_duration_kate, packet_duration_kate,
NULL, NULL,
extract_tags_kate, extract_tags_kate,
NULL,
NULL NULL
}, },
{ {
@ -2400,6 +2439,7 @@ const GstOggMap mappers[] = {
packet_duration_constant, packet_duration_constant,
granulepos_to_key_granule_dirac, granulepos_to_key_granule_dirac,
NULL, NULL,
NULL,
NULL NULL
}, },
{ {
@ -2415,7 +2455,8 @@ const GstOggMap mappers[] = {
packet_duration_vp8, packet_duration_vp8,
granulepos_to_key_granule_vp8, granulepos_to_key_granule_vp8,
extract_tags_vp8, extract_tags_vp8,
get_headers_vp8 get_headers_vp8,
update_stats_vp8
}, },
{ {
"OpusHead", 8, 0, "OpusHead", 8, 0,
@ -2430,6 +2471,7 @@ const GstOggMap mappers[] = {
packet_duration_opus, packet_duration_opus,
NULL, NULL,
extract_tags_opus, extract_tags_opus,
NULL,
NULL NULL
}, },
{ {
@ -2445,6 +2487,7 @@ const GstOggMap mappers[] = {
packet_duration_ogm, packet_duration_ogm,
NULL, NULL,
NULL, NULL,
NULL,
NULL NULL
}, },
{ {
@ -2460,6 +2503,7 @@ const GstOggMap mappers[] = {
packet_duration_constant, packet_duration_constant,
NULL, NULL,
NULL, NULL,
NULL,
NULL NULL
}, },
{ {
@ -2475,6 +2519,7 @@ const GstOggMap mappers[] = {
packet_duration_ogm, packet_duration_ogm,
NULL, NULL,
extract_tags_ogm, extract_tags_ogm,
NULL,
NULL NULL
}, },
{ {
@ -2490,6 +2535,7 @@ const GstOggMap mappers[] = {
packet_duration_constant, packet_duration_constant,
NULL, NULL,
extract_tags_daala, extract_tags_daala,
NULL,
NULL NULL
}, },

View file

@ -94,6 +94,7 @@ struct _GstOggStream
gboolean theora_has_zero_keyoffset; gboolean theora_has_zero_keyoffset;
/* VP8 stuff */ /* VP8 stuff */
gboolean is_vp8; gboolean is_vp8;
gint64 invisible_count;
/* opus stuff */ /* opus stuff */
gint64 first_granpos; gint64 first_granpos;
/* OGM stuff */ /* 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); void gst_ogg_stream_extract_tags (GstOggStream * pad, ogg_packet * packet);
const char *gst_ogg_stream_get_media_type (GstOggStream * pad); const char *gst_ogg_stream_get_media_type (GstOggStream * pad);
GstBuffer *gst_ogg_stream_get_headers (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, gboolean gst_ogg_map_parse_fisbone (GstOggStream * pad, const guint8 * data, guint size,
guint32 * serialno, GstOggSkeleton *type); guint32 * serialno, GstOggSkeleton *type);