Merge branch 'master' into 0.11

Conflicts:
	ext/ogg/gstoggmux.c
	gst/playback/gstplaysink.c
This commit is contained in:
Wim Taymans 2011-08-18 19:36:50 +02:00
commit ba41bb5ca7
8 changed files with 141 additions and 83 deletions

View file

@ -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 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, ("p frame"). The granulepos is constructed as the sum of the first number,
shifted to the left for granuleshift bits, and the second 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 (This means that given a framenumber or a timestamp, one cannot generate
the one and only granulepos for that page; several granulepos possibilities the one and only granulepos for that page; several granulepos possibilities

View file

@ -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_src_query (GstPad * pad, GstQuery * query);
static gboolean gst_ogg_pad_event (GstPad * pad, GstEvent * event); static gboolean gst_ogg_pad_event (GstPad * pad, GstEvent * event);
static GstOggPad *gst_ogg_chain_get_stream (GstOggChain * chain, static GstOggPad *gst_ogg_chain_get_stream (GstOggChain * chain,
glong serialno); guint32 serialno);
static GstFlowReturn gst_ogg_demux_combine_flows (GstOggDemux * ogg, static GstFlowReturn gst_ogg_demux_combine_flows (GstOggDemux * ogg,
GstOggPad * pad, GstFlowReturn ret); GstOggPad * pad, GstFlowReturn ret);
@ -419,8 +419,8 @@ gst_ogg_demux_queue_data (GstOggPad * pad, ogg_packet * packet)
GstOggDemux *ogg = pad->ogg; GstOggDemux *ogg = pad->ogg;
#endif #endif
GST_DEBUG_OBJECT (ogg, "%p queueing data serial %08lx", pad, GST_DEBUG_OBJECT (ogg, "%p queueing data serial %08" G_GINT32_MODIFIER "x",
pad->map.serialno); pad, pad->map.serialno);
pad->map.queued = g_list_append (pad->map.queued, _ogg_packet_copy (packet)); 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; cret = GST_FLOW_OK;
GST_DEBUG_OBJECT (ogg, 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) { if (pad->map.is_ogm) {
const guint8 *data; const guint8 *data;
@ -697,8 +698,8 @@ gst_ogg_pad_submit_packet (GstOggPad * pad, ogg_packet * packet)
GstOggDemux *ogg = pad->ogg; GstOggDemux *ogg = pad->ogg;
GST_DEBUG_OBJECT (ogg, "%p submit packet serial %08lx", pad, GST_DEBUG_OBJECT (ogg, "%p submit packet serial %08" G_GINT32_MODIFIER "x",
pad->map.serialno); pad, pad->map.serialno);
if (!pad->have_type) { if (!pad->have_type) {
pad->have_type = gst_ogg_stream_setup_map (&pad->map, packet); 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: could_not_submit:
{ {
GST_WARNING_OBJECT (ogg, GST_WARNING_OBJECT (ogg,
"could not submit packet for stream %08lx, error: %d", "could not submit packet for stream %08" G_GINT32_MODIFIER
pad->map.serialno, result); "x, error: %d", pad->map.serialno, result);
gst_ogg_pad_reset (pad); gst_ogg_pad_reset (pad);
return result; return result;
} }
@ -1075,8 +1076,8 @@ done:
choked: choked:
{ {
GST_WARNING_OBJECT (ogg, GST_WARNING_OBJECT (ogg,
"ogg stream choked on page (serial %08lx), resetting stream", "ogg stream choked on page (serial %08" G_GINT32_MODIFIER
pad->map.serialno); "x), resetting stream", pad->map.serialno);
gst_ogg_pad_reset (pad); gst_ogg_pad_reset (pad);
/* we continue to recover */ /* we continue to recover */
return GST_FLOW_OK; return GST_FLOW_OK;
@ -1149,14 +1150,15 @@ gst_ogg_chain_reset (GstOggChain * chain)
} }
static GstOggPad * static GstOggPad *
gst_ogg_chain_new_stream (GstOggChain * chain, glong serialno) gst_ogg_chain_new_stream (GstOggChain * chain, guint32 serialno)
{ {
GstOggPad *ret; GstOggPad *ret;
GstTagList *list; GstTagList *list;
gchar *name; gchar *name;
GST_DEBUG_OBJECT (chain->ogg, "creating new stream %08lx in chain %p", GST_DEBUG_OBJECT (chain->ogg,
serialno, chain); "creating new stream %08" G_GINT32_MODIFIER "x in chain %p", serialno,
chain);
ret = g_object_new (GST_TYPE_OGG_PAD, NULL); ret = g_object_new (GST_TYPE_OGG_PAD, NULL);
/* we own this one */ /* 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) if (ogg_stream_init (&ret->map.stream, serialno) != 0)
goto init_failed; 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); gst_object_set_name (GST_OBJECT (ret), name);
g_free (name); g_free (name);
@ -1183,7 +1185,8 @@ gst_ogg_chain_new_stream (GstOggChain * chain, glong serialno)
gst_tag_list_free (list); gst_tag_list_free (list);
GST_DEBUG_OBJECT (chain->ogg, 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); g_array_append_val (chain->streams, ret);
gst_pad_set_active (GST_PAD_CAST (ret), TRUE); gst_pad_set_active (GST_PAD_CAST (ret), TRUE);
@ -1193,15 +1196,15 @@ gst_ogg_chain_new_stream (GstOggChain * chain, glong serialno)
/* ERRORS */ /* ERRORS */
init_failed: init_failed:
{ {
GST_ERROR ("Could not initialize ogg_stream struct for serial %08lx.", GST_ERROR ("Could not initialize ogg_stream struct for serial %08"
serialno); G_GINT32_MODIFIER "x.", serialno);
gst_object_unref (ret); gst_object_unref (ret);
return NULL; return NULL;
} }
} }
static GstOggPad * static GstOggPad *
gst_ogg_chain_get_stream (GstOggChain * chain, glong serialno) gst_ogg_chain_get_stream (GstOggChain * chain, guint32 serialno)
{ {
gint i; gint i;
@ -1215,7 +1218,7 @@ gst_ogg_chain_get_stream (GstOggChain * chain, glong serialno)
} }
static gboolean 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; 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 */ /* get time of the keyframe */
keyframe_time = keyframe_time =
gst_ogg_stream_granule_to_time (&pad->map, pad->keyframe_granule); 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)); pad->map.serialno, GST_TIME_ARGS (keyframe_time));
/* collect smallest value */ /* collect smallest value */
@ -2566,7 +2570,7 @@ gst_ogg_demux_bisect_forward_serialno (GstOggDemux * ogg,
if (ret == GST_FLOW_UNEXPECTED) { if (ret == GST_FLOW_UNEXPECTED) {
endsearched = bisect; endsearched = bisect;
} else if (ret == GST_FLOW_OK) { } 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)) { if (!gst_ogg_chain_has_stream (chain, serial)) {
endsearched = bisect; endsearched = bisect;
@ -2635,7 +2639,7 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
* the decoders, send data to the decoders. */ * the decoders, send data to the decoders. */
while (TRUE) { while (TRUE) {
GstOggPad *pad; GstOggPad *pad;
glong serial; guint32 serial;
ret = gst_ogg_demux_get_next_page (ogg, &op, -1, NULL); ret = gst_ogg_demux_get_next_page (ogg, &op, -1, NULL);
if (ret != GST_FLOW_OK) { if (ret != GST_FLOW_OK) {
@ -2658,7 +2662,8 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
serial = ogg_page_serialno (&op); serial = ogg_page_serialno (&op);
if (gst_ogg_chain_get_stream (chain, serial) != NULL) { 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); serial);
continue; continue;
} }
@ -2699,7 +2704,7 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
done = FALSE; done = FALSE;
while (!done) { while (!done) {
glong serial; guint32 serial;
gboolean known_serial = FALSE; gboolean known_serial = FALSE;
GstFlowReturn ret; GstFlowReturn ret;
@ -2708,7 +2713,8 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
for (i = 0; i < chain->streams->len; i++) { for (i = 0; i < chain->streams->len; i++) {
GstOggPad *pad = g_array_index (chain->streams, GstOggPad *, 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)); pad->map.serialno, GST_TIME_ARGS (pad->start_time));
if (pad->map.serialno == serial) { if (pad->map.serialno == serial) {
@ -2732,14 +2738,15 @@ gst_ogg_demux_read_chain (GstOggDemux * ogg, GstOggChain ** res_chain)
if (!pad->map.is_sparse) if (!pad->map.is_sparse)
done &= (pad->start_time != GST_CLOCK_TIME_NONE); 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 /* we read a page not belonging to the current chain: seek back to the
* beginning of the chain * beginning of the chain
*/ */
if (!known_serial) { 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); gst_ogg_demux_seek (ogg, offset);
break; break;
} }
@ -2836,7 +2843,7 @@ gst_ogg_demux_read_end_chain (GstOggDemux * ogg, GstOggChain * chain)
/* find a pad with a given serial number /* find a pad with a given serial number
*/ */
static GstOggPad * static GstOggPad *
gst_ogg_demux_find_pad (GstOggDemux * ogg, glong serialno) gst_ogg_demux_find_pad (GstOggDemux * ogg, guint32 serialno)
{ {
GstOggPad *pad; GstOggPad *pad;
gint i; gint i;
@ -2868,7 +2875,7 @@ gst_ogg_demux_find_pad (GstOggDemux * ogg, glong serialno)
/* find a chain with a given serial number /* find a chain with a given serial number
*/ */
static GstOggChain * static GstOggChain *
gst_ogg_demux_find_chain (GstOggDemux * ogg, glong serialno) gst_ogg_demux_find_chain (GstOggDemux * ogg, guint32 serialno)
{ {
GstOggPad *pad; GstOggPad *pad;
@ -2936,7 +2943,7 @@ gst_ogg_demux_find_chains (GstOggDemux * ogg)
ogg_page og; ogg_page og;
GstPad *peer; GstPad *peer;
gboolean res; gboolean res;
gulong serialno; guint32 serialno;
GstOggChain *chain; GstOggChain *chain;
GstFlowReturn ret; GstFlowReturn ret;
@ -3024,16 +3031,16 @@ gst_ogg_demux_handle_page (GstOggDemux * ogg, ogg_page * page)
{ {
GstOggPad *pad; GstOggPad *pad;
gint64 granule; gint64 granule;
glong serialno; guint32 serialno;
GstFlowReturn result = GST_FLOW_OK; GstFlowReturn result = GST_FLOW_OK;
serialno = ogg_page_serialno (page); serialno = ogg_page_serialno (page);
granule = ogg_page_granulepos (page); granule = ogg_page_granulepos (page);
GST_LOG_OBJECT (ogg, GST_LOG_OBJECT (ogg,
"processing ogg page (serial %08lx, pageno %ld, granulepos %" "processing ogg page (serial %08" G_GINT32_MODIFIER
G_GINT64_FORMAT ", bos %d)", "x, pageno %ld, granulepos %" G_GINT64_FORMAT ", bos %d)", serialno,
serialno, ogg_page_pageno (page), granule, ogg_page_bos (page)); ogg_page_pageno (page), granule, ogg_page_bos (page));
if (ogg_page_bos (page)) { if (ogg_page_bos (page)) {
GstOggChain *chain; 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 /* no pad. This means an ogg page without bos has been seen for this
* serialno. we just ignore it but post a warning... */ * serialno. we just ignore it but post a warning... */
GST_ELEMENT_WARNING (ogg, STREAM, DECODE, 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 GST_FLOW_OK;
} }
return result; return result;
@ -3113,7 +3122,9 @@ gst_ogg_demux_handle_page (GstOggDemux * ogg, ogg_page * page)
unknown_chain: unknown_chain:
{ {
GST_ELEMENT_ERROR (ogg, STREAM, DECODE, 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; return GST_FLOW_ERROR;
} }
} }
@ -3675,7 +3686,8 @@ gst_ogg_print (GstOggDemux * ogg)
for (j = 0; j < chain->streams->len; j++) { for (j = 0; j < chain->streams->len; j++) {
GstOggPad *stream = g_array_index (chain->streams, GstOggPad *, 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_INFO_OBJECT (ogg, " start time: %" GST_TIME_FORMAT,
GST_TIME_ARGS (stream->start_time)); GST_TIME_ARGS (stream->start_time));
} }

View file

@ -366,7 +366,7 @@ gst_ogg_mux_request_new_pad (GstElement * element,
goto wrong_template; goto wrong_template;
{ {
gint serial; guint32 serial;
gchar *name; gchar *name;
if (req_name == NULL || strlen (req_name) < 6) { 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); serial = gst_ogg_mux_generate_serialno (ogg_mux);
} else { } else {
/* parse serial number from requested padname */ /* 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 */ /* create new pad with the name */
GST_DEBUG_OBJECT (ogg_mux, "Creating new pad for serial %d", serial); 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"); 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")) { } else if (gst_structure_has_name (structure, "video/x-dirac")) {
res = g_list_append (res, pad->buffer); res = g_list_append (res, pad->buffer);
pad->buffer = NULL; pad->buffer = NULL;
pad->always_flush_page = TRUE;
} else { } else {
GST_LOG_OBJECT (thepad, "caps don't have streamheader"); 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; 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 * For each pad we need to write out one (small) header in one
* page that allows decoders to identify the type of the stream. * 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 */ /* create a packet from the buffer */
packet.packet = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); create_header_packet (&packet, buf, pad);
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;
/* swap the packet in */ /* swap the packet in */
ogg_stream_packetin (&pad->map.stream, &packet); 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_LOG_OBJECT (mux, "swapped out page with mime type %s",
gst_structure_get_name (structure)); 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 * Ideally, we would have a settable enum for which Ogg
* profile we work with, and order based on that. * profile we work with, and order based on that.
* (FIXME: if there is more than one video stream, shouldn't we only put * (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 * 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?) */ * only then followed by the remaining video and audio streams?) */
if (gst_structure_has_name (structure, "video/x-theora")) { if (pad->map.is_video) {
GST_DEBUG_OBJECT (thepad, "putting %s page at the front", "Theora"); GST_DEBUG_OBJECT (thepad, "putting %s page at the front",
hbufs = g_list_prepend (hbufs, hbuf); gst_structure_get_name (structure));
} 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");
hbufs = g_list_prepend (hbufs, hbuf); hbufs = g_list_prepend (hbufs, hbuf);
} else { } else {
hbufs = g_list_append (hbufs, hbuf); hbufs = g_list_append (hbufs, hbuf);
} }
gst_caps_unref (caps); gst_caps_unref (caps);
} }
@ -1223,16 +1228,7 @@ gst_ogg_mux_send_headers (GstOggMux * mux)
hwalk = hwalk->next; hwalk = hwalk->next;
/* create a packet from the buffer */ /* create a packet from the buffer */
packet.packet = gst_buffer_map (buf, &size, NULL, GST_MAP_READ); create_header_packet (&packet, buf, pad);
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;
/* swap the packet in */ /* swap the packet in */
ogg_stream_packetin (&pad->map.stream, &packet); ogg_stream_packetin (&pad->map.stream, &packet);
@ -1453,7 +1449,8 @@ gst_ogg_mux_process_best_pad (GstOggMux * ogg_mux, GstOggPadData * best)
tmpbuf = NULL; tmpbuf = NULL;
/* we flush when we see a new keyframe */ /* 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) { if (duration != -1) {
pad->duration += duration; pad->duration += duration;
/* if page duration exceeds max, flush page */ /* if page duration exceeds max, flush page */

View file

@ -83,8 +83,6 @@ typedef struct
gint64 keyframe_granule; /* granule of last preceding keyframe */ gint64 keyframe_granule; /* granule of last preceding keyframe */
GstPadEventFunction collect_event; GstPadEventFunction collect_event;
gboolean always_flush_page;
} }
GstOggPadData; GstOggPadData;

View file

@ -225,6 +225,19 @@ gst_ogg_stream_extract_tags (GstOggStream * pad, ogg_packet * packet)
mappers[pad->map].extract_tags_func (pad, 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 */ /* some generic functions */
static gboolean static gboolean
@ -467,6 +480,7 @@ setup_dirac_mapper (GstOggStream * pad, ogg_packet * packet)
} }
pad->is_video = TRUE; pad->is_video = TRUE;
pad->always_flush_page = TRUE;
pad->granulerate_n = header.frame_rate_numerator * 2; pad->granulerate_n = header.frame_rate_numerator * 2;
pad->granulerate_d = header.frame_rate_denominator; pad->granulerate_d = header.frame_rate_denominator;
pad->granuleshift = 22; 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_n = GST_READ_UINT32_LE (data);
pad->granulerate_d = 1; pad->granulerate_d = 1;
pad->granuleshift = 0; pad->granuleshift = 0;
pad->preroll = 2;
pad->last_size = 0; pad->last_size = 0;
GST_LOG ("sample rate: %d", pad->granulerate_n); 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)); GST_DEBUG ("blocksize1: %u", 1 << (data[0] & 0x0F));
pad->caps = gst_caps_new_simple ("text/x-cmml", NULL); pad->caps = gst_caps_new_simple ("text/x-cmml", NULL);
pad->always_flush_page = TRUE;
pad->is_sparse = TRUE; pad->is_sparse = TRUE;
return TRUE; return TRUE;
@ -1722,6 +1738,7 @@ setup_kate_mapper (GstOggStream * pad, ogg_packet * packet)
} }
pad->is_sparse = TRUE; pad->is_sparse = TRUE;
pad->always_flush_page = TRUE;
return TRUE; return TRUE;
} }

View file

@ -45,7 +45,7 @@ struct _GstOggStream
{ {
ogg_stream_state stream; ogg_stream_state stream;
glong serialno; guint32 serialno;
GList *headers; GList *headers;
gboolean have_headers; gboolean have_headers;
GList *queued; GList *queued;
@ -73,6 +73,8 @@ struct _GstOggStream
GstCaps *caps; GstCaps *caps;
gboolean is_video; gboolean is_video;
gboolean always_flush_page;
/* vorbis stuff */ /* vorbis stuff */
int nln_increments[4]; int nln_increments[4];
int nsn_increment; 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); gboolean gst_ogg_stream_packet_is_header (GstOggStream *pad, ogg_packet *packet);
gint64 gst_ogg_stream_get_packet_duration (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); 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, gboolean gst_ogg_map_parse_fisbone (GstOggStream * pad, const guint8 * data, guint size,
guint32 * serialno, GstOggSkeleton *type); guint32 * serialno, GstOggSkeleton *type);

View file

@ -924,6 +924,7 @@ speex_resampler_init (spx_uint32_t nb_channels, spx_uint32_t in_rate,
out_rate, quality, err); out_rate, quality, err);
} }
#if defined HAVE_ORC && !defined DISABLE_ORC
static void static void
check_insn_set (SpeexResamplerState * st, const char *name) check_insn_set (SpeexResamplerState * st, const char *name)
{ {
@ -934,6 +935,7 @@ check_insn_set (SpeexResamplerState * st, const char *name)
if (!strcmp (name, "sse2")) if (!strcmp (name, "sse2"))
st->use_sse = st->use_sse2 = 1; st->use_sse = st->use_sse2 = 1;
} }
#endif
EXPORT SpeexResamplerState * EXPORT SpeexResamplerState *
speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num, speex_resampler_init_frac (spx_uint32_t nb_channels, spx_uint32_t ratio_num,

View file

@ -127,6 +127,19 @@ typedef struct
g_static_rec_mutex_unlock (GST_PLAY_SINK_GET_LOCK (playsink)); \ g_static_rec_mutex_unlock (GST_PLAY_SINK_GET_LOCK (playsink)); \
} G_STMT_END } 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 struct _GstPlaySink
{ {
GstBin bin; GstBin bin;
@ -173,6 +186,8 @@ struct _GstPlaySink
GstPad *text_sinkpad_stream_synchronizer; GstPad *text_sinkpad_stream_synchronizer;
gulong text_block_id; gulong text_block_id;
guint32 pending_blocked_pads;
/* properties */ /* properties */
GstElement *audio_sink; GstElement *audio_sink;
GstElement *video_sink; GstElement *video_sink;
@ -2880,6 +2895,8 @@ video_set_blocked (GstPlaySink * playsink, gboolean blocked)
gst_object_ref (playsink), (GDestroyNotify) gst_object_unref); gst_object_ref (playsink), (GDestroyNotify) gst_object_unref);
} else if (!blocked && playsink->video_block_id) { } else if (!blocked && playsink->video_block_id) {
gst_pad_remove_probe (opad, 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_block_id = 0;
playsink->video_pad_blocked = FALSE; playsink->video_pad_blocked = FALSE;
} }
@ -2900,6 +2917,8 @@ audio_set_blocked (GstPlaySink * playsink, gboolean blocked)
gst_object_ref (playsink), (GDestroyNotify) gst_object_unref); gst_object_ref (playsink), (GDestroyNotify) gst_object_unref);
} else if (!blocked && playsink->audio_block_id) { } else if (!blocked && playsink->audio_block_id) {
gst_pad_remove_probe (opad, 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_block_id = 0;
playsink->audio_pad_blocked = FALSE; playsink->audio_pad_blocked = FALSE;
} }
@ -2920,6 +2939,7 @@ text_set_blocked (GstPlaySink * playsink, gboolean blocked)
gst_object_ref (playsink), (GDestroyNotify) gst_object_unref); gst_object_ref (playsink), (GDestroyNotify) gst_object_unref);
} else if (!blocked && playsink->text_block_id) { } else if (!blocked && playsink->text_block_id) {
gst_pad_remove_probe (opad, 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_block_id = 0;
playsink->text_pad_blocked = FALSE; 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"); GST_DEBUG_OBJECT (pad, "Text pad blocked");
} }
if ((!playsink->video_pad || playsink->video_pad_blocked) && /* We reconfigure when for ALL streams:
(!playsink->audio_pad || playsink->audio_pad_blocked) && * * there isn't a pad
(!playsink->text_pad || playsink->text_pad_blocked)) { * * 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"); GST_DEBUG_OBJECT (playsink, "All pads blocked -- reconfiguring");
if (playsink->video_pad) { if (playsink->video_pad) {
@ -2992,14 +3020,14 @@ caps_notify_cb (GstPad * pad, GParamSpec * unused, GstPlaySink * playsink)
if (pad == playsink->audio_pad) { if (pad == playsink->audio_pad) {
raw = is_raw_pad (pad); raw = is_raw_pad (pad);
reconfigure = (!!playsink->audio_pad_raw != !!raw) reconfigure = (! !playsink->audio_pad_raw != ! !raw)
&& playsink->audiochain; && playsink->audiochain;
GST_DEBUG_OBJECT (pad, GST_DEBUG_OBJECT (pad,
"Audio caps changed: raw %d reconfigure %d caps %" GST_PTR_FORMAT, raw, "Audio caps changed: raw %d reconfigure %d caps %" GST_PTR_FORMAT, raw,
reconfigure, caps); reconfigure, caps);
} else if (pad == playsink->video_pad) { } else if (pad == playsink->video_pad) {
raw = is_raw_pad (pad); raw = is_raw_pad (pad);
reconfigure = (!!playsink->video_pad_raw != !!raw) reconfigure = (! !playsink->video_pad_raw != ! !raw)
&& playsink->videochain; && playsink->videochain;
GST_DEBUG_OBJECT (pad, GST_DEBUG_OBJECT (pad,
"Video caps changed: raw %d reconfigure %d caps %" GST_PTR_FORMAT, raw, "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 = *block_id =
gst_pad_add_probe (blockpad, GST_PROBE_TYPE_BLOCK, sinkpad_blocked_cb, gst_pad_add_probe (blockpad, GST_PROBE_TYPE_BLOCK, sinkpad_blocked_cb,
gst_object_ref (playsink), (GDestroyNotify) gst_object_unref); gst_object_ref (playsink), (GDestroyNotify) gst_object_unref);
PENDING_FLAG_SET (playsink, type);
gst_object_unref (blockpad); gst_object_unref (blockpad);
} }
if (!activate) if (!activate)