mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-10-31 22:49:02 +00:00
audioparsers: adjust to modified baseparse API
This commit is contained in:
parent
e3b5a2e40d
commit
1ae32656ae
6 changed files with 287 additions and 389 deletions
|
@ -89,11 +89,8 @@ static gboolean gst_aac_parse_sink_setcaps (GstBaseParse * parse,
|
|||
static GstCaps *gst_aac_parse_sink_getcaps (GstBaseParse * parse,
|
||||
GstCaps * filter);
|
||||
|
||||
static gboolean gst_aac_parse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * size, gint * skipsize);
|
||||
|
||||
static GstFlowReturn gst_aac_parse_parse_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame);
|
||||
static GstFlowReturn gst_aac_parse_handle_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, gint * skipsize);
|
||||
|
||||
gboolean gst_aac_parse_convert (GstBaseParse * parse,
|
||||
GstFormat src_format,
|
||||
|
@ -146,9 +143,7 @@ gst_aac_parse_class_init (GstAacParseClass * klass)
|
|||
parse_class->stop = GST_DEBUG_FUNCPTR (gst_aac_parse_stop);
|
||||
parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_aac_parse_sink_setcaps);
|
||||
parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_aac_parse_sink_getcaps);
|
||||
parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_aac_parse_parse_frame);
|
||||
parse_class->check_valid_frame =
|
||||
GST_DEBUG_FUNCPTR (gst_aac_parse_check_valid_frame);
|
||||
parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_aac_parse_handle_frame);
|
||||
}
|
||||
|
||||
|
||||
|
@ -900,84 +895,11 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
|
|||
/**
|
||||
* gst_aac_parse_check_valid_frame:
|
||||
* @parse: #GstBaseParse.
|
||||
* @buffer: #GstBuffer.
|
||||
* @framesize: If the buffer contains a valid frame, its size will be put here
|
||||
* @frame: #GstBaseParseFrame.
|
||||
* @skipsize: How much data parent class should skip in order to find the
|
||||
* frame header.
|
||||
*
|
||||
* Implementation of "check_valid_frame" vmethod in #GstBaseParse class.
|
||||
*
|
||||
* Returns: TRUE if buffer contains a valid frame.
|
||||
*/
|
||||
static gboolean
|
||||
gst_aac_parse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
||||
{
|
||||
GstMapInfo map;
|
||||
GstAacParse *aacparse;
|
||||
gboolean ret = FALSE;
|
||||
gboolean lost_sync;
|
||||
GstBuffer *buffer;
|
||||
|
||||
aacparse = GST_AAC_PARSE (parse);
|
||||
buffer = frame->buffer;
|
||||
|
||||
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||
|
||||
lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
|
||||
|
||||
if (aacparse->header_type == DSPAAC_HEADER_ADIF ||
|
||||
aacparse->header_type == DSPAAC_HEADER_NONE) {
|
||||
/* There is nothing to parse */
|
||||
*framesize = map.size;
|
||||
ret = TRUE;
|
||||
|
||||
} else if (aacparse->header_type == DSPAAC_HEADER_NOT_PARSED || lost_sync) {
|
||||
|
||||
ret = gst_aac_parse_detect_stream (aacparse, map.data, map.size,
|
||||
GST_BASE_PARSE_DRAINING (parse), framesize, skipsize);
|
||||
|
||||
} else if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
|
||||
guint needed_data = 1024;
|
||||
|
||||
ret = gst_aac_parse_check_adts_frame (aacparse, map.data, map.size,
|
||||
GST_BASE_PARSE_DRAINING (parse), framesize, &needed_data);
|
||||
|
||||
if (!ret) {
|
||||
GST_DEBUG ("buffer didn't contain valid frame");
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
|
||||
needed_data);
|
||||
}
|
||||
|
||||
} else if (aacparse->header_type == DSPAAC_HEADER_LOAS) {
|
||||
guint needed_data = 1024;
|
||||
|
||||
ret = gst_aac_parse_check_loas_frame (aacparse, map.data,
|
||||
map.size, GST_BASE_PARSE_DRAINING (parse), framesize, &needed_data);
|
||||
|
||||
if (!ret) {
|
||||
GST_DEBUG ("buffer didn't contain valid frame");
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
|
||||
needed_data);
|
||||
}
|
||||
|
||||
} else {
|
||||
GST_DEBUG ("buffer didn't contain valid frame");
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
|
||||
ADTS_MAX_SIZE);
|
||||
}
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_aac_parse_parse_frame:
|
||||
* @parse: #GstBaseParse.
|
||||
* @buffer: #GstBuffer.
|
||||
*
|
||||
* Implementation of "parse_frame" vmethod in #GstBaseParse class.
|
||||
* Implementation of "handle_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
|
||||
|
@ -992,46 +914,91 @@ gst_aac_parse_check_valid_frame (GstBaseParse * parse,
|
|||
* 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.
|
||||
* Returns: a #GstFlowReturn.
|
||||
*/
|
||||
static GstFlowReturn
|
||||
gst_aac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||
gst_aac_parse_handle_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, gint * skipsize)
|
||||
{
|
||||
GstAacParse *aacparse;
|
||||
GstBuffer *buffer;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
gint rate, channels;
|
||||
GstMapInfo map;
|
||||
GstAacParse *aacparse;
|
||||
gboolean ret = FALSE;
|
||||
gboolean lost_sync;
|
||||
GstBuffer *buffer;
|
||||
guint framesize;
|
||||
gint rate, channels;
|
||||
|
||||
aacparse = GST_AAC_PARSE (parse);
|
||||
buffer = frame->buffer;
|
||||
|
||||
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||
|
||||
*skipsize = -1;
|
||||
lost_sync = GST_BASE_PARSE_LOST_SYNC (parse);
|
||||
|
||||
if (aacparse->header_type == DSPAAC_HEADER_ADIF ||
|
||||
aacparse->header_type == DSPAAC_HEADER_NONE) {
|
||||
/* There is nothing to parse */
|
||||
framesize = map.size;
|
||||
ret = TRUE;
|
||||
|
||||
} else if (aacparse->header_type == DSPAAC_HEADER_NOT_PARSED || lost_sync) {
|
||||
|
||||
ret = gst_aac_parse_detect_stream (aacparse, map.data, map.size,
|
||||
GST_BASE_PARSE_DRAINING (parse), &framesize, skipsize);
|
||||
|
||||
} else if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
|
||||
guint needed_data = 1024;
|
||||
|
||||
ret = gst_aac_parse_check_adts_frame (aacparse, map.data, map.size,
|
||||
GST_BASE_PARSE_DRAINING (parse), &framesize, &needed_data);
|
||||
|
||||
if (!ret) {
|
||||
GST_DEBUG ("buffer didn't contain valid frame");
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
|
||||
needed_data);
|
||||
}
|
||||
|
||||
} else if (aacparse->header_type == DSPAAC_HEADER_LOAS) {
|
||||
guint needed_data = 1024;
|
||||
|
||||
ret = gst_aac_parse_check_loas_frame (aacparse, map.data,
|
||||
map.size, GST_BASE_PARSE_DRAINING (parse), &framesize, &needed_data);
|
||||
|
||||
if (!ret) {
|
||||
GST_DEBUG ("buffer didn't contain valid frame");
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
|
||||
needed_data);
|
||||
}
|
||||
|
||||
} else {
|
||||
GST_DEBUG ("buffer didn't contain valid frame");
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (aacparse),
|
||||
ADTS_MAX_SIZE);
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (!ret))
|
||||
goto exit;
|
||||
|
||||
if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
|
||||
/* see above */
|
||||
frame->overhead = 7;
|
||||
|
||||
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||
gst_aac_parse_parse_adts_header (aacparse, map.data,
|
||||
&rate, &channels, NULL, NULL);
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
|
||||
GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
|
||||
|
||||
if (G_UNLIKELY (rate != aacparse->sample_rate
|
||||
|| channels != aacparse->channels)) {
|
||||
GstCaps *sinkcaps;
|
||||
|
||||
aacparse->sample_rate = rate;
|
||||
aacparse->channels = channels;
|
||||
|
||||
if ((sinkcaps =
|
||||
gst_pad_get_current_caps (GST_BASE_PARSE (aacparse)->sinkpad))) {
|
||||
if (!gst_aac_parse_set_src_caps (aacparse, sinkcaps)) {
|
||||
/* If linking fails, we need to return appropriate error */
|
||||
ret = GST_FLOW_NOT_LINKED;
|
||||
}
|
||||
gst_caps_unref (sinkcaps);
|
||||
GST_DEBUG_OBJECT (aacparse, "here");
|
||||
|
||||
if (!gst_aac_parse_set_src_caps (aacparse, NULL)) {
|
||||
/* If linking fails, we need to return appropriate error */
|
||||
ret = GST_FLOW_NOT_LINKED;
|
||||
}
|
||||
|
||||
gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
|
||||
|
@ -1043,7 +1010,6 @@ gst_aac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
/* see above */
|
||||
frame->overhead = 3;
|
||||
|
||||
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||
if (!gst_aac_parse_read_loas_config (aacparse, map.data, map.size, &rate,
|
||||
&channels, NULL)) {
|
||||
GST_WARNING_OBJECT (aacparse, "Error reading LOAS config");
|
||||
|
@ -1055,22 +1021,15 @@ gst_aac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
GST_INFO_OBJECT (aacparse, "New LOAS config: %d Hz, %d channels", rate,
|
||||
channels);
|
||||
}
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
|
||||
/* We want to set caps both at start, and when rate/channels change.
|
||||
Since only some LOAS frames have that info, we may receive frames
|
||||
before knowing about rate/channels. */
|
||||
if (setcaps
|
||||
|| !gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (aacparse))) {
|
||||
GstCaps *sinkcaps;
|
||||
|
||||
if ((sinkcaps =
|
||||
gst_pad_get_current_caps (GST_BASE_PARSE (aacparse)->sinkpad))) {
|
||||
if (!gst_aac_parse_set_src_caps (aacparse, sinkcaps)) {
|
||||
/* If linking fails, we need to return appropriate error */
|
||||
ret = GST_FLOW_NOT_LINKED;
|
||||
}
|
||||
gst_caps_unref (sinkcaps);
|
||||
if (!gst_aac_parse_set_src_caps (aacparse, NULL)) {
|
||||
/* If linking fails, we need to return appropriate error */
|
||||
ret = GST_FLOW_NOT_LINKED;
|
||||
}
|
||||
|
||||
gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
|
||||
|
@ -1078,7 +1037,24 @@ gst_aac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
exit:
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
|
||||
if (ret) {
|
||||
/* found, skip if needed */
|
||||
if (*skipsize > 0)
|
||||
return GST_FLOW_OK;
|
||||
*skipsize = 0;
|
||||
} else {
|
||||
if (*skipsize < 0)
|
||||
*skipsize = 1;
|
||||
}
|
||||
|
||||
if (ret && framesize <= map.size) {
|
||||
return gst_base_parse_finish_frame (parse, frame, framesize);
|
||||
}
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -159,10 +159,8 @@ 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,
|
||||
GstBaseParseFrame * frame, guint * size, gint * skipsize);
|
||||
static GstFlowReturn gst_ac3_parse_parse_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame);
|
||||
static GstFlowReturn gst_ac3_parse_handle_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, gint * skipsize);
|
||||
static gboolean gst_ac3_parse_src_event (GstBaseParse * parse,
|
||||
GstEvent * event);
|
||||
static GstCaps *gst_ac3_parse_get_sink_caps (GstBaseParse * parse,
|
||||
|
@ -194,9 +192,7 @@ gst_ac3_parse_class_init (GstAc3ParseClass * klass)
|
|||
|
||||
parse_class->start = GST_DEBUG_FUNCPTR (gst_ac3_parse_start);
|
||||
parse_class->stop = GST_DEBUG_FUNCPTR (gst_ac3_parse_stop);
|
||||
parse_class->check_valid_frame =
|
||||
GST_DEBUG_FUNCPTR (gst_ac3_parse_check_valid_frame);
|
||||
parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_ac3_parse_parse_frame);
|
||||
parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_ac3_parse_handle_frame);
|
||||
parse_class->src_event = GST_DEBUG_FUNCPTR (gst_ac3_parse_src_event);
|
||||
parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_ac3_parse_get_sink_caps);
|
||||
}
|
||||
|
@ -481,9 +477,9 @@ cleanup:
|
|||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
||||
static GstFlowReturn
|
||||
gst_ac3_parse_handle_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, gint * skipsize)
|
||||
{
|
||||
GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
|
||||
GstBuffer *buf = frame->buffer;
|
||||
|
@ -491,14 +487,20 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
|
|||
gint off;
|
||||
gboolean lost_sync, draining, eac, more = FALSE;
|
||||
guint frmsiz, blocks, sid;
|
||||
guint rate, chans;
|
||||
gboolean update_rate = FALSE;
|
||||
gint framesize = 0;
|
||||
gint have_blocks = 0;
|
||||
GstMapInfo map;
|
||||
gboolean ret = FALSE;
|
||||
GstFlowReturn res = GST_FLOW_OK;
|
||||
|
||||
gst_buffer_map (buf, &map, GST_MAP_READ);
|
||||
|
||||
if (G_UNLIKELY (map.size < 6))
|
||||
if (G_UNLIKELY (map.size < 6)) {
|
||||
*skipsize = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
gst_byte_reader_init (&reader, map.data, map.size);
|
||||
off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffff0000, 0x0b770000,
|
||||
|
@ -519,13 +521,16 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
|
|||
}
|
||||
|
||||
/* make sure the values in the frame header look sane */
|
||||
if (!gst_ac3_parse_frame_header (ac3parse, buf, 0, &frmsiz, NULL, NULL,
|
||||
if (!gst_ac3_parse_frame_header (ac3parse, buf, 0, &frmsiz, &rate, &chans,
|
||||
&blocks, &sid, &eac)) {
|
||||
*skipsize = off + 2;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
*framesize = frmsiz;
|
||||
GST_LOG_OBJECT (parse, "size: %u, blocks: %u, rate: %u, chans: %u", frmsiz,
|
||||
blocks, rate, chans);
|
||||
|
||||
framesize = frmsiz;
|
||||
|
||||
if (G_UNLIKELY (g_atomic_int_get (&ac3parse->align) ==
|
||||
GST_AC3_PARSE_ALIGN_NONE))
|
||||
|
@ -550,21 +555,21 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
|
|||
goto cleanup;
|
||||
}
|
||||
|
||||
*framesize = 0;
|
||||
framesize = 0;
|
||||
|
||||
/* Loop till we have 6 blocks per substream */
|
||||
for (have_blocks = 0; !more && have_blocks < 6; have_blocks += blocks) {
|
||||
/* Loop till we get one frame from each substream */
|
||||
do {
|
||||
*framesize += frmsiz;
|
||||
framesize += frmsiz;
|
||||
|
||||
if (!gst_byte_reader_skip (&reader, frmsiz)
|
||||
|| map.size < (*framesize + 6)) {
|
||||
|| map.size < (framesize + 6)) {
|
||||
more = TRUE;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!gst_ac3_parse_frame_header (ac3parse, buf, *framesize, &frmsiz,
|
||||
if (!gst_ac3_parse_frame_header (ac3parse, buf, framesize, &frmsiz,
|
||||
NULL, NULL, NULL, &sid, &eac)) {
|
||||
*skipsize = off + 2;
|
||||
goto cleanup;
|
||||
|
@ -584,7 +589,7 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
|
|||
if (more || !gst_byte_reader_skip (&reader, frmsiz) ||
|
||||
!gst_byte_reader_get_uint16_be (&reader, &word)) {
|
||||
GST_DEBUG_OBJECT (ac3parse, "... but not sufficient data");
|
||||
gst_base_parse_set_min_frame_size (parse, *framesize + 6);
|
||||
gst_base_parse_set_min_frame_size (parse, framesize + 6);
|
||||
*skipsize = 0;
|
||||
goto cleanup;
|
||||
} else {
|
||||
|
@ -594,34 +599,16 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
|
|||
goto cleanup;
|
||||
} else {
|
||||
/* ok, got sync now, let's assume constant frame size */
|
||||
gst_base_parse_set_min_frame_size (parse, *framesize);
|
||||
gst_base_parse_set_min_frame_size (parse, framesize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* expect to have found a frame here */
|
||||
g_assert (framesize);
|
||||
ret = TRUE;
|
||||
|
||||
cleanup:
|
||||
gst_buffer_unmap (buf, &map);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
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, update_rate = FALSE;
|
||||
|
||||
if (!gst_ac3_parse_frame_header (ac3parse, buf, 0, &fsize, &rate, &chans,
|
||||
&blocks, &sid, &eac))
|
||||
goto broken_header;
|
||||
|
||||
GST_LOG_OBJECT (parse, "size: %u, blocks: %u, rate: %u, chans: %u", fsize,
|
||||
blocks, rate, chans);
|
||||
|
||||
/* arrange for metadata setup */
|
||||
if (G_UNLIKELY (sid)) {
|
||||
/* dependent frame, no need to (ac)count for or consider further */
|
||||
GST_LOG_OBJECT (parse, "sid: %d", sid);
|
||||
|
@ -631,9 +618,9 @@ gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
/* occupies same time space as previous base frame */
|
||||
if (G_LIKELY (GST_BUFFER_TIMESTAMP (buf) >= GST_BUFFER_DURATION (buf)))
|
||||
GST_BUFFER_TIMESTAMP (buf) -= GST_BUFFER_DURATION (buf);
|
||||
/* only return if we already arranged for caps */
|
||||
/* only shortcut if we already arranged for caps */
|
||||
if (G_LIKELY (ac3parse->sample_rate > 0))
|
||||
return GST_FLOW_OK;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
if (G_UNLIKELY (ac3parse->sample_rate != rate || ac3parse->channels != chans
|
||||
|
@ -663,15 +650,14 @@ gst_ac3_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
if (G_UNLIKELY (update_rate))
|
||||
gst_base_parse_set_frame_rate (parse, rate, 256 * blocks, 2, 2);
|
||||
|
||||
return GST_FLOW_OK;
|
||||
cleanup:
|
||||
gst_buffer_unmap (buf, &map);
|
||||
|
||||
/* ERRORS */
|
||||
broken_header:
|
||||
{
|
||||
/* this really shouldn't ever happen */
|
||||
GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), (NULL));
|
||||
return GST_FLOW_ERROR;
|
||||
if (ret && framesize <= map.size) {
|
||||
res = gst_base_parse_finish_frame (parse, frame, framesize);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
|
@ -79,11 +79,8 @@ static gboolean gst_amr_parse_sink_setcaps (GstBaseParse * parse,
|
|||
static GstCaps *gst_amr_parse_sink_getcaps (GstBaseParse * parse,
|
||||
GstCaps * filter);
|
||||
|
||||
static gboolean gst_amr_parse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
|
||||
|
||||
static GstFlowReturn gst_amr_parse_parse_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame);
|
||||
static GstFlowReturn gst_amr_parse_handle_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, gint * skipsize);
|
||||
|
||||
G_DEFINE_TYPE (GstAmrParse, gst_amr_parse, GST_TYPE_BASE_PARSE);
|
||||
|
||||
|
@ -115,9 +112,7 @@ gst_amr_parse_class_init (GstAmrParseClass * klass)
|
|||
parse_class->stop = GST_DEBUG_FUNCPTR (gst_amr_parse_stop);
|
||||
parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_amr_parse_sink_setcaps);
|
||||
parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_amr_parse_sink_getcaps);
|
||||
parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_amr_parse_parse_frame);
|
||||
parse_class->check_valid_frame =
|
||||
GST_DEBUG_FUNCPTR (gst_amr_parse_check_valid_frame);
|
||||
parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_amr_parse_handle_frame);
|
||||
}
|
||||
|
||||
|
||||
|
@ -254,15 +249,16 @@ gst_amr_parse_parse_header (GstAmrParse * amrparse,
|
|||
*
|
||||
* Returns: TRUE if the given data contains valid frame.
|
||||
*/
|
||||
static gboolean
|
||||
gst_amr_parse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
||||
static GstFlowReturn
|
||||
gst_amr_parse_handle_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, gint * skipsize)
|
||||
{
|
||||
GstBuffer *buffer;
|
||||
GstMapInfo map;
|
||||
gint fsize, mode, dsize;
|
||||
gint fsize = 0, mode, dsize;
|
||||
GstAmrParse *amrparse;
|
||||
gboolean ret = FALSE;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
gboolean found = FALSE;
|
||||
|
||||
amrparse = GST_AMR_PARSE (parse);
|
||||
buffer = frame->buffer;
|
||||
|
@ -285,6 +281,7 @@ gst_amr_parse_check_valid_frame (GstBaseParse * parse,
|
|||
goto done;
|
||||
}
|
||||
|
||||
*skipsize = 1;
|
||||
/* Does this look like a possible frame header candidate? */
|
||||
if ((map.data[0] & 0x83) == 0) {
|
||||
/* Yep. Retrieve the frame size */
|
||||
|
@ -299,8 +296,7 @@ gst_amr_parse_check_valid_frame (GstBaseParse * parse,
|
|||
* perform this check)
|
||||
*/
|
||||
if (fsize) {
|
||||
gboolean found = FALSE;
|
||||
|
||||
*skipsize = 0;
|
||||
/* in sync, no further check */
|
||||
if (!GST_BASE_PARSE_LOST_SYNC (parse)) {
|
||||
found = TRUE;
|
||||
|
@ -311,42 +307,20 @@ gst_amr_parse_check_valid_frame (GstBaseParse * parse,
|
|||
} else if (GST_BASE_PARSE_DRAINING (parse)) {
|
||||
/* not enough, but draining, so ok */
|
||||
found = TRUE;
|
||||
} else {
|
||||
/* indicate we need not skip, but need more data */
|
||||
*skipsize = 0;
|
||||
*framesize = fsize + 1;
|
||||
}
|
||||
if (found) {
|
||||
*framesize = fsize;
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
GST_LOG ("sync lost");
|
||||
|
||||
done:
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
|
||||
if (found && fsize <= map.size) {
|
||||
ret = gst_base_parse_finish_frame (parse, frame, fsize);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_amr_parse_parse_frame:
|
||||
* @parse: #GstBaseParse.
|
||||
* @buffer: #GstBuffer.
|
||||
*
|
||||
* Implementation of "parse" vmethod in #GstBaseParse class.
|
||||
*
|
||||
* Returns: #GstFlowReturn defining the parsing status.
|
||||
*/
|
||||
static GstFlowReturn
|
||||
gst_amr_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||
{
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* gst_amr_parse_start:
|
||||
* @parse: #GstBaseParse.
|
||||
|
|
|
@ -74,10 +74,8 @@ 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,
|
||||
GstBaseParseFrame * frame, guint * size, gint * skipsize);
|
||||
static GstFlowReturn gst_dca_parse_parse_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame);
|
||||
static GstFlowReturn gst_dca_parse_handle_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, gint * skipsize);
|
||||
static GstCaps *gst_dca_parse_get_sink_caps (GstBaseParse * parse,
|
||||
GstCaps * filter);
|
||||
|
||||
|
@ -98,9 +96,7 @@ gst_dca_parse_class_init (GstDcaParseClass * klass)
|
|||
|
||||
parse_class->start = GST_DEBUG_FUNCPTR (gst_dca_parse_start);
|
||||
parse_class->stop = GST_DEBUG_FUNCPTR (gst_dca_parse_stop);
|
||||
parse_class->check_valid_frame =
|
||||
GST_DEBUG_FUNCPTR (gst_dca_parse_check_valid_frame);
|
||||
parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_dca_parse_parse_frame);
|
||||
parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_dca_parse_handle_frame);
|
||||
parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_dca_parse_get_sink_caps);
|
||||
|
||||
gst_element_class_add_pad_template (element_class,
|
||||
|
@ -305,9 +301,9 @@ gst_dca_parse_find_sync (GstDcaParse * dcaparse, GstByteReader * reader,
|
|||
return best_offset;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_dca_parse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
||||
static GstFlowReturn
|
||||
gst_dca_parse_handle_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, gint * skipsize)
|
||||
{
|
||||
GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
|
||||
GstBuffer *buf = frame->buffer;
|
||||
|
@ -316,15 +312,19 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse,
|
|||
gboolean parser_in_sync;
|
||||
gboolean terminator;
|
||||
guint32 sync = 0;
|
||||
guint size, rate, chans, num_blocks, samples_per_block;
|
||||
guint size, rate, chans, num_blocks, samples_per_block, depth;
|
||||
gint block_size;
|
||||
gint endianness;
|
||||
gint off = -1;
|
||||
GstMapInfo map;
|
||||
gboolean ret = FALSE;
|
||||
GstFlowReturn ret = GST_FLOW_EOS;
|
||||
|
||||
gst_buffer_map (buf, &map, GST_MAP_READ);
|
||||
|
||||
if (G_UNLIKELY (map.size < 16))
|
||||
if (G_UNLIKELY (map.size < 16)) {
|
||||
*skipsize = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
parser_in_sync = !GST_BASE_PARSE_LOST_SYNC (parse);
|
||||
|
||||
|
@ -355,8 +355,8 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse,
|
|||
}
|
||||
|
||||
/* make sure the values in the frame header look sane */
|
||||
if (!gst_dca_parse_parse_header (dcaparse, &r, &size, &rate, &chans, NULL,
|
||||
NULL, &num_blocks, &samples_per_block, &terminator)) {
|
||||
if (!gst_dca_parse_parse_header (dcaparse, &r, &size, &rate, &chans, &depth,
|
||||
&endianness, &num_blocks, &samples_per_block, &terminator)) {
|
||||
*skipsize = 4;
|
||||
goto cleanup;
|
||||
}
|
||||
|
@ -364,8 +364,6 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse,
|
|||
GST_LOG_OBJECT (parse, "got frame, sync %08x, size %u, rate %d, channels %d",
|
||||
sync, size, rate, chans);
|
||||
|
||||
*framesize = size;
|
||||
|
||||
dcaparse->last_sync = sync;
|
||||
|
||||
parser_draining = GST_BASE_PARSE_DRAINING (parse);
|
||||
|
@ -391,41 +389,18 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse,
|
|||
/* ok, got sync now, let's assume constant frame size */
|
||||
gst_base_parse_set_min_frame_size (parse, size);
|
||||
} else {
|
||||
/* FIXME: baseparse always seems to hand us buffers of min_frame_size
|
||||
* bytes, which is unhelpful here */
|
||||
/* wait for some more data */
|
||||
GST_LOG_OBJECT (dcaparse,
|
||||
"next sync out of reach (%" G_GSIZE_FORMAT " < %u)", map.size,
|
||||
size + 16);
|
||||
/* *skipsize = 0; */
|
||||
/* return FALSE; */
|
||||
goto cleanup;
|
||||
}
|
||||
}
|
||||
|
||||
ret = TRUE;
|
||||
|
||||
cleanup:
|
||||
gst_buffer_unmap (buf, &map);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_dca_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||
{
|
||||
GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
|
||||
GstBuffer *buf = frame->buffer;
|
||||
GstByteReader r;
|
||||
guint size, rate, chans, depth, block_size, num_blocks, samples_per_block;
|
||||
gint endianness;
|
||||
gboolean terminator;
|
||||
GstMapInfo map;
|
||||
|
||||
gst_buffer_map (buf, &map, GST_MAP_READ);
|
||||
gst_byte_reader_init (&r, map.data, map.size);
|
||||
|
||||
if (!gst_dca_parse_parse_header (dcaparse, &r, &size, &rate, &chans, &depth,
|
||||
&endianness, &num_blocks, &samples_per_block, &terminator))
|
||||
goto broken_header;
|
||||
/* found frame */
|
||||
ret = GST_FLOW_OK;
|
||||
|
||||
/* metadata handling */
|
||||
block_size = num_blocks * samples_per_block;
|
||||
|
||||
if (G_UNLIKELY (dcaparse->rate != rate || dcaparse->channels != chans
|
||||
|
@ -453,17 +428,16 @@ gst_dca_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
gst_base_parse_set_frame_rate (parse, rate, block_size, 0, 0);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
gst_buffer_unmap (buf, &map);
|
||||
return GST_FLOW_OK;
|
||||
|
||||
/* ERRORS */
|
||||
broken_header:
|
||||
{
|
||||
/* this really shouldn't ever happen */
|
||||
GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), (NULL));
|
||||
gst_buffer_unmap (buf, &map);
|
||||
return GST_FLOW_ERROR;
|
||||
if (ret == GST_FLOW_OK && size <= map.size) {
|
||||
ret = gst_base_parse_finish_frame (parse, frame, size);
|
||||
} else {
|
||||
ret = GST_FLOW_OK;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
|
|
|
@ -192,10 +192,10 @@ 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,
|
||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
|
||||
static GstFlowReturn gst_flac_parse_handle_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, gint * skipsize);
|
||||
static GstFlowReturn gst_flac_parse_parse_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame);
|
||||
GstBaseParseFrame * frame, gint size);
|
||||
static GstFlowReturn gst_flac_parse_pre_push_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame);
|
||||
static gboolean gst_flac_parse_convert (GstBaseParse * parse,
|
||||
|
@ -229,9 +229,8 @@ gst_flac_parse_class_init (GstFlacParseClass * klass)
|
|||
|
||||
baseparse_class->start = GST_DEBUG_FUNCPTR (gst_flac_parse_start);
|
||||
baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_flac_parse_stop);
|
||||
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->handle_frame =
|
||||
GST_DEBUG_FUNCPTR (gst_flac_parse_handle_frame);
|
||||
baseparse_class->pre_push_frame =
|
||||
GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
|
||||
baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert);
|
||||
|
@ -704,17 +703,21 @@ cleanup:
|
|||
return result;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_flac_parse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
||||
static GstFlowReturn
|
||||
gst_flac_parse_handle_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, gint * skipsize)
|
||||
{
|
||||
GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
|
||||
GstBuffer *buffer = frame->buffer;
|
||||
GstMapInfo map;
|
||||
gboolean result = TRUE;
|
||||
GstFlowReturn ret = GST_FLOW_OK;
|
||||
guint framesize;
|
||||
|
||||
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||
|
||||
*skipsize = 1;
|
||||
|
||||
if (G_UNLIKELY (map.size < 4)) {
|
||||
result = FALSE;
|
||||
goto cleanup;
|
||||
|
@ -723,7 +726,7 @@ gst_flac_parse_check_valid_frame (GstBaseParse * parse,
|
|||
if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
|
||||
if (memcmp (map.data, "fLaC", 4) == 0) {
|
||||
GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
|
||||
*framesize = 4;
|
||||
framesize = 4;
|
||||
goto cleanup;
|
||||
}
|
||||
if (map.data[0] == 0xff && (map.data[1] >> 2) == 0x3e) {
|
||||
|
@ -744,7 +747,7 @@ gst_flac_parse_check_valid_frame (GstBaseParse * parse,
|
|||
guint size = 4 + ((map.data[1] << 16) | (map.data[2] << 8) | (map.data[3]));
|
||||
|
||||
GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
|
||||
*framesize = size;
|
||||
framesize = size;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
|
@ -759,7 +762,7 @@ gst_flac_parse_check_valid_frame (GstBaseParse * parse,
|
|||
GST_DEBUG_OBJECT (flacparse, "Found sync code");
|
||||
ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
|
||||
if (ret) {
|
||||
*framesize = next;
|
||||
framesize = next;
|
||||
goto cleanup;
|
||||
} else {
|
||||
/* If we're at EOS and the frame was not valid, drop it! */
|
||||
|
@ -809,7 +812,21 @@ gst_flac_parse_check_valid_frame (GstBaseParse * parse,
|
|||
|
||||
cleanup:
|
||||
gst_buffer_unmap (buffer, &map);
|
||||
return result;
|
||||
|
||||
if (result)
|
||||
*skipsize = 0;
|
||||
|
||||
if (result && framesize <= map.size) {
|
||||
ret = gst_flac_parse_parse_frame (parse, frame, framesize);
|
||||
if (ret == GST_BASE_PARSE_FLOW_DROPPED) {
|
||||
frame->flags |= GST_BASE_PARSE_FRAME_FLAG_DROP;
|
||||
ret = GST_FLOW_OK;
|
||||
}
|
||||
if (ret == GST_FLOW_OK)
|
||||
ret = gst_base_parse_finish_frame (parse, frame, framesize);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -1166,6 +1183,7 @@ push_headers:
|
|||
res = FALSE;
|
||||
break;
|
||||
}
|
||||
gst_base_parse_frame_free (&frame);
|
||||
}
|
||||
g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
|
||||
g_list_free (flacparse->headers);
|
||||
|
@ -1291,27 +1309,28 @@ gst_flac_parse_generate_headers (GstFlacParse * flacparse)
|
|||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
||||
gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame,
|
||||
gint size)
|
||||
{
|
||||
GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
|
||||
GstBuffer *buffer = frame->buffer;
|
||||
GstBuffer *buffer = frame->buffer, *sbuffer;
|
||||
GstMapInfo map;
|
||||
GstFlowReturn res = GST_FLOW_ERROR;
|
||||
|
||||
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||
|
||||
if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
|
||||
GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_OFFSET (buffer) = 0;
|
||||
GST_BUFFER_OFFSET_END (buffer) = 0;
|
||||
sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
|
||||
GST_BUFFER_TIMESTAMP (sbuffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_DURATION (sbuffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_OFFSET (sbuffer) = 0;
|
||||
GST_BUFFER_OFFSET_END (sbuffer) = 0;
|
||||
|
||||
/* 32 bits metadata block */
|
||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
|
||||
flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
|
||||
|
||||
flacparse->headers =
|
||||
g_list_append (flacparse->headers, gst_buffer_ref (buffer));
|
||||
flacparse->headers = g_list_append (flacparse->headers, sbuffer);
|
||||
|
||||
res = GST_BASE_PARSE_FLOW_DROPPED;
|
||||
} else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
|
||||
|
@ -1326,21 +1345,23 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
|
||||
GST_DEBUG_OBJECT (flacparse, "Handling metadata block of type %u", type);
|
||||
|
||||
sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
|
||||
|
||||
switch (type) {
|
||||
case 0: /* STREAMINFO */
|
||||
if (!gst_flac_parse_handle_streaminfo (flacparse, buffer))
|
||||
if (!gst_flac_parse_handle_streaminfo (flacparse, sbuffer))
|
||||
goto cleanup;
|
||||
break;
|
||||
case 3: /* SEEKTABLE */
|
||||
if (!gst_flac_parse_handle_seektable (flacparse, buffer))
|
||||
if (!gst_flac_parse_handle_seektable (flacparse, sbuffer))
|
||||
goto cleanup;
|
||||
break;
|
||||
case 4: /* VORBIS_COMMENT */
|
||||
if (!gst_flac_parse_handle_vorbiscomment (flacparse, buffer))
|
||||
if (!gst_flac_parse_handle_vorbiscomment (flacparse, sbuffer))
|
||||
goto cleanup;
|
||||
break;
|
||||
case 6: /* PICTURE */
|
||||
if (!gst_flac_parse_handle_picture (flacparse, buffer))
|
||||
if (!gst_flac_parse_handle_picture (flacparse, sbuffer))
|
||||
goto cleanup;
|
||||
break;
|
||||
case 1: /* PADDING */
|
||||
|
@ -1350,13 +1371,12 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||
break;
|
||||
}
|
||||
|
||||
GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_OFFSET (buffer) = 0;
|
||||
GST_BUFFER_OFFSET_END (buffer) = 0;
|
||||
GST_BUFFER_TIMESTAMP (sbuffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_DURATION (sbuffer) = GST_CLOCK_TIME_NONE;
|
||||
GST_BUFFER_OFFSET (sbuffer) = 0;
|
||||
GST_BUFFER_OFFSET_END (sbuffer) = 0;
|
||||
|
||||
flacparse->headers =
|
||||
g_list_append (flacparse->headers, gst_buffer_ref (buffer));
|
||||
flacparse->headers = g_list_append (flacparse->headers, sbuffer);
|
||||
|
||||
if (is_last) {
|
||||
if (!gst_flac_parse_handle_headers (flacparse))
|
||||
|
|
|
@ -91,10 +91,8 @@ 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,
|
||||
GstBaseParseFrame * frame, guint * size, gint * skipsize);
|
||||
static GstFlowReturn gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame);
|
||||
static GstFlowReturn gst_mpeg_audio_parse_handle_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, gint * skipsize);
|
||||
static GstFlowReturn gst_mpeg_audio_parse_pre_push_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame);
|
||||
static gboolean gst_mpeg_audio_parse_convert (GstBaseParse * parse,
|
||||
|
@ -103,6 +101,9 @@ static gboolean gst_mpeg_audio_parse_convert (GstBaseParse * parse,
|
|||
static GstCaps *gst_mpeg_audio_parse_get_sink_caps (GstBaseParse * parse,
|
||||
GstCaps * filter);
|
||||
|
||||
static void gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse *
|
||||
mp3parse, GstBuffer * buf);
|
||||
|
||||
#define gst_mpeg_audio_parse_parent_class parent_class
|
||||
G_DEFINE_TYPE (GstMpegAudioParse, gst_mpeg_audio_parse, GST_TYPE_BASE_PARSE);
|
||||
|
||||
|
@ -156,10 +157,8 @@ gst_mpeg_audio_parse_class_init (GstMpegAudioParseClass * klass)
|
|||
|
||||
parse_class->start = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_start);
|
||||
parse_class->stop = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_stop);
|
||||
parse_class->check_valid_frame =
|
||||
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->handle_frame =
|
||||
GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_handle_frame);
|
||||
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);
|
||||
|
@ -485,9 +484,9 @@ gst_mpeg_audio_parse_head_check (GstMpegAudioParse * mp3parse,
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
||||
static GstFlowReturn
|
||||
gst_mpeg_audio_parse_handle_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame, gint * skipsize)
|
||||
{
|
||||
GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
|
||||
GstBuffer *buf = frame->buffer;
|
||||
|
@ -500,8 +499,10 @@ gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
|
|||
gboolean res = FALSE;
|
||||
|
||||
gst_buffer_map (buf, &map, GST_MAP_READ);
|
||||
if (G_UNLIKELY (map.size < 6))
|
||||
if (G_UNLIKELY (map.size < 6)) {
|
||||
*skipsize = 1;
|
||||
goto cleanup;
|
||||
}
|
||||
|
||||
gst_byte_reader_init (&reader, map.data, map.size);
|
||||
|
||||
|
@ -566,12 +567,67 @@ gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
|
|||
/* restore default minimum */
|
||||
gst_base_parse_set_min_frame_size (parse, MIN_FRAME_SIZE);
|
||||
|
||||
*framesize = bpf;
|
||||
res = TRUE;
|
||||
|
||||
/* metadata handling */
|
||||
if (G_UNLIKELY (caps_change)) {
|
||||
GstCaps *caps = gst_caps_new_simple ("audio/mpeg",
|
||||
"mpegversion", G_TYPE_INT, 1,
|
||||
"mpegaudioversion", G_TYPE_INT, version,
|
||||
"layer", G_TYPE_INT, layer,
|
||||
"rate", G_TYPE_INT, rate,
|
||||
"channels", G_TYPE_INT, channels, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
|
||||
gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
mp3parse->rate = rate;
|
||||
mp3parse->channels = channels;
|
||||
mp3parse->layer = layer;
|
||||
mp3parse->version = version;
|
||||
|
||||
/* see http://www.codeproject.com/audio/MPEGAudioInfo.asp */
|
||||
if (mp3parse->layer == 1)
|
||||
mp3parse->spf = 384;
|
||||
else if (mp3parse->layer == 2)
|
||||
mp3parse->spf = 1152;
|
||||
else if (mp3parse->version == 1) {
|
||||
mp3parse->spf = 1152;
|
||||
} else {
|
||||
/* MPEG-2 or "2.5" */
|
||||
mp3parse->spf = 576;
|
||||
}
|
||||
|
||||
/* lead_in:
|
||||
* We start pushing 9 frames earlier (29 frames for MPEG2) than
|
||||
* segment start to be able to decode the first frame we want.
|
||||
* 9 (29) frames are the theoretical maximum of frames that contain
|
||||
* data for the current frame (bit reservoir).
|
||||
*
|
||||
* lead_out:
|
||||
* Some mp3 streams have an offset in the timestamps, for which we have to
|
||||
* push the frame *after* the end position in order for the decoder to be
|
||||
* able to decode everything up until the segment.stop position. */
|
||||
gst_base_parse_set_frame_rate (parse, mp3parse->rate, mp3parse->spf,
|
||||
(version == 1) ? 10 : 30, 2);
|
||||
}
|
||||
|
||||
mp3parse->hdr_bitrate = bitrate;
|
||||
|
||||
/* For first frame; check for seek tables and output a codec tag */
|
||||
gst_mpeg_audio_parse_handle_first_frame (mp3parse, buf);
|
||||
|
||||
/* store some frame info for later processing */
|
||||
mp3parse->last_crc = crc;
|
||||
mp3parse->last_mode = mode;
|
||||
|
||||
cleanup:
|
||||
gst_buffer_unmap (buf, &map);
|
||||
return res;
|
||||
|
||||
if (res && bpf <= map.size) {
|
||||
return gst_base_parse_finish_frame (parse, frame, bpf);
|
||||
}
|
||||
|
||||
return GST_FLOW_OK;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -977,94 +1033,6 @@ cleanup:
|
|||
gst_buffer_unmap (buf, &map);
|
||||
}
|
||||
|
||||
static GstFlowReturn
|
||||
gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
|
||||
GstBaseParseFrame * frame)
|
||||
{
|
||||
GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
|
||||
GstBuffer *buf = frame->buffer;
|
||||
GstMapInfo map;
|
||||
guint bitrate, layer, rate, channels, version, mode, crc;
|
||||
|
||||
gst_buffer_map (buf, &map, GST_MAP_READ);
|
||||
if (G_UNLIKELY (map.size < 4))
|
||||
goto short_buffer;
|
||||
|
||||
if (!mp3_type_frame_length_from_header (mp3parse,
|
||||
GST_READ_UINT32_BE (map.data),
|
||||
&version, &layer, &channels, &bitrate, &rate, &mode, &crc))
|
||||
goto broken_header;
|
||||
|
||||
if (G_UNLIKELY (channels != mp3parse->channels || rate != mp3parse->rate ||
|
||||
layer != mp3parse->layer || version != mp3parse->version)) {
|
||||
GstCaps *caps = gst_caps_new_simple ("audio/mpeg",
|
||||
"mpegversion", G_TYPE_INT, 1,
|
||||
"mpegaudioversion", G_TYPE_INT, version,
|
||||
"layer", G_TYPE_INT, layer,
|
||||
"rate", G_TYPE_INT, rate,
|
||||
"channels", G_TYPE_INT, channels, "parsed", G_TYPE_BOOLEAN, TRUE, NULL);
|
||||
gst_pad_set_caps (GST_BASE_PARSE_SRC_PAD (parse), caps);
|
||||
gst_caps_unref (caps);
|
||||
|
||||
mp3parse->rate = rate;
|
||||
mp3parse->channels = channels;
|
||||
mp3parse->layer = layer;
|
||||
mp3parse->version = version;
|
||||
|
||||
/* see http://www.codeproject.com/audio/MPEGAudioInfo.asp */
|
||||
if (mp3parse->layer == 1)
|
||||
mp3parse->spf = 384;
|
||||
else if (mp3parse->layer == 2)
|
||||
mp3parse->spf = 1152;
|
||||
else if (mp3parse->version == 1) {
|
||||
mp3parse->spf = 1152;
|
||||
} else {
|
||||
/* MPEG-2 or "2.5" */
|
||||
mp3parse->spf = 576;
|
||||
}
|
||||
|
||||
/* lead_in:
|
||||
* We start pushing 9 frames earlier (29 frames for MPEG2) than
|
||||
* segment start to be able to decode the first frame we want.
|
||||
* 9 (29) frames are the theoretical maximum of frames that contain
|
||||
* data for the current frame (bit reservoir).
|
||||
*
|
||||
* lead_out:
|
||||
* Some mp3 streams have an offset in the timestamps, for which we have to
|
||||
* push the frame *after* the end position in order for the decoder to be
|
||||
* able to decode everything up until the segment.stop position. */
|
||||
gst_base_parse_set_frame_rate (parse, mp3parse->rate, mp3parse->spf,
|
||||
(version == 1) ? 10 : 30, 2);
|
||||
}
|
||||
|
||||
mp3parse->hdr_bitrate = bitrate;
|
||||
|
||||
/* For first frame; check for seek tables and output a codec tag */
|
||||
gst_mpeg_audio_parse_handle_first_frame (mp3parse, buf);
|
||||
|
||||
/* store some frame info for later processing */
|
||||
mp3parse->last_crc = crc;
|
||||
mp3parse->last_mode = mode;
|
||||
|
||||
gst_buffer_unmap (buf, &map);
|
||||
return GST_FLOW_OK;
|
||||
|
||||
/* ERRORS */
|
||||
broken_header:
|
||||
{
|
||||
/* this really shouldn't ever happen */
|
||||
gst_buffer_unmap (buf, &map);
|
||||
GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), (NULL));
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
|
||||
short_buffer:
|
||||
{
|
||||
gst_buffer_unmap (buf, &map);
|
||||
return GST_FLOW_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
gst_mpeg_audio_parse_time_to_bytepos (GstMpegAudioParse * mp3parse,
|
||||
GstClockTime ts, gint64 * bytepos)
|
||||
|
|
Loading…
Reference in a new issue