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 diff --git a/ext/ogg/gstoggdemux.c b/ext/ogg/gstoggdemux.c index 72e162447a..f1010015c8 100644 --- a/ext/ogg/gstoggdemux.c +++ b/ext/ogg/gstoggdemux.c @@ -115,7 +115,7 @@ static const GstQueryType *gst_ogg_pad_query_types (GstPad * pad); static gboolean gst_ogg_pad_src_query (GstPad * pad, GstQuery * query); static gboolean gst_ogg_pad_event (GstPad * pad, GstEvent * event); 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); @@ -419,8 +419,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)); @@ -447,7 +447,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; @@ -697,8 +698,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); @@ -982,8 +983,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; } @@ -1075,8 +1076,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; @@ -1149,14 +1150,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 */ @@ -1172,7 +1174,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); @@ -1183,7 +1185,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); gst_pad_set_active (GST_PAD_CAST (ret), TRUE); @@ -1193,15 +1196,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; @@ -1215,7 +1218,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; } @@ -2162,7 +2165,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 */ @@ -2566,7 +2570,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; @@ -2635,7 +2639,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) { @@ -2658,7 +2662,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; } @@ -2699,7 +2704,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; @@ -2708,7 +2713,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) { @@ -2732,14 +2738,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; } @@ -2836,7 +2843,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; @@ -2868,7 +2875,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; @@ -2936,7 +2943,7 @@ gst_ogg_demux_find_chains (GstOggDemux * ogg) ogg_page og; GstPad *peer; gboolean res; - gulong serialno; + guint32 serialno; GstOggChain *chain; GstFlowReturn ret; @@ -3024,16 +3031,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; @@ -3104,7 +3111,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; @@ -3113,7 +3122,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; } } @@ -3675,7 +3686,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 a87e4fc3d8..2f043ec111 100644 --- a/ext/ogg/gstoggmux.c +++ b/ext/ogg/gstoggmux.c @@ -366,7 +366,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) { @@ -374,7 +374,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); @@ -1014,13 +1022,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"); } @@ -1070,6 +1074,21 @@ 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) +{ + gsize size; + + packet->packet = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); + packet->bytes = size; + 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. @@ -1151,16 +1170,7 @@ gst_ogg_mux_send_headers (GstOggMux * mux) } /* create a packet from the buffer */ - packet.packet = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); - packet.bytes = size; - packet.granulepos = GST_BUFFER_OFFSET_END (buf); - if (packet.granulepos == -1) - 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); @@ -1177,25 +1187,20 @@ 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); } + gst_caps_unref (caps); } @@ -1223,16 +1228,7 @@ gst_ogg_mux_send_headers (GstOggMux * mux) hwalk = hwalk->next; /* create a packet from the buffer */ - packet.packet = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); - packet.bytes = size; - packet.granulepos = GST_BUFFER_OFFSET_END (buf); - if (packet.granulepos == -1) - 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); @@ -1453,7 +1449,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 83730d5e01..fb19d87b66 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 @@ -467,6 +480,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; @@ -696,6 +710,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); @@ -1661,6 +1676,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; @@ -1722,6 +1738,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 f843692eaf..d6c4de61c1 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; @@ -73,6 +73,8 @@ struct _GstOggStream GstCaps *caps; gboolean is_video; + gboolean always_flush_page; + /* vorbis stuff */ int nln_increments[4]; int nsn_increment; @@ -123,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); diff --git a/gst/audioresample/resample.c b/gst/audioresample/resample.c index 22004d0a57..66c2c6dc56 100644 --- a/gst/audioresample/resample.c +++ b/gst/audioresample/resample.c @@ -924,6 +924,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) { @@ -934,6 +935,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, diff --git a/gst/playback/gstplaysink.c b/gst/playback/gstplaysink.c index 23e9526345..e0a540b761 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; @@ -173,6 +186,8 @@ struct _GstPlaySink GstPad *text_sinkpad_stream_synchronizer; gulong text_block_id; + guint32 pending_blocked_pads; + /* properties */ GstElement *audio_sink; GstElement *video_sink; @@ -2880,6 +2895,8 @@ video_set_blocked (GstPlaySink * playsink, gboolean blocked) gst_object_ref (playsink), (GDestroyNotify) gst_object_unref); } else if (!blocked && playsink->video_block_id) { gst_pad_remove_probe (opad, playsink->video_block_id); + PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_VIDEO_RAW); + PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_VIDEO); playsink->video_block_id = 0; playsink->video_pad_blocked = FALSE; } @@ -2900,6 +2917,8 @@ audio_set_blocked (GstPlaySink * playsink, gboolean blocked) gst_object_ref (playsink), (GDestroyNotify) gst_object_unref); } else if (!blocked && playsink->audio_block_id) { gst_pad_remove_probe (opad, playsink->audio_block_id); + PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_AUDIO_RAW); + PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_AUDIO); playsink->audio_block_id = 0; playsink->audio_pad_blocked = FALSE; } @@ -2920,6 +2939,7 @@ text_set_blocked (GstPlaySink * playsink, gboolean blocked) gst_object_ref (playsink), (GDestroyNotify) gst_object_unref); } else if (!blocked && playsink->text_block_id) { gst_pad_remove_probe (opad, playsink->text_block_id); + PENDING_FLAG_UNSET (playsink, GST_PLAY_SINK_TYPE_TEXT); playsink->text_block_id = 0; playsink->text_pad_blocked = FALSE; } @@ -2948,9 +2968,17 @@ sinkpad_blocked_cb (GstPad * blockedpad, GstProbeType type, gpointer type_data, GST_DEBUG_OBJECT (pad, "Text pad blocked"); } - 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) { @@ -2992,14 +3020,14 @@ caps_notify_cb (GstPad * pad, GParamSpec * unused, GstPlaySink * playsink) if (pad == playsink->audio_pad) { raw = is_raw_pad (pad); - reconfigure = (!!playsink->audio_pad_raw != !!raw) + reconfigure = (! !playsink->audio_pad_raw != ! !raw) && playsink->audiochain; GST_DEBUG_OBJECT (pad, "Audio caps changed: raw %d reconfigure %d caps %" GST_PTR_FORMAT, raw, reconfigure, caps); } else if (pad == playsink->video_pad) { raw = is_raw_pad (pad); - reconfigure = (!!playsink->video_pad_raw != !!raw) + reconfigure = (! !playsink->video_pad_raw != ! !raw) && playsink->videochain; GST_DEBUG_OBJECT (pad, "Video caps changed: raw %d reconfigure %d caps %" GST_PTR_FORMAT, raw, @@ -3131,6 +3159,7 @@ gst_play_sink_request_pad (GstPlaySink * playsink, GstPlaySinkType type) *block_id = gst_pad_add_probe (blockpad, GST_PROBE_TYPE_BLOCK, sinkpad_blocked_cb, gst_object_ref (playsink), (GDestroyNotify) gst_object_unref); + PENDING_FLAG_SET (playsink, type); gst_object_unref (blockpad); } if (!activate)