Commit 4163969a authored by Mark Nauwelaerts's avatar Mark Nauwelaerts Committed by Tim-Philipp Müller

baseparse: introduce a baseparse frame to serve as context

... and adjust subclass parsers accordingly
parent b45821c8
......@@ -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;
}
......@@ -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
......
......@@ -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;
}
......
This diff is collapsed.
......@@ -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);
......
......@@ -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,
......
......@@ -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;
}
......@@ -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,