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,
"%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;

View file

@ -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 */

View file

@ -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
},

View file

@ -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);