From 1c89488c50501826ff1336e722ee0d1602c9715b Mon Sep 17 00:00:00 2001 From: Mark Nauwelaerts Date: Mon, 10 Jan 2011 15:34:48 +0100 Subject: baseparse: introduce a baseparse frame to serve as context ... and adjust subclass parsers accordingly --- gst/audioparsers/gstaacparse.c | 78 ++++++------ gst/audioparsers/gstac3parse.c | 20 ++-- gst/audioparsers/gstamrparse.c | 15 +-- gst/audioparsers/gstbaseparse.c | 224 +++++++++++++++++++++-------------- gst/audioparsers/gstbaseparse.h | 101 ++++++++++++---- gst/audioparsers/gstdcaparse.c | 20 ++-- gst/audioparsers/gstflacparse.c | 66 +++++------ gst/audioparsers/gstmpegaudioparse.c | 34 +++--- 8 files changed, 324 insertions(+), 234 deletions(-) diff --git a/gst/audioparsers/gstaacparse.c b/gst/audioparsers/gstaacparse.c index 4dd2dc761..140f5e4df 100644 --- a/gst/audioparsers/gstaacparse.c +++ b/gst/audioparsers/gstaacparse.c @@ -77,10 +77,10 @@ static gboolean gst_aacparse_sink_setcaps (GstBaseParse * parse, GstCaps * caps); gboolean gst_aacparse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * size, gint * skipsize); + GstBaseParseFrame * frame, guint * size, gint * skipsize); GstFlowReturn gst_aacparse_parse_frame (GstBaseParse * parse, - GstBuffer * buffer); + GstBaseParseFrame * frame); gboolean gst_aacparse_convert (GstBaseParse * parse, GstFormat src_format, @@ -147,8 +147,6 @@ gst_aacparse_class_init (GstAacParseClass * klass) parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_aacparse_parse_frame); parse_class->check_valid_frame = GST_DEBUG_FUNCPTR (gst_aacparse_check_valid_frame); - parse_class->get_frame_overhead = - GST_DEBUG_FUNCPTR (gst_aacparse_get_frame_overhead); } @@ -330,8 +328,8 @@ gst_aacparse_adts_get_frame_len (const guint8 * data) */ static gboolean gst_aacparse_check_adts_frame (GstAacParse * aacparse, - const guint8 * data, - const guint avail, guint * framesize, guint * needed_data) + const guint8 * data, const guint avail, gboolean drain, + guint * framesize, guint * needed_data) { if (G_UNLIKELY (avail < 2)) return FALSE; @@ -340,7 +338,7 @@ gst_aacparse_check_adts_frame (GstAacParse * aacparse, *framesize = gst_aacparse_adts_get_frame_len (data); /* In EOS mode this is enough. No need to examine the data further */ - if (gst_base_parse_get_drain (GST_BASE_PARSE (aacparse))) { + if (drain) { return TRUE; } @@ -408,7 +406,8 @@ gst_aacparse_parse_adts_header (GstAacParse * aacparse, const guint8 * data, */ static gboolean gst_aacparse_detect_stream (GstAacParse * aacparse, - const guint8 * data, const guint avail, guint * framesize, gint * skipsize) + const guint8 * data, const guint avail, gboolean drain, + guint * framesize, gint * skipsize) { gboolean found = FALSE; guint need_data = 0; @@ -444,7 +443,7 @@ gst_aacparse_detect_stream (GstAacParse * aacparse, return FALSE; } - if (gst_aacparse_check_adts_frame (aacparse, data, avail, + if (gst_aacparse_check_adts_frame (aacparse, data, avail, drain, framesize, &need_data)) { gint rate, channels; @@ -568,17 +567,19 @@ gst_aacparse_detect_stream (GstAacParse * aacparse, */ gboolean gst_aacparse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize) + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { const guint8 *data; GstAacParse *aacparse; gboolean ret = FALSE; gboolean sync; + GstBuffer *buffer; aacparse = GST_AACPARSE (parse); + buffer = frame->buffer; data = GST_BUFFER_DATA (buffer); - sync = gst_base_parse_get_sync (parse); + sync = GST_BASE_PARSE_FRAME_SYNC (frame); if (aacparse->header_type == DSPAAC_HEADER_ADIF || aacparse->header_type == DSPAAC_HEADER_NONE) { @@ -589,13 +590,14 @@ gst_aacparse_check_valid_frame (GstBaseParse * parse, } else if (aacparse->header_type == DSPAAC_HEADER_NOT_PARSED || sync == FALSE) { ret = gst_aacparse_detect_stream (aacparse, data, GST_BUFFER_SIZE (buffer), - framesize, skipsize); + GST_BASE_PARSE_FRAME_DRAIN (frame), framesize, skipsize); } else if (aacparse->header_type == DSPAAC_HEADER_ADTS) { guint needed_data = 1024; ret = gst_aacparse_check_adts_frame (aacparse, data, - GST_BUFFER_SIZE (buffer), framesize, &needed_data); + GST_BUFFER_SIZE (buffer), GST_BASE_PARSE_FRAME_DRAIN (frame), + framesize, &needed_data); if (!ret) { GST_DEBUG ("buffer didn't contain valid frame"); @@ -619,21 +621,39 @@ gst_aacparse_check_valid_frame (GstBaseParse * parse, * * Implementation of "parse_frame" vmethod in #GstBaseParse class. * + * Also determines frame overhead. + * ADTS streams have a 7 byte header in each frame. MP4 and ADIF streams don't have + * a per-frame header. + * + * We're making a couple of simplifying assumptions: + * + * 1. We count Program Configuration Elements rather than searching for them + * in the streams to discount them - the overhead is negligible. + * + * 2. We ignore CRC. This has a worst-case impact of (num_raw_blocks + 1)*16 + * bits, which should still not be significant enough to warrant the + * additional parsing through the headers + * * Returns: GST_FLOW_OK if frame was successfully parsed and can be pushed * forward. Otherwise appropriate error is returned. */ GstFlowReturn -gst_aacparse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) +gst_aacparse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { GstAacParse *aacparse; + GstBuffer *buffer; GstFlowReturn ret = GST_FLOW_OK; gint rate, channels; aacparse = GST_AACPARSE (parse); + buffer = frame->buffer; if (G_UNLIKELY (aacparse->header_type != DSPAAC_HEADER_ADTS)) return ret; + /* see above */ + frame->overhead = 7; + gst_aacparse_parse_adts_header (aacparse, GST_BUFFER_DATA (buffer), &rate, &channels, NULL, NULL); GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels); @@ -692,33 +712,3 @@ gst_aacparse_stop (GstBaseParse * parse) GST_DEBUG ("stop"); return TRUE; } - - -/** - * gst_aacparse_get_frame_overhead: - * @parse: #GstBaseParse. - * @buffer: #GstBuffer. - * - * Implementation of "get_frame_overhead" vmethod in #GstBaseParse class. ADTS - * streams have a 7 byte header in each frame. MP4 and ADIF streams don't have - * a per-frame header. - * - * We're making a couple of simplifying assumptions: - * - * 1. We count Program Configuration Elements rather than searching for them - * in the streams to discount them - the overhead is negligible. - * - * 2. We ignore CRC. This has a worst-case impact of (num_raw_blocks + 1)*16 - * bits, which should still not be significant enough to warrant the - * additional parsing through the headers - */ -gint -gst_aacparse_get_frame_overhead (GstBaseParse * parse, GstBuffer * buffer) -{ - GstAacParse *aacparse = GST_AACPARSE (parse); - - if (aacparse->header_type == DSPAAC_HEADER_ADTS) - return 7; - else - return 0; -} diff --git a/gst/audioparsers/gstac3parse.c b/gst/audioparsers/gstac3parse.c index 7e3a8b49c..0c7fba33c 100644 --- a/gst/audioparsers/gstac3parse.c +++ b/gst/audioparsers/gstac3parse.c @@ -160,9 +160,9 @@ static void gst_ac3_parse_finalize (GObject * object); static gboolean gst_ac3_parse_start (GstBaseParse * parse); static gboolean gst_ac3_parse_stop (GstBaseParse * parse); static gboolean gst_ac3_parse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * size, gint * skipsize); + GstBaseParseFrame * frame, guint * size, gint * skipsize); static GstFlowReturn gst_ac3_parse_parse_frame (GstBaseParse * parse, - GstBuffer * buf); + GstBaseParseFrame * frame); GST_BOILERPLATE (GstAc3Parse, gst_ac3_parse, GstBaseParse, GST_TYPE_BASE_PARSE); @@ -384,11 +384,12 @@ gst_ac3_parse_frame_header (GstAc3Parse * parse, GstBuffer * buf, } static gboolean -gst_ac3_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, - guint * framesize, gint * skipsize) +gst_ac3_parse_check_valid_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { - GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf); GstAc3Parse *ac3parse = GST_AC3_PARSE (parse); + GstBuffer *buf = frame->buffer; + GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf); gint off; gboolean sync, drain; @@ -421,8 +422,8 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, GST_LOG_OBJECT (parse, "got frame"); - sync = gst_base_parse_get_sync (parse); - drain = gst_base_parse_get_drain (parse); + sync = GST_BASE_PARSE_FRAME_SYNC (frame); + drain = GST_BASE_PARSE_FRAME_DRAIN (frame); if (!sync && !drain) { guint16 word = 0; @@ -451,9 +452,10 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, } static GstFlowReturn -gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf) +gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { GstAc3Parse *ac3parse = GST_AC3_PARSE (parse); + GstBuffer *buf = frame->buffer; guint fsize, rate, chans, blocks, sid; gboolean eac; @@ -465,7 +467,7 @@ gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf) if (G_UNLIKELY (sid)) { GST_LOG_OBJECT (parse, "sid: %d", sid); - GST_BUFFER_FLAG_SET (buf, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME); + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_NO_FRAME; } if (G_UNLIKELY (ac3parse->sample_rate != rate || ac3parse->channels != chans diff --git a/gst/audioparsers/gstamrparse.c b/gst/audioparsers/gstamrparse.c index a182e765b..191a0291b 100644 --- a/gst/audioparsers/gstamrparse.c +++ b/gst/audioparsers/gstamrparse.c @@ -78,10 +78,10 @@ static gboolean gst_amrparse_sink_setcaps (GstBaseParse * parse, GstCaps * caps); gboolean gst_amrparse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize); + GstBaseParseFrame * frame, guint * framesize, gint * skipsize); GstFlowReturn gst_amrparse_parse_frame (GstBaseParse * parse, - GstBuffer * buffer); + GstBaseParseFrame * frame); #define _do_init(bla) \ GST_DEBUG_CATEGORY_INIT (gst_amrparse_debug, "amrparse", 0, \ @@ -267,13 +267,15 @@ gst_amrparse_parse_header (GstAmrParse * amrparse, */ gboolean gst_amrparse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize) + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { + GstBuffer *buffer; const guint8 *data; gint fsize, mode, dsize; GstAmrParse *amrparse; amrparse = GST_AMRPARSE (parse); + buffer = frame->buffer; data = GST_BUFFER_DATA (buffer); dsize = GST_BUFFER_SIZE (buffer); @@ -305,8 +307,8 @@ gst_amrparse_check_valid_frame (GstBaseParse * parse, * to contain a valid header as well (and there is enough data to * perform this check) */ - if (gst_base_parse_get_sync (parse) || gst_base_parse_get_drain (parse) || - (dsize >= fsize && (data[fsize] & 0x83) == 0)) { + if (GST_BASE_PARSE_FRAME_SYNC (frame) || GST_BASE_PARSE_FRAME_DRAIN (frame) + || (dsize >= fsize && (data[fsize] & 0x83) == 0)) { *framesize = fsize; return TRUE; } @@ -327,9 +329,8 @@ gst_amrparse_check_valid_frame (GstBaseParse * parse, * Returns: #GstFlowReturn defining the parsing status. */ GstFlowReturn -gst_amrparse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) +gst_amrparse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { - gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad)); return GST_FLOW_OK; } diff --git a/gst/audioparsers/gstbaseparse.c b/gst/audioparsers/gstbaseparse.c index 8f7a5d523..91898466f 100644 --- a/gst/audioparsers/gstbaseparse.c +++ b/gst/audioparsers/gstbaseparse.c @@ -352,10 +352,9 @@ static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstBuffer * buffer); static void gst_base_parse_loop (GstPad * pad); static gboolean gst_base_parse_check_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize); - + GstBaseParseFrame * frame, guint * framesize, gint * skipsize); static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse, - GstBuffer * buffer); + GstBaseParseFrame * frame); static gboolean gst_base_parse_sink_eventfunc (GstBaseParse * parse, GstEvent * event); @@ -504,6 +503,49 @@ gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass) GST_DEBUG_OBJECT (parse, "init ok"); } +/** + * gst_base_parse_frame_init: + * @parse: #GstBaseParse. + * @fmt: #GstBaseParseFrame. + * + * Sets a #GstBaseParseFrame to initial state. Currently this means + * all fields are zero-ed. + */ +void +gst_base_parse_frame_init (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + memset (frame, 0, sizeof (*frame)); +} + +/* clear == frame no longer to be used following this */ +static void +gst_base_parse_frame_clear (GstBaseParse * parse, GstBaseParseFrame * frame) +{ + /* limited for now */ + if (frame->buffer) { + gst_buffer_unref (frame->buffer); + frame->buffer = NULL; + } +} + +static inline void +gst_base_parse_frame_update (GstBaseParse * parse, GstBaseParseFrame * frame, + GstBuffer * buf) +{ + gst_buffer_replace (&frame->buffer, buf); + if (parse->priv->drain) { + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DRAIN; + } else { + frame->flags &= ~(GST_BASE_PARSE_FRAME_FLAG_DRAIN); + } + /* losing sync is pretty much a discont (and vice versa), no ? */ + if (!parse->priv->discont) { + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_SYNC; + } else { + frame->flags &= ~(GST_BASE_PARSE_FRAME_FLAG_SYNC); + } +} + static void gst_base_parse_reset (GstBaseParse * parse) { @@ -587,9 +629,9 @@ gst_base_parse_reset (GstBaseParse * parse) */ static gboolean gst_base_parse_check_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize) + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { - *framesize = GST_BUFFER_SIZE (buffer); + *framesize = GST_BUFFER_SIZE (frame->buffer); *skipsize = 0; return TRUE; } @@ -603,8 +645,10 @@ gst_base_parse_check_frame (GstBaseParse * parse, * Default callback for parse_frame. */ static GstFlowReturn -gst_base_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) +gst_base_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { + GstBuffer *buffer = frame->buffer; + if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && GST_CLOCK_TIME_IS_VALID (parse->priv->next_ts)) { GST_BUFFER_TIMESTAMP (buffer) = parse->priv->next_ts; @@ -1114,23 +1158,22 @@ gst_base_parse_post_bitrates (GstBaseParse * parse, gboolean post_min, * running average bitrate of the stream so far. */ static void -gst_base_parse_update_bitrates (GstBaseParse * parse, GstBuffer * buffer) +gst_base_parse_update_bitrates (GstBaseParse * parse, GstBaseParseFrame * frame) { /* Only update the tag on a 10 kbps delta */ static const gint update_threshold = 10000; GstBaseParseClass *klass; guint64 data_len, frame_dur; - gint overhead = 0, frame_bitrate, old_avg_bitrate; + gint overhead, frame_bitrate, old_avg_bitrate; gboolean update_min = FALSE, update_avg = FALSE, update_max = FALSE; + GstBuffer *buffer = frame->buffer; klass = GST_BASE_PARSE_GET_CLASS (parse); - if (klass->get_frame_overhead) { - overhead = klass->get_frame_overhead (parse, buffer); - if (overhead == -1) - return; - } + overhead = frame->overhead; + if (overhead == -1) + return; data_len = GST_BUFFER_SIZE (buffer) - overhead; parse->priv->data_bytecount += data_len; @@ -1391,11 +1434,16 @@ gst_base_parse_check_media (GstBaseParse * parse) * Returns: #GstFlowReturn */ static GstFlowReturn -gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, - GstBaseParseClass * klass, GstBuffer * buffer) +gst_base_parse_handle_and_push_frame (GstBaseParse * parse, + GstBaseParseClass * klass, GstBaseParseFrame * frame) { GstFlowReturn ret; gint64 offset; + GstBuffer *buffer; + + g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); + + buffer = frame->buffer; if (parse->priv->discont) { GST_DEBUG_OBJECT (parse, "marking DISCONT"); @@ -1417,7 +1465,11 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, /* store offset as it might get overwritten */ offset = GST_BUFFER_OFFSET (buffer); - ret = klass->parse_frame (parse, buffer); + ret = klass->parse_frame (parse, frame); + /* sync */ + buffer = frame->buffer; + /* subclass must play nice */ + g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); /* check initial frame to determine if subclass/format can provide ts. * If so, that allows and enables extra seek and duration determining options */ @@ -1446,7 +1498,7 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, } /* re-use default handler to add missing metadata as-much-as-possible */ - gst_base_parse_parse_frame (parse, buffer); + gst_base_parse_parse_frame (parse, frame); if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && GST_BUFFER_DURATION_IS_VALID (buffer)) { parse->priv->next_ts = @@ -1468,34 +1520,40 @@ gst_base_parse_handle_and_push_buffer (GstBaseParse * parse, * frames to decide on the format and queues them internally */ /* convert internal flow to OK and mark discont for the next buffer. */ if (ret == GST_BASE_PARSE_FLOW_DROPPED) { - gst_buffer_unref (buffer); + gst_base_parse_frame_clear (parse, frame); return GST_FLOW_OK; } else if (ret != GST_FLOW_OK) { return ret; } - return gst_base_parse_push_buffer (parse, buffer); + return gst_base_parse_push_frame (parse, frame); } /** - * gst_base_parse_push_buffer: + * gst_base_parse_push_frame: * @parse: #GstBaseParse. - * @buffer: #GstBuffer. + * @frame: #GstBaseParseFrame. * - * Pushes the buffer downstream, sends any pending events and + * Pushes the frame downstream, sends any pending events and * does some timestamp and segment handling. * - * This must be called with srcpad STREAM_LOCK held. + * This must be called with sinkpad STREAM_LOCK held. * * Returns: #GstFlowReturn */ GstFlowReturn -gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) +gst_base_parse_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { GstFlowReturn ret = GST_FLOW_OK; GstClockTime last_start = GST_CLOCK_TIME_NONE; GstClockTime last_stop = GST_CLOCK_TIME_NONE; GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse); + GstBuffer *buffer; + + g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (frame->buffer != NULL, GST_FLOW_ERROR); + + buffer = frame->buffer; GST_LOG_OBJECT (parse, "processing buffer of size %d with ts %" GST_TIME_FORMAT @@ -1505,13 +1563,12 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) /* update stats */ parse->priv->bytecount += GST_BUFFER_SIZE (buffer); - if (!GST_BUFFER_FLAG_IS_SET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME)) { + if (G_LIKELY (!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_NO_FRAME))) { parse->priv->framecount++; if (GST_BUFFER_DURATION_IS_VALID (buffer)) { parse->priv->acc_duration += GST_BUFFER_DURATION (buffer); } } - GST_BUFFER_FLAG_UNSET (buffer, GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME); if (parse->priv->update_interval && (parse->priv->framecount % parse->priv->update_interval) == 0) gst_base_parse_update_duration (parse); @@ -1525,8 +1582,6 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) /* should have caps by now */ g_return_val_if_fail (GST_PAD_CAPS (parse->srcpad), GST_FLOW_ERROR); - gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad)); - /* segment adjustment magic; only if we are running the whole show */ if (!parse->priv->passthrough && parse->segment.rate > 0.0 && (parse->priv->pad_mode == GST_ACTIVATE_PULL || @@ -1615,7 +1670,7 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) /* update bitrates and optionally post corresponding tags * (following newsegment) */ - gst_base_parse_update_bitrates (parse, buffer); + gst_base_parse_update_bitrates (parse, frame); if (G_UNLIKELY (parse->priv->pending_events)) { GList *l; @@ -1627,15 +1682,26 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) parse->priv->pending_events = NULL; } - if (klass->pre_push_buffer) - ret = klass->pre_push_buffer (parse, buffer); - else - ret = GST_BASE_PARSE_FLOW_CLIP; + if (klass->pre_push_frame) { + ret = klass->pre_push_frame (parse, frame); + } else { + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP; + } + + /* take final ownership of frame buffer */ + buffer = frame->buffer; + frame->buffer = NULL; + + /* subclass must play nice */ + g_return_val_if_fail (buffer != NULL, GST_FLOW_ERROR); + + /* decorate */ + gst_buffer_set_caps (buffer, GST_PAD_CAPS (parse->srcpad)); parse->priv->seen_keyframe |= parse->priv->is_video && !GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT); - if (ret == GST_BASE_PARSE_FLOW_CLIP) { + if (frame->flags & GST_BASE_PARSE_FRAME_FLAG_CLIP) { if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) && GST_CLOCK_TIME_IS_VALID (parse->segment.stop) && GST_BUFFER_TIMESTAMP (buffer) > @@ -1693,6 +1759,8 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer) parse->segment.last_stop < last_stop) gst_segment_set_last_stop (&parse->segment, GST_FORMAT_TIME, last_stop); + gst_base_parse_frame_clear (parse, frame); + return ret; } @@ -1879,16 +1947,19 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) const guint8 *data; guint old_min_size = 0, min_size, av; GstClockTime timestamp; + GstBaseParseFrame _frame = { 0, }; + GstBaseParseFrame *frame; parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad)); bclass = GST_BASE_PARSE_GET_CLASS (parse); + frame = &_frame; if (G_LIKELY (buffer)) { GST_LOG_OBJECT (parse, "buffer size: %d, offset = %" G_GINT64_FORMAT, GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer)); if (G_UNLIKELY (parse->priv->passthrough)) { - buffer = gst_buffer_make_metadata_writable (buffer); - return gst_base_parse_push_buffer (parse, buffer); + frame->buffer = gst_buffer_make_metadata_writable (buffer); + return gst_base_parse_push_frame (parse, frame); } /* upstream feeding us in reverse playback; * gather each fragment, then process it in single run */ @@ -1906,6 +1977,8 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) /* Parse and push as many frames as possible */ /* Stop either when adapter is empty or we are flushing */ while (!parse->priv->flushing) { + gboolean res; + tmpbuf = gst_buffer_new (); old_min_size = 0; @@ -1949,7 +2022,10 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) } skip = -1; - if (bclass->check_valid_frame (parse, tmpbuf, &fsize, &skip)) { + gst_base_parse_frame_update (parse, frame, tmpbuf); + res = bclass->check_valid_frame (parse, frame, &fsize, &skip); + gst_buffer_replace (&frame->buffer, NULL); + if (res) { if (gst_adapter_available (parse->adapter) < fsize) { GST_DEBUG_OBJECT (parse, "found valid frame but not enough data available (only %d bytes)", @@ -2031,7 +2107,8 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer) parse->priv->prev_ts = parse->priv->next_ts = timestamp; } - ret = gst_base_parse_handle_and_push_buffer (parse, bclass, outbuf); + frame->buffer = outbuf; + ret = gst_base_parse_handle_and_push_frame (parse, bclass, frame); GST_PAD_STREAM_UNLOCK (parse->srcpad); if (ret != GST_FLOW_OK) { @@ -2195,19 +2272,20 @@ exit: * ajusts sync, drain and offset going along */ static GstFlowReturn gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, - GstBuffer ** buf, gboolean full) + GstBaseParseFrame * frame, gboolean full) { GstBuffer *buffer, *outbuf; GstFlowReturn ret = GST_FLOW_OK; guint fsize = 0, min_size, old_min_size = 0; gint skip = 0; - g_return_val_if_fail (buf != NULL, GST_FLOW_ERROR); + g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR); GST_LOG_OBJECT (parse, "scanning for frame at offset %" G_GUINT64_FORMAT " (%#" G_GINT64_MODIFIER "x)", parse->priv->offset, parse->priv->offset); while (TRUE) { + gboolean res; min_size = MAX (parse->priv->min_frame_size, fsize); /* loop safety check */ @@ -2230,7 +2308,10 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, parse->priv->drain = TRUE; skip = -1; - if (klass->check_valid_frame (parse, buffer, &fsize, &skip)) { + gst_base_parse_frame_update (parse, frame, buffer); + res = klass->check_valid_frame (parse, frame, &fsize, &skip); + gst_buffer_replace (&frame->buffer, NULL); + if (res) { parse->priv->drain = FALSE; GST_LOG_OBJECT (parse, "valid frame of size %d at pos %d", fsize, skip); break; @@ -2289,7 +2370,7 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass, parse->priv->offset += fsize; - *buf = outbuf; + frame->buffer = outbuf; done: return ret; @@ -2315,8 +2396,8 @@ gst_base_parse_loop (GstPad * pad) { GstBaseParse *parse; GstBaseParseClass *klass; - GstBuffer *outbuf; GstFlowReturn ret = GST_FLOW_OK; + GstBaseParseFrame frame = { 0, }; parse = GST_BASE_PARSE (gst_pad_get_parent (pad)); klass = GST_BASE_PARSE_GET_CLASS (parse); @@ -2333,12 +2414,12 @@ gst_base_parse_loop (GstPad * pad) } } - ret = gst_base_parse_scan_frame (parse, klass, &outbuf, TRUE); + ret = gst_base_parse_scan_frame (parse, klass, &frame, TRUE); if (ret != GST_FLOW_OK) goto done; - /* This always unrefs the outbuf, even if error occurs */ - ret = gst_base_parse_handle_and_push_buffer (parse, klass, outbuf); + /* This always cleans up frame, even if error occurs */ + ret = gst_base_parse_handle_and_push_frame (parse, klass, &frame); /* eat expected eos signalling past segment in reverse playback */ if (parse->segment.rate < 0.0 && ret == GST_FLOW_UNEXPECTED && @@ -2708,48 +2789,6 @@ gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, lead_out, parse->priv->lead_out_ts / GST_MSECOND); } -/** - * gst_base_parse_get_sync: - * @parse: the #GstBaseParse to query - * - * Returns: TRUE if parser is considered 'in sync'. That is, frames have been - * continuously successfully parsed and pushed. - */ -gboolean -gst_base_parse_get_sync (GstBaseParse * parse) -{ - gboolean ret; - - g_return_val_if_fail (parse != NULL, FALSE); - - /* losing sync is pretty much a discont (and vice versa), no ? */ - ret = !parse->priv->discont; - - GST_DEBUG_OBJECT (parse, "sync: %d", ret); - return ret; -} - -/** - * gst_base_parse_get_drain: - * @parse: the #GstBaseParse to query - * - * Returns: TRUE if parser is currently 'draining'. That is, leftover data - * (e.g. in FLUSH or EOS situation) is being parsed. - */ -gboolean -gst_base_parse_get_drain (GstBaseParse * parse) -{ - gboolean ret; - - g_return_val_if_fail (parse != NULL, FALSE); - - /* losing sync is pretty much a discont (and vice versa), no ? */ - ret = parse->priv->drain; - - GST_DEBUG_OBJECT (parse, "drain: %d", ret); - return ret; -} - static gboolean gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format, GstClockTime * duration) @@ -2941,6 +2980,7 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos, gboolean orig_drain, orig_discont; GstFlowReturn ret = GST_FLOW_OK; GstBuffer *buf = NULL; + GstBaseParseFrame frame = { 0, }; g_return_val_if_fail (GST_FLOW_ERROR, pos != NULL); g_return_val_if_fail (GST_FLOW_ERROR, time != NULL); @@ -2961,10 +3001,11 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos, /* jump elsewhere and locate next frame */ parse->priv->offset = *pos; - ret = gst_base_parse_scan_frame (parse, klass, &buf, FALSE); + ret = gst_base_parse_scan_frame (parse, klass, &frame, FALSE); if (ret != GST_FLOW_OK) goto done; + buf = frame.buffer; GST_LOG_OBJECT (parse, "peek parsing frame at offset %" G_GUINT64_FORMAT " (%#" G_GINT64_MODIFIER "x) of size %d", @@ -2972,12 +3013,13 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos, /* get offset first, subclass parsing might dump other stuff in there */ *pos = GST_BUFFER_OFFSET (buf); - ret = klass->parse_frame (parse, buf); + ret = klass->parse_frame (parse, &frame); + buf = frame.buffer; /* but it should provide proper time */ *time = GST_BUFFER_TIMESTAMP (buf); *duration = GST_BUFFER_DURATION (buf); - gst_buffer_unref (buf); + gst_base_parse_frame_clear (parse, &frame); GST_LOG_OBJECT (parse, "frame with time %" GST_TIME_FORMAT " at offset %" G_GINT64_FORMAT, diff --git a/gst/audioparsers/gstbaseparse.h b/gst/audioparsers/gstbaseparse.h index 5a4b67447..d5d4415a1 100644 --- a/gst/audioparsers/gstbaseparse.h +++ b/gst/audioparsers/gstbaseparse.h @@ -90,25 +90,78 @@ G_BEGIN_DECLS #define GST_BASE_PARSE_FLOW_DROPPED GST_FLOW_CUSTOM_SUCCESS /** - * GST_BASE_PARSE_FLOW_CLIP: + * GstBaseParseFrameFlags: + * @GST_BASE_PARSE_FRAME_FLAG_NONE: no flag + * @GST_BASE_PARSE_FRAME_FLAG_SYNC: indicates if parsing is 'in sync' + * @GST_BASE_PARSE_FRAME_FLAG_DRAIN: indicates if parser is 'draining'. + * That is, leftover data (e.g. in FLUSH or EOS situation) is being parsed. + * @GST_BASE_PARSE_FRAME_FLAG_NO_FRAME: set to indicate this buffer should not be + * counted as frame, e.g. if this frame is dependent on a previous one. + * As it is not counted as a frame, bitrate increases but frame to time + * conversions are maintained. + * @GST_BASE_PARSE_FRAME_FLAG_CLIP: @pre_push_buffer can set this to indicate + * that regular segment clipping can still be performed (as opposed to + * any custom one having been done). * - * A #GstFlowReturn that can be returned from pre_push_buffer to - * indicate that regular segment clipping should be performed. + * Flags to be used in a #GstBaseParseFrame. * * Since: 0.10.x */ -#define GST_BASE_PARSE_FLOW_CLIP GST_FLOW_CUSTOM_SUCCESS_1 +typedef enum { + GST_BASE_PARSE_FRAME_FLAG_NONE = 0, + GST_BASE_PARSE_FRAME_FLAG_SYNC = (1 << 0), + GST_BASE_PARSE_FRAME_FLAG_DRAIN = (1 << 1), + GST_BASE_PARSE_FRAME_FLAG_NO_FRAME = (1 << 2), + GST_BASE_PARSE_FRAME_FLAG_CLIP = (1 << 3) +} GstBaseParseFrameFlags; /** - * GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME: + * GstBaseParseFrame: + * @buffer: data to check for valid frame or parsed frame. + * Subclass is allowed to replace this buffer. + * @overhead: subclass can set this to indicates the metadata overhead + * for the given frame, which is then used to enable more accurate bitrate + * computations. If this is -1, it is assumed that this frame should be + * skipped in bitrate calculation. + * @flags: a combination of input and output #GstBaseParseFrameFlags that + * convey additional context to subclass or allow subclass to tune + * subsequent #GstBaseParse actions. * - * A #GstBufferFlag that can be set to have this buffer not counted as frame, - * e.g. if this frame is dependent on a previous one. As it is not counted as - * a frame, bitrate increases but frame to time conversions are maintained. + * Frame (context) data passed to each frame parsing virtual methods. In + * addition to providing the data to be checked for a valid frame or an already + * identified frame, it conveys additional metadata or control information + * from and to the subclass w.r.t. the particular frame in question (rather + * than global parameters). Some of these may apply to each parsing stage, others + * only to some a particular one. These parameters are effectively zeroed at start + * of each frame's processing, i.e. parsing virtual method invocation sequence. * * Since: 0.10.x */ -#define GST_BASE_PARSE_BUFFER_FLAG_NO_FRAME GST_BUFFER_FLAG_LAST +typedef struct { + GstBuffer *buffer; + guint flags; + gint overhead; +} GstBaseParseFrame; + +/** + * GST_BASE_PARSE_FRAME_SYNC: + * @frame: base parse frame instance + * + * Obtains current sync status indicated in frame. + * + * Since: 0.10.x + */ +#define GST_BASE_PARSE_FRAME_SYNC(frame) (!!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_SYNC)) + +/** + * GST_BASE_PARSE_FRAME_DRAIN: + * @frame: base parse frame instance + * + * Obtains current drain status indicated in frame. + * + * Since: 0.10.x + */ +#define GST_BASE_PARSE_FRAME_DRAIN(frame) (!!(frame->flags & GST_BASE_PARSE_FRAME_FLAG_DRAIN)) /** @@ -118,6 +171,8 @@ G_BEGIN_DECLS * GST_BASE_PARSE_SEEK_TABLE: Additional metadata provides more accurate seeking. * * Indicates what level (of quality) of seeking is possible. + * + * Since: 0.10.x */ typedef enum _GstBaseParseSeekable { GST_BASE_PARSE_SEEK_NONE, @@ -221,12 +276,15 @@ struct _GstBaseParseClass { GstCaps *caps); gboolean (*check_valid_frame) (GstBaseParse *parse, - GstBuffer *buffer, + GstBaseParseFrame *frame, guint *framesize, gint *skipsize); GstFlowReturn (*parse_frame) (GstBaseParse *parse, - GstBuffer *buffer); + GstBaseParseFrame *frame); + + GstFlowReturn (*pre_push_frame) (GstBaseParse *parse, + GstBaseParseFrame *frame); gboolean (*convert) (GstBaseParse * parse, GstFormat src_format, @@ -240,21 +298,16 @@ struct _GstBaseParseClass { gboolean (*src_event) (GstBaseParse *parse, GstEvent *event); - gint (*get_frame_overhead) (GstBaseParse *parse, - GstBuffer *buf); - - GstFlowReturn (*pre_push_buffer) (GstBaseParse *parse, - GstBuffer *buf); - /*< private >*/ - gpointer _gst_reserved[GST_PADDING_LARGE]; + gpointer _gst_reserved[GST_PADDING_LARGE]; }; GType gst_base_parse_get_type (void); +void gst_base_parse_frame_init (GstBaseParse * parse, GstBaseParseFrame * frame); -GstFlowReturn gst_base_parse_push_buffer (GstBaseParse *parse, - GstBuffer *buffer); +GstFlowReturn gst_base_parse_push_frame (GstBaseParse *parse, + GstBaseParseFrame *frame); void gst_base_parse_set_duration (GstBaseParse *parse, GstFormat fmt, gint64 duration, gint interval); @@ -262,17 +315,13 @@ void gst_base_parse_set_duration (GstBaseParse *parse, void gst_base_parse_set_seek (GstBaseParse * parse, GstBaseParseSeekable seek, guint bitrate); -void gst_base_parse_set_min_frame_size (GstBaseParse *parse, - guint min_size); +void gst_base_parse_set_min_frame_size (GstBaseParse *parse, guint min_size); + void gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough); void gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num, guint fps_den, guint lead_in, guint lead_out); -gboolean gst_base_parse_get_sync (GstBaseParse * parse); - -gboolean gst_base_parse_get_drain (GstBaseParse * parse); - gboolean gst_base_parse_convert_default (GstBaseParse * parse, GstFormat src_format, gint64 src_value, GstFormat dest_format, gint64 * dest_value); diff --git a/gst/audioparsers/gstdcaparse.c b/gst/audioparsers/gstdcaparse.c index 4573d3bbb..8ef6acd0f 100644 --- a/gst/audioparsers/gstdcaparse.c +++ b/gst/audioparsers/gstdcaparse.c @@ -70,9 +70,9 @@ static void gst_dca_parse_finalize (GObject * object); static gboolean gst_dca_parse_start (GstBaseParse * parse); static gboolean gst_dca_parse_stop (GstBaseParse * parse); static gboolean gst_dca_parse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * size, gint * skipsize); + GstBaseParseFrame * frame, guint * size, gint * skipsize); static GstFlowReturn gst_dca_parse_parse_frame (GstBaseParse * parse, - GstBuffer * buf); + GstBaseParseFrame * frame); GST_BOILERPLATE (GstDcaParse, gst_dca_parse, GstBaseParse, GST_TYPE_BASE_PARSE); @@ -289,11 +289,12 @@ gst_dca_parse_find_sync (GstDcaParse * dcaparse, GstByteReader * reader, } static gboolean -gst_dca_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, - guint * framesize, gint * skipsize) +gst_dca_parse_check_valid_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { - GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf); GstDcaParse *dcaparse = GST_DCA_PARSE (parse); + GstBuffer *buf = frame->buffer; + GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf); gboolean parser_draining; gboolean parser_in_sync; guint32 sync = 0; @@ -303,7 +304,7 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 16)) return FALSE; - parser_in_sync = gst_base_parse_get_sync (parse); + parser_in_sync = GST_BASE_PARSE_FRAME_SYNC (frame); if (G_LIKELY (parser_in_sync && dcaparse->last_sync != 0)) { off = gst_byte_reader_masked_scan_uint32 (&r, 0xffffffff, @@ -343,7 +344,7 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, dcaparse->last_sync = sync; - parser_draining = gst_base_parse_get_drain (parse); + parser_draining = GST_BASE_PARSE_FRAME_DRAIN (frame); if (!parser_in_sync && !parser_draining) { /* check for second frame to be sure */ @@ -377,10 +378,11 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, } static GstFlowReturn -gst_dca_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf) +gst_dca_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { - GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf); GstDcaParse *dcaparse = GST_DCA_PARSE (parse); + GstBuffer *buf = frame->buffer; + GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf); guint size, rate, chans, samples; if (!gst_dca_parse_parse_header (dcaparse, &r, &size, &rate, &chans, diff --git a/gst/audioparsers/gstflacparse.c b/gst/audioparsers/gstflacparse.c index 378caf428..f991095f8 100644 --- a/gst/audioparsers/gstflacparse.c +++ b/gst/audioparsers/gstflacparse.c @@ -193,13 +193,11 @@ static void gst_flac_parse_get_property (GObject * object, guint prop_id, static gboolean gst_flac_parse_start (GstBaseParse * parse); static gboolean gst_flac_parse_stop (GstBaseParse * parse); static gboolean gst_flac_parse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize); + GstBaseParseFrame * frame, guint * framesize, gint * skipsize); static GstFlowReturn gst_flac_parse_parse_frame (GstBaseParse * parse, - GstBuffer * buffer); -static gint gst_flac_parse_get_frame_overhead (GstBaseParse * parse, - GstBuffer * buffer); -static GstFlowReturn gst_flac_parse_pre_push_buffer (GstBaseParse * parse, - GstBuffer * buf); + GstBaseParseFrame * frame); +static GstFlowReturn gst_flac_parse_pre_push_frame (GstBaseParse * parse, + GstBaseParseFrame * frame); GST_BOILERPLATE (GstFlacParse, gst_flac_parse, GstBaseParse, GST_TYPE_BASE_PARSE); @@ -244,10 +242,8 @@ gst_flac_parse_class_init (GstFlacParseClass * klass) baseparse_class->check_valid_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_check_valid_frame); baseparse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_parse_frame); - baseparse_class->get_frame_overhead = - GST_DEBUG_FUNCPTR (gst_flac_parse_get_frame_overhead); - baseparse_class->pre_push_buffer = - GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_buffer); + baseparse_class->pre_push_frame = + GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame); } static void @@ -563,15 +559,17 @@ need_more_data: } static gboolean -gst_flac_parse_frame_is_valid (GstFlacParse * flacparse, GstBuffer * buffer, - guint * ret) +gst_flac_parse_frame_is_valid (GstFlacParse * flacparse, + GstBaseParseFrame * frame, guint * ret) { + GstBuffer *buffer; const guint8 *data; guint max, size, remaining; guint i, search_start, search_end; FrameHeaderCheckReturn header_ret; guint16 block_size; + buffer = frame->buffer; data = GST_BUFFER_DATA (buffer); size = GST_BUFFER_SIZE (buffer); @@ -621,7 +619,7 @@ gst_flac_parse_frame_is_valid (GstFlacParse * flacparse, GstBuffer * buffer, } /* For the last frame output everything to the end */ - if (G_UNLIKELY (gst_base_parse_get_drain (GST_BASE_PARSE (flacparse)))) { + if (G_UNLIKELY (GST_BASE_PARSE_FRAME_DRAIN (frame))) { if (flacparse->check_frame_checksums) { guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2); guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2); @@ -648,9 +646,10 @@ need_more: static gboolean gst_flac_parse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * framesize, gint * skipsize) + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { GstFlacParse *flacparse = GST_FLAC_PARSE (parse); + GstBuffer *buffer = frame->buffer; const guint8 *data = GST_BUFFER_DATA (buffer); if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 4)) @@ -689,13 +688,13 @@ gst_flac_parse_check_valid_frame (GstBaseParse * parse, flacparse->sample_number = 0; GST_DEBUG_OBJECT (flacparse, "Found sync code"); - ret = gst_flac_parse_frame_is_valid (flacparse, buffer, &next); + ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next); if (ret) { *framesize = next; return TRUE; } else { /* If we're at EOS and the frame was not valid, drop it! */ - if (G_UNLIKELY (gst_base_parse_get_drain (parse))) { + if (G_UNLIKELY (GST_BASE_PARSE_FRAME_DRAIN (frame))) { GST_WARNING_OBJECT (flacparse, "EOS"); return FALSE; } @@ -1044,6 +1043,7 @@ push_headers: while (flacparse->headers) { GstBuffer *buf = GST_BUFFER (flacparse->headers->data); GstFlowReturn ret; + GstBaseParseFrame frame; flacparse->headers = g_list_delete_link (flacparse->headers, flacparse->headers); @@ -1051,7 +1051,11 @@ push_headers: gst_buffer_set_caps (buf, GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse)))); - ret = gst_base_parse_push_buffer (GST_BASE_PARSE (flacparse), buf); + /* init, set and give away frame */ + gst_base_parse_frame_init (GST_BASE_PARSE (flacparse), &frame); + frame.buffer = buf; + frame.overhead = -1; + ret = gst_base_parse_push_frame (GST_BASE_PARSE (flacparse), &frame); if (ret != GST_FLOW_OK) { res = FALSE; break; @@ -1175,9 +1179,10 @@ gst_flac_parse_generate_headers (GstFlacParse * flacparse) } static GstFlowReturn -gst_flac_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) +gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { GstFlacParse *flacparse = GST_FLAC_PARSE (parse); + GstBuffer *buffer = frame->buffer; const guint8 *data = GST_BUFFER_DATA (buffer); if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) { @@ -1312,6 +1317,11 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) GST_BUFFER_DURATION (buffer) = GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (buffer); + /* To simplify, we just assume that it's a fixed size header and ignore + * subframe headers. The first could lead us to being off by 88 bits and + * the second even less, so the total inaccuracy is negligible. */ + frame->overhead = 7; + /* Minimal size of a frame header */ gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9, flacparse->min_framesize)); @@ -1324,22 +1334,8 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBuffer * buffer) } } -static gint -gst_flac_parse_get_frame_overhead (GstBaseParse * parse, GstBuffer * buffer) -{ - GstFlacParse *flacparse = GST_FLAC_PARSE (parse); - - if (flacparse->state != GST_FLAC_PARSE_STATE_DATA) - return -1; - else - /* To simplify, we just assume that it's a fixed size header and ignore - * subframe headers. The first could lead us to being off by 88 bits and - * the second even less, so the total inaccuracy is negligible. */ - return 7; -} - static GstFlowReturn -gst_flac_parse_pre_push_buffer (GstBaseParse * parse, GstBuffer * buf) +gst_flac_parse_pre_push_frame (GstBaseParse * parse, GstBaseParseFrame * frame) { GstFlacParse *flacparse = GST_FLAC_PARSE (parse); @@ -1349,5 +1345,7 @@ gst_flac_parse_pre_push_buffer (GstBaseParse * parse, GstBuffer * buf) flacparse->tags = NULL; } - return GST_BASE_PARSE_FLOW_CLIP; + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP; + + return GST_FLOW_OK; } diff --git a/gst/audioparsers/gstmpegaudioparse.c b/gst/audioparsers/gstmpegaudioparse.c index 889efec1f..d95f8aeaa 100644 --- a/gst/audioparsers/gstmpegaudioparse.c +++ b/gst/audioparsers/gstmpegaudioparse.c @@ -82,11 +82,11 @@ static void gst_mpeg_audio_parse_finalize (GObject * object); static gboolean gst_mpeg_audio_parse_start (GstBaseParse * parse); static gboolean gst_mpeg_audio_parse_stop (GstBaseParse * parse); static gboolean gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse, - GstBuffer * buffer, guint * size, gint * skipsize); + GstBaseParseFrame * frame, guint * size, gint * skipsize); static GstFlowReturn gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse, - GstBuffer * buf); -static GstFlowReturn gst_mpeg_audio_parse_pre_push_buffer (GstBaseParse * parse, - GstBuffer * buf); + GstBaseParseFrame * frame); +static GstFlowReturn gst_mpeg_audio_parse_pre_push_frame (GstBaseParse * parse, + GstBaseParseFrame * frame); static gboolean gst_mpeg_audio_parse_convert (GstBaseParse * parse, GstFormat src_format, gint64 src_value, GstFormat dest_format, gint64 * dest_value); @@ -164,8 +164,8 @@ gst_mpeg_audio_parse_class_init (GstMpegAudioParseClass * klass) GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_check_valid_frame); parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_parse_frame); - parse_class->pre_push_buffer = - GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_pre_push_buffer); + parse_class->pre_push_frame = + GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_pre_push_frame); parse_class->convert = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_convert); /* register tags */ @@ -470,11 +470,12 @@ gst_mpeg_audio_parse_head_check (GstMpegAudioParse * mp3parse, } static gboolean -gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, - guint * framesize, gint * skipsize) +gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse, + GstBaseParseFrame * frame, guint * framesize, gint * skipsize) { - GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf); GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse); + GstBuffer *buf = frame->buffer; + GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf); gint off, bpf; gboolean sync, drain, valid, caps_change; guint32 header; @@ -519,8 +520,8 @@ gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf, else caps_change = FALSE; - sync = gst_base_parse_get_sync (parse); - drain = gst_base_parse_get_drain (parse); + sync = GST_BASE_PARSE_FRAME_SYNC (frame); + drain = GST_BASE_PARSE_FRAME_DRAIN (frame); if (!drain && (!sync || caps_change)) { if (!gst_mp3parse_validate_extended (mp3parse, buf, header, bpf, drain, @@ -900,9 +901,11 @@ gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse * mp3parse, } static GstFlowReturn -gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf) +gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse, + GstBaseParseFrame * frame) { GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse); + GstBuffer *buf = frame->buffer; guint bitrate, layer, rate, channels, version, mode, crc; g_return_val_if_fail (GST_BUFFER_SIZE (buf) >= 4, GST_FLOW_ERROR); @@ -1122,7 +1125,8 @@ gst_mpeg_audio_parse_convert (GstBaseParse * parse, GstFormat src_format, } static GstFlowReturn -gst_mpeg_audio_parse_pre_push_buffer (GstBaseParse * parse, GstBuffer * buf) +gst_mpeg_audio_parse_pre_push_frame (GstBaseParse * parse, + GstBaseParseFrame * frame) { GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse); GstTagList *taglist; @@ -1188,5 +1192,7 @@ gst_mpeg_audio_parse_pre_push_buffer (GstBaseParse * parse, GstBuffer * buf) } /* usual clipping applies */ - return GST_BASE_PARSE_FLOW_CLIP; + frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP; + + return GST_FLOW_OK; } -- cgit v1.2.3