From 635d2411cc9f890d890f508d5bc3da36f006bba3 Mon Sep 17 00:00:00 2001 From: Robert Swain Date: Fri, 23 Sep 2011 17:50:31 +0200 Subject: [PATCH 01/16] encodebin: Avoid unnecessary read only caps copy --- gst/encoding/gstencodebin.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gst/encoding/gstencodebin.c b/gst/encoding/gstencodebin.c index 062bae745f..740c9c9ea8 100644 --- a/gst/encoding/gstencodebin.c +++ b/gst/encoding/gstencodebin.c @@ -1202,7 +1202,7 @@ _create_stream_group (GstEncodeBin * ebin, GstEncodingProfile * sprof, /* Check if stream format is compatible */ srcpad = gst_element_get_static_pad (sgroup->smartencoder, "src"); - tmpcaps = gst_pad_get_caps (srcpad); + tmpcaps = gst_pad_get_caps_reffed (srcpad); if (!gst_caps_can_intersect (tmpcaps, format)) { GST_DEBUG ("We don't have a smart encoder for the stream format"); gst_object_unref (sgroup->smartencoder); From bfb33e09a9b5428943c37f002566cf625f5d52f8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sun, 25 Sep 2011 15:24:56 +0100 Subject: [PATCH 02/16] typefindfunctions: fix indentation --- gst/typefind/gsttypefindfunctions.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gst/typefind/gsttypefindfunctions.c b/gst/typefind/gsttypefindfunctions.c index 62d398466c..a5eb13241d 100644 --- a/gst/typefind/gsttypefindfunctions.c +++ b/gst/typefind/gsttypefindfunctions.c @@ -4103,7 +4103,7 @@ degas_type_find (GstTypeFind * tf, gpointer private) if (resolution <= 2) { data = gst_type_find_peek (tf, len - 16, 8); if (G_UNLIKELY (data == NULL)) - return; + return; for (n = 0; n < 4; n++) { if (GST_READ_UINT16_BE (data + n * 2) > 2) return; @@ -4117,7 +4117,7 @@ degas_type_find (GstTypeFind * tf, gpointer private) if ((resolution & 0x8000) && (resolution & 0x7fff) <= 2) { data = gst_type_find_peek (tf, len - 16, 8); if (G_UNLIKELY (data == NULL)) - return; + return; for (n = 0; n < 4; n++) { if (GST_READ_UINT16_BE (data + n * 2) > 2) return; From 09e06add6600f1b627322da8c13669279abecd25 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tim-Philipp=20M=C3=BCller?= Date: Sun, 25 Sep 2011 15:31:01 +0100 Subject: [PATCH 03/16] typefindfunctions: backport some const-ifications from 0.11 branch To keep code identical as much as possible between the two branches, for easier merging. --- gst/typefind/gsttypefindfunctions.c | 153 ++++++++++++++-------------- 1 file changed, 78 insertions(+), 75 deletions(-) diff --git a/gst/typefind/gsttypefindfunctions.c b/gst/typefind/gsttypefindfunctions.c index a5eb13241d..2e2a56702a 100644 --- a/gst/typefind/gsttypefindfunctions.c +++ b/gst/typefind/gsttypefindfunctions.c @@ -45,6 +45,10 @@ GST_DEBUG_CATEGORY_STATIC (type_find_debug); #define GST_CAT_DEFAULT type_find_debug +/* so our code stays ready for 0.11 */ +#define gst_type_find_peek(tf,off,len) \ + ((const guint8 *)gst_type_find_peek((tf),(off),(len))) + /* DataScanCtx: helper for typefind functions that scan through data * step-by-step, to avoid doing a peek at each and every offset */ @@ -130,7 +134,7 @@ static gboolean utf8_type_find_have_valid_utf8_at_offset (GstTypeFind * tf, guint64 offset, GstTypeFindProbability * prob) { - guint8 *data; + const guint8 *data; /* randomly decided values */ guint min_size = 16; /* minimum size */ @@ -222,7 +226,7 @@ static GstStaticCaps uri_caps = GST_STATIC_CAPS ("text/uri-list"); static void uri_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, BUFFER_SIZE); + const guint8 *data = gst_type_find_peek (tf, 0, BUFFER_SIZE); guint pos = 0; guint offset = 0; @@ -322,7 +326,7 @@ xml_check_first_element (GstTypeFind * tf, const gchar * element, guint elen, gboolean strict) { gboolean got_xmldec; - guint8 *data; + const guint8 *data; guint offset = 0; guint pos = 0; @@ -386,7 +390,7 @@ static GstStaticCaps sdp_caps = GST_STATIC_CAPS ("application/sdp"); static gboolean sdp_check_header (GstTypeFind * tf) { - guint8 *data; + const guint8 *data; data = gst_type_find_peek (tf, 0, 5); if (!data) @@ -433,9 +437,9 @@ static GstStaticCaps html_caps = GST_STATIC_CAPS ("text/html"); static void html_type_find (GstTypeFind * tf, gpointer unused) { - gchar *d, *data; + const gchar *d, *data; - data = (gchar *) gst_type_find_peek (tf, 0, 16); + data = (const gchar *) gst_type_find_peek (tf, 0, 16); if (!data) return; @@ -444,7 +448,7 @@ html_type_find (GstTypeFind * tf, gpointer unused) } else if (xml_check_first_element (tf, "html", 4, FALSE)) { gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, HTML_CAPS); } else if ((d = memchr (data, '<', 16))) { - data = (gchar *) gst_type_find_peek (tf, d - data, 6); + data = (const gchar *) gst_type_find_peek (tf, d - data, 6); if (data && g_ascii_strncasecmp (data, "", 6) == 0) { gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, HTML_CAPS); } @@ -459,7 +463,7 @@ static GstStaticCaps mid_caps = GST_STATIC_CAPS ("audio/midi"); static void mid_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 4); + const guint8 *data = gst_type_find_peek (tf, 0, 4); /* http://jedi.ks.uiuc.edu/~johns/links/music/midifile.html */ if (data && data[0] == 'M' && data[1] == 'T' && data[2] == 'h' @@ -475,7 +479,7 @@ static GstStaticCaps mxmf_caps = GST_STATIC_CAPS ("audio/mobile-xmf"); static void mxmf_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = NULL; + const guint8 *data = NULL; /* Search FileId "XMF_" 4 bytes */ data = gst_type_find_peek (tf, 0, 4); @@ -503,7 +507,7 @@ static GstStaticCaps flx_caps = GST_STATIC_CAPS ("video/x-fli"); static void flx_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 134); + const guint8 *data = gst_type_find_peek (tf, 0, 134); if (data) { /* check magic and the frame type of the first frame */ @@ -534,7 +538,7 @@ static GstStaticCaps id3_caps = GST_STATIC_CAPS ("application/x-id3"); static void id3v2_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 10); + const guint8 *data = gst_type_find_peek (tf, 0, 10); if (data && memcmp (data, "ID3", 3) == 0 && data[3] != 0xFF && data[4] != 0xFF && @@ -547,7 +551,7 @@ id3v2_type_find (GstTypeFind * tf, gpointer unused) static void id3v1_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, -128, 3); + const guint8 *data = gst_type_find_peek (tf, -128, 3); if (data && memcmp (data, "TAG", 3) == 0) { gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, ID3_CAPS); @@ -562,7 +566,7 @@ static GstStaticCaps apetag_caps = GST_STATIC_CAPS ("application/x-apetag"); static void apetag_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data; + const guint8 *data; /* APEv1/2 at start of file */ data = gst_type_find_peek (tf, 0, 8); @@ -587,7 +591,7 @@ static GstStaticCaps tta_caps = GST_STATIC_CAPS ("audio/x-ttafile"); static void tta_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 3); + const guint8 *data = gst_type_find_peek (tf, 0, 3); if (data) { if (memcmp (data, "TTA", 3) == 0) { @@ -985,8 +989,8 @@ static void mp3_type_find_at_offset (GstTypeFind * tf, guint64 start_off, guint * found_layer, GstTypeFindProbability * found_prob) { - guint8 *data = NULL; - guint8 *data_end = NULL; + const guint8 *data = NULL; + const guint8 *data_end = NULL; guint size; guint64 skipped; gint last_free_offset = -1; @@ -1010,7 +1014,7 @@ mp3_type_find_at_offset (GstTypeFind * tf, guint64 start_off, data_end = data + size; } if (*data == 0xFF) { - guint8 *head_data = NULL; + const guint8 *head_data = NULL; guint layer = 0, bitrate, samplerate, channels; guint found = 0; /* number of valid headers found */ guint64 offset = skipped; @@ -1128,7 +1132,7 @@ static void mp3_type_find (GstTypeFind * tf, gpointer unused) { GstTypeFindProbability prob, mid_prob; - guint8 *data; + const guint8 *data; guint layer, mid_layer; guint64 length; @@ -1198,7 +1202,7 @@ GST_STATIC_CAPS ("audio/x-musepack, streamversion= (int) { 7, 8 }"); static void musepack_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 4); + const guint8 *data = gst_type_find_peek (tf, 0, 4); GstTypeFindProbability prop = GST_TYPE_FIND_MINIMUM; gint streamversion = -1; @@ -1520,7 +1524,7 @@ wavpack_type_find (GstTypeFind * tf, gpointer unused) { guint64 offset; guint32 blocksize; - guint8 *data; + const guint8 *data; data = gst_type_find_peek (tf, 0, 32); if (!data) @@ -1583,7 +1587,7 @@ GST_STATIC_CAPS ("application/postscript"); static void postscript_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 3); + const guint8 *data = gst_type_find_peek (tf, 0, 3); if (!data) return; @@ -1633,8 +1637,8 @@ GST_STATIC_CAPS ("multipart/x-mixed-replace"); static void multipart_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data; - guint8 *x; + const guint8 *data; + const guint8 *x; #define MULTIPART_MAX_BOUNDARY_OFFSET 16 data = gst_type_find_peek (tf, 0, MULTIPART_MAX_BOUNDARY_OFFSET); @@ -1743,7 +1747,7 @@ mpeg_sys_is_valid_pack (GstTypeFind * tf, const guint8 * data, guint len, } static gboolean -mpeg_sys_is_valid_pes (GstTypeFind * tf, guint8 * data, guint len, +mpeg_sys_is_valid_pes (GstTypeFind * tf, const guint8 * data, guint len, guint * pack_size) { guint pes_packet_len; @@ -1771,7 +1775,7 @@ mpeg_sys_is_valid_pes (GstTypeFind * tf, guint8 * data, guint len, } static gboolean -mpeg_sys_is_valid_sys (GstTypeFind * tf, guint8 * data, guint len, +mpeg_sys_is_valid_sys (GstTypeFind * tf, const guint8 * data, guint len, guint * pack_size) { guint sys_hdr_len; @@ -1812,7 +1816,7 @@ mpeg_sys_is_valid_sys (GstTypeFind * tf, guint8 * data, guint len, static void mpeg_sys_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data, *data0, *first_sync, *end; + const guint8 *data, *data0, *first_sync, *end; gint mpegversion = 0; guint pack_headers = 0; guint pes_headers = 0; @@ -1953,7 +1957,7 @@ mpeg_ts_probe_headers (GstTypeFind * tf, guint64 offset, gint packet_size) { /* We always enter this function having found at least one header already */ gint found = 1; - guint8 *data = NULL; + const guint8 *data = NULL; GST_LOG ("looking for mpeg-ts packets of size %u", packet_size); while (found < GST_MPEGTS_TYPEFIND_MAX_HEADERS) { @@ -1978,8 +1982,7 @@ mpeg_ts_type_find (GstTypeFind * tf, gpointer unused) /* TS packet sizes to test: normal, DVHS packet size and * FEC with 16 or 20 byte codes packet size. */ const gint pack_sizes[] = { 188, 192, 204, 208 }; - - guint8 *data = NULL; + const guint8 *data = NULL; guint size = 0; guint64 skipped = 0; @@ -2414,7 +2417,7 @@ static GstStaticCaps aiff_caps = GST_STATIC_CAPS ("audio/x-aiff"); static void aiff_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 4); + const guint8 *data = gst_type_find_peek (tf, 0, 4); if (data && memcmp (data, "FORM", 4) == 0) { data += 8; @@ -2431,7 +2434,7 @@ static GstStaticCaps svx_caps = GST_STATIC_CAPS ("audio/x-svx"); static void svx_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 4); + const guint8 *data = gst_type_find_peek (tf, 0, 4); if (data && memcmp (data, "FORM", 4) == 0) { data += 8; @@ -2448,7 +2451,7 @@ static GstStaticCaps shn_caps = GST_STATIC_CAPS ("audio/x-shorten"); static void shn_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 4); + const guint8 *data = gst_type_find_peek (tf, 0, 4); if (data && memcmp (data, "ajkg", 4) == 0) { gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, SHN_CAPS); @@ -2467,7 +2470,7 @@ static GstStaticCaps ape_caps = GST_STATIC_CAPS ("application/x-ape"); static void ape_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 4); + const guint8 *data = gst_type_find_peek (tf, 0, 4); if (data && memcmp (data, "MAC ", 4) == 0) { gst_type_find_suggest (tf, GST_TYPE_FIND_LIKELY + 10, APE_CAPS); @@ -2484,7 +2487,7 @@ static GstStaticCaps m4a_caps = GST_STATIC_CAPS ("audio/x-m4a"); static void m4a_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 4, 8); + const guint8 *data = gst_type_find_peek (tf, 4, 8); if (data && (memcmp (data, "ftypM4A ", 8) == 0)) { gst_type_find_suggest (tf, GST_TYPE_FIND_MAXIMUM, M4A_CAPS); @@ -2521,7 +2524,7 @@ q3gp_type_find (GstTypeFind * tf, gpointer unused) const gchar *profile; guint32 ftyp_size = 0; gint offset = 0; - guint8 *data = NULL; + const guint8 *data = NULL; if ((data = gst_type_find_peek (tf, 0, 12)) == NULL) { return; @@ -2571,7 +2574,7 @@ static GstStaticCaps jp2_caps = GST_STATIC_CAPS ("image/jp2"); static void jp2_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data; + const guint8 *data; data = gst_type_find_peek (tf, 0, 24); if (!data) @@ -2602,7 +2605,7 @@ static GstStaticCaps qt_caps = GST_STATIC_CAPS ("video/quicktime"); static void qt_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data; + const guint8 *data; guint tip = 0; guint64 offset = 0; guint64 size; @@ -2669,7 +2672,7 @@ qt_type_find (GstTypeFind * tf, gpointer unused) } } if (size == 1) { - guint8 *sizedata; + const guint8 *sizedata; sizedata = gst_type_find_peek (tf, offset + 8, 8); if (sizedata == NULL) @@ -2765,7 +2768,7 @@ static GstStaticCaps mod_caps = GST_STATIC_CAPS ("audio/x-mod"); static void mod_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data; + const guint8 *data; /* MOD */ if ((data = gst_type_find_peek (tf, 1080, 4)) != NULL) { @@ -2821,7 +2824,7 @@ mod_type_find (GstTypeFind * tf, gpointer unused) } /* DSM */ if (memcmp (data, "RIFF", 4) == 0) { - guint8 *data2 = gst_type_find_peek (tf, 8, 4); + const guint8 *data2 = gst_type_find_peek (tf, 8, 4); if (data2) { if (memcmp (data2, "DSMF", 4) == 0) { @@ -2832,7 +2835,7 @@ mod_type_find (GstTypeFind * tf, gpointer unused) } /* FAM */ if (memcmp (data, "FAM\xFE", 4) == 0) { - guint8 *data2 = gst_type_find_peek (tf, 44, 3); + const guint8 *data2 = gst_type_find_peek (tf, 44, 3); if (data2) { if (memcmp (data2, "compare", 3) == 0) { @@ -2846,7 +2849,7 @@ mod_type_find (GstTypeFind * tf, gpointer unused) } /* GDM */ if (memcmp (data, "GDM\xFE", 4) == 0) { - guint8 *data2 = gst_type_find_peek (tf, 71, 4); + const guint8 *data2 = gst_type_find_peek (tf, 71, 4); if (data2) { if (memcmp (data2, "GMFS", 4) == 0) { @@ -2877,7 +2880,7 @@ mod_type_find (GstTypeFind * tf, gpointer unused) if ((data = gst_type_find_peek (tf, 20, 8)) != NULL) { if (g_ascii_strncasecmp ((gchar *) data, "!Scream!", 8) == 0 || g_ascii_strncasecmp ((gchar *) data, "BMOD2STM", 8) == 0) { - guint8 *id, *stmtype; + const guint8 *id, *stmtype; if ((id = gst_type_find_peek (tf, 28, 1)) == NULL) return; @@ -2905,7 +2908,7 @@ GST_STATIC_CAPS ("application/x-shockwave-flash"); static void swf_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 4); + const guint8 *data = gst_type_find_peek (tf, 0, 4); if (data && (data[0] == 'F' || data[0] == 'C') && data[1] == 'W' && data[2] == 'S') { @@ -3096,7 +3099,7 @@ static GstStaticCaps tiff_le_caps = GST_STATIC_CAPS ("image/tiff, " static void tiff_type_find (GstTypeFind * tf, gpointer ununsed) { - guint8 *data = gst_type_find_peek (tf, 0, 8); + const guint8 *data = gst_type_find_peek (tf, 0, 8); guint8 le_header[4] = { 0x49, 0x49, 0x2A, 0x00 }; guint8 be_header[4] = { 0x4D, 0x4D, 0x00, 0x2A }; @@ -3213,7 +3216,7 @@ static GstStaticCaps sds_caps = GST_STATIC_CAPS ("audio/x-sds"); static void sds_type_find (GstTypeFind * tf, gpointer ununsed) { - guint8 *data = gst_type_find_peek (tf, 0, 4); + const guint8 *data = gst_type_find_peek (tf, 0, 4); guint8 mask[4] = { 0xFF, 0xFF, 0x80, 0xFF }; guint8 match[4] = { 0xF0, 0x7E, 0, 0x01 }; gint x; @@ -3234,7 +3237,7 @@ static GstStaticCaps ircam_caps = GST_STATIC_CAPS ("audio/x-ircam"); static void ircam_type_find (GstTypeFind * tf, gpointer ununsed) { - guint8 *data = gst_type_find_peek (tf, 0, 4); + const guint8 *data = gst_type_find_peek (tf, 0, 4); guint8 mask[4] = { 0xFF, 0xFF, 0xF8, 0xFF }; guint8 match[4] = { 0x64, 0xA3, 0x00, 0x00 }; gint x; @@ -3266,7 +3269,7 @@ static gboolean ebml_check_header (GstTypeFind * tf, const gchar * doctype, int doctype_len) { /* 4 bytes for EBML ID, 1 byte for header length identifier */ - guint8 *data = gst_type_find_peek (tf, 0, 4 + 1); + const guint8 *data = gst_type_find_peek (tf, 0, 4 + 1); gint len_mask = 0x80, size = 1, n = 1, total; if (!data) @@ -3394,7 +3397,7 @@ static GstStaticCaps dv_caps = GST_STATIC_CAPS ("video/x-dv, " static void dv_type_find (GstTypeFind * tf, gpointer private) { - guint8 *data; + const guint8 *data; data = gst_type_find_peek (tf, 0, 5); @@ -3426,7 +3429,7 @@ static GstStaticCaps ogg_annodex_caps = static void ogganx_type_find (GstTypeFind * tf, gpointer private) { - guint8 *data = gst_type_find_peek (tf, 0, 4); + const guint8 *data = gst_type_find_peek (tf, 0, 4); if ((data != NULL) && (memcmp (data, "OggS", 4) == 0)) { @@ -3448,7 +3451,7 @@ static GstStaticCaps vorbis_caps = GST_STATIC_CAPS ("audio/x-vorbis"); static void vorbis_type_find (GstTypeFind * tf, gpointer private) { - guint8 *data = gst_type_find_peek (tf, 0, 30); + const guint8 *data = gst_type_find_peek (tf, 0, 30); if (data) { guint blocksize_0; @@ -3493,7 +3496,7 @@ static GstStaticCaps theora_caps = GST_STATIC_CAPS ("video/x-theora"); static void theora_type_find (GstTypeFind * tf, gpointer private) { - guint8 *data = gst_type_find_peek (tf, 0, 7); //42); + const guint8 *data = gst_type_find_peek (tf, 0, 7); //42); if (data) { if (data[0] != 0x80) @@ -3510,7 +3513,7 @@ theora_type_find (GstTypeFind * tf, gpointer private) static void kate_type_find (GstTypeFind * tf, gpointer private) { - guint8 *data = gst_type_find_peek (tf, 0, 64); + const guint8 *data = gst_type_find_peek (tf, 0, 64); gchar category[16] = { 0, }; if (G_UNLIKELY (data == NULL)) @@ -3543,7 +3546,7 @@ GST_STATIC_CAPS ("application/x-ogm-video"); static void ogmvideo_type_find (GstTypeFind * tf, gpointer private) { - guint8 *data = gst_type_find_peek (tf, 0, 9); + const guint8 *data = gst_type_find_peek (tf, 0, 9); if (data) { if (memcmp (data, "\001video\000\000\000", 9) != 0) @@ -3558,7 +3561,7 @@ GST_STATIC_CAPS ("application/x-ogm-audio"); static void ogmaudio_type_find (GstTypeFind * tf, gpointer private) { - guint8 *data = gst_type_find_peek (tf, 0, 9); + const guint8 *data = gst_type_find_peek (tf, 0, 9); if (data) { if (memcmp (data, "\001audio\000\000\000", 9) != 0) @@ -3573,7 +3576,7 @@ static GstStaticCaps ogmtext_caps = GST_STATIC_CAPS ("application/x-ogm-text"); static void ogmtext_type_find (GstTypeFind * tf, gpointer private) { - guint8 *data = gst_type_find_peek (tf, 0, 9); + const guint8 *data = gst_type_find_peek (tf, 0, 9); if (data) { if (memcmp (data, "\001text\000\000\000\000", 9) != 0) @@ -3590,7 +3593,7 @@ static GstStaticCaps speex_caps = GST_STATIC_CAPS ("audio/x-speex"); static void speex_type_find (GstTypeFind * tf, gpointer private) { - guint8 *data = gst_type_find_peek (tf, 0, 80); + const guint8 *data = gst_type_find_peek (tf, 0, 80); if (data) { /* 8 byte string "Speex " @@ -3626,7 +3629,7 @@ static GstStaticCaps celt_caps = GST_STATIC_CAPS ("audio/x-celt"); static void celt_type_find (GstTypeFind * tf, gpointer private) { - guint8 *data = gst_type_find_peek (tf, 0, 8); + const guint8 *data = gst_type_find_peek (tf, 0, 8); if (data) { /* 8 byte string "CELT " */ @@ -3645,7 +3648,7 @@ GST_STATIC_CAPS ("application/x-ogg-skeleton, parsed=(boolean)FALSE"); static void oggskel_type_find (GstTypeFind * tf, gpointer private) { - guint8 *data = gst_type_find_peek (tf, 0, 12); + const guint8 *data = gst_type_find_peek (tf, 0, 12); if (data) { /* 8 byte string "fishead\0" for the ogg skeleton stream */ @@ -3671,7 +3674,7 @@ static void cmml_type_find (GstTypeFind * tf, gpointer private) { /* Header is 12 bytes minimum (though we don't check the minor version */ - guint8 *data = gst_type_find_peek (tf, 0, 12); + const guint8 *data = gst_type_find_peek (tf, 0, 12); if (data) { @@ -3698,7 +3701,7 @@ static GstStaticCaps tar_caps = GST_STATIC_CAPS ("application/x-tar"); static void tar_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 257, 8); + const guint8 *data = gst_type_find_peek (tf, 257, 8); /* of course we are not certain, but we don't want other typefind funcs * to detect formats of files within the tar archive, e.g. mp3s */ @@ -3720,7 +3723,7 @@ static GstStaticCaps ar_caps = GST_STATIC_CAPS ("application/x-ar"); static void ar_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 24); + const guint8 *data = gst_type_find_peek (tf, 0, 24); if (data && memcmp (data, "!", 7) == 0) { gint i; @@ -3747,7 +3750,7 @@ static GstStaticCaps au_caps = GST_STATIC_CAPS ("audio/x-au"); static void au_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 4); + const guint8 *data = gst_type_find_peek (tf, 0, 4); if (data) { if (memcmp (data, ".snd", 4) == 0 || memcmp (data, "dns.", 4) == 0) { @@ -3769,7 +3772,7 @@ static GstStaticCaps nuv_caps = GST_STATIC_CAPS ("video/x-nuv"); static void nuv_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 11); + const guint8 *data = gst_type_find_peek (tf, 0, 11); if (data) { if (memcmp (data, "MythTVVideo", 11) == 0 @@ -3787,7 +3790,7 @@ static GstStaticCaps paris_caps = GST_STATIC_CAPS ("audio/x-paris"); static void paris_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 4); + const guint8 *data = gst_type_find_peek (tf, 0, 4); if (data) { if (memcmp (data, " paf", 4) == 0 || memcmp (data, "fap ", 4) == 0) { @@ -3804,7 +3807,7 @@ static GstStaticCaps ilbc_caps = GST_STATIC_CAPS ("audio/iLBC-sh"); static void ilbc_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 8); + const guint8 *data = gst_type_find_peek (tf, 0, 8); if (data) { if (memcmp (data, "#!iLBC30", 8) == 0 || memcmp (data, "#!iLBC20", 8) == 0) { @@ -3822,7 +3825,7 @@ GST_STATIC_CAPS ("application/x-ms-dos-executable"); static void msdos_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 64); + const guint8 *data = gst_type_find_peek (tf, 0, 64); if (data && data[0] == 'M' && data[1] == 'Z' && GST_READ_UINT16_LE (data + 8) == 4) { @@ -3849,7 +3852,7 @@ mmsh_type_find (GstTypeFind * tf, gpointer unused) 0xcf, 0x11, 0xa6, 0xd9, 0x00, 0xaa, 0x00, 0x62, 0xce, 0x6c }; - guint8 *data; + const guint8 *data; data = gst_type_find_peek (tf, 0, 2 + 2 + 4 + 2 + 2 + 16); if (data && data[0] == 0x24 && data[1] == 0x48 && @@ -3871,7 +3874,7 @@ static GstStaticCaps dirac_caps = GST_STATIC_CAPS ("video/x-dirac"); static void dirac_type_find (GstTypeFind * tf, gpointer unused) { - guint8 *data = gst_type_find_peek (tf, 0, 8); + const guint8 *data = gst_type_find_peek (tf, 0, 8); if (data) { if (memcmp (data, "BBCD", 4) == 0 || memcmp (data, "KW-DIRAC", 8) == 0) { @@ -3892,7 +3895,7 @@ vivo_type_find (GstTypeFind * tf, gpointer unused) static const guint8 vivo_marker[] = { 'V', 'e', 'r', 's', 'i', 'o', 'n', ':', 'V', 'i', 'v', 'o', '/' }; - guint8 *data; + const guint8 *data; guint hdr_len, pos; data = gst_type_find_peek (tf, 0, 1024); @@ -3930,7 +3933,7 @@ xdgmime_typefind (GstTypeFind * find, gpointer user_data) gchar *mimetype; gsize length = 16384; guint64 tf_length; - guint8 *data; + const guint8 *data; gchar *tmp; if ((tf_length = gst_type_find_get_length (find)) > 0) @@ -3982,7 +3985,7 @@ xdgmime_typefind (GstTypeFind * find, gpointer user_data) static void windows_icon_typefind (GstTypeFind * find, gpointer user_data) { - guint8 *data; + const guint8 *data; gint64 datalen; guint16 type, nimages; gint32 size, offset; @@ -4024,7 +4027,7 @@ windows_icon_typefind (GstTypeFind * find, gpointer user_data) static void wbmp_typefind (GstTypeFind * find, gpointer user_data) { - guint8 *data; + const guint8 *data; gint64 datalen; guint w, h, size; @@ -4142,7 +4145,7 @@ static void start_with_type_find (GstTypeFind * tf, gpointer private) { GstTypeFindData *start_with = (GstTypeFindData *) private; - guint8 *data; + const guint8 *data; GST_LOG ("trying to find mime type %s with the first %u bytes of data", gst_structure_get_name (gst_caps_get_structure (start_with->caps, 0)), @@ -4182,7 +4185,7 @@ static void riff_type_find (GstTypeFind * tf, gpointer private) { GstTypeFindData *riff_data = (GstTypeFindData *) private; - guint8 *data = gst_type_find_peek (tf, 0, 12); + const guint8 *data = gst_type_find_peek (tf, 0, 12); if (data && (memcmp (data, "RIFF", 4) == 0 || memcmp (data, "AVF0", 4) == 0)) { data += 8; From aae0312e1071df56586166c73c584988a45fa67e Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 26 Sep 2011 13:42:38 +0200 Subject: [PATCH 04/16] audioencoder: filter AUDIO_CODEC/CODEC tags from passing tag events --- gst-libs/gst/audio/gstaudioencoder.c | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/gst-libs/gst/audio/gstaudioencoder.c b/gst-libs/gst/audio/gstaudioencoder.c index edd9263c88..514ec53ce8 100644 --- a/gst-libs/gst/audio/gstaudioencoder.c +++ b/gst-libs/gst/audio/gstaudioencoder.c @@ -1194,6 +1194,22 @@ gst_audio_encoder_sink_eventfunc (GstAudioEncoder * enc, GstEvent * event) gst_audio_encoder_drain (enc); break; + case GST_EVENT_TAG: + { + GstTagList *tags; + + gst_event_parse_tag (event, &tags); + tags = gst_tag_list_copy (tags); + gst_event_unref (event); + gst_tag_list_remove_tag (tags, GST_TAG_CODEC); + gst_tag_list_remove_tag (tags, GST_TAG_AUDIO_CODEC); + event = gst_event_new_tag (tags); + + gst_pad_push_event (enc->srcpad, event); + handled = TRUE; + break; + } + default: break; } From a99b313c262da8938ede02402da6889430fc5c64 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 26 Sep 2011 14:48:55 +0200 Subject: [PATCH 05/16] audioencoder: provide CODEC/AUDIO_CODEC handling --- gst-libs/gst/audio/gstaudioencoder.c | 30 ++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/gst-libs/gst/audio/gstaudioencoder.c b/gst-libs/gst/audio/gstaudioencoder.c index 514ec53ce8..32543f2792 100644 --- a/gst-libs/gst/audio/gstaudioencoder.c +++ b/gst-libs/gst/audio/gstaudioencoder.c @@ -155,6 +155,7 @@ #include "gstaudioencoder.h" #include #include +#include #include #include @@ -239,6 +240,9 @@ struct _GstAudioEncoderPrivate gboolean perfect_ts; gboolean hard_resync; gboolean granule; + + /* pending tags */ + GstTagList *tags; }; @@ -399,12 +403,18 @@ gst_audio_encoder_reset (GstAudioEncoder * enc, gboolean full) { GST_OBJECT_LOCK (enc); + GST_LOG_OBJECT (enc, "reset full %d", full); + if (full) { enc->priv->active = FALSE; enc->priv->samples_in = 0; enc->priv->bytes_out = 0; gst_audio_info_clear (&enc->priv->ctx.info); memset (&enc->priv->ctx, 0, sizeof (enc->priv->ctx)); + + if (enc->priv->tags) + gst_tag_list_free (enc->priv->tags); + enc->priv->tags = NULL; } gst_segment_init (&enc->segment, GST_FORMAT_TIME); @@ -475,6 +485,21 @@ gst_audio_encoder_finish_frame (GstAudioEncoder * enc, GstBuffer * buf, g_return_val_if_fail (buf == NULL || GST_BUFFER_SIZE (buf) > 0, GST_FLOW_ERROR); + if (G_UNLIKELY (enc->priv->tags)) { + GstTagList *tags; + + /* add codec info to pending tags */ + tags = enc->priv->tags; + /* no more pending */ + enc->priv->tags = NULL; + gst_pb_utils_add_codec_description_to_tag_list (tags, GST_TAG_CODEC, + GST_PAD_CAPS (enc->srcpad)); + gst_pb_utils_add_codec_description_to_tag_list (tags, GST_TAG_AUDIO_CODEC, + GST_PAD_CAPS (enc->srcpad)); + GST_DEBUG_OBJECT (enc, "sending tags %" GST_PTR_FORMAT, tags); + gst_element_found_tags_for_pad (GST_ELEMENT (enc), enc->srcpad, tags); + } + GST_LOG_OBJECT (enc, "accepting %d bytes encoded data as %d samples", buf ? GST_BUFFER_SIZE (buf) : -1, samples); @@ -1557,6 +1582,11 @@ gst_audio_encoder_activate (GstAudioEncoder * enc, gboolean active) GST_DEBUG_OBJECT (enc, "activate %d", active); if (active) { + + if (enc->priv->tags) + gst_tag_list_free (enc->priv->tags); + enc->priv->tags = gst_tag_list_new (); + if (!enc->priv->active && klass->start) result = klass->start (enc); } else { From abafb030ac995c01e20a4ceb7aac6f2d52f71010 Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 26 Sep 2011 15:14:41 +0200 Subject: [PATCH 06/16] audioencoder: add some tag handling convenience help --- gst-libs/gst/audio/gstaudioencoder.c | 37 ++++++++++++++++++++++++++++ gst-libs/gst/audio/gstaudioencoder.h | 3 +++ 2 files changed, 40 insertions(+) diff --git a/gst-libs/gst/audio/gstaudioencoder.c b/gst-libs/gst/audio/gstaudioencoder.c index 32543f2792..19e946c975 100644 --- a/gst-libs/gst/audio/gstaudioencoder.c +++ b/gst-libs/gst/audio/gstaudioencoder.c @@ -1982,3 +1982,40 @@ gst_audio_encoder_get_tolerance (GstAudioEncoder * enc) return result; } + +/** + * gst_audio_encoder_merge_tags: + * @enc: a #GstAudioEncoder + * @tags: a #GstTagList to merge + * @mode: the #GstTagMergeMode to use + * + * Adds tags to so-called pending tags, which will be processed + * before pushing out data downstream. + * + * Note that this is provided for convenience, and the subclass is + * not required to use this and can still do tag handling on its own, + * although it should be aware that baseclass already takes care + * of the usual CODEC/AUDIO_CODEC tags. + * + * MT safe. + * + * Since: 0.10.36 + */ +void +gst_audio_encoder_merge_tags (GstAudioEncoder * enc, + const GstTagList * tags, GstTagMergeMode mode) +{ + GstTagList *otags; + + g_return_if_fail (GST_IS_AUDIO_ENCODER (enc)); + g_return_if_fail (tags == NULL || GST_IS_TAG_LIST (tags)); + + GST_OBJECT_LOCK (enc); + if (tags) + GST_DEBUG_OBJECT (enc, "merging tags %" GST_PTR_FORMAT, tags); + otags = enc->priv->tags; + enc->priv->tags = gst_tag_list_merge (enc->priv->tags, tags, mode); + if (otags) + gst_tag_list_free (otags); + GST_OBJECT_UNLOCK (enc); +} diff --git a/gst-libs/gst/audio/gstaudioencoder.h b/gst-libs/gst/audio/gstaudioencoder.h index a8ff018874..e4f4e50f2c 100644 --- a/gst-libs/gst/audio/gstaudioencoder.h +++ b/gst-libs/gst/audio/gstaudioencoder.h @@ -238,6 +238,9 @@ void gst_audio_encoder_set_tolerance (GstAudioEncoder * enc, gint64 gst_audio_encoder_get_tolerance (GstAudioEncoder * enc); +void gst_audio_encoder_merge_tags (GstAudioEncoder * enc, + const GstTagList * tags, GstTagMergeMode mode); + G_END_DECLS #endif /* __GST_AUDIO_ENCODER_H__ */ From 11e375486e07cfa0686a97b5cf6110909b3a828c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 26 Sep 2011 15:34:54 +0200 Subject: [PATCH 07/16] audioencoder: Use GST_BOILERPLATE instead of custom GObject boilerplate code --- gst-libs/gst/audio/gstaudioencoder.c | 59 +++++++++------------------- 1 file changed, 19 insertions(+), 40 deletions(-) diff --git a/gst-libs/gst/audio/gstaudioencoder.c b/gst-libs/gst/audio/gstaudioencoder.c index 19e946c975..9a3d75c0f9 100644 --- a/gst-libs/gst/audio/gstaudioencoder.c +++ b/gst-libs/gst/audio/gstaudioencoder.c @@ -245,45 +245,6 @@ struct _GstAudioEncoderPrivate GstTagList *tags; }; - -static GstElementClass *parent_class = NULL; - -static void gst_audio_encoder_class_init (GstAudioEncoderClass * klass); -static void gst_audio_encoder_init (GstAudioEncoder * parse, - GstAudioEncoderClass * klass); - -GType -gst_audio_encoder_get_type (void) -{ - static GType audio_encoder_type = 0; - - if (!audio_encoder_type) { - static const GTypeInfo audio_encoder_info = { - sizeof (GstAudioEncoderClass), - (GBaseInitFunc) NULL, - (GBaseFinalizeFunc) NULL, - (GClassInitFunc) gst_audio_encoder_class_init, - NULL, - NULL, - sizeof (GstAudioEncoder), - 0, - (GInstanceInitFunc) gst_audio_encoder_init, - }; - const GInterfaceInfo preset_interface_info = { - NULL, /* interface_init */ - NULL, /* interface_finalize */ - NULL /* interface_data */ - }; - - audio_encoder_type = g_type_register_static (GST_TYPE_ELEMENT, - "GstAudioEncoder", &audio_encoder_info, G_TYPE_FLAG_ABSTRACT); - - g_type_add_interface_static (audio_encoder_type, GST_TYPE_PRESET, - &preset_interface_info); - } - return audio_encoder_type; -} - static void gst_audio_encoder_finalize (GObject * object); static void gst_audio_encoder_reset (GstAudioEncoder * enc, gboolean full); @@ -303,6 +264,20 @@ static gboolean gst_audio_encoder_sink_query (GstPad * pad, GstQuery * query); static const GstQueryType *gst_audio_encoder_get_query_types (GstPad * pad); static GstCaps *gst_audio_encoder_sink_getcaps (GstPad * pad); +static void +do_init (GType gtype) +{ + const GInterfaceInfo preset_interface_info = { + NULL, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + + g_type_add_interface_static (gtype, GST_TYPE_PRESET, &preset_interface_info); +} + +GST_BOILERPLATE_FULL (GstAudioEncoder, gst_audio_encoder, GstElement, + GST_TYPE_ELEMENT, do_init); static void gst_audio_encoder_class_init (GstAudioEncoderClass * klass) @@ -310,7 +285,6 @@ gst_audio_encoder_class_init (GstAudioEncoderClass * klass) GObjectClass *gobject_class; gobject_class = G_OBJECT_CLASS (klass); - parent_class = g_type_class_peek_parent (klass); GST_DEBUG_CATEGORY_INIT (gst_audio_encoder_debug, "audioencoder", 0, "audio encoder base class"); @@ -342,6 +316,11 @@ gst_audio_encoder_class_init (GstAudioEncoderClass * klass) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } +static void +gst_audio_encoder_base_init (gpointer g_class) +{ +} + static void gst_audio_encoder_init (GstAudioEncoder * enc, GstAudioEncoderClass * bclass) { From 61ffd7cb42b072a3fde7e262a61589e0992c568f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 26 Sep 2011 15:42:14 +0200 Subject: [PATCH 08/16] audioencoder: Delay sending of serialized events to finish_frame() This makes sure that the caps are already set before any serialized events are sent downstream. --- gst-libs/gst/audio/gstaudioencoder.c | 54 ++++++++++++++++++++++++++-- 1 file changed, 51 insertions(+), 3 deletions(-) diff --git a/gst-libs/gst/audio/gstaudioencoder.c b/gst-libs/gst/audio/gstaudioencoder.c index 9a3d75c0f9..c5c65247a0 100644 --- a/gst-libs/gst/audio/gstaudioencoder.c +++ b/gst-libs/gst/audio/gstaudioencoder.c @@ -243,6 +243,8 @@ struct _GstAudioEncoderPrivate /* pending tags */ GstTagList *tags; + /* pending serialized sink events, will be sent from finish_frame() */ + GList *pending_events; }; static void gst_audio_encoder_finalize (GObject * object); @@ -394,6 +396,10 @@ gst_audio_encoder_reset (GstAudioEncoder * enc, gboolean full) if (enc->priv->tags) gst_tag_list_free (enc->priv->tags); enc->priv->tags = NULL; + + g_list_foreach (enc->priv->pending_events, (GFunc) gst_event_unref, NULL); + g_list_free (enc->priv->pending_events); + enc->priv->pending_events = NULL; } gst_segment_init (&enc->segment, GST_FORMAT_TIME); @@ -485,6 +491,19 @@ gst_audio_encoder_finish_frame (GstAudioEncoder * enc, GstBuffer * buf, /* mark subclass still alive and providing */ priv->got_data = TRUE; + if (priv->pending_events) { + GList *pending_events, *l; + GST_OBJECT_LOCK (enc); + pending_events = priv->pending_events; + priv->pending_events = NULL; + GST_OBJECT_UNLOCK (enc); + + GST_DEBUG_OBJECT (enc, "Pushing pending events"); + for (l = priv->pending_events; l; l = l->next) + gst_pad_push_event (enc->srcpad, l->data); + g_list_free (pending_events); + } + /* remove corresponding samples from input */ if (samples < 0) samples = (enc->priv->offset / ctx->info.bpf); @@ -1192,6 +1211,13 @@ gst_audio_encoder_sink_eventfunc (GstAudioEncoder * enc, GstEvent * event) klass->flush (enc); /* and get (re)set for the sequel */ gst_audio_encoder_reset (enc, FALSE); + + GST_OBJECT_LOCK (enc); + g_list_foreach (enc->priv->pending_events, (GFunc) gst_event_unref, NULL); + g_list_free (enc->priv->pending_events); + enc->priv->pending_events = NULL; + GST_OBJECT_UNLOCK (enc); + break; case GST_EVENT_EOS: @@ -1209,7 +1235,10 @@ gst_audio_encoder_sink_eventfunc (GstAudioEncoder * enc, GstEvent * event) gst_tag_list_remove_tag (tags, GST_TAG_AUDIO_CODEC); event = gst_event_new_tag (tags); - gst_pad_push_event (enc->srcpad, event); + GST_OBJECT_LOCK (enc); + enc->priv->pending_events = + g_list_append (enc->priv->pending_events, event); + GST_OBJECT_UNLOCK (enc); handled = TRUE; break; } @@ -1241,8 +1270,27 @@ gst_audio_encoder_sink_event (GstPad * pad, GstEvent * event) if (!handled) handled = gst_audio_encoder_sink_eventfunc (enc, event); - if (!handled) - ret = gst_pad_event_default (pad, event); + if (!handled) { + /* Forward non-serialized events and EOS/FLUSH_STOP immediately. + * For EOS this is required because no buffer or serialized event + * will come after EOS and nothing could trigger another + * _finish_frame() call. + * + * For FLUSH_STOP this is required because it is expected + * to be forwarded immediately and no buffers are queued anyway. + */ + if (!GST_EVENT_IS_SERIALIZED (event) + || GST_EVENT_TYPE (event) == GST_EVENT_EOS + || GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) { + ret = gst_pad_event_default (pad, event); + } else { + GST_OBJECT_LOCK (enc); + enc->priv->pending_events = + g_list_append (enc->priv->pending_events, event); + GST_OBJECT_UNLOCK (enc); + ret = TRUE; + } + } GST_DEBUG_OBJECT (enc, "event handled"); From 16c3d6b3d5df1cb85fd28eb451629aa3a6363d87 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 26 Sep 2011 15:45:40 +0200 Subject: [PATCH 09/16] audioencoder: Fix thread safety issues if both pads have different streaming threads --- gst-libs/gst/audio/gstaudioencoder.c | 49 +++++++++++++++++++++------- gst-libs/gst/audio/gstaudioencoder.h | 7 ++++ 2 files changed, 44 insertions(+), 12 deletions(-) diff --git a/gst-libs/gst/audio/gstaudioencoder.c b/gst-libs/gst/audio/gstaudioencoder.c index c5c65247a0..561cc8172d 100644 --- a/gst-libs/gst/audio/gstaudioencoder.c +++ b/gst-libs/gst/audio/gstaudioencoder.c @@ -368,6 +368,8 @@ gst_audio_encoder_init (GstAudioEncoder * enc, GstAudioEncoderClass * bclass) enc->priv->adapter = gst_adapter_new (); + g_static_rec_mutex_init (&enc->stream_lock); + /* property default */ enc->priv->granule = DEFAULT_GRANULE; enc->priv->perfect_ts = DEFAULT_PERFECT_TS; @@ -382,7 +384,7 @@ gst_audio_encoder_init (GstAudioEncoder * enc, GstAudioEncoderClass * bclass) static void gst_audio_encoder_reset (GstAudioEncoder * enc, gboolean full) { - GST_OBJECT_LOCK (enc); + GST_AUDIO_ENCODER_STREAM_LOCK (enc); GST_LOG_OBJECT (enc, "reset full %d", full); @@ -413,7 +415,7 @@ gst_audio_encoder_reset (GstAudioEncoder * enc, gboolean full) enc->priv->samples = 0; enc->priv->discont = FALSE; - GST_OBJECT_UNLOCK (enc); + GST_AUDIO_ENCODER_STREAM_UNLOCK (enc); } static void @@ -423,6 +425,8 @@ gst_audio_encoder_finalize (GObject * object) g_object_unref (enc->priv->adapter); + g_static_rec_mutex_free (&enc->stream_lock); + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -470,6 +474,8 @@ gst_audio_encoder_finish_frame (GstAudioEncoder * enc, GstBuffer * buf, g_return_val_if_fail (buf == NULL || GST_BUFFER_SIZE (buf) > 0, GST_FLOW_ERROR); + GST_AUDIO_ENCODER_STREAM_LOCK (enc); + if (G_UNLIKELY (enc->priv->tags)) { GstTagList *tags; @@ -493,10 +499,9 @@ gst_audio_encoder_finish_frame (GstAudioEncoder * enc, GstBuffer * buf, if (priv->pending_events) { GList *pending_events, *l; - GST_OBJECT_LOCK (enc); + pending_events = priv->pending_events; priv->pending_events = NULL; - GST_OBJECT_UNLOCK (enc); GST_DEBUG_OBJECT (enc, "Pushing pending events"); for (l = priv->pending_events; l; l = l->next) @@ -650,6 +655,8 @@ gst_audio_encoder_finish_frame (GstAudioEncoder * enc, GstBuffer * buf, } exit: + GST_AUDIO_ENCODER_STREAM_UNLOCK (enc); + return ret; /* ERRORS */ @@ -660,7 +667,8 @@ overflow: samples, priv->offset / ctx->info.bpf), (NULL)); if (buf) gst_buffer_unref (buf); - return GST_FLOW_ERROR; + ret = GST_FLOW_ERROR; + goto exit; } } @@ -800,6 +808,8 @@ gst_audio_encoder_chain (GstPad * pad, GstBuffer * buffer) priv = enc->priv; ctx = &enc->priv->ctx; + GST_AUDIO_ENCODER_STREAM_LOCK (enc); + /* should know what is coming by now */ if (!ctx->info.bpf) goto not_negotiated; @@ -931,6 +941,9 @@ gst_audio_encoder_chain (GstPad * pad, GstBuffer * buffer) done: GST_LOG_OBJECT (enc, "chain leaving"); + + GST_AUDIO_ENCODER_STREAM_UNLOCK (enc); + return ret; /* ERRORS */ @@ -939,7 +952,8 @@ not_negotiated: GST_ELEMENT_ERROR (enc, CORE, NEGOTIATION, (NULL), ("encoder not initialized")); gst_buffer_unref (buffer); - return GST_FLOW_NOT_NEGOTIATED; + ret = GST_FLOW_NOT_NEGOTIATED; + goto done; } wrong_buffer: { @@ -947,7 +961,8 @@ wrong_buffer: ("buffer size %d not a multiple of %d", GST_BUFFER_SIZE (buffer), ctx->info.bpf)); gst_buffer_unref (buffer); - return GST_FLOW_ERROR; + ret = GST_FLOW_ERROR; + goto done; } } @@ -989,6 +1004,8 @@ gst_audio_encoder_sink_setcaps (GstPad * pad, GstCaps * caps) ctx = &enc->priv->ctx; state = &ctx->info; + GST_AUDIO_ENCODER_STREAM_LOCK (enc); + GST_DEBUG_OBJECT (enc, "caps: %" GST_PTR_FORMAT, caps); if (!gst_caps_is_fixed (caps)) @@ -1045,13 +1062,17 @@ gst_audio_encoder_sink_setcaps (GstPad * pad, GstCaps * caps) GST_DEBUG_OBJECT (enc, "new audio format identical to configured format"); } +exit: + + GST_AUDIO_ENCODER_STREAM_UNLOCK (enc); + return res; /* ERRORS */ refuse_caps: { GST_WARNING_OBJECT (enc, "rejected caps %" GST_PTR_FORMAT, caps); - return res; + goto exit; } } @@ -1191,6 +1212,7 @@ gst_audio_encoder_sink_eventfunc (GstAudioEncoder * enc, GstEvent * event) break; } + GST_AUDIO_ENCODER_STREAM_LOCK (enc); /* finish current segment */ gst_audio_encoder_drain (enc); /* reset partially for new segment */ @@ -1198,6 +1220,7 @@ gst_audio_encoder_sink_eventfunc (GstAudioEncoder * enc, GstEvent * event) /* and follow along with segment */ gst_segment_set_newsegment_full (&enc->segment, update, rate, arate, format, start, stop, time); + GST_AUDIO_ENCODER_STREAM_UNLOCK (enc); break; } @@ -1205,6 +1228,7 @@ gst_audio_encoder_sink_eventfunc (GstAudioEncoder * enc, GstEvent * event) break; case GST_EVENT_FLUSH_STOP: + GST_AUDIO_ENCODER_STREAM_LOCK (enc); /* discard any pending stuff */ /* TODO route through drain ?? */ if (!enc->priv->drained && klass->flush) @@ -1212,16 +1236,17 @@ gst_audio_encoder_sink_eventfunc (GstAudioEncoder * enc, GstEvent * event) /* and get (re)set for the sequel */ gst_audio_encoder_reset (enc, FALSE); - GST_OBJECT_LOCK (enc); g_list_foreach (enc->priv->pending_events, (GFunc) gst_event_unref, NULL); g_list_free (enc->priv->pending_events); enc->priv->pending_events = NULL; - GST_OBJECT_UNLOCK (enc); + GST_AUDIO_ENCODER_STREAM_UNLOCK (enc); break; case GST_EVENT_EOS: + GST_AUDIO_ENCODER_STREAM_LOCK (enc); gst_audio_encoder_drain (enc); + GST_AUDIO_ENCODER_STREAM_UNLOCK (enc); break; case GST_EVENT_TAG: @@ -1284,10 +1309,10 @@ gst_audio_encoder_sink_event (GstPad * pad, GstEvent * event) || GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) { ret = gst_pad_event_default (pad, event); } else { - GST_OBJECT_LOCK (enc); + GST_AUDIO_ENCODER_STREAM_LOCK (enc); enc->priv->pending_events = g_list_append (enc->priv->pending_events, event); - GST_OBJECT_UNLOCK (enc); + GST_AUDIO_ENCODER_STREAM_UNLOCK (enc); ret = TRUE; } } diff --git a/gst-libs/gst/audio/gstaudioencoder.h b/gst-libs/gst/audio/gstaudioencoder.h index e4f4e50f2c..8174257384 100644 --- a/gst-libs/gst/audio/gstaudioencoder.h +++ b/gst-libs/gst/audio/gstaudioencoder.h @@ -87,6 +87,8 @@ G_BEGIN_DECLS */ #define GST_AUDIO_ENCODER_SEGMENT(obj) (GST_AUDIO_ENCODER_CAST (obj)->segment) +#define GST_AUDIO_ENCODER_STREAM_LOCK(enc) g_static_rec_mutex_lock (&GST_AUDIO_ENCODER (enc)->stream_lock) +#define GST_AUDIO_ENCODER_STREAM_UNLOCK(enc) g_static_rec_mutex_unlock (&GST_AUDIO_ENCODER (enc)->stream_lock) typedef struct _GstAudioEncoder GstAudioEncoder; typedef struct _GstAudioEncoderClass GstAudioEncoderClass; @@ -108,6 +110,11 @@ struct _GstAudioEncoder { GstPad *sinkpad; GstPad *srcpad; + /* protects all data processing, i.e. is locked + * in the chain function, finish_frame and when + * processing serialized events */ + GStaticRecMutex stream_lock; + /* MT-protected (with STREAM_LOCK) */ GstSegment segment; From 4fa9749106ae8377b8091b79fe66dcb2e8bcfb7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 26 Sep 2011 15:59:22 +0200 Subject: [PATCH 10/16] audioencoder: Add support for requesting a minimum and maximum number of samples per frame This extends the special case of a fixed number of samples per frame that was supported before already. --- gst-libs/gst/audio/gstaudioencoder.c | 87 +++++++++++++++++++++------- gst-libs/gst/audio/gstaudioencoder.h | 8 ++- 2 files changed, 71 insertions(+), 24 deletions(-) diff --git a/gst-libs/gst/audio/gstaudioencoder.c b/gst-libs/gst/audio/gstaudioencoder.c index 561cc8172d..b3ad1d4f6e 100644 --- a/gst-libs/gst/audio/gstaudioencoder.c +++ b/gst-libs/gst/audio/gstaudioencoder.c @@ -188,7 +188,7 @@ typedef struct _GstAudioEncoderContext GstAudioInfo info; /* output */ - gint frame_samples; + gint frame_samples_min, frame_samples_max; gint frame_max; gint lookahead; /* MT-protected (with LOCK) */ @@ -701,9 +701,11 @@ gst_audio_encoder_push_buffers (GstAudioEncoder * enc, gboolean force) g_assert (priv->offset <= av); av -= priv->offset; - need = ctx->frame_samples > 0 ? ctx->frame_samples * ctx->info.bpf : av; - GST_LOG_OBJECT (enc, "available: %d, needed: %d, force: %d", - av, need, force); + need = + ctx->frame_samples_min > + 0 ? ctx->frame_samples_min * ctx->info.bpf : av; + GST_LOG_OBJECT (enc, "available: %d, needed: %d, force: %d", av, need, + force); if ((need > av) || !av) { if (G_UNLIKELY (force)) { @@ -716,14 +718,19 @@ gst_audio_encoder_push_buffers (GstAudioEncoder * enc, gboolean force) priv->force = FALSE; } - /* if we have some extra metadata, - * provide for integer multiple of frames to allow for better granularity - * of processing */ - if (ctx->frame_samples > 0 && need) { - if (ctx->frame_max > 1) - need = need * MIN ((av / need), ctx->frame_max); - else if (ctx->frame_max == 0) - need = need * (av / need); + if (ctx->frame_samples_max > 0) + need = MIN (av, ctx->frame_samples_max * ctx->info.bpf); + + if (ctx->frame_samples_min == ctx->frame_samples_max) { + /* if we have some extra metadata, + * provide for integer multiple of frames to allow for better granularity + * of processing */ + if (ctx->frame_samples_min > 0 && need) { + if (ctx->frame_max > 1) + need = need * MIN ((av / need), ctx->frame_max); + else if (ctx->frame_max == 0) + need = need * (av / need); + } } if (need) { @@ -1034,7 +1041,8 @@ gst_audio_encoder_sink_setcaps (GstPad * pad, GstCaps * caps) gst_audio_encoder_drain (enc); /* context defaults */ - enc->priv->ctx.frame_samples = 0; + enc->priv->ctx.frame_samples_min = 0; + enc->priv->ctx.frame_samples_max = 0; enc->priv->ctx.frame_max = 0; enc->priv->ctx.lookahead = 0; @@ -1696,37 +1704,71 @@ gst_audio_encoder_get_audio_info (GstAudioEncoder * enc) } /** - * gst_audio_encoder_set_frame_samples: + * gst_audio_encoder_set_frame_samples_min: * @enc: a #GstAudioEncoder * @num: number of samples per frame * * Sets number of samples (per channel) subclass needs to be handed, - * or will be handed all available if 0. + * at least or will be handed all available if 0. * * Since: 0.10.36 */ void -gst_audio_encoder_set_frame_samples (GstAudioEncoder * enc, gint num) +gst_audio_encoder_set_frame_samples_min (GstAudioEncoder * enc, gint num) { g_return_if_fail (GST_IS_AUDIO_ENCODER (enc)); - enc->priv->ctx.frame_samples = num; + enc->priv->ctx.frame_samples_min = num; } /** - * gst_audio_encoder_get_frame_samples: + * gst_audio_encoder_get_frame_samples_min: * @enc: a #GstAudioEncoder * - * Returns: currently requested samples per frame + * Returns: currently minimum requested samples per frame * * Since: 0.10.36 */ gint -gst_audio_encoder_get_frame_samples (GstAudioEncoder * enc) +gst_audio_encoder_get_frame_samples_min (GstAudioEncoder * enc) { g_return_val_if_fail (GST_IS_AUDIO_ENCODER (enc), 0); - return enc->priv->ctx.frame_samples; + return enc->priv->ctx.frame_samples_min; +} + +/** + * gst_audio_encoder_set_frame_samples_max: + * @enc: a #GstAudioEncoder + * @num: number of samples per frame + * + * Sets number of samples (per channel) subclass needs to be handed, + * at most or will be handed all available if 0. + * + * Since: 0.10.36 + */ +void +gst_audio_encoder_set_frame_samples_max (GstAudioEncoder * enc, gint num) +{ + g_return_if_fail (GST_IS_AUDIO_ENCODER (enc)); + + enc->priv->ctx.frame_samples_max = num; +} + +/** + * gst_audio_encoder_get_frame_samples_min: + * @enc: a #GstAudioEncoder + * + * Returns: currently maximum requested samples per frame + * + * Since: 0.10.36 + */ +gint +gst_audio_encoder_get_frame_samples_max (GstAudioEncoder * enc) +{ + g_return_val_if_fail (GST_IS_AUDIO_ENCODER (enc), 0); + + return enc->priv->ctx.frame_samples_max; } /** @@ -1734,7 +1776,8 @@ gst_audio_encoder_get_frame_samples (GstAudioEncoder * enc) * @enc: a #GstAudioEncoder * @num: number of frames * - * Sets max number of frames accepted at once (assumed minimally 1) + * Sets max number of frames accepted at once (assumed minimally 1). + * Requires @frame_samples_min and @frame_samples_max to be the equal. * * Since: 0.10.36 */ diff --git a/gst-libs/gst/audio/gstaudioencoder.h b/gst-libs/gst/audio/gstaudioencoder.h index 8174257384..263a635d92 100644 --- a/gst-libs/gst/audio/gstaudioencoder.h +++ b/gst-libs/gst/audio/gstaudioencoder.h @@ -203,9 +203,13 @@ GstCaps * gst_audio_encoder_proxy_getcaps (GstAudioEncoder * enc, /* context parameters */ GstAudioInfo * gst_audio_encoder_get_audio_info (GstAudioEncoder * enc); -gint gst_audio_encoder_get_frame_samples (GstAudioEncoder * enc); +gint gst_audio_encoder_get_frame_samples_min (GstAudioEncoder * enc); -void gst_audio_encoder_set_frame_samples (GstAudioEncoder * enc, gint num); +void gst_audio_encoder_set_frame_samples_min (GstAudioEncoder * enc, gint num); + +gint gst_audio_encoder_get_frame_samples_max (GstAudioEncoder * enc); + +void gst_audio_encoder_set_frame_samples_max (GstAudioEncoder * enc, gint num); gint gst_audio_encoder_get_frame_max (GstAudioEncoder * enc); From f3f416004f70190449a9d9353cbb80620411e754 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 26 Sep 2011 16:02:51 +0200 Subject: [PATCH 11/16] Revert "audioencoder: Use GST_BOILERPLATE instead of custom GObject boilerplate code" This reverts commit 11e375486e07cfa0686a97b5cf6110909b3a828c. GST_BOILERPLATE() can't define an abstract type and G_DEFINE_ABSTRACT_TYPE() does not pass the class struct to the instance_init function and there's no way to get the class struct of the current type in instance_init(). --- gst-libs/gst/audio/gstaudioencoder.c | 59 +++++++++++++++++++--------- 1 file changed, 40 insertions(+), 19 deletions(-) diff --git a/gst-libs/gst/audio/gstaudioencoder.c b/gst-libs/gst/audio/gstaudioencoder.c index b3ad1d4f6e..57f6460663 100644 --- a/gst-libs/gst/audio/gstaudioencoder.c +++ b/gst-libs/gst/audio/gstaudioencoder.c @@ -247,6 +247,45 @@ struct _GstAudioEncoderPrivate GList *pending_events; }; + +static GstElementClass *parent_class = NULL; + +static void gst_audio_encoder_class_init (GstAudioEncoderClass * klass); +static void gst_audio_encoder_init (GstAudioEncoder * parse, + GstAudioEncoderClass * klass); + +GType +gst_audio_encoder_get_type (void) +{ + static GType audio_encoder_type = 0; + + if (!audio_encoder_type) { + static const GTypeInfo audio_encoder_info = { + sizeof (GstAudioEncoderClass), + (GBaseInitFunc) NULL, + (GBaseFinalizeFunc) NULL, + (GClassInitFunc) gst_audio_encoder_class_init, + NULL, + NULL, + sizeof (GstAudioEncoder), + 0, + (GInstanceInitFunc) gst_audio_encoder_init, + }; + const GInterfaceInfo preset_interface_info = { + NULL, /* interface_init */ + NULL, /* interface_finalize */ + NULL /* interface_data */ + }; + + audio_encoder_type = g_type_register_static (GST_TYPE_ELEMENT, + "GstAudioEncoder", &audio_encoder_info, G_TYPE_FLAG_ABSTRACT); + + g_type_add_interface_static (audio_encoder_type, GST_TYPE_PRESET, + &preset_interface_info); + } + return audio_encoder_type; +} + static void gst_audio_encoder_finalize (GObject * object); static void gst_audio_encoder_reset (GstAudioEncoder * enc, gboolean full); @@ -266,20 +305,6 @@ static gboolean gst_audio_encoder_sink_query (GstPad * pad, GstQuery * query); static const GstQueryType *gst_audio_encoder_get_query_types (GstPad * pad); static GstCaps *gst_audio_encoder_sink_getcaps (GstPad * pad); -static void -do_init (GType gtype) -{ - const GInterfaceInfo preset_interface_info = { - NULL, /* interface_init */ - NULL, /* interface_finalize */ - NULL /* interface_data */ - }; - - g_type_add_interface_static (gtype, GST_TYPE_PRESET, &preset_interface_info); -} - -GST_BOILERPLATE_FULL (GstAudioEncoder, gst_audio_encoder, GstElement, - GST_TYPE_ELEMENT, do_init); static void gst_audio_encoder_class_init (GstAudioEncoderClass * klass) @@ -287,6 +312,7 @@ gst_audio_encoder_class_init (GstAudioEncoderClass * klass) GObjectClass *gobject_class; gobject_class = G_OBJECT_CLASS (klass); + parent_class = g_type_class_peek_parent (klass); GST_DEBUG_CATEGORY_INIT (gst_audio_encoder_debug, "audioencoder", 0, "audio encoder base class"); @@ -318,11 +344,6 @@ gst_audio_encoder_class_init (GstAudioEncoderClass * klass) G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); } -static void -gst_audio_encoder_base_init (gpointer g_class) -{ -} - static void gst_audio_encoder_init (GstAudioEncoder * enc, GstAudioEncoderClass * bclass) { From d0bf4652480c87c411d45c48fb108329043cba73 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 26 Sep 2011 16:19:42 +0200 Subject: [PATCH 12/16] audiodecoder: Delay sending of serialized events to finish_frame() --- gst-libs/gst/audio/gstaudiodecoder.c | 49 ++++++++++++++++++++++++++-- 1 file changed, 47 insertions(+), 2 deletions(-) diff --git a/gst-libs/gst/audio/gstaudiodecoder.c b/gst-libs/gst/audio/gstaudiodecoder.c index 21c75bcd6e..84729cb1c9 100644 --- a/gst-libs/gst/audio/gstaudiodecoder.c +++ b/gst-libs/gst/audio/gstaudiodecoder.c @@ -260,6 +260,8 @@ struct _GstAudioDecoderPrivate GstClockTime tolerance; gboolean plc; + /* pending serialized sink events, will be sent from finish_frame() */ + GList *pending_events; }; @@ -417,6 +419,10 @@ gst_audio_decoder_reset (GstAudioDecoder * dec, gboolean full) } gst_segment_init (&dec->segment, GST_FORMAT_TIME); + + g_list_foreach (dec->priv->pending_events, (GFunc) gst_event_unref, NULL); + g_list_free (dec->priv->pending_events); + dec->priv->pending_events = NULL; } g_queue_foreach (&dec->priv->frames, (GFunc) gst_buffer_unref, NULL); @@ -707,6 +713,20 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf, buf ? GST_BUFFER_SIZE (buf) : -1, buf ? GST_BUFFER_SIZE (buf) / ctx->info.bpf : -1, frames); + if (priv->pending_events) { + GList *pending_events, *l; + + GST_OBJECT_LOCK (dec); + pending_events = priv->pending_events; + priv->pending_events = NULL; + GST_OBJECT_UNLOCK (dec); + + GST_DEBUG_OBJECT (dec, "Pushing pending events"); + for (l = priv->pending_events; l; l = l->next) + gst_pad_push_event (dec->srcpad, l->data); + g_list_free (pending_events); + } + /* output shoud be whole number of sample frames */ if (G_LIKELY (buf && ctx->info.bpf)) { if (GST_BUFFER_SIZE (buf) % ctx->info.bpf) @@ -1374,6 +1394,12 @@ gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event) case GST_EVENT_FLUSH_STOP: /* prepare for fresh start */ gst_audio_decoder_flush (dec, TRUE); + + GST_OBJECT_LOCK (dec); + g_list_foreach (dec->priv->pending_events, (GFunc) gst_event_unref, NULL); + g_list_free (dec->priv->pending_events); + dec->priv->pending_events = NULL; + GST_OBJECT_UNLOCK (dec); break; case GST_EVENT_EOS: @@ -1407,8 +1433,27 @@ gst_audio_decoder_sink_event (GstPad * pad, GstEvent * event) if (!handled) handled = gst_audio_decoder_sink_eventfunc (dec, event); - if (!handled) - ret = gst_pad_event_default (pad, event); + if (!handled) { + /* Forward non-serialized events and EOS/FLUSH_STOP immediately. + * For EOS this is required because no buffer or serialized event + * will come after EOS and nothing could trigger another + * _finish_frame() call. + * + * For FLUSH_STOP this is required because it is expected + * to be forwarded immediately and no buffers are queued anyway. + */ + if (!GST_EVENT_IS_SERIALIZED (event) + || GST_EVENT_TYPE (event) == GST_EVENT_EOS + || GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) { + ret = gst_pad_event_default (pad, event); + } else { + GST_OBJECT_LOCK (dec); + dec->priv->pending_events = + g_list_append (dec->priv->pending_events, event); + GST_OBJECT_UNLOCK (dec); + ret = TRUE; + } + } GST_DEBUG_OBJECT (dec, "event handled"); From b767be2f689970f3d0ff4875f4254c43e4991fa1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 26 Sep 2011 16:22:00 +0200 Subject: [PATCH 13/16] audiodecoder: Fix thread safety issues if both pads have different streaming threads --- gst-libs/gst/audio/gstaudiodecoder.c | 57 +++++++++++++++++++++------- gst-libs/gst/audio/gstaudiodecoder.h | 9 ++++- 2 files changed, 51 insertions(+), 15 deletions(-) diff --git a/gst-libs/gst/audio/gstaudiodecoder.c b/gst-libs/gst/audio/gstaudiodecoder.c index 84729cb1c9..3a910a81da 100644 --- a/gst-libs/gst/audio/gstaudiodecoder.c +++ b/gst-libs/gst/audio/gstaudiodecoder.c @@ -385,6 +385,8 @@ gst_audio_decoder_init (GstAudioDecoder * dec, GstAudioDecoderClass * klass) dec->priv->adapter_out = gst_adapter_new (); g_queue_init (&dec->priv->frames); + g_static_rec_mutex_init (&dec->stream_lock); + /* property default */ dec->priv->latency = DEFAULT_LATENCY; dec->priv->tolerance = DEFAULT_TOLERANCE; @@ -400,7 +402,7 @@ gst_audio_decoder_reset (GstAudioDecoder * dec, gboolean full) { GST_DEBUG_OBJECT (dec, "gst_audio_decoder_reset"); - GST_OBJECT_LOCK (dec); + GST_AUDIO_DECODER_STREAM_LOCK (dec); if (full) { dec->priv->active = FALSE; @@ -438,7 +440,7 @@ gst_audio_decoder_reset (GstAudioDecoder * dec, gboolean full) dec->priv->discont = TRUE; dec->priv->sync_flush = FALSE; - GST_OBJECT_UNLOCK (dec); + GST_AUDIO_DECODER_STREAM_UNLOCK (dec); } static void @@ -456,6 +458,8 @@ gst_audio_decoder_finalize (GObject * object) g_object_unref (dec->priv->adapter_out); } + g_static_rec_mutex_free (&dec->stream_lock); + G_OBJECT_CLASS (parent_class)->finalize (object); } @@ -472,6 +476,8 @@ gst_audio_decoder_src_setcaps (GstPad * pad, GstCaps * caps) GST_DEBUG_OBJECT (dec, "setting src caps %" GST_PTR_FORMAT, caps); + GST_AUDIO_DECODER_STREAM_LOCK (dec); + /* parse caps here to check subclass; * also makes us aware of output format */ if (!gst_caps_is_fixed (caps)) @@ -488,6 +494,9 @@ gst_audio_decoder_src_setcaps (GstPad * pad, GstCaps * caps) if (!gst_audio_info_from_caps (&dec->priv->ctx.info, caps)) goto refuse_caps; +done: + GST_AUDIO_DECODER_STREAM_UNLOCK (dec); + gst_object_unref (dec); return res; @@ -495,8 +504,8 @@ gst_audio_decoder_src_setcaps (GstPad * pad, GstCaps * caps) refuse_caps: { GST_WARNING_OBJECT (dec, "rejected caps %" GST_PTR_FORMAT, caps); - gst_object_unref (dec); - return res; + res = FALSE; + goto done; } } @@ -512,6 +521,7 @@ gst_audio_decoder_sink_setcaps (GstPad * pad, GstCaps * caps) GST_DEBUG_OBJECT (dec, "caps: %" GST_PTR_FORMAT, caps); + GST_AUDIO_DECODER_STREAM_LOCK (dec); /* NOTE pbutils only needed here */ /* TODO maybe (only) upstream demuxer/parser etc should handle this ? */ if (dec->priv->taglist) @@ -523,6 +533,8 @@ gst_audio_decoder_sink_setcaps (GstPad * pad, GstCaps * caps) if (klass->set_format) res = klass->set_format (dec, caps); + GST_AUDIO_DECODER_STREAM_UNLOCK (dec); + g_object_unref (dec); return res; } @@ -696,6 +708,7 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf, GstAudioDecoderContext *ctx; gint samples = 0; GstClockTime ts, next_ts; + GstFlowReturn ret = GST_FLOW_OK; /* subclass should know what it is producing by now */ g_return_val_if_fail (buf == NULL || GST_PAD_CAPS (dec->srcpad) != NULL, @@ -713,13 +726,13 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf, buf ? GST_BUFFER_SIZE (buf) : -1, buf ? GST_BUFFER_SIZE (buf) / ctx->info.bpf : -1, frames); + GST_AUDIO_DECODER_STREAM_LOCK (dec); + if (priv->pending_events) { GList *pending_events, *l; - GST_OBJECT_LOCK (dec); pending_events = priv->pending_events; priv->pending_events = NULL; - GST_OBJECT_UNLOCK (dec); GST_DEBUG_OBJECT (dec, "Pushing pending events"); for (l = priv->pending_events; l; l = l->next) @@ -833,7 +846,11 @@ gst_audio_decoder_finish_frame (GstAudioDecoder * dec, GstBuffer * buf, dec->priv->error_count--; exit: - return gst_audio_decoder_output (dec, buf); + ret = gst_audio_decoder_output (dec, buf); + + GST_AUDIO_DECODER_STREAM_UNLOCK (dec); + + return ret; /* ERRORS */ wrong_buffer: @@ -842,7 +859,8 @@ wrong_buffer: ("buffer size %d not a multiple of %d", GST_BUFFER_SIZE (buf), ctx->info.bpf)); gst_buffer_unref (buf); - return GST_FLOW_ERROR; + ret = GST_FLOW_ERROR; + goto exit; } overflow: { @@ -851,7 +869,8 @@ overflow: priv->frames.length), (NULL)); if (buf) gst_buffer_unref (buf); - return GST_FLOW_ERROR; + ret = GST_FLOW_ERROR; + goto exit; } } @@ -1255,6 +1274,8 @@ gst_audio_decoder_chain (GstPad * pad, GstBuffer * buffer) GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buffer)), GST_TIME_ARGS (GST_BUFFER_DURATION (buffer))); + GST_AUDIO_DECODER_STREAM_LOCK (dec); + if (GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DISCONT)) { gint64 samples, ts; @@ -1281,6 +1302,8 @@ gst_audio_decoder_chain (GstPad * pad, GstBuffer * buffer) else ret = gst_audio_decoder_chain_reverse (dec, buffer); + GST_AUDIO_DECODER_STREAM_UNLOCK (dec); + return ret; } @@ -1306,6 +1329,7 @@ gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event) gint64 start, stop, time; gboolean update; + GST_AUDIO_DECODER_STREAM_LOCK (dec); gst_event_parse_new_segment_full (event, &update, &rate, &arate, &format, &start, &stop, &time); @@ -1341,6 +1365,7 @@ gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event) GST_FORMAT_TIME, start, stop, time); } else { GST_DEBUG_OBJECT (dec, "unsupported format; ignoring"); + GST_AUDIO_DECODER_STREAM_UNLOCK (dec); break; } } @@ -1383,8 +1408,10 @@ gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event) gst_segment_set_newsegment_full (&dec->segment, update, rate, arate, format, start, stop, time); - gst_pad_push_event (dec->srcpad, event); + dec->priv->pending_events = + g_list_append (dec->priv->pending_events, event); handled = TRUE; + GST_AUDIO_DECODER_STREAM_UNLOCK (dec); break; } @@ -1392,18 +1419,20 @@ gst_audio_decoder_sink_eventfunc (GstAudioDecoder * dec, GstEvent * event) break; case GST_EVENT_FLUSH_STOP: + GST_AUDIO_DECODER_STREAM_LOCK (dec); /* prepare for fresh start */ gst_audio_decoder_flush (dec, TRUE); - GST_OBJECT_LOCK (dec); g_list_foreach (dec->priv->pending_events, (GFunc) gst_event_unref, NULL); g_list_free (dec->priv->pending_events); dec->priv->pending_events = NULL; - GST_OBJECT_UNLOCK (dec); + GST_AUDIO_DECODER_STREAM_UNLOCK (dec); break; case GST_EVENT_EOS: + GST_AUDIO_DECODER_STREAM_LOCK (dec); gst_audio_decoder_drain (dec); + GST_AUDIO_DECODER_STREAM_UNLOCK (dec); break; default: @@ -1447,10 +1476,10 @@ gst_audio_decoder_sink_event (GstPad * pad, GstEvent * event) || GST_EVENT_TYPE (event) == GST_EVENT_FLUSH_STOP) { ret = gst_pad_event_default (pad, event); } else { - GST_OBJECT_LOCK (dec); + GST_AUDIO_DECODER_STREAM_LOCK (dec); dec->priv->pending_events = g_list_append (dec->priv->pending_events, event); - GST_OBJECT_UNLOCK (dec); + GST_AUDIO_DECODER_STREAM_UNLOCK (dec); ret = TRUE; } } diff --git a/gst-libs/gst/audio/gstaudiodecoder.h b/gst-libs/gst/audio/gstaudiodecoder.h index 1c47e1a7d5..783f83ea42 100644 --- a/gst-libs/gst/audio/gstaudiodecoder.h +++ b/gst-libs/gst/audio/gstaudiodecoder.h @@ -20,7 +20,6 @@ * Free Software Foundation, Inc., 59 Temple Place - Suite 330, * Boston, MA 02111-1307, USA. */ - #ifndef _GST_AUDIO_DECODER_H_ #define _GST_AUDIO_DECODER_H_ @@ -85,6 +84,9 @@ G_BEGIN_DECLS */ #define GST_AUDIO_DECODER_SINK_PAD(obj) (((GstAudioDecoder *) (obj))->sinkpad) +#define GST_AUDIO_DECODER_STREAM_LOCK(dec) g_static_rec_mutex_lock (&GST_AUDIO_DECODER (dec)->stream_lock) +#define GST_AUDIO_DECODER_STREAM_UNLOCK(dec) g_static_rec_mutex_unlock (&GST_AUDIO_DECODER (dec)->stream_lock) + typedef struct _GstAudioDecoder GstAudioDecoder; typedef struct _GstAudioDecoderClass GstAudioDecoderClass; @@ -146,6 +148,11 @@ struct _GstAudioDecoder GstPad *sinkpad; GstPad *srcpad; + /* protects all data processing, i.e. is locked + * in the chain function, finish_frame and when + * processing serialized events */ + GStaticRecMutex stream_lock; + /* MT-protected (with STREAM_LOCK) */ GstSegment segment; From e4c895dfafd3b478aaaa1ac396c49e5113ff251e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 26 Sep 2011 16:35:55 +0200 Subject: [PATCH 14/16] audioencoder: Improve set_frame_sample_{min,max} documentation --- gst-libs/gst/audio/gstaudioencoder.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/gst-libs/gst/audio/gstaudioencoder.c b/gst-libs/gst/audio/gstaudioencoder.c index 57f6460663..c11843843b 100644 --- a/gst-libs/gst/audio/gstaudioencoder.c +++ b/gst-libs/gst/audio/gstaudioencoder.c @@ -1732,6 +1732,9 @@ gst_audio_encoder_get_audio_info (GstAudioEncoder * enc) * Sets number of samples (per channel) subclass needs to be handed, * at least or will be handed all available if 0. * + * If an exact number of samples is required, gst_audio_encoder_set_frame_samples_max() + * must be called with the same number. + * * Since: 0.10.36 */ void @@ -1766,6 +1769,9 @@ gst_audio_encoder_get_frame_samples_min (GstAudioEncoder * enc) * Sets number of samples (per channel) subclass needs to be handed, * at most or will be handed all available if 0. * + * If an exact number of samples is required, gst_audio_encoder_set_frame_samples_min() + * must be called with the same number. + * * Since: 0.10.36 */ void From c4a8778a4509bb67de8f2ae91ed43465e4344d4c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 26 Sep 2011 16:36:22 +0200 Subject: [PATCH 15/16] win32: Adjust for GstAudioEncoder API changes --- win32/common/libgstaudio.def | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/win32/common/libgstaudio.def b/win32/common/libgstaudio.def index 0500ea6860..8395b0005f 100644 --- a/win32/common/libgstaudio.def +++ b/win32/common/libgstaudio.def @@ -34,7 +34,8 @@ EXPORTS gst_audio_encoder_finish_frame gst_audio_encoder_get_audio_info gst_audio_encoder_get_frame_max - gst_audio_encoder_get_frame_samples + gst_audio_encoder_get_frame_samples_max + gst_audio_encoder_get_frame_samples_min gst_audio_encoder_get_hard_resync gst_audio_encoder_get_latency gst_audio_encoder_get_lookahead @@ -42,9 +43,11 @@ EXPORTS gst_audio_encoder_get_perfect_timestamp gst_audio_encoder_get_tolerance gst_audio_encoder_get_type + gst_audio_encoder_merge_tags gst_audio_encoder_proxy_getcaps gst_audio_encoder_set_frame_max - gst_audio_encoder_set_frame_samples + gst_audio_encoder_set_frame_samples_max + gst_audio_encoder_set_frame_samples_min gst_audio_encoder_set_hard_resync gst_audio_encoder_set_latency gst_audio_encoder_set_lookahead From 49ebe7c053755973ea1aa13b428a1b8b0aae38a2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Sebastian=20Dr=C3=B6ge?= Date: Mon, 26 Sep 2011 16:36:56 +0200 Subject: [PATCH 16/16] docs: Adjust for GstAudioEncoder API changes --- docs/libs/gst-plugins-base-libs-sections.txt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/docs/libs/gst-plugins-base-libs-sections.txt b/docs/libs/gst-plugins-base-libs-sections.txt index d8dc07d6f5..70c6868403 100644 --- a/docs/libs/gst-plugins-base-libs-sections.txt +++ b/docs/libs/gst-plugins-base-libs-sections.txt @@ -215,7 +215,8 @@ GST_AUDIO_ENCODER_SRC_PAD gst_audio_encoder_finish_frame gst_audio_encoder_get_audio_info gst_audio_encoder_get_frame_max -gst_audio_encoder_get_frame_samples +gst_audio_encoder_get_frame_samples_min +gst_audio_encoder_get_frame_samples_max gst_audio_encoder_get_hard_resync gst_audio_encoder_get_latency gst_audio_encoder_get_lookahead @@ -224,7 +225,8 @@ gst_audio_encoder_get_perfect_timestamp gst_audio_encoder_get_tolerance gst_audio_encoder_proxy_getcaps gst_audio_encoder_set_frame_max -gst_audio_encoder_set_frame_samples +gst_audio_encoder_set_frame_samples_min +gst_audio_encoder_set_frame_samples_max gst_audio_encoder_set_hard_resync gst_audio_encoder_set_latency gst_audio_encoder_set_lookahead