From 30236ddfd39f50400f5a779de1d28cd4069e6577 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Thu, 18 Aug 2011 09:48:16 +0100 Subject: [PATCH 01/10] audioresample: fix build without orc https://bugzilla.gnome.org/show_bug.cgi?id=656781 --- gst/audioresample/resample.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/gst/audioresample/resample.c b/gst/audioresample/resample.c index ca4960804e..7cc04d66cf 100644 --- a/gst/audioresample/resample.c +++ b/gst/audioresample/resample.c @@ -928,6 +928,7 @@ speex_resampler_init (spx_uint32_t nb_channels, spx_uint32_t in_rate, out_rate, quality, err); } +#if defined HAVE_ORC && !defined DISABLE_ORC static void check_insn_set (SpeexResamplerState * st, const char *name) { @@ -938,6 +939,7 @@ check_insn_set (SpeexResamplerState * st, const char *name) if (!strcmp (name, "sse2")) st->use_sse = st->use_sse2 = 1; } +#endif EXPORT SpeexResamplerState * speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num, From 3fe42b8e7e30d064ea60b649d681b0e0fcff5c1c Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 17 Aug 2011 17:18:47 +0100 Subject: [PATCH 02/10] oggmux: headers should always have granpos 0 https://bugzilla.gnome.org/show_bug.cgi?id=656775 --- ext/ogg/gstoggmux.c | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/ext/ogg/gstoggmux.c b/ext/ogg/gstoggmux.c index 083e21cd12..60e92a0097 100644 --- a/ext/ogg/gstoggmux.c +++ b/ext/ogg/gstoggmux.c @@ -1198,9 +1198,7 @@ gst_ogg_mux_send_headers (GstOggMux * mux) /* create a packet from the buffer */ packet.packet = GST_BUFFER_DATA (buf); packet.bytes = GST_BUFFER_SIZE (buf); - packet.granulepos = GST_BUFFER_OFFSET_END (buf); - if (packet.granulepos == -1) - packet.granulepos = 0; + packet.granulepos = 0; /* mark BOS and packet number */ packet.b_o_s = (pad->packetno == 0); packet.packetno = pad->packetno++; @@ -1267,9 +1265,7 @@ gst_ogg_mux_send_headers (GstOggMux * mux) /* create a packet from the buffer */ packet.packet = GST_BUFFER_DATA (buf); packet.bytes = GST_BUFFER_SIZE (buf); - packet.granulepos = GST_BUFFER_OFFSET_END (buf); - if (packet.granulepos == -1) - packet.granulepos = 0; + packet.granulepos = 0; /* mark BOS and packet number */ packet.b_o_s = (pad->packetno == 0); packet.packetno = pad->packetno++; From 684b90ba74ed8997bd252ddef9f3bac8d5e3e245 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 17 Aug 2011 17:39:18 +0100 Subject: [PATCH 03/10] oggmux: factor the header packet creation code https://bugzilla.gnome.org/show_bug.cgi?id=656775 --- ext/ogg/gstoggmux.c | 31 +++++++++++++++---------------- 1 file changed, 15 insertions(+), 16 deletions(-) diff --git a/ext/ogg/gstoggmux.c b/ext/ogg/gstoggmux.c index 60e92a0097..40348acf09 100644 --- a/ext/ogg/gstoggmux.c +++ b/ext/ogg/gstoggmux.c @@ -1116,6 +1116,19 @@ gst_ogg_mux_set_header_on_caps (GstCaps * caps, GList * buffers) return caps; } +static void +create_header_packet (ogg_packet * packet, GstBuffer * buf, GstOggPadData * pad) +{ + packet->packet = GST_BUFFER_DATA (buf); + packet->bytes = GST_BUFFER_SIZE (buf); + packet->granulepos = 0; + /* mark BOS and packet number */ + packet->b_o_s = (pad->packetno == 0); + packet->packetno = pad->packetno++; + /* mark EOS */ + packet->e_o_s = 0; +} + /* * For each pad we need to write out one (small) header in one * page that allows decoders to identify the type of the stream. @@ -1196,14 +1209,7 @@ gst_ogg_mux_send_headers (GstOggMux * mux) } /* create a packet from the buffer */ - packet.packet = GST_BUFFER_DATA (buf); - packet.bytes = GST_BUFFER_SIZE (buf); - packet.granulepos = 0; - /* mark BOS and packet number */ - packet.b_o_s = (pad->packetno == 0); - packet.packetno = pad->packetno++; - /* mark EOS */ - packet.e_o_s = 0; + create_header_packet (&packet, buf, pad); /* swap the packet in */ ogg_stream_packetin (&pad->map.stream, &packet); @@ -1263,14 +1269,7 @@ gst_ogg_mux_send_headers (GstOggMux * mux) hwalk = hwalk->next; /* create a packet from the buffer */ - packet.packet = GST_BUFFER_DATA (buf); - packet.bytes = GST_BUFFER_SIZE (buf); - packet.granulepos = 0; - /* mark BOS and packet number */ - packet.b_o_s = (pad->packetno == 0); - packet.packetno = pad->packetno++; - /* mark EOS */ - packet.e_o_s = 0; + create_header_packet (&packet, buf, pad); /* swap the packet in */ ogg_stream_packetin (&pad->map.stream, &packet); From 5bbf7109ec681fecdedbe9e48c8045bb9525e87f Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 17 Aug 2011 18:03:16 +0100 Subject: [PATCH 04/10] ogg: rationalize serialno type to guint32 It is a 32 bit unsigned number. Sure, the libogg API uses a long, but that's an unfortunate oversight. https://bugzilla.gnome.org/show_bug.cgi?id=656775 --- ext/ogg/gstoggdemux.c | 86 ++++++++++++++++++++++++------------------ ext/ogg/gstoggmux.c | 12 +++++- ext/ogg/gstoggstream.h | 2 +- 3 files changed, 60 insertions(+), 40 deletions(-) diff --git a/ext/ogg/gstoggdemux.c b/ext/ogg/gstoggdemux.c index 67d232137c..eddaa44e76 100644 --- a/ext/ogg/gstoggdemux.c +++ b/ext/ogg/gstoggdemux.c @@ -116,7 +116,7 @@ static gboolean gst_ogg_pad_src_query (GstPad * pad, GstQuery * query); static gboolean gst_ogg_pad_event (GstPad * pad, GstEvent * event); static GstCaps *gst_ogg_pad_getcaps (GstPad * pad); static GstOggPad *gst_ogg_chain_get_stream (GstOggChain * chain, - glong serialno); + guint32 serialno); static GstFlowReturn gst_ogg_demux_combine_flows (GstOggDemux * ogg, GstOggPad * pad, GstFlowReturn ret); @@ -427,8 +427,8 @@ gst_ogg_demux_queue_data (GstOggPad * pad, ogg_packet * packet) GstOggDemux *ogg = pad->ogg; #endif - GST_DEBUG_OBJECT (ogg, "%p queueing data serial %08lx", pad, - pad->map.serialno); + GST_DEBUG_OBJECT (ogg, "%p queueing data serial %08" G_GINT32_MODIFIER "x", + pad, pad->map.serialno); pad->map.queued = g_list_append (pad->map.queued, _ogg_packet_copy (packet)); @@ -455,7 +455,8 @@ gst_ogg_demux_chain_peer (GstOggPad * pad, ogg_packet * packet, cret = GST_FLOW_OK; GST_DEBUG_OBJECT (ogg, - "%p streaming to peer serial %08lx", pad, pad->map.serialno); + "%p streaming to peer serial %08" G_GINT32_MODIFIER "x", pad, + pad->map.serialno); if (pad->map.is_ogm) { const guint8 *data; @@ -705,8 +706,8 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet) GstOggDemux *ogg = pad->ogg; - GST_DEBUG_OBJECT (ogg, "%p submit packet serial %08lx", pad, - pad->map.serialno); + GST_DEBUG_OBJECT (ogg, "%p submit packet serial %08" G_GINT32_MODIFIER "x", + pad, pad->map.serialno); if (!pad->have_type) { pad->have_type = gst_ogg_stream_setup_map (&pad->map, packet); @@ -979,8 +980,8 @@ gst_ogg_pad_stream_out (GstOggPad * pad, gint npackets) could_not_submit: { GST_WARNING_OBJECT (ogg, - "could not submit packet for stream %08lx, error: %d", - pad->map.serialno, result); + "could not submit packet for stream %08" G_GINT32_MODIFIER + "x, error: %d", pad->map.serialno, result); gst_ogg_pad_reset (pad); return result; } @@ -1072,8 +1073,8 @@ done: choked: { GST_WARNING_OBJECT (ogg, - "ogg stream choked on page (serial %08lx), resetting stream", - pad->map.serialno); + "ogg stream choked on page (serial %08" G_GINT32_MODIFIER + "x), resetting stream", pad->map.serialno); gst_ogg_pad_reset (pad); /* we continue to recover */ return GST_FLOW_OK; @@ -1146,14 +1147,15 @@ gst_ogg_chain_reset (GstOggChain * chain) } static GstOggPad * -gst_ogg_chain_new_stream (GstOggChain * chain, glong serialno) +gst_ogg_chain_new_stream (GstOggChain * chain, guint32 serialno) { GstOggPad *ret; GstTagList *list; gchar *name; - GST_DEBUG_OBJECT (chain->ogg, "creating new stream %08lx in chain %p", - serialno, chain); + GST_DEBUG_OBJECT (chain->ogg, + "creating new stream %08" G_GINT32_MODIFIER "x in chain %p", serialno, + chain); ret = g_object_new (GST_TYPE_OGG_PAD, NULL); /* we own this one */ @@ -1170,7 +1172,7 @@ gst_ogg_chain_new_stream (GstOggChain * chain, glong serialno) if (ogg_stream_init (&ret->map.stream, serialno) != 0) goto init_failed; - name = g_strdup_printf ("serial_%08lx", serialno); + name = g_strdup_printf ("serial_%08" G_GINT32_MODIFIER "x", serialno); gst_object_set_name (GST_OBJECT (ret), name); g_free (name); @@ -1181,7 +1183,8 @@ gst_ogg_chain_new_stream (GstOggChain * chain, glong serialno) gst_tag_list_free (list); GST_DEBUG_OBJECT (chain->ogg, - "created new ogg src %p for stream with serial %08lx", ret, serialno); + "created new ogg src %p for stream with serial %08" G_GINT32_MODIFIER "x", + ret, serialno); g_array_append_val (chain->streams, ret); @@ -1190,15 +1193,15 @@ gst_ogg_chain_new_stream (GstOggChain * chain, glong serialno) /* ERRORS */ init_failed: { - GST_ERROR ("Could not initialize ogg_stream struct for serial %08lx.", - serialno); + GST_ERROR ("Could not initialize ogg_stream struct for serial %08" + G_GINT32_MODIFIER "x.", serialno); gst_object_unref (ret); return NULL; } } static GstOggPad * -gst_ogg_chain_get_stream (GstOggChain * chain, glong serialno) +gst_ogg_chain_get_stream (GstOggChain * chain, guint32 serialno) { gint i; @@ -1212,7 +1215,7 @@ gst_ogg_chain_get_stream (GstOggChain * chain, glong serialno) } static gboolean -gst_ogg_chain_has_stream (GstOggChain * chain, glong serialno) +gst_ogg_chain_has_stream (GstOggChain * chain, guint32 serialno) { return gst_ogg_chain_get_stream (chain, serialno) != NULL; } @@ -2165,7 +2168,8 @@ gst_ogg_demux_do_seek (GstOggDemux * ogg, GstSegment * segment, /* get time of the keyframe */ keyframe_time = gst_ogg_stream_granule_to_time (&pad->map, pad->keyframe_granule); - GST_LOG_OBJECT (ogg, "stream %08lx granule time %" GST_TIME_FORMAT, + GST_LOG_OBJECT (ogg, + "stream %08" G_GINT32_MODIFIER "x granule time %" GST_TIME_FORMAT, pad->map.serialno, GST_TIME_ARGS (keyframe_time)); /* collect smallest value */ @@ -2586,7 +2590,7 @@ gst_ogg_demux_bisect_forward_serialno (GstOggDemux * ogg, if (ret == GST_FLOW_UNEXPECTED) { endsearched = bisect; } else if (ret == GST_FLOW_OK) { - glong serial = ogg_page_serialno (&og); + guint32 serial = ogg_page_serialno (&og); if (!gst_ogg_chain_has_stream (chain, serial)) { endsearched = bisect; @@ -2655,7 +2659,7 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain) * the decoders, send data to the decoders. */ while (TRUE) { GstOggPad *pad; - glong serial; + guint32 serial; ret = gst_ogg_demux_get_next_page (ogg, &op, -1, NULL); if (ret != GST_FLOW_OK) { @@ -2678,7 +2682,8 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain) serial = ogg_page_serialno (&op); if (gst_ogg_chain_get_stream (chain, serial) != NULL) { - GST_WARNING_OBJECT (ogg, "found serial %08lx BOS page twice, ignoring", + GST_WARNING_OBJECT (ogg, + "found serial %08" G_GINT32_MODIFIER "x BOS page twice, ignoring", serial); continue; } @@ -2719,7 +2724,7 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain) done = FALSE; while (!done) { - glong serial; + guint32 serial; gboolean known_serial = FALSE; GstFlowReturn ret; @@ -2728,7 +2733,8 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain) for (i = 0; i < chain->streams->len; i++) { GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, i); - GST_LOG_OBJECT (ogg, "serial %08lx time %" GST_TIME_FORMAT, + GST_LOG_OBJECT (ogg, + "serial %08" G_GINT32_MODIFIER "x time %" GST_TIME_FORMAT, pad->map.serialno, GST_TIME_ARGS (pad->start_time)); if (pad->map.serialno == serial) { @@ -2752,14 +2758,15 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain) if (!pad->map.is_sparse) done &= (pad->start_time != GST_CLOCK_TIME_NONE); - GST_LOG_OBJECT (ogg, "done %08lx now %d", pad->map.serialno, done); + GST_LOG_OBJECT (ogg, "done %08" G_GINT32_MODIFIER "x now %d", + pad->map.serialno, done); } /* we read a page not belonging to the current chain: seek back to the * beginning of the chain */ if (!known_serial) { - GST_LOG_OBJECT (ogg, "unknown serial %08lx", serial); + GST_LOG_OBJECT (ogg, "unknown serial %08" G_GINT32_MODIFIER "x", serial); gst_ogg_demux_seek (ogg, offset); break; } @@ -2856,7 +2863,7 @@ gst_ogg_demux_read_end_chain (GstOggDemux * ogg, GstOggChain * chain) /* find a pad with a given serial number */ static GstOggPad * -gst_ogg_demux_find_pad (GstOggDemux * ogg, glong serialno) +gst_ogg_demux_find_pad (GstOggDemux * ogg, guint32 serialno) { GstOggPad *pad; gint i; @@ -2888,7 +2895,7 @@ gst_ogg_demux_find_pad (GstOggDemux * ogg, glong serialno) /* find a chain with a given serial number */ static GstOggChain * -gst_ogg_demux_find_chain (GstOggDemux * ogg, glong serialno) +gst_ogg_demux_find_chain (GstOggDemux * ogg, guint32 serialno) { GstOggPad *pad; @@ -2957,7 +2964,7 @@ gst_ogg_demux_find_chains (GstOggDemux * ogg) GstPad *peer; GstFormat format; gboolean res; - gulong serialno; + guint32 serialno; GstOggChain *chain; GstFlowReturn ret; @@ -3046,16 +3053,16 @@ gst_ogg_demux_handle_page (GstOggDemux * ogg, ogg_page * page) { GstOggPad *pad; gint64 granule; - glong serialno; + guint32 serialno; GstFlowReturn result = GST_FLOW_OK; serialno = ogg_page_serialno (page); granule = ogg_page_granulepos (page); GST_LOG_OBJECT (ogg, - "processing ogg page (serial %08lx, pageno %ld, granulepos %" - G_GINT64_FORMAT ", bos %d)", - serialno, ogg_page_pageno (page), granule, ogg_page_bos (page)); + "processing ogg page (serial %08" G_GINT32_MODIFIER + "x, pageno %ld, granulepos %" G_GINT64_FORMAT ", bos %d)", serialno, + ogg_page_pageno (page), granule, ogg_page_bos (page)); if (ogg_page_bos (page)) { GstOggChain *chain; @@ -3122,7 +3129,9 @@ gst_ogg_demux_handle_page (GstOggDemux * ogg, ogg_page * page) /* no pad. This means an ogg page without bos has been seen for this * serialno. we just ignore it but post a warning... */ GST_ELEMENT_WARNING (ogg, STREAM, DECODE, - (NULL), ("unknown ogg pad for serial %08lx detected", serialno)); + (NULL), + ("unknown ogg pad for serial %08" G_GINT32_MODIFIER "x detected", + serialno)); return GST_FLOW_OK; } return result; @@ -3131,7 +3140,9 @@ gst_ogg_demux_handle_page (GstOggDemux * ogg, ogg_page * page) unknown_chain: { GST_ELEMENT_ERROR (ogg, STREAM, DECODE, - (NULL), ("unknown ogg chain for serial %08lx detected", serialno)); + (NULL), + ("unknown ogg chain for serial %08" G_GINT32_MODIFIER "x detected", + serialno)); return GST_FLOW_ERROR; } } @@ -3674,7 +3685,8 @@ gst_ogg_print (GstOggDemux * ogg) for (j = 0; j < chain->streams->len; j++) { GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, j); - GST_INFO_OBJECT (ogg, " stream %08lx:", stream->map.serialno); + GST_INFO_OBJECT (ogg, " stream %08" G_GINT32_MODIFIER "x:", + stream->map.serialno); GST_INFO_OBJECT (ogg, " start time: %" GST_TIME_FORMAT, GST_TIME_ARGS (stream->start_time)); } diff --git a/ext/ogg/gstoggmux.c b/ext/ogg/gstoggmux.c index 40348acf09..0ac8442598 100644 --- a/ext/ogg/gstoggmux.c +++ b/ext/ogg/gstoggmux.c @@ -414,7 +414,7 @@ gst_ogg_mux_request_new_pad (GstElement * element, goto wrong_template; { - gint serial; + guint32 serial; gchar *name; if (req_name == NULL || strlen (req_name) < 6) { @@ -422,7 +422,15 @@ gst_ogg_mux_request_new_pad (GstElement * element, serial = gst_ogg_mux_generate_serialno (ogg_mux); } else { /* parse serial number from requested padname */ - serial = atoi (&req_name[5]); + unsigned long long_serial; + char *endptr = NULL; + long_serial = strtoul (&req_name[5], &endptr, 10); + if ((endptr && *endptr) || (long_serial & ~0xffffffff)) { + GST_WARNING_OBJECT (ogg_mux, "Invalid serial number specification: %s", + req_name + 5); + return NULL; + } + serial = (guint32) long_serial; } /* create new pad with the name */ GST_DEBUG_OBJECT (ogg_mux, "Creating new pad for serial %d", serial); diff --git a/ext/ogg/gstoggstream.h b/ext/ogg/gstoggstream.h index f843692eaf..b45c88a285 100644 --- a/ext/ogg/gstoggstream.h +++ b/ext/ogg/gstoggstream.h @@ -45,7 +45,7 @@ struct _GstOggStream { ogg_stream_state stream; - glong serialno; + guint32 serialno; GList *headers; gboolean have_headers; GList *queued; From fd8434fc7450dc3bdc057d2d89a875be9b683181 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 17 Aug 2011 18:38:39 +0100 Subject: [PATCH 05/10] oggmux: use oggstream to decide which BOS packets to place first Ogg recommends video BOS packets to be first. Use the "is_video" flag in oggstream to select those, rather than check for known mime types. https://bugzilla.gnome.org/show_bug.cgi?id=656775 --- ext/ogg/gstoggmux.c | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/ext/ogg/gstoggmux.c b/ext/ogg/gstoggmux.c index 0ac8442598..d24e4bb282 100644 --- a/ext/ogg/gstoggmux.c +++ b/ext/ogg/gstoggmux.c @@ -1232,25 +1232,23 @@ gst_ogg_mux_send_headers (GstOggMux * mux) GST_LOG_OBJECT (mux, "swapped out page with mime type %s", gst_structure_get_name (structure)); - /* quick hack: put Theora, VP8 and Dirac video pages at the front. + /* quick hack: put video pages at the front. * Ideally, we would have a settable enum for which Ogg * profile we work with, and order based on that. * (FIXME: if there is more than one video stream, shouldn't we only put * one's BOS into the first page, followed by an audio stream's BOS, and * only then followed by the remaining video and audio streams?) */ - if (gst_structure_has_name (structure, "video/x-theora")) { - GST_DEBUG_OBJECT (thepad, "putting %s page at the front", "Theora"); - hbufs = g_list_prepend (hbufs, hbuf); - } else if (gst_structure_has_name (structure, "video/x-dirac")) { - GST_DEBUG_OBJECT (thepad, "putting %s page at the front", "Dirac"); - hbufs = g_list_prepend (hbufs, hbuf); - pad->always_flush_page = TRUE; - } else if (gst_structure_has_name (structure, "video/x-vp8")) { - GST_DEBUG_OBJECT (thepad, "putting %s page at the front", "VP8"); + if (pad->map.is_video) { + GST_DEBUG_OBJECT (thepad, "putting %s page at the front", + gst_structure_get_name (structure)); hbufs = g_list_prepend (hbufs, hbuf); } else { hbufs = g_list_append (hbufs, hbuf); } + + if (gst_structure_has_name (structure, "video/x-dirac")) { + pad->always_flush_page = TRUE; + } gst_caps_unref (caps); } From 8304b7b40d2f791947d3e0360c7a50fa6365a28e Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 17 Aug 2011 18:48:54 +0100 Subject: [PATCH 06/10] ogg: move the "always flush page" to oggstream It avoids checking for specific media types in the muxer. https://bugzilla.gnome.org/show_bug.cgi?id=656775 --- ext/ogg/gstoggmux.c | 10 ++-------- ext/ogg/gstoggmux.h | 2 -- ext/ogg/gstoggstream.c | 3 +++ ext/ogg/gstoggstream.h | 2 ++ 4 files changed, 7 insertions(+), 10 deletions(-) diff --git a/ext/ogg/gstoggmux.c b/ext/ogg/gstoggmux.c index d24e4bb282..f039efca6e 100644 --- a/ext/ogg/gstoggmux.c +++ b/ext/ogg/gstoggmux.c @@ -1069,13 +1069,9 @@ gst_ogg_mux_get_headers (GstOggPadData * pad) GST_LOG_OBJECT (thepad, "streamheader is not fixed list"); } - /* Start a new page for every CMML buffer */ - if (gst_structure_has_name (structure, "text/x-cmml")) - pad->always_flush_page = TRUE; } else if (gst_structure_has_name (structure, "video/x-dirac")) { res = g_list_append (res, pad->buffer); pad->buffer = NULL; - pad->always_flush_page = TRUE; } else { GST_LOG_OBJECT (thepad, "caps don't have streamheader"); } @@ -1246,9 +1242,6 @@ gst_ogg_mux_send_headers (GstOggMux * mux) hbufs = g_list_append (hbufs, hbuf); } - if (gst_structure_has_name (structure, "video/x-dirac")) { - pad->always_flush_page = TRUE; - } gst_caps_unref (caps); } @@ -1494,7 +1487,8 @@ gst_ogg_mux_process_best_pad (GstOggMux * ogg_mux, GstOggPadData * best) tmpbuf = NULL; /* we flush when we see a new keyframe */ - force_flush = (pad->prev_delta && !delta_unit) || pad->always_flush_page; + force_flush = (pad->prev_delta && !delta_unit) + || pad->map.always_flush_page; if (duration != -1) { pad->duration += duration; /* if page duration exceeds max, flush page */ diff --git a/ext/ogg/gstoggmux.h b/ext/ogg/gstoggmux.h index ec94224d85..3edc1f5b51 100644 --- a/ext/ogg/gstoggmux.h +++ b/ext/ogg/gstoggmux.h @@ -83,8 +83,6 @@ typedef struct gint64 keyframe_granule; /* granule of last preceding keyframe */ GstPadEventFunction collect_event; - - gboolean always_flush_page; } GstOggPadData; diff --git a/ext/ogg/gstoggstream.c b/ext/ogg/gstoggstream.c index 77f39d44ae..5c9ae296a2 100644 --- a/ext/ogg/gstoggstream.c +++ b/ext/ogg/gstoggstream.c @@ -474,6 +474,7 @@ setup_dirac_mapper (GstOggStream * pad, ogg_packet * packet) } pad->is_video = TRUE; + pad->always_flush_page = TRUE; pad->granulerate_n = header.frame_rate_numerator * 2; pad->granulerate_d = header.frame_rate_denominator; pad->granuleshift = 22; @@ -1668,6 +1669,7 @@ setup_cmml_mapper (GstOggStream * pad, ogg_packet * packet) GST_DEBUG ("blocksize1: %u", 1 << (data[0] & 0x0F)); pad->caps = gst_caps_new_simple ("text/x-cmml", NULL); + pad->always_flush_page = TRUE; pad->is_sparse = TRUE; return TRUE; @@ -1729,6 +1731,7 @@ setup_kate_mapper (GstOggStream * pad, ogg_packet * packet) } pad->is_sparse = TRUE; + pad->always_flush_page = TRUE; return TRUE; } diff --git a/ext/ogg/gstoggstream.h b/ext/ogg/gstoggstream.h index b45c88a285..6f4a3f8c8f 100644 --- a/ext/ogg/gstoggstream.h +++ b/ext/ogg/gstoggstream.h @@ -73,6 +73,8 @@ struct _GstOggStream GstCaps *caps; gboolean is_video; + gboolean always_flush_page; + /* vorbis stuff */ int nln_increments[4]; int nsn_increment; From 96e7bf53e98970cc51dcc463e61bff50ab995073 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Wed, 17 Aug 2011 19:40:08 +0100 Subject: [PATCH 07/10] oggstream: new convenience function to get a stream's media type This will make logging a lot clearer, both in code and in output. https://bugzilla.gnome.org/show_bug.cgi?id=656775 --- ext/ogg/gstoggstream.c | 13 +++++++++++++ ext/ogg/gstoggstream.h | 1 + 2 files changed, 14 insertions(+) diff --git a/ext/ogg/gstoggstream.c b/ext/ogg/gstoggstream.c index 5c9ae296a2..1b859a2b27 100644 --- a/ext/ogg/gstoggstream.c +++ b/ext/ogg/gstoggstream.c @@ -225,6 +225,19 @@ gst_ogg_stream_extract_tags (GstOggStream * pad, ogg_packet * packet) mappers[pad->map].extract_tags_func (pad, packet); } +const char * +gst_ogg_stream_get_media_type (GstOggStream * pad) +{ + const GstCaps *caps = pad->caps; + const GstStructure *structure; + if (!caps) + return NULL; + structure = gst_caps_get_structure (caps, 0); + if (!structure) + return NULL; + return gst_structure_get_name (structure); +} + /* some generic functions */ static gboolean diff --git a/ext/ogg/gstoggstream.h b/ext/ogg/gstoggstream.h index 6f4a3f8c8f..d6c4de61c1 100644 --- a/ext/ogg/gstoggstream.h +++ b/ext/ogg/gstoggstream.h @@ -125,6 +125,7 @@ gboolean gst_ogg_stream_granulepos_is_key_frame (GstOggStream *pad, gboolean gst_ogg_stream_packet_is_header (GstOggStream *pad, ogg_packet *packet); gint64 gst_ogg_stream_get_packet_duration (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); gboolean gst_ogg_map_parse_fisbone (GstOggStream * pad, const guint8 * data, guint size, guint32 * serialno, GstOggSkeleton *type); From cf370e02194479247be6940c7e427b13ce8fda04 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Thu, 18 Aug 2011 09:30:46 +0100 Subject: [PATCH 08/10] oggstream: vorbis has a preroll of 2 https://bugzilla.gnome.org/show_bug.cgi?id=656775 --- ext/ogg/gstoggstream.c | 1 + 1 file changed, 1 insertion(+) diff --git a/ext/ogg/gstoggstream.c b/ext/ogg/gstoggstream.c index 1b859a2b27..a0b4e687c6 100644 --- a/ext/ogg/gstoggstream.c +++ b/ext/ogg/gstoggstream.c @@ -717,6 +717,7 @@ setup_vorbis_mapper (GstOggStream * pad, ogg_packet * packet) pad->granulerate_n = GST_READ_UINT32_LE (data); pad->granulerate_d = 1; pad->granuleshift = 0; + pad->preroll = 2; pad->last_size = 0; GST_LOG ("sample rate: %d", pad->granulerate_n); From 1dadc5eac13804847426a220978d1da87048a900 Mon Sep 17 00:00:00 2001 From: Vincent Penquerc'h Date: Thu, 18 Aug 2011 09:37:38 +0100 Subject: [PATCH 09/10] ogg: get the operator precedence right, even if only a doc https://bugzilla.gnome.org/show_bug.cgi?id=656775 --- ext/ogg/README | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/ogg/README b/ext/ogg/README index 557e9d5035..da449e149b 100644 --- a/ext/ogg/README +++ b/ext/ogg/README @@ -30,7 +30,7 @@ The granulepos in theora is an encoding of the frame number of the last key frame ("i frame"), and the number of frames since the last key frame ("p frame"). The granulepos is constructed as the sum of the first number, shifted to the left for granuleshift bits, and the second number: -granulepos = pframe << granuleshift + iframe +granulepos = (pframe << granuleshift) + iframe (This means that given a framenumber or a timestamp, one cannot generate the one and only granulepos for that page; several granulepos possibilities From 2ee31ccac93ebaf9fc8706b1d07f54dba1ad7eef Mon Sep 17 00:00:00 2001 From: Edward Hervey Date: Wed, 27 Jul 2011 11:05:31 +0000 Subject: [PATCH 10/10] playsink: Reconfigure when pads are added later Instead of just assuming all pads are created at the same time, remember which ones are actually new (via ->pending_blocked_pads). This allows the following use-case to properly work: * Upstream starts with audio-only * Only that pad gets data, blocks and a real audio sink is created * Upstream laters adds a video stream * A new pad is requested, blocks and reconfiguration kicks in in order to add a new real video sink --- gst/playback/gstplaysink.c | 40 +++++++++++++++++++++++++++++++++++--- 1 file changed, 37 insertions(+), 3 deletions(-) diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index b36ab1bb4d..019dcc3ec6 100644 --- a/gst/playback/gstplaysink.c +++ b/gst/playback/gstplaysink.c @@ -127,6 +127,19 @@ typedef struct g_static_rec_mutex_unlock (GST_PLAY_SINK_GET_LOCK (playsink)); \ } G_STMT_END +#define PENDING_FLAG_SET(playsink, flagtype) \ + ((playsink->pending_blocked_pads) |= (1 << flagtype)) +#define PENDING_FLAG_UNSET(playsink, flagtype) \ + ((playsink->pending_blocked_pads) &= ~(1 << flagtype)) +#define PENDING_FLAG_IS_SET(playsink, flagtype) \ + ((playsink->pending_blocked_pads) & (1 << flagtype)) +#define PENDING_VIDEO_BLOCK(playsink) \ + ((playsink->pending_blocked_pads) & (1 << GST_PLAY_SINK_TYPE_VIDEO_RAW | 1 << GST_PLAY_SINK_TYPE_VIDEO)) +#define PENDING_AUDIO_BLOCK(playsink) \ + ((playsink->pending_blocked_pads) & (1 << GST_PLAY_SINK_TYPE_AUDIO_RAW | 1 << GST_PLAY_SINK_TYPE_AUDIO)) +#define PENDING_TEXT_BLOCK(playsink) \ + PENDING_FLAG_IS_SET(playsink, GST_PLAY_SINK_TYPE_TEXT) + struct _GstPlaySink { GstBin bin; @@ -170,6 +183,8 @@ struct _GstPlaySink GstPad *text_srcpad_stream_synchronizer; GstPad *text_sinkpad_stream_synchronizer; + guint32 pending_blocked_pads; + /* properties */ GstElement *audio_sink; GstElement *video_sink; @@ -2868,12 +2883,22 @@ sinkpad_blocked_cb (GstPad * blockedpad, gboolean blocked, gpointer user_data) if (pad == playsink->video_pad) { playsink->video_pad_blocked = blocked; GST_DEBUG_OBJECT (pad, "Video pad blocked: %d", blocked); + if (!blocked) { + PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_VIDEO_RAW); + PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_VIDEO); + } } else if (pad == playsink->audio_pad) { playsink->audio_pad_blocked = blocked; GST_DEBUG_OBJECT (pad, "Audio pad blocked: %d", blocked); + if (!blocked) { + PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_AUDIO_RAW); + PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_AUDIO); + } } else if (pad == playsink->text_pad) { playsink->text_pad_blocked = blocked; GST_DEBUG_OBJECT (pad, "Text pad blocked: %d", blocked); + if (!blocked) + PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_TEXT); } if (!blocked) { @@ -2882,9 +2907,17 @@ sinkpad_blocked_cb (GstPad * blockedpad, gboolean blocked, gpointer user_data) return; } - if ((!playsink->video_pad || playsink->video_pad_blocked) && - (!playsink->audio_pad || playsink->audio_pad_blocked) && - (!playsink->text_pad || playsink->text_pad_blocked)) { + /* We reconfigure when for ALL streams: + * * there isn't a pad + * * OR the pad is blocked + * * OR there are no pending blocks on that pad + */ + + if ((!playsink->video_pad || playsink->video_pad_blocked + || !PENDING_VIDEO_BLOCK (playsink)) && (!playsink->audio_pad + || playsink->audio_pad_blocked || !PENDING_AUDIO_BLOCK (playsink)) + && (!playsink->text_pad || playsink->text_pad_blocked + || !PENDING_TEXT_BLOCK (playsink))) { GST_DEBUG_OBJECT (playsink, "All pads blocked -- reconfiguring"); if (playsink->video_pad) { @@ -3104,6 +3137,7 @@ gst_play_sink_request_pad (GstPlaySink * playsink, GstPlaySinkType type) gst_pad_set_blocked_async_full (blockpad, TRUE, sinkpad_blocked_cb, gst_object_ref (playsink), (GDestroyNotify) gst_object_unref); + PENDING_FLAG_SET (playsink, type); gst_object_unref (blockpad); } if (!activate)