mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2025-01-11 09:55:36 +00:00
baseparse: introduce a baseparse frame to serve as context
... and adjust subclass parsers accordingly
This commit is contained in:
parent
b45821c83f
commit
4163969a24
8 changed files with 324 additions and 234 deletions
|
@ -77,10 +77,10 @@ static gboolean gst_aacparse_sink_setcaps (GstBaseParse * parse,
|
||||||
GstCaps * caps);
|
GstCaps * caps);
|
||||||
|
|
||||||
gboolean gst_aacparse_check_valid_frame (GstBaseParse * parse,
|
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,
|
GstFlowReturn gst_aacparse_parse_frame (GstBaseParse * parse,
|
||||||
GstBuffer * buffer);
|
GstBaseParseFrame * frame);
|
||||||
|
|
||||||
gboolean gst_aacparse_convert (GstBaseParse * parse,
|
gboolean gst_aacparse_convert (GstBaseParse * parse,
|
||||||
GstFormat src_format,
|
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->parse_frame = GST_DEBUG_FUNCPTR (gst_aacparse_parse_frame);
|
||||||
parse_class->check_valid_frame =
|
parse_class->check_valid_frame =
|
||||||
GST_DEBUG_FUNCPTR (gst_aacparse_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
|
static gboolean
|
||||||
gst_aacparse_check_adts_frame (GstAacParse * aacparse,
|
gst_aacparse_check_adts_frame (GstAacParse * aacparse,
|
||||||
const guint8 * data,
|
const guint8 * data, const guint avail, gboolean drain,
|
||||||
const guint avail, guint * framesize, guint * needed_data)
|
guint * framesize, guint * needed_data)
|
||||||
{
|
{
|
||||||
if (G_UNLIKELY (avail < 2))
|
if (G_UNLIKELY (avail < 2))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
@ -340,7 +338,7 @@ gst_aacparse_check_adts_frame (GstAacParse * aacparse,
|
||||||
*framesize = gst_aacparse_adts_get_frame_len (data);
|
*framesize = gst_aacparse_adts_get_frame_len (data);
|
||||||
|
|
||||||
/* In EOS mode this is enough. No need to examine the data further */
|
/* 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;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -408,7 +406,8 @@ gst_aacparse_parse_adts_header (GstAacParse * aacparse, const guint8 * data,
|
||||||
*/
|
*/
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_aacparse_detect_stream (GstAacParse * aacparse,
|
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;
|
gboolean found = FALSE;
|
||||||
guint need_data = 0;
|
guint need_data = 0;
|
||||||
|
@ -444,7 +443,7 @@ gst_aacparse_detect_stream (GstAacParse * aacparse,
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (gst_aacparse_check_adts_frame (aacparse, data, avail,
|
if (gst_aacparse_check_adts_frame (aacparse, data, avail, drain,
|
||||||
framesize, &need_data)) {
|
framesize, &need_data)) {
|
||||||
gint rate, channels;
|
gint rate, channels;
|
||||||
|
|
||||||
|
@ -568,17 +567,19 @@ gst_aacparse_detect_stream (GstAacParse * aacparse,
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
gst_aacparse_check_valid_frame (GstBaseParse * parse,
|
gst_aacparse_check_valid_frame (GstBaseParse * parse,
|
||||||
GstBuffer * buffer, guint * framesize, gint * skipsize)
|
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
||||||
{
|
{
|
||||||
const guint8 *data;
|
const guint8 *data;
|
||||||
GstAacParse *aacparse;
|
GstAacParse *aacparse;
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
gboolean sync;
|
gboolean sync;
|
||||||
|
GstBuffer *buffer;
|
||||||
|
|
||||||
aacparse = GST_AACPARSE (parse);
|
aacparse = GST_AACPARSE (parse);
|
||||||
|
buffer = frame->buffer;
|
||||||
data = GST_BUFFER_DATA (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 ||
|
if (aacparse->header_type == DSPAAC_HEADER_ADIF ||
|
||||||
aacparse->header_type == DSPAAC_HEADER_NONE) {
|
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) {
|
} else if (aacparse->header_type == DSPAAC_HEADER_NOT_PARSED || sync == FALSE) {
|
||||||
|
|
||||||
ret = gst_aacparse_detect_stream (aacparse, data, GST_BUFFER_SIZE (buffer),
|
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) {
|
} else if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
|
||||||
guint needed_data = 1024;
|
guint needed_data = 1024;
|
||||||
|
|
||||||
ret = gst_aacparse_check_adts_frame (aacparse, data,
|
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) {
|
if (!ret) {
|
||||||
GST_DEBUG ("buffer didn't contain valid frame");
|
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.
|
* 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
|
* Returns: GST_FLOW_OK if frame was successfully parsed and can be pushed
|
||||||
* forward. Otherwise appropriate error is returned.
|
* forward. Otherwise appropriate error is returned.
|
||||||
*/
|
*/
|
||||||
GstFlowReturn
|
GstFlowReturn
|
||||||
gst_aacparse_parse_frame (GstBaseParse * parse, GstBuffer * buffer)
|
gst_aacparse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||||
{
|
{
|
||||||
GstAacParse *aacparse;
|
GstAacParse *aacparse;
|
||||||
|
GstBuffer *buffer;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
gint rate, channels;
|
gint rate, channels;
|
||||||
|
|
||||||
aacparse = GST_AACPARSE (parse);
|
aacparse = GST_AACPARSE (parse);
|
||||||
|
buffer = frame->buffer;
|
||||||
|
|
||||||
if (G_UNLIKELY (aacparse->header_type != DSPAAC_HEADER_ADTS))
|
if (G_UNLIKELY (aacparse->header_type != DSPAAC_HEADER_ADTS))
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
/* see above */
|
||||||
|
frame->overhead = 7;
|
||||||
|
|
||||||
gst_aacparse_parse_adts_header (aacparse, GST_BUFFER_DATA (buffer),
|
gst_aacparse_parse_adts_header (aacparse, GST_BUFFER_DATA (buffer),
|
||||||
&rate, &channels, NULL, NULL);
|
&rate, &channels, NULL, NULL);
|
||||||
GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
|
GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
|
||||||
|
@ -692,33 +712,3 @@ gst_aacparse_stop (GstBaseParse * parse)
|
||||||
GST_DEBUG ("stop");
|
GST_DEBUG ("stop");
|
||||||
return TRUE;
|
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_start (GstBaseParse * parse);
|
||||||
static gboolean gst_ac3_parse_stop (GstBaseParse * parse);
|
static gboolean gst_ac3_parse_stop (GstBaseParse * parse);
|
||||||
static gboolean gst_ac3_parse_check_valid_frame (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,
|
static GstFlowReturn gst_ac3_parse_parse_frame (GstBaseParse * parse,
|
||||||
GstBuffer * buf);
|
GstBaseParseFrame * frame);
|
||||||
|
|
||||||
GST_BOILERPLATE (GstAc3Parse, gst_ac3_parse, GstBaseParse, GST_TYPE_BASE_PARSE);
|
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
|
static gboolean
|
||||||
gst_ac3_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
|
gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
|
||||||
guint * framesize, gint * skipsize)
|
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
||||||
{
|
{
|
||||||
GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
|
|
||||||
GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
|
GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
|
||||||
|
GstBuffer *buf = frame->buffer;
|
||||||
|
GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
|
||||||
gint off;
|
gint off;
|
||||||
gboolean sync, drain;
|
gboolean sync, drain;
|
||||||
|
|
||||||
|
@ -421,8 +422,8 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
|
||||||
|
|
||||||
GST_LOG_OBJECT (parse, "got frame");
|
GST_LOG_OBJECT (parse, "got frame");
|
||||||
|
|
||||||
sync = gst_base_parse_get_sync (parse);
|
sync = GST_BASE_PARSE_FRAME_SYNC (frame);
|
||||||
drain = gst_base_parse_get_drain (parse);
|
drain = GST_BASE_PARSE_FRAME_DRAIN (frame);
|
||||||
|
|
||||||
if (!sync && !drain) {
|
if (!sync && !drain) {
|
||||||
guint16 word = 0;
|
guint16 word = 0;
|
||||||
|
@ -451,9 +452,10 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
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);
|
GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
|
||||||
|
GstBuffer *buf = frame->buffer;
|
||||||
guint fsize, rate, chans, blocks, sid;
|
guint fsize, rate, chans, blocks, sid;
|
||||||
gboolean eac;
|
gboolean eac;
|
||||||
|
|
||||||
|
@ -465,7 +467,7 @@ gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBuffer * buf)
|
||||||
|
|
||||||
if (G_UNLIKELY (sid)) {
|
if (G_UNLIKELY (sid)) {
|
||||||
GST_LOG_OBJECT (parse, "sid: %d", 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
|
if (G_UNLIKELY (ac3parse->sample_rate != rate || ac3parse->channels != chans
|
||||||
|
|
|
@ -78,10 +78,10 @@ static gboolean gst_amrparse_sink_setcaps (GstBaseParse * parse,
|
||||||
GstCaps * caps);
|
GstCaps * caps);
|
||||||
|
|
||||||
gboolean gst_amrparse_check_valid_frame (GstBaseParse * parse,
|
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,
|
GstFlowReturn gst_amrparse_parse_frame (GstBaseParse * parse,
|
||||||
GstBuffer * buffer);
|
GstBaseParseFrame * frame);
|
||||||
|
|
||||||
#define _do_init(bla) \
|
#define _do_init(bla) \
|
||||||
GST_DEBUG_CATEGORY_INIT (gst_amrparse_debug, "amrparse", 0, \
|
GST_DEBUG_CATEGORY_INIT (gst_amrparse_debug, "amrparse", 0, \
|
||||||
|
@ -267,13 +267,15 @@ gst_amrparse_parse_header (GstAmrParse * amrparse,
|
||||||
*/
|
*/
|
||||||
gboolean
|
gboolean
|
||||||
gst_amrparse_check_valid_frame (GstBaseParse * parse,
|
gst_amrparse_check_valid_frame (GstBaseParse * parse,
|
||||||
GstBuffer * buffer, guint * framesize, gint * skipsize)
|
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
||||||
{
|
{
|
||||||
|
GstBuffer *buffer;
|
||||||
const guint8 *data;
|
const guint8 *data;
|
||||||
gint fsize, mode, dsize;
|
gint fsize, mode, dsize;
|
||||||
GstAmrParse *amrparse;
|
GstAmrParse *amrparse;
|
||||||
|
|
||||||
amrparse = GST_AMRPARSE (parse);
|
amrparse = GST_AMRPARSE (parse);
|
||||||
|
buffer = frame->buffer;
|
||||||
data = GST_BUFFER_DATA (buffer);
|
data = GST_BUFFER_DATA (buffer);
|
||||||
dsize = GST_BUFFER_SIZE (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
|
* to contain a valid header as well (and there is enough data to
|
||||||
* perform this check)
|
* perform this check)
|
||||||
*/
|
*/
|
||||||
if (gst_base_parse_get_sync (parse) || gst_base_parse_get_drain (parse) ||
|
if (GST_BASE_PARSE_FRAME_SYNC (frame) || GST_BASE_PARSE_FRAME_DRAIN (frame)
|
||||||
(dsize >= fsize && (data[fsize] & 0x83) == 0)) {
|
|| (dsize >= fsize && (data[fsize] & 0x83) == 0)) {
|
||||||
*framesize = fsize;
|
*framesize = fsize;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -327,9 +329,8 @@ gst_amrparse_check_valid_frame (GstBaseParse * parse,
|
||||||
* Returns: #GstFlowReturn defining the parsing status.
|
* Returns: #GstFlowReturn defining the parsing status.
|
||||||
*/
|
*/
|
||||||
GstFlowReturn
|
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;
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -352,10 +352,9 @@ static GstFlowReturn gst_base_parse_chain (GstPad * pad, GstBuffer * buffer);
|
||||||
static void gst_base_parse_loop (GstPad * pad);
|
static void gst_base_parse_loop (GstPad * pad);
|
||||||
|
|
||||||
static gboolean gst_base_parse_check_frame (GstBaseParse * parse,
|
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,
|
static GstFlowReturn gst_base_parse_parse_frame (GstBaseParse * parse,
|
||||||
GstBuffer * buffer);
|
GstBaseParseFrame * frame);
|
||||||
|
|
||||||
static gboolean gst_base_parse_sink_eventfunc (GstBaseParse * parse,
|
static gboolean gst_base_parse_sink_eventfunc (GstBaseParse * parse,
|
||||||
GstEvent * event);
|
GstEvent * event);
|
||||||
|
@ -504,6 +503,49 @@ gst_base_parse_init (GstBaseParse * parse, GstBaseParseClass * bclass)
|
||||||
GST_DEBUG_OBJECT (parse, "init ok");
|
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
|
static void
|
||||||
gst_base_parse_reset (GstBaseParse * parse)
|
gst_base_parse_reset (GstBaseParse * parse)
|
||||||
{
|
{
|
||||||
|
@ -587,9 +629,9 @@ gst_base_parse_reset (GstBaseParse * parse)
|
||||||
*/
|
*/
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_base_parse_check_frame (GstBaseParse * parse,
|
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;
|
*skipsize = 0;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -603,8 +645,10 @@ gst_base_parse_check_frame (GstBaseParse * parse,
|
||||||
* Default callback for parse_frame.
|
* Default callback for parse_frame.
|
||||||
*/
|
*/
|
||||||
static GstFlowReturn
|
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) &&
|
if (!GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
|
||||||
GST_CLOCK_TIME_IS_VALID (parse->priv->next_ts)) {
|
GST_CLOCK_TIME_IS_VALID (parse->priv->next_ts)) {
|
||||||
GST_BUFFER_TIMESTAMP (buffer) = 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.
|
* running average bitrate of the stream so far.
|
||||||
*/
|
*/
|
||||||
static void
|
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 */
|
/* Only update the tag on a 10 kbps delta */
|
||||||
static const gint update_threshold = 10000;
|
static const gint update_threshold = 10000;
|
||||||
|
|
||||||
GstBaseParseClass *klass;
|
GstBaseParseClass *klass;
|
||||||
guint64 data_len, frame_dur;
|
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;
|
gboolean update_min = FALSE, update_avg = FALSE, update_max = FALSE;
|
||||||
|
GstBuffer *buffer = frame->buffer;
|
||||||
|
|
||||||
klass = GST_BASE_PARSE_GET_CLASS (parse);
|
klass = GST_BASE_PARSE_GET_CLASS (parse);
|
||||||
|
|
||||||
if (klass->get_frame_overhead) {
|
overhead = frame->overhead;
|
||||||
overhead = klass->get_frame_overhead (parse, buffer);
|
if (overhead == -1)
|
||||||
if (overhead == -1)
|
return;
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
data_len = GST_BUFFER_SIZE (buffer) - overhead;
|
data_len = GST_BUFFER_SIZE (buffer) - overhead;
|
||||||
parse->priv->data_bytecount += data_len;
|
parse->priv->data_bytecount += data_len;
|
||||||
|
@ -1391,11 +1434,16 @@ gst_base_parse_check_media (GstBaseParse * parse)
|
||||||
* Returns: #GstFlowReturn
|
* Returns: #GstFlowReturn
|
||||||
*/
|
*/
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_base_parse_handle_and_push_buffer (GstBaseParse * parse,
|
gst_base_parse_handle_and_push_frame (GstBaseParse * parse,
|
||||||
GstBaseParseClass * klass, GstBuffer * buffer)
|
GstBaseParseClass * klass, GstBaseParseFrame * frame)
|
||||||
{
|
{
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
gint64 offset;
|
gint64 offset;
|
||||||
|
GstBuffer *buffer;
|
||||||
|
|
||||||
|
g_return_val_if_fail (frame != NULL, GST_FLOW_ERROR);
|
||||||
|
|
||||||
|
buffer = frame->buffer;
|
||||||
|
|
||||||
if (parse->priv->discont) {
|
if (parse->priv->discont) {
|
||||||
GST_DEBUG_OBJECT (parse, "marking 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 */
|
/* store offset as it might get overwritten */
|
||||||
offset = GST_BUFFER_OFFSET (buffer);
|
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.
|
/* check initial frame to determine if subclass/format can provide ts.
|
||||||
* If so, that allows and enables extra seek and duration determining options */
|
* 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 */
|
/* 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) &&
|
if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
|
||||||
GST_BUFFER_DURATION_IS_VALID (buffer)) {
|
GST_BUFFER_DURATION_IS_VALID (buffer)) {
|
||||||
parse->priv->next_ts =
|
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 */
|
* frames to decide on the format and queues them internally */
|
||||||
/* convert internal flow to OK and mark discont for the next buffer. */
|
/* convert internal flow to OK and mark discont for the next buffer. */
|
||||||
if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
|
if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
|
||||||
gst_buffer_unref (buffer);
|
gst_base_parse_frame_clear (parse, frame);
|
||||||
return GST_FLOW_OK;
|
return GST_FLOW_OK;
|
||||||
} else if (ret != GST_FLOW_OK) {
|
} else if (ret != GST_FLOW_OK) {
|
||||||
return ret;
|
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.
|
* @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.
|
* 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
|
* Returns: #GstFlowReturn
|
||||||
*/
|
*/
|
||||||
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;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
GstClockTime last_start = GST_CLOCK_TIME_NONE;
|
GstClockTime last_start = GST_CLOCK_TIME_NONE;
|
||||||
GstClockTime last_stop = GST_CLOCK_TIME_NONE;
|
GstClockTime last_stop = GST_CLOCK_TIME_NONE;
|
||||||
GstBaseParseClass *klass = GST_BASE_PARSE_GET_CLASS (parse);
|
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,
|
GST_LOG_OBJECT (parse,
|
||||||
"processing buffer of size %d with ts %" GST_TIME_FORMAT
|
"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 */
|
/* update stats */
|
||||||
parse->priv->bytecount += GST_BUFFER_SIZE (buffer);
|
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++;
|
parse->priv->framecount++;
|
||||||
if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
|
if (GST_BUFFER_DURATION_IS_VALID (buffer)) {
|
||||||
parse->priv->acc_duration += GST_BUFFER_DURATION (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 &&
|
if (parse->priv->update_interval &&
|
||||||
(parse->priv->framecount % parse->priv->update_interval) == 0)
|
(parse->priv->framecount % parse->priv->update_interval) == 0)
|
||||||
gst_base_parse_update_duration (parse);
|
gst_base_parse_update_duration (parse);
|
||||||
|
@ -1525,8 +1582,6 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
|
||||||
/* should have caps by now */
|
/* should have caps by now */
|
||||||
g_return_val_if_fail (GST_PAD_CAPS (parse->srcpad), GST_FLOW_ERROR);
|
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 */
|
/* segment adjustment magic; only if we are running the whole show */
|
||||||
if (!parse->priv->passthrough && parse->segment.rate > 0.0 &&
|
if (!parse->priv->passthrough && parse->segment.rate > 0.0 &&
|
||||||
(parse->priv->pad_mode == GST_ACTIVATE_PULL ||
|
(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
|
/* update bitrates and optionally post corresponding tags
|
||||||
* (following newsegment) */
|
* (following newsegment) */
|
||||||
gst_base_parse_update_bitrates (parse, buffer);
|
gst_base_parse_update_bitrates (parse, frame);
|
||||||
|
|
||||||
if (G_UNLIKELY (parse->priv->pending_events)) {
|
if (G_UNLIKELY (parse->priv->pending_events)) {
|
||||||
GList *l;
|
GList *l;
|
||||||
|
@ -1627,15 +1682,26 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
|
||||||
parse->priv->pending_events = NULL;
|
parse->priv->pending_events = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (klass->pre_push_buffer)
|
if (klass->pre_push_frame) {
|
||||||
ret = klass->pre_push_buffer (parse, buffer);
|
ret = klass->pre_push_frame (parse, frame);
|
||||||
else
|
} else {
|
||||||
ret = GST_BASE_PARSE_FLOW_CLIP;
|
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 &&
|
parse->priv->seen_keyframe |= parse->priv->is_video &&
|
||||||
!GST_BUFFER_FLAG_IS_SET (buffer, GST_BUFFER_FLAG_DELTA_UNIT);
|
!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) &&
|
if (GST_BUFFER_TIMESTAMP_IS_VALID (buffer) &&
|
||||||
GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
|
GST_CLOCK_TIME_IS_VALID (parse->segment.stop) &&
|
||||||
GST_BUFFER_TIMESTAMP (buffer) >
|
GST_BUFFER_TIMESTAMP (buffer) >
|
||||||
|
@ -1693,6 +1759,8 @@ gst_base_parse_push_buffer (GstBaseParse * parse, GstBuffer * buffer)
|
||||||
parse->segment.last_stop < last_stop)
|
parse->segment.last_stop < last_stop)
|
||||||
gst_segment_set_last_stop (&parse->segment, GST_FORMAT_TIME, last_stop);
|
gst_segment_set_last_stop (&parse->segment, GST_FORMAT_TIME, last_stop);
|
||||||
|
|
||||||
|
gst_base_parse_frame_clear (parse, frame);
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1879,16 +1947,19 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
const guint8 *data;
|
const guint8 *data;
|
||||||
guint old_min_size = 0, min_size, av;
|
guint old_min_size = 0, min_size, av;
|
||||||
GstClockTime timestamp;
|
GstClockTime timestamp;
|
||||||
|
GstBaseParseFrame _frame = { 0, };
|
||||||
|
GstBaseParseFrame *frame;
|
||||||
|
|
||||||
parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad));
|
parse = GST_BASE_PARSE (GST_OBJECT_PARENT (pad));
|
||||||
bclass = GST_BASE_PARSE_GET_CLASS (parse);
|
bclass = GST_BASE_PARSE_GET_CLASS (parse);
|
||||||
|
frame = &_frame;
|
||||||
|
|
||||||
if (G_LIKELY (buffer)) {
|
if (G_LIKELY (buffer)) {
|
||||||
GST_LOG_OBJECT (parse, "buffer size: %d, offset = %" G_GINT64_FORMAT,
|
GST_LOG_OBJECT (parse, "buffer size: %d, offset = %" G_GINT64_FORMAT,
|
||||||
GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer));
|
GST_BUFFER_SIZE (buffer), GST_BUFFER_OFFSET (buffer));
|
||||||
if (G_UNLIKELY (parse->priv->passthrough)) {
|
if (G_UNLIKELY (parse->priv->passthrough)) {
|
||||||
buffer = gst_buffer_make_metadata_writable (buffer);
|
frame->buffer = gst_buffer_make_metadata_writable (buffer);
|
||||||
return gst_base_parse_push_buffer (parse, buffer);
|
return gst_base_parse_push_frame (parse, frame);
|
||||||
}
|
}
|
||||||
/* upstream feeding us in reverse playback;
|
/* upstream feeding us in reverse playback;
|
||||||
* gather each fragment, then process it in single run */
|
* 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 */
|
/* Parse and push as many frames as possible */
|
||||||
/* Stop either when adapter is empty or we are flushing */
|
/* Stop either when adapter is empty or we are flushing */
|
||||||
while (!parse->priv->flushing) {
|
while (!parse->priv->flushing) {
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
tmpbuf = gst_buffer_new ();
|
tmpbuf = gst_buffer_new ();
|
||||||
|
|
||||||
old_min_size = 0;
|
old_min_size = 0;
|
||||||
|
@ -1949,7 +2022,10 @@ gst_base_parse_chain (GstPad * pad, GstBuffer * buffer)
|
||||||
}
|
}
|
||||||
|
|
||||||
skip = -1;
|
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) {
|
if (gst_adapter_available (parse->adapter) < fsize) {
|
||||||
GST_DEBUG_OBJECT (parse,
|
GST_DEBUG_OBJECT (parse,
|
||||||
"found valid frame but not enough data available (only %d bytes)",
|
"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;
|
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);
|
GST_PAD_STREAM_UNLOCK (parse->srcpad);
|
||||||
|
|
||||||
if (ret != GST_FLOW_OK) {
|
if (ret != GST_FLOW_OK) {
|
||||||
|
@ -2195,19 +2272,20 @@ exit:
|
||||||
* ajusts sync, drain and offset going along */
|
* ajusts sync, drain and offset going along */
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
|
gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
|
||||||
GstBuffer ** buf, gboolean full)
|
GstBaseParseFrame * frame, gboolean full)
|
||||||
{
|
{
|
||||||
GstBuffer *buffer, *outbuf;
|
GstBuffer *buffer, *outbuf;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
guint fsize = 0, min_size, old_min_size = 0;
|
guint fsize = 0, min_size, old_min_size = 0;
|
||||||
gint skip = 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
|
GST_LOG_OBJECT (parse, "scanning for frame at offset %" G_GUINT64_FORMAT
|
||||||
" (%#" G_GINT64_MODIFIER "x)", parse->priv->offset, parse->priv->offset);
|
" (%#" G_GINT64_MODIFIER "x)", parse->priv->offset, parse->priv->offset);
|
||||||
|
|
||||||
while (TRUE) {
|
while (TRUE) {
|
||||||
|
gboolean res;
|
||||||
|
|
||||||
min_size = MAX (parse->priv->min_frame_size, fsize);
|
min_size = MAX (parse->priv->min_frame_size, fsize);
|
||||||
/* loop safety check */
|
/* loop safety check */
|
||||||
|
@ -2230,7 +2308,10 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
|
||||||
parse->priv->drain = TRUE;
|
parse->priv->drain = TRUE;
|
||||||
|
|
||||||
skip = -1;
|
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;
|
parse->priv->drain = FALSE;
|
||||||
GST_LOG_OBJECT (parse, "valid frame of size %d at pos %d", fsize, skip);
|
GST_LOG_OBJECT (parse, "valid frame of size %d at pos %d", fsize, skip);
|
||||||
break;
|
break;
|
||||||
|
@ -2289,7 +2370,7 @@ gst_base_parse_scan_frame (GstBaseParse * parse, GstBaseParseClass * klass,
|
||||||
|
|
||||||
parse->priv->offset += fsize;
|
parse->priv->offset += fsize;
|
||||||
|
|
||||||
*buf = outbuf;
|
frame->buffer = outbuf;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -2315,8 +2396,8 @@ gst_base_parse_loop (GstPad * pad)
|
||||||
{
|
{
|
||||||
GstBaseParse *parse;
|
GstBaseParse *parse;
|
||||||
GstBaseParseClass *klass;
|
GstBaseParseClass *klass;
|
||||||
GstBuffer *outbuf;
|
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
GstBaseParseFrame frame = { 0, };
|
||||||
|
|
||||||
parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
|
parse = GST_BASE_PARSE (gst_pad_get_parent (pad));
|
||||||
klass = GST_BASE_PARSE_GET_CLASS (parse);
|
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)
|
if (ret != GST_FLOW_OK)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
/* This always unrefs the outbuf, even if error occurs */
|
/* This always cleans up frame, even if error occurs */
|
||||||
ret = gst_base_parse_handle_and_push_buffer (parse, klass, outbuf);
|
ret = gst_base_parse_handle_and_push_frame (parse, klass, &frame);
|
||||||
|
|
||||||
/* eat expected eos signalling past segment in reverse playback */
|
/* eat expected eos signalling past segment in reverse playback */
|
||||||
if (parse->segment.rate < 0.0 && ret == GST_FLOW_UNEXPECTED &&
|
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);
|
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
|
static gboolean
|
||||||
gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format,
|
gst_base_parse_get_duration (GstBaseParse * parse, GstFormat format,
|
||||||
GstClockTime * duration)
|
GstClockTime * duration)
|
||||||
|
@ -2941,6 +2980,7 @@ gst_base_parse_find_frame (GstBaseParse * parse, gint64 * pos,
|
||||||
gboolean orig_drain, orig_discont;
|
gboolean orig_drain, orig_discont;
|
||||||
GstFlowReturn ret = GST_FLOW_OK;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
GstBuffer *buf = NULL;
|
GstBuffer *buf = NULL;
|
||||||
|
GstBaseParseFrame frame = { 0, };
|
||||||
|
|
||||||
g_return_val_if_fail (GST_FLOW_ERROR, pos != NULL);
|
g_return_val_if_fail (GST_FLOW_ERROR, pos != NULL);
|
||||||
g_return_val_if_fail (GST_FLOW_ERROR, time != 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 */
|
/* jump elsewhere and locate next frame */
|
||||||
parse->priv->offset = *pos;
|
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)
|
if (ret != GST_FLOW_OK)
|
||||||
goto done;
|
goto done;
|
||||||
|
|
||||||
|
buf = frame.buffer;
|
||||||
GST_LOG_OBJECT (parse,
|
GST_LOG_OBJECT (parse,
|
||||||
"peek parsing frame at offset %" G_GUINT64_FORMAT
|
"peek parsing frame at offset %" G_GUINT64_FORMAT
|
||||||
" (%#" G_GINT64_MODIFIER "x) of size %d",
|
" (%#" 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 */
|
/* get offset first, subclass parsing might dump other stuff in there */
|
||||||
*pos = GST_BUFFER_OFFSET (buf);
|
*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 */
|
/* but it should provide proper time */
|
||||||
*time = GST_BUFFER_TIMESTAMP (buf);
|
*time = GST_BUFFER_TIMESTAMP (buf);
|
||||||
*duration = GST_BUFFER_DURATION (buf);
|
*duration = GST_BUFFER_DURATION (buf);
|
||||||
gst_buffer_unref (buf);
|
gst_base_parse_frame_clear (parse, &frame);
|
||||||
|
|
||||||
GST_LOG_OBJECT (parse,
|
GST_LOG_OBJECT (parse,
|
||||||
"frame with time %" GST_TIME_FORMAT " at offset %" G_GINT64_FORMAT,
|
"frame with time %" GST_TIME_FORMAT " at offset %" G_GINT64_FORMAT,
|
||||||
|
|
|
@ -90,25 +90,78 @@ G_BEGIN_DECLS
|
||||||
#define GST_BASE_PARSE_FLOW_DROPPED GST_FLOW_CUSTOM_SUCCESS
|
#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
|
* Flags to be used in a #GstBaseParseFrame.
|
||||||
* indicate that regular segment clipping should be performed.
|
|
||||||
*
|
*
|
||||||
* Since: 0.10.x
|
* 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,
|
* Frame (context) data passed to each frame parsing virtual methods. In
|
||||||
* e.g. if this frame is dependent on a previous one. As it is not counted as
|
* addition to providing the data to be checked for a valid frame or an already
|
||||||
* a frame, bitrate increases but frame to time conversions are maintained.
|
* 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
|
* 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.
|
* GST_BASE_PARSE_SEEK_TABLE: Additional metadata provides more accurate seeking.
|
||||||
*
|
*
|
||||||
* Indicates what level (of quality) of seeking is possible.
|
* Indicates what level (of quality) of seeking is possible.
|
||||||
|
*
|
||||||
|
* Since: 0.10.x
|
||||||
*/
|
*/
|
||||||
typedef enum _GstBaseParseSeekable {
|
typedef enum _GstBaseParseSeekable {
|
||||||
GST_BASE_PARSE_SEEK_NONE,
|
GST_BASE_PARSE_SEEK_NONE,
|
||||||
|
@ -221,12 +276,15 @@ struct _GstBaseParseClass {
|
||||||
GstCaps *caps);
|
GstCaps *caps);
|
||||||
|
|
||||||
gboolean (*check_valid_frame) (GstBaseParse *parse,
|
gboolean (*check_valid_frame) (GstBaseParse *parse,
|
||||||
GstBuffer *buffer,
|
GstBaseParseFrame *frame,
|
||||||
guint *framesize,
|
guint *framesize,
|
||||||
gint *skipsize);
|
gint *skipsize);
|
||||||
|
|
||||||
GstFlowReturn (*parse_frame) (GstBaseParse *parse,
|
GstFlowReturn (*parse_frame) (GstBaseParse *parse,
|
||||||
GstBuffer *buffer);
|
GstBaseParseFrame *frame);
|
||||||
|
|
||||||
|
GstFlowReturn (*pre_push_frame) (GstBaseParse *parse,
|
||||||
|
GstBaseParseFrame *frame);
|
||||||
|
|
||||||
gboolean (*convert) (GstBaseParse * parse,
|
gboolean (*convert) (GstBaseParse * parse,
|
||||||
GstFormat src_format,
|
GstFormat src_format,
|
||||||
|
@ -240,21 +298,16 @@ struct _GstBaseParseClass {
|
||||||
gboolean (*src_event) (GstBaseParse *parse,
|
gboolean (*src_event) (GstBaseParse *parse,
|
||||||
GstEvent *event);
|
GstEvent *event);
|
||||||
|
|
||||||
gint (*get_frame_overhead) (GstBaseParse *parse,
|
|
||||||
GstBuffer *buf);
|
|
||||||
|
|
||||||
GstFlowReturn (*pre_push_buffer) (GstBaseParse *parse,
|
|
||||||
GstBuffer *buf);
|
|
||||||
|
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
gpointer _gst_reserved[GST_PADDING_LARGE];
|
gpointer _gst_reserved[GST_PADDING_LARGE];
|
||||||
};
|
};
|
||||||
|
|
||||||
GType gst_base_parse_get_type (void);
|
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,
|
GstFlowReturn gst_base_parse_push_frame (GstBaseParse *parse,
|
||||||
GstBuffer *buffer);
|
GstBaseParseFrame *frame);
|
||||||
|
|
||||||
void gst_base_parse_set_duration (GstBaseParse *parse,
|
void gst_base_parse_set_duration (GstBaseParse *parse,
|
||||||
GstFormat fmt, gint64 duration, gint interval);
|
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,
|
void gst_base_parse_set_seek (GstBaseParse * parse,
|
||||||
GstBaseParseSeekable seek, guint bitrate);
|
GstBaseParseSeekable seek, guint bitrate);
|
||||||
|
|
||||||
void gst_base_parse_set_min_frame_size (GstBaseParse *parse,
|
void gst_base_parse_set_min_frame_size (GstBaseParse *parse, guint min_size);
|
||||||
guint min_size);
|
|
||||||
void gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough);
|
void gst_base_parse_set_passthrough (GstBaseParse * parse, gboolean passthrough);
|
||||||
|
|
||||||
void gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num,
|
void gst_base_parse_set_frame_props (GstBaseParse * parse, guint fps_num,
|
||||||
guint fps_den, guint lead_in, guint lead_out);
|
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,
|
gboolean gst_base_parse_convert_default (GstBaseParse * parse,
|
||||||
GstFormat src_format, gint64 src_value,
|
GstFormat src_format, gint64 src_value,
|
||||||
GstFormat dest_format, gint64 * dest_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_start (GstBaseParse * parse);
|
||||||
static gboolean gst_dca_parse_stop (GstBaseParse * parse);
|
static gboolean gst_dca_parse_stop (GstBaseParse * parse);
|
||||||
static gboolean gst_dca_parse_check_valid_frame (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,
|
static GstFlowReturn gst_dca_parse_parse_frame (GstBaseParse * parse,
|
||||||
GstBuffer * buf);
|
GstBaseParseFrame * frame);
|
||||||
|
|
||||||
GST_BOILERPLATE (GstDcaParse, gst_dca_parse, GstBaseParse, GST_TYPE_BASE_PARSE);
|
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
|
static gboolean
|
||||||
gst_dca_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
|
gst_dca_parse_check_valid_frame (GstBaseParse * parse,
|
||||||
guint * framesize, gint * skipsize)
|
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
||||||
{
|
{
|
||||||
GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
|
|
||||||
GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
|
GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
|
||||||
|
GstBuffer *buf = frame->buffer;
|
||||||
|
GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
|
||||||
gboolean parser_draining;
|
gboolean parser_draining;
|
||||||
gboolean parser_in_sync;
|
gboolean parser_in_sync;
|
||||||
guint32 sync = 0;
|
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))
|
if (G_UNLIKELY (GST_BUFFER_SIZE (buf) < 16))
|
||||||
return FALSE;
|
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)) {
|
if (G_LIKELY (parser_in_sync && dcaparse->last_sync != 0)) {
|
||||||
off = gst_byte_reader_masked_scan_uint32 (&r, 0xffffffff,
|
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;
|
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) {
|
if (!parser_in_sync && !parser_draining) {
|
||||||
/* check for second frame to be sure */
|
/* check for second frame to be sure */
|
||||||
|
@ -377,10 +378,11 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
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);
|
GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
|
||||||
|
GstBuffer *buf = frame->buffer;
|
||||||
|
GstByteReader r = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
|
||||||
guint size, rate, chans, samples;
|
guint size, rate, chans, samples;
|
||||||
|
|
||||||
if (!gst_dca_parse_parse_header (dcaparse, &r, &size, &rate, &chans,
|
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_start (GstBaseParse * parse);
|
||||||
static gboolean gst_flac_parse_stop (GstBaseParse * parse);
|
static gboolean gst_flac_parse_stop (GstBaseParse * parse);
|
||||||
static gboolean gst_flac_parse_check_valid_frame (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,
|
static GstFlowReturn gst_flac_parse_parse_frame (GstBaseParse * parse,
|
||||||
GstBuffer * buffer);
|
GstBaseParseFrame * frame);
|
||||||
static gint gst_flac_parse_get_frame_overhead (GstBaseParse * parse,
|
static GstFlowReturn gst_flac_parse_pre_push_frame (GstBaseParse * parse,
|
||||||
GstBuffer * buffer);
|
GstBaseParseFrame * frame);
|
||||||
static GstFlowReturn gst_flac_parse_pre_push_buffer (GstBaseParse * parse,
|
|
||||||
GstBuffer * buf);
|
|
||||||
|
|
||||||
GST_BOILERPLATE (GstFlacParse, gst_flac_parse, GstBaseParse,
|
GST_BOILERPLATE (GstFlacParse, gst_flac_parse, GstBaseParse,
|
||||||
GST_TYPE_BASE_PARSE);
|
GST_TYPE_BASE_PARSE);
|
||||||
|
@ -244,10 +242,8 @@ gst_flac_parse_class_init (GstFlacParseClass * klass)
|
||||||
baseparse_class->check_valid_frame =
|
baseparse_class->check_valid_frame =
|
||||||
GST_DEBUG_FUNCPTR (gst_flac_parse_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->parse_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_parse_frame);
|
||||||
baseparse_class->get_frame_overhead =
|
baseparse_class->pre_push_frame =
|
||||||
GST_DEBUG_FUNCPTR (gst_flac_parse_get_frame_overhead);
|
GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
|
||||||
baseparse_class->pre_push_buffer =
|
|
||||||
GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_buffer);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -563,15 +559,17 @@ need_more_data:
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_flac_parse_frame_is_valid (GstFlacParse * flacparse, GstBuffer * buffer,
|
gst_flac_parse_frame_is_valid (GstFlacParse * flacparse,
|
||||||
guint * ret)
|
GstBaseParseFrame * frame, guint * ret)
|
||||||
{
|
{
|
||||||
|
GstBuffer *buffer;
|
||||||
const guint8 *data;
|
const guint8 *data;
|
||||||
guint max, size, remaining;
|
guint max, size, remaining;
|
||||||
guint i, search_start, search_end;
|
guint i, search_start, search_end;
|
||||||
FrameHeaderCheckReturn header_ret;
|
FrameHeaderCheckReturn header_ret;
|
||||||
guint16 block_size;
|
guint16 block_size;
|
||||||
|
|
||||||
|
buffer = frame->buffer;
|
||||||
data = GST_BUFFER_DATA (buffer);
|
data = GST_BUFFER_DATA (buffer);
|
||||||
size = GST_BUFFER_SIZE (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 */
|
/* 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) {
|
if (flacparse->check_frame_checksums) {
|
||||||
guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2);
|
guint16 actual_crc = gst_flac_calculate_crc16 (data, size - 2);
|
||||||
guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2);
|
guint16 expected_crc = GST_READ_UINT16_BE (data + size - 2);
|
||||||
|
@ -648,9 +646,10 @@ need_more:
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_flac_parse_check_valid_frame (GstBaseParse * parse,
|
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);
|
GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
|
||||||
|
GstBuffer *buffer = frame->buffer;
|
||||||
const guint8 *data = GST_BUFFER_DATA (buffer);
|
const guint8 *data = GST_BUFFER_DATA (buffer);
|
||||||
|
|
||||||
if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 4))
|
if (G_UNLIKELY (GST_BUFFER_SIZE (buffer) < 4))
|
||||||
|
@ -689,13 +688,13 @@ gst_flac_parse_check_valid_frame (GstBaseParse * parse,
|
||||||
flacparse->sample_number = 0;
|
flacparse->sample_number = 0;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (flacparse, "Found sync code");
|
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) {
|
if (ret) {
|
||||||
*framesize = next;
|
*framesize = next;
|
||||||
return TRUE;
|
return TRUE;
|
||||||
} else {
|
} else {
|
||||||
/* If we're at EOS and the frame was not valid, drop it! */
|
/* 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");
|
GST_WARNING_OBJECT (flacparse, "EOS");
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
@ -1044,6 +1043,7 @@ push_headers:
|
||||||
while (flacparse->headers) {
|
while (flacparse->headers) {
|
||||||
GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
|
GstBuffer *buf = GST_BUFFER (flacparse->headers->data);
|
||||||
GstFlowReturn ret;
|
GstFlowReturn ret;
|
||||||
|
GstBaseParseFrame frame;
|
||||||
|
|
||||||
flacparse->headers =
|
flacparse->headers =
|
||||||
g_list_delete_link (flacparse->headers, flacparse->headers);
|
g_list_delete_link (flacparse->headers, flacparse->headers);
|
||||||
|
@ -1051,7 +1051,11 @@ push_headers:
|
||||||
gst_buffer_set_caps (buf,
|
gst_buffer_set_caps (buf,
|
||||||
GST_PAD_CAPS (GST_BASE_PARSE_SRC_PAD (GST_BASE_PARSE (flacparse))));
|
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) {
|
if (ret != GST_FLOW_OK) {
|
||||||
res = FALSE;
|
res = FALSE;
|
||||||
break;
|
break;
|
||||||
|
@ -1175,9 +1179,10 @@ gst_flac_parse_generate_headers (GstFlacParse * flacparse)
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
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);
|
GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
|
||||||
|
GstBuffer *buffer = frame->buffer;
|
||||||
const guint8 *data = GST_BUFFER_DATA (buffer);
|
const guint8 *data = GST_BUFFER_DATA (buffer);
|
||||||
|
|
||||||
if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
|
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_DURATION (buffer) =
|
||||||
GST_BUFFER_OFFSET (buffer) - GST_BUFFER_TIMESTAMP (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 */
|
/* Minimal size of a frame header */
|
||||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
|
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), MAX (9,
|
||||||
flacparse->min_framesize));
|
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
|
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);
|
GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
|
||||||
|
|
||||||
|
@ -1349,5 +1345,7 @@ gst_flac_parse_pre_push_buffer (GstBaseParse * parse, GstBuffer * buf)
|
||||||
flacparse->tags = NULL;
|
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_start (GstBaseParse * parse);
|
||||||
static gboolean gst_mpeg_audio_parse_stop (GstBaseParse * parse);
|
static gboolean gst_mpeg_audio_parse_stop (GstBaseParse * parse);
|
||||||
static gboolean gst_mpeg_audio_parse_check_valid_frame (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,
|
static GstFlowReturn gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
|
||||||
GstBuffer * buf);
|
GstBaseParseFrame * frame);
|
||||||
static GstFlowReturn gst_mpeg_audio_parse_pre_push_buffer (GstBaseParse * parse,
|
static GstFlowReturn gst_mpeg_audio_parse_pre_push_frame (GstBaseParse * parse,
|
||||||
GstBuffer * buf);
|
GstBaseParseFrame * frame);
|
||||||
static gboolean gst_mpeg_audio_parse_convert (GstBaseParse * parse,
|
static gboolean gst_mpeg_audio_parse_convert (GstBaseParse * parse,
|
||||||
GstFormat src_format, gint64 src_value,
|
GstFormat src_format, gint64 src_value,
|
||||||
GstFormat dest_format, gint64 * dest_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);
|
GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_check_valid_frame);
|
||||||
parse_class->parse_frame =
|
parse_class->parse_frame =
|
||||||
GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_parse_frame);
|
GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_parse_frame);
|
||||||
parse_class->pre_push_buffer =
|
parse_class->pre_push_frame =
|
||||||
GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_pre_push_buffer);
|
GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_pre_push_frame);
|
||||||
parse_class->convert = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_convert);
|
parse_class->convert = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_convert);
|
||||||
|
|
||||||
/* register tags */
|
/* register tags */
|
||||||
|
@ -470,11 +470,12 @@ gst_mpeg_audio_parse_head_check (GstMpegAudioParse * mp3parse,
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
|
gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
|
||||||
guint * framesize, gint * skipsize)
|
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
||||||
{
|
{
|
||||||
GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
|
|
||||||
GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
|
GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
|
||||||
|
GstBuffer *buf = frame->buffer;
|
||||||
|
GstByteReader reader = GST_BYTE_READER_INIT_FROM_BUFFER (buf);
|
||||||
gint off, bpf;
|
gint off, bpf;
|
||||||
gboolean sync, drain, valid, caps_change;
|
gboolean sync, drain, valid, caps_change;
|
||||||
guint32 header;
|
guint32 header;
|
||||||
|
@ -519,8 +520,8 @@ gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse, GstBuffer * buf,
|
||||||
else
|
else
|
||||||
caps_change = FALSE;
|
caps_change = FALSE;
|
||||||
|
|
||||||
sync = gst_base_parse_get_sync (parse);
|
sync = GST_BASE_PARSE_FRAME_SYNC (frame);
|
||||||
drain = gst_base_parse_get_drain (parse);
|
drain = GST_BASE_PARSE_FRAME_DRAIN (frame);
|
||||||
|
|
||||||
if (!drain && (!sync || caps_change)) {
|
if (!drain && (!sync || caps_change)) {
|
||||||
if (!gst_mp3parse_validate_extended (mp3parse, buf, header, bpf, drain,
|
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
|
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);
|
GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
|
||||||
|
GstBuffer *buf = frame->buffer;
|
||||||
guint bitrate, layer, rate, channels, version, mode, crc;
|
guint bitrate, layer, rate, channels, version, mode, crc;
|
||||||
|
|
||||||
g_return_val_if_fail (GST_BUFFER_SIZE (buf) >= 4, GST_FLOW_ERROR);
|
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
|
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);
|
GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
|
||||||
GstTagList *taglist;
|
GstTagList *taglist;
|
||||||
|
@ -1188,5 +1192,7 @@ gst_mpeg_audio_parse_pre_push_buffer (GstBaseParse * parse, GstBuffer * buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* usual clipping applies */
|
/* usual clipping applies */
|
||||||
return GST_BASE_PARSE_FLOW_CLIP;
|
frame->flags |= GST_BASE_PARSE_FRAME_FLAG_CLIP;
|
||||||
|
|
||||||
|
return GST_FLOW_OK;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue