audioparsers: adjust to modified baseparse API
This commit is contained in:
parent
e3b5a2e40d
commit
1ae32656ae
@ -89,11 +89,8 @@ static gboolean gst_aac_parse_sink_setcaps (GstBaseParse * parse,
|
|||||||
static GstCaps *gst_aac_parse_sink_getcaps (GstBaseParse * parse,
|
static GstCaps *gst_aac_parse_sink_getcaps (GstBaseParse * parse,
|
||||||
GstCaps * filter);
|
GstCaps * filter);
|
||||||
|
|
||||||
static gboolean gst_aac_parse_check_valid_frame (GstBaseParse * parse,
|
static GstFlowReturn gst_aac_parse_handle_frame (GstBaseParse * parse,
|
||||||
GstBaseParseFrame * frame, guint * size, gint * skipsize);
|
GstBaseParseFrame * frame, gint * skipsize);
|
||||||
|
|
||||||
static GstFlowReturn gst_aac_parse_parse_frame (GstBaseParse * parse,
|
|
||||||
GstBaseParseFrame * frame);
|
|
||||||
|
|
||||||
gboolean gst_aac_parse_convert (GstBaseParse * parse,
|
gboolean gst_aac_parse_convert (GstBaseParse * parse,
|
||||||
GstFormat src_format,
|
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->stop = GST_DEBUG_FUNCPTR (gst_aac_parse_stop);
|
||||||
parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_aac_parse_sink_setcaps);
|
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->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->handle_frame = GST_DEBUG_FUNCPTR (gst_aac_parse_handle_frame);
|
||||||
parse_class->check_valid_frame =
|
|
||||||
GST_DEBUG_FUNCPTR (gst_aac_parse_check_valid_frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -900,84 +895,11 @@ gst_aac_parse_detect_stream (GstAacParse * aacparse,
|
|||||||
/**
|
/**
|
||||||
* gst_aac_parse_check_valid_frame:
|
* gst_aac_parse_check_valid_frame:
|
||||||
* @parse: #GstBaseParse.
|
* @parse: #GstBaseParse.
|
||||||
* @buffer: #GstBuffer.
|
* @frame: #GstBaseParseFrame.
|
||||||
* @framesize: If the buffer contains a valid frame, its size will be put here
|
|
||||||
* @skipsize: How much data parent class should skip in order to find the
|
* @skipsize: How much data parent class should skip in order to find the
|
||||||
* frame header.
|
* frame header.
|
||||||
*
|
*
|
||||||
* Implementation of "check_valid_frame" vmethod in #GstBaseParse class.
|
* Implementation of "handle_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.
|
|
||||||
*
|
*
|
||||||
* Also determines frame overhead.
|
* Also determines frame overhead.
|
||||||
* ADTS streams have a 7 byte header in each frame. MP4 and ADIF streams don't have
|
* ADTS streams have a 7 byte header in each frame. MP4 and ADIF streams don't have
|
||||||
@ -992,47 +914,92 @@ gst_aac_parse_check_valid_frame (GstBaseParse * parse,
|
|||||||
* bits, which should still not be significant enough to warrant the
|
* bits, which should still not be significant enough to warrant the
|
||||||
* additional parsing through the headers
|
* additional parsing through the headers
|
||||||
*
|
*
|
||||||
* Returns: GST_FLOW_OK if frame was successfully parsed and can be pushed
|
* Returns: a #GstFlowReturn.
|
||||||
* forward. Otherwise appropriate error is returned.
|
|
||||||
*/
|
*/
|
||||||
static 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;
|
GstMapInfo map;
|
||||||
|
GstAacParse *aacparse;
|
||||||
|
gboolean ret = FALSE;
|
||||||
|
gboolean lost_sync;
|
||||||
|
GstBuffer *buffer;
|
||||||
|
guint framesize;
|
||||||
|
gint rate, channels;
|
||||||
|
|
||||||
aacparse = GST_AAC_PARSE (parse);
|
aacparse = GST_AAC_PARSE (parse);
|
||||||
buffer = frame->buffer;
|
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) {
|
if (aacparse->header_type == DSPAAC_HEADER_ADTS) {
|
||||||
/* see above */
|
/* see above */
|
||||||
frame->overhead = 7;
|
frame->overhead = 7;
|
||||||
|
|
||||||
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
|
||||||
gst_aac_parse_parse_adts_header (aacparse, map.data,
|
gst_aac_parse_parse_adts_header (aacparse, map.data,
|
||||||
&rate, &channels, NULL, NULL);
|
&rate, &channels, NULL, NULL);
|
||||||
gst_buffer_unmap (buffer, &map);
|
|
||||||
|
|
||||||
GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
|
GST_LOG_OBJECT (aacparse, "rate: %d, chans: %d", rate, channels);
|
||||||
|
|
||||||
if (G_UNLIKELY (rate != aacparse->sample_rate
|
if (G_UNLIKELY (rate != aacparse->sample_rate
|
||||||
|| channels != aacparse->channels)) {
|
|| channels != aacparse->channels)) {
|
||||||
GstCaps *sinkcaps;
|
|
||||||
|
|
||||||
aacparse->sample_rate = rate;
|
aacparse->sample_rate = rate;
|
||||||
aacparse->channels = channels;
|
aacparse->channels = channels;
|
||||||
|
|
||||||
if ((sinkcaps =
|
GST_DEBUG_OBJECT (aacparse, "here");
|
||||||
gst_pad_get_current_caps (GST_BASE_PARSE (aacparse)->sinkpad))) {
|
|
||||||
if (!gst_aac_parse_set_src_caps (aacparse, sinkcaps)) {
|
if (!gst_aac_parse_set_src_caps (aacparse, NULL)) {
|
||||||
/* If linking fails, we need to return appropriate error */
|
/* If linking fails, we need to return appropriate error */
|
||||||
ret = GST_FLOW_NOT_LINKED;
|
ret = GST_FLOW_NOT_LINKED;
|
||||||
}
|
}
|
||||||
gst_caps_unref (sinkcaps);
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
|
gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
|
||||||
aacparse->sample_rate, aacparse->frame_samples, 2, 2);
|
aacparse->sample_rate, aacparse->frame_samples, 2, 2);
|
||||||
@ -1043,7 +1010,6 @@ gst_aac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||||||
/* see above */
|
/* see above */
|
||||||
frame->overhead = 3;
|
frame->overhead = 3;
|
||||||
|
|
||||||
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
|
||||||
if (!gst_aac_parse_read_loas_config (aacparse, map.data, map.size, &rate,
|
if (!gst_aac_parse_read_loas_config (aacparse, map.data, map.size, &rate,
|
||||||
&channels, NULL)) {
|
&channels, NULL)) {
|
||||||
GST_WARNING_OBJECT (aacparse, "Error reading LOAS config");
|
GST_WARNING_OBJECT (aacparse, "Error reading LOAS config");
|
||||||
@ -1055,30 +1021,40 @@ gst_aac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||||||
GST_INFO_OBJECT (aacparse, "New LOAS config: %d Hz, %d channels", rate,
|
GST_INFO_OBJECT (aacparse, "New LOAS config: %d Hz, %d channels", rate,
|
||||||
channels);
|
channels);
|
||||||
}
|
}
|
||||||
gst_buffer_unmap (buffer, &map);
|
|
||||||
|
|
||||||
/* We want to set caps both at start, and when rate/channels change.
|
/* 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
|
Since only some LOAS frames have that info, we may receive frames
|
||||||
before knowing about rate/channels. */
|
before knowing about rate/channels. */
|
||||||
if (setcaps
|
if (setcaps
|
||||||
|| !gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (aacparse))) {
|
|| !gst_pad_has_current_caps (GST_BASE_PARSE_SRC_PAD (aacparse))) {
|
||||||
GstCaps *sinkcaps;
|
if (!gst_aac_parse_set_src_caps (aacparse, NULL)) {
|
||||||
|
|
||||||
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 */
|
/* If linking fails, we need to return appropriate error */
|
||||||
ret = GST_FLOW_NOT_LINKED;
|
ret = GST_FLOW_NOT_LINKED;
|
||||||
}
|
}
|
||||||
gst_caps_unref (sinkcaps);
|
|
||||||
}
|
|
||||||
|
|
||||||
gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
|
gst_base_parse_set_frame_rate (GST_BASE_PARSE (aacparse),
|
||||||
aacparse->sample_rate, aacparse->frame_samples, 2, 2);
|
aacparse->sample_rate, aacparse->frame_samples, 2, 2);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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_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 GstFlowReturn gst_ac3_parse_handle_frame (GstBaseParse * parse,
|
||||||
GstBaseParseFrame * frame, guint * size, gint * skipsize);
|
GstBaseParseFrame * frame, gint * skipsize);
|
||||||
static GstFlowReturn gst_ac3_parse_parse_frame (GstBaseParse * parse,
|
|
||||||
GstBaseParseFrame * frame);
|
|
||||||
static gboolean gst_ac3_parse_src_event (GstBaseParse * parse,
|
static gboolean gst_ac3_parse_src_event (GstBaseParse * parse,
|
||||||
GstEvent * event);
|
GstEvent * event);
|
||||||
static GstCaps *gst_ac3_parse_get_sink_caps (GstBaseParse * parse,
|
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->start = GST_DEBUG_FUNCPTR (gst_ac3_parse_start);
|
||||||
parse_class->stop = GST_DEBUG_FUNCPTR (gst_ac3_parse_stop);
|
parse_class->stop = GST_DEBUG_FUNCPTR (gst_ac3_parse_stop);
|
||||||
parse_class->check_valid_frame =
|
parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_ac3_parse_handle_frame);
|
||||||
GST_DEBUG_FUNCPTR (gst_ac3_parse_check_valid_frame);
|
|
||||||
parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_ac3_parse_parse_frame);
|
|
||||||
parse_class->src_event = GST_DEBUG_FUNCPTR (gst_ac3_parse_src_event);
|
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);
|
parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_ac3_parse_get_sink_caps);
|
||||||
}
|
}
|
||||||
@ -481,9 +477,9 @@ cleanup:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static GstFlowReturn
|
||||||
gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
|
gst_ac3_parse_handle_frame (GstBaseParse * parse,
|
||||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
GstBaseParseFrame * frame, gint * skipsize)
|
||||||
{
|
{
|
||||||
GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
|
GstAc3Parse *ac3parse = GST_AC3_PARSE (parse);
|
||||||
GstBuffer *buf = frame->buffer;
|
GstBuffer *buf = frame->buffer;
|
||||||
@ -491,14 +487,20 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
|
|||||||
gint off;
|
gint off;
|
||||||
gboolean lost_sync, draining, eac, more = FALSE;
|
gboolean lost_sync, draining, eac, more = FALSE;
|
||||||
guint frmsiz, blocks, sid;
|
guint frmsiz, blocks, sid;
|
||||||
|
guint rate, chans;
|
||||||
|
gboolean update_rate = FALSE;
|
||||||
|
gint framesize = 0;
|
||||||
gint have_blocks = 0;
|
gint have_blocks = 0;
|
||||||
GstMapInfo map;
|
GstMapInfo map;
|
||||||
gboolean ret = FALSE;
|
gboolean ret = FALSE;
|
||||||
|
GstFlowReturn res = GST_FLOW_OK;
|
||||||
|
|
||||||
gst_buffer_map (buf, &map, GST_MAP_READ);
|
gst_buffer_map (buf, &map, GST_MAP_READ);
|
||||||
|
|
||||||
if (G_UNLIKELY (map.size < 6))
|
if (G_UNLIKELY (map.size < 6)) {
|
||||||
|
*skipsize = 1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
gst_byte_reader_init (&reader, map.data, map.size);
|
gst_byte_reader_init (&reader, map.data, map.size);
|
||||||
off = gst_byte_reader_masked_scan_uint32 (&reader, 0xffff0000, 0x0b770000,
|
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 */
|
/* 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)) {
|
&blocks, &sid, &eac)) {
|
||||||
*skipsize = off + 2;
|
*skipsize = off + 2;
|
||||||
goto cleanup;
|
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) ==
|
if (G_UNLIKELY (g_atomic_int_get (&ac3parse->align) ==
|
||||||
GST_AC3_PARSE_ALIGN_NONE))
|
GST_AC3_PARSE_ALIGN_NONE))
|
||||||
@ -550,21 +555,21 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
*framesize = 0;
|
framesize = 0;
|
||||||
|
|
||||||
/* Loop till we have 6 blocks per substream */
|
/* Loop till we have 6 blocks per substream */
|
||||||
for (have_blocks = 0; !more && have_blocks < 6; have_blocks += blocks) {
|
for (have_blocks = 0; !more && have_blocks < 6; have_blocks += blocks) {
|
||||||
/* Loop till we get one frame from each substream */
|
/* Loop till we get one frame from each substream */
|
||||||
do {
|
do {
|
||||||
*framesize += frmsiz;
|
framesize += frmsiz;
|
||||||
|
|
||||||
if (!gst_byte_reader_skip (&reader, frmsiz)
|
if (!gst_byte_reader_skip (&reader, frmsiz)
|
||||||
|| map.size < (*framesize + 6)) {
|
|| map.size < (framesize + 6)) {
|
||||||
more = TRUE;
|
more = TRUE;
|
||||||
break;
|
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)) {
|
NULL, NULL, NULL, &sid, &eac)) {
|
||||||
*skipsize = off + 2;
|
*skipsize = off + 2;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -584,7 +589,7 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
|
|||||||
if (more || !gst_byte_reader_skip (&reader, frmsiz) ||
|
if (more || !gst_byte_reader_skip (&reader, frmsiz) ||
|
||||||
!gst_byte_reader_get_uint16_be (&reader, &word)) {
|
!gst_byte_reader_get_uint16_be (&reader, &word)) {
|
||||||
GST_DEBUG_OBJECT (ac3parse, "... but not sufficient data");
|
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;
|
*skipsize = 0;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else {
|
} else {
|
||||||
@ -594,34 +599,16 @@ gst_ac3_parse_check_valid_frame (GstBaseParse * parse,
|
|||||||
goto cleanup;
|
goto cleanup;
|
||||||
} else {
|
} else {
|
||||||
/* ok, got sync now, let's assume constant frame size */
|
/* 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;
|
ret = TRUE;
|
||||||
|
|
||||||
cleanup:
|
/* arrange for metadata setup */
|
||||||
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);
|
|
||||||
|
|
||||||
if (G_UNLIKELY (sid)) {
|
if (G_UNLIKELY (sid)) {
|
||||||
/* dependent frame, no need to (ac)count for or consider further */
|
/* dependent frame, no need to (ac)count for or consider further */
|
||||||
GST_LOG_OBJECT (parse, "sid: %d", sid);
|
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 */
|
/* occupies same time space as previous base frame */
|
||||||
if (G_LIKELY (GST_BUFFER_TIMESTAMP (buf) >= GST_BUFFER_DURATION (buf)))
|
if (G_LIKELY (GST_BUFFER_TIMESTAMP (buf) >= GST_BUFFER_DURATION (buf)))
|
||||||
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))
|
if (G_LIKELY (ac3parse->sample_rate > 0))
|
||||||
return GST_FLOW_OK;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (G_UNLIKELY (ac3parse->sample_rate != rate || ac3parse->channels != chans
|
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))
|
if (G_UNLIKELY (update_rate))
|
||||||
gst_base_parse_set_frame_rate (parse, rate, 256 * blocks, 2, 2);
|
gst_base_parse_set_frame_rate (parse, rate, 256 * blocks, 2, 2);
|
||||||
|
|
||||||
return GST_FLOW_OK;
|
cleanup:
|
||||||
|
gst_buffer_unmap (buf, &map);
|
||||||
|
|
||||||
/* ERRORS */
|
if (ret && framesize <= map.size) {
|
||||||
broken_header:
|
res = gst_base_parse_finish_frame (parse, frame, framesize);
|
||||||
{
|
|
||||||
/* this really shouldn't ever happen */
|
|
||||||
GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), (NULL));
|
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
|
@ -79,11 +79,8 @@ static gboolean gst_amr_parse_sink_setcaps (GstBaseParse * parse,
|
|||||||
static GstCaps *gst_amr_parse_sink_getcaps (GstBaseParse * parse,
|
static GstCaps *gst_amr_parse_sink_getcaps (GstBaseParse * parse,
|
||||||
GstCaps * filter);
|
GstCaps * filter);
|
||||||
|
|
||||||
static gboolean gst_amr_parse_check_valid_frame (GstBaseParse * parse,
|
static GstFlowReturn gst_amr_parse_handle_frame (GstBaseParse * parse,
|
||||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
|
GstBaseParseFrame * frame, gint * skipsize);
|
||||||
|
|
||||||
static GstFlowReturn gst_amr_parse_parse_frame (GstBaseParse * parse,
|
|
||||||
GstBaseParseFrame * frame);
|
|
||||||
|
|
||||||
G_DEFINE_TYPE (GstAmrParse, gst_amr_parse, GST_TYPE_BASE_PARSE);
|
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->stop = GST_DEBUG_FUNCPTR (gst_amr_parse_stop);
|
||||||
parse_class->set_sink_caps = GST_DEBUG_FUNCPTR (gst_amr_parse_sink_setcaps);
|
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->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->handle_frame = GST_DEBUG_FUNCPTR (gst_amr_parse_handle_frame);
|
||||||
parse_class->check_valid_frame =
|
|
||||||
GST_DEBUG_FUNCPTR (gst_amr_parse_check_valid_frame);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -254,15 +249,16 @@ gst_amr_parse_parse_header (GstAmrParse * amrparse,
|
|||||||
*
|
*
|
||||||
* Returns: TRUE if the given data contains valid frame.
|
* Returns: TRUE if the given data contains valid frame.
|
||||||
*/
|
*/
|
||||||
static gboolean
|
static GstFlowReturn
|
||||||
gst_amr_parse_check_valid_frame (GstBaseParse * parse,
|
gst_amr_parse_handle_frame (GstBaseParse * parse,
|
||||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
GstBaseParseFrame * frame, gint * skipsize)
|
||||||
{
|
{
|
||||||
GstBuffer *buffer;
|
GstBuffer *buffer;
|
||||||
GstMapInfo map;
|
GstMapInfo map;
|
||||||
gint fsize, mode, dsize;
|
gint fsize = 0, mode, dsize;
|
||||||
GstAmrParse *amrparse;
|
GstAmrParse *amrparse;
|
||||||
gboolean ret = FALSE;
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
gboolean found = FALSE;
|
||||||
|
|
||||||
amrparse = GST_AMR_PARSE (parse);
|
amrparse = GST_AMR_PARSE (parse);
|
||||||
buffer = frame->buffer;
|
buffer = frame->buffer;
|
||||||
@ -285,6 +281,7 @@ gst_amr_parse_check_valid_frame (GstBaseParse * parse,
|
|||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
*skipsize = 1;
|
||||||
/* Does this look like a possible frame header candidate? */
|
/* Does this look like a possible frame header candidate? */
|
||||||
if ((map.data[0] & 0x83) == 0) {
|
if ((map.data[0] & 0x83) == 0) {
|
||||||
/* Yep. Retrieve the frame size */
|
/* Yep. Retrieve the frame size */
|
||||||
@ -299,8 +296,7 @@ gst_amr_parse_check_valid_frame (GstBaseParse * parse,
|
|||||||
* perform this check)
|
* perform this check)
|
||||||
*/
|
*/
|
||||||
if (fsize) {
|
if (fsize) {
|
||||||
gboolean found = FALSE;
|
*skipsize = 0;
|
||||||
|
|
||||||
/* in sync, no further check */
|
/* in sync, no further check */
|
||||||
if (!GST_BASE_PARSE_LOST_SYNC (parse)) {
|
if (!GST_BASE_PARSE_LOST_SYNC (parse)) {
|
||||||
found = TRUE;
|
found = TRUE;
|
||||||
@ -311,42 +307,20 @@ gst_amr_parse_check_valid_frame (GstBaseParse * parse,
|
|||||||
} else if (GST_BASE_PARSE_DRAINING (parse)) {
|
} else if (GST_BASE_PARSE_DRAINING (parse)) {
|
||||||
/* not enough, but draining, so ok */
|
/* not enough, but draining, so ok */
|
||||||
found = TRUE;
|
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:
|
done:
|
||||||
gst_buffer_unmap (buffer, &map);
|
gst_buffer_unmap (buffer, &map);
|
||||||
|
|
||||||
|
if (found && fsize <= map.size) {
|
||||||
|
ret = gst_base_parse_finish_frame (parse, frame, fsize);
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
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:
|
* gst_amr_parse_start:
|
||||||
* @parse: #GstBaseParse.
|
* @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_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 GstFlowReturn gst_dca_parse_handle_frame (GstBaseParse * parse,
|
||||||
GstBaseParseFrame * frame, guint * size, gint * skipsize);
|
GstBaseParseFrame * frame, gint * skipsize);
|
||||||
static GstFlowReturn gst_dca_parse_parse_frame (GstBaseParse * parse,
|
|
||||||
GstBaseParseFrame * frame);
|
|
||||||
static GstCaps *gst_dca_parse_get_sink_caps (GstBaseParse * parse,
|
static GstCaps *gst_dca_parse_get_sink_caps (GstBaseParse * parse,
|
||||||
GstCaps * filter);
|
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->start = GST_DEBUG_FUNCPTR (gst_dca_parse_start);
|
||||||
parse_class->stop = GST_DEBUG_FUNCPTR (gst_dca_parse_stop);
|
parse_class->stop = GST_DEBUG_FUNCPTR (gst_dca_parse_stop);
|
||||||
parse_class->check_valid_frame =
|
parse_class->handle_frame = GST_DEBUG_FUNCPTR (gst_dca_parse_handle_frame);
|
||||||
GST_DEBUG_FUNCPTR (gst_dca_parse_check_valid_frame);
|
|
||||||
parse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_dca_parse_parse_frame);
|
|
||||||
parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_dca_parse_get_sink_caps);
|
parse_class->get_sink_caps = GST_DEBUG_FUNCPTR (gst_dca_parse_get_sink_caps);
|
||||||
|
|
||||||
gst_element_class_add_pad_template (element_class,
|
gst_element_class_add_pad_template (element_class,
|
||||||
@ -305,9 +301,9 @@ gst_dca_parse_find_sync (GstDcaParse * dcaparse, GstByteReader * reader,
|
|||||||
return best_offset;
|
return best_offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static GstFlowReturn
|
||||||
gst_dca_parse_check_valid_frame (GstBaseParse * parse,
|
gst_dca_parse_handle_frame (GstBaseParse * parse,
|
||||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
GstBaseParseFrame * frame, gint * skipsize)
|
||||||
{
|
{
|
||||||
GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
|
GstDcaParse *dcaparse = GST_DCA_PARSE (parse);
|
||||||
GstBuffer *buf = frame->buffer;
|
GstBuffer *buf = frame->buffer;
|
||||||
@ -316,15 +312,19 @@ gst_dca_parse_check_valid_frame (GstBaseParse * parse,
|
|||||||
gboolean parser_in_sync;
|
gboolean parser_in_sync;
|
||||||
gboolean terminator;
|
gboolean terminator;
|
||||||
guint32 sync = 0;
|
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;
|
gint off = -1;
|
||||||
GstMapInfo map;
|
GstMapInfo map;
|
||||||
gboolean ret = FALSE;
|
GstFlowReturn ret = GST_FLOW_EOS;
|
||||||
|
|
||||||
gst_buffer_map (buf, &map, GST_MAP_READ);
|
gst_buffer_map (buf, &map, GST_MAP_READ);
|
||||||
|
|
||||||
if (G_UNLIKELY (map.size < 16))
|
if (G_UNLIKELY (map.size < 16)) {
|
||||||
|
*skipsize = 1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
parser_in_sync = !GST_BASE_PARSE_LOST_SYNC (parse);
|
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 */
|
/* make sure the values in the frame header look sane */
|
||||||
if (!gst_dca_parse_parse_header (dcaparse, &r, &size, &rate, &chans, NULL,
|
if (!gst_dca_parse_parse_header (dcaparse, &r, &size, &rate, &chans, &depth,
|
||||||
NULL, &num_blocks, &samples_per_block, &terminator)) {
|
&endianness, &num_blocks, &samples_per_block, &terminator)) {
|
||||||
*skipsize = 4;
|
*skipsize = 4;
|
||||||
goto cleanup;
|
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",
|
GST_LOG_OBJECT (parse, "got frame, sync %08x, size %u, rate %d, channels %d",
|
||||||
sync, size, rate, chans);
|
sync, size, rate, chans);
|
||||||
|
|
||||||
*framesize = size;
|
|
||||||
|
|
||||||
dcaparse->last_sync = sync;
|
dcaparse->last_sync = sync;
|
||||||
|
|
||||||
parser_draining = GST_BASE_PARSE_DRAINING (parse);
|
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 */
|
/* ok, got sync now, let's assume constant frame size */
|
||||||
gst_base_parse_set_min_frame_size (parse, size);
|
gst_base_parse_set_min_frame_size (parse, size);
|
||||||
} else {
|
} else {
|
||||||
/* FIXME: baseparse always seems to hand us buffers of min_frame_size
|
/* wait for some more data */
|
||||||
* bytes, which is unhelpful here */
|
|
||||||
GST_LOG_OBJECT (dcaparse,
|
GST_LOG_OBJECT (dcaparse,
|
||||||
"next sync out of reach (%" G_GSIZE_FORMAT " < %u)", map.size,
|
"next sync out of reach (%" G_GSIZE_FORMAT " < %u)", map.size,
|
||||||
size + 16);
|
size + 16);
|
||||||
/* *skipsize = 0; */
|
goto cleanup;
|
||||||
/* return FALSE; */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = TRUE;
|
/* found frame */
|
||||||
|
ret = GST_FLOW_OK;
|
||||||
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;
|
|
||||||
|
|
||||||
|
/* metadata handling */
|
||||||
block_size = num_blocks * samples_per_block;
|
block_size = num_blocks * samples_per_block;
|
||||||
|
|
||||||
if (G_UNLIKELY (dcaparse->rate != rate || dcaparse->channels != chans
|
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);
|
gst_base_parse_set_frame_rate (parse, rate, block_size, 0, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
cleanup:
|
||||||
gst_buffer_unmap (buf, &map);
|
gst_buffer_unmap (buf, &map);
|
||||||
return GST_FLOW_OK;
|
|
||||||
|
|
||||||
/* ERRORS */
|
if (ret == GST_FLOW_OK && size <= map.size) {
|
||||||
broken_header:
|
ret = gst_base_parse_finish_frame (parse, frame, size);
|
||||||
{
|
} else {
|
||||||
/* this really shouldn't ever happen */
|
ret = GST_FLOW_OK;
|
||||||
GST_ELEMENT_ERROR (parse, STREAM, DECODE, (NULL), (NULL));
|
|
||||||
gst_buffer_unmap (buf, &map);
|
|
||||||
return GST_FLOW_ERROR;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static GstCaps *
|
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_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 GstFlowReturn gst_flac_parse_handle_frame (GstBaseParse * parse,
|
||||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize);
|
GstBaseParseFrame * frame, gint * skipsize);
|
||||||
static GstFlowReturn gst_flac_parse_parse_frame (GstBaseParse * parse,
|
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,
|
static GstFlowReturn gst_flac_parse_pre_push_frame (GstBaseParse * parse,
|
||||||
GstBaseParseFrame * frame);
|
GstBaseParseFrame * frame);
|
||||||
static gboolean gst_flac_parse_convert (GstBaseParse * parse,
|
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->start = GST_DEBUG_FUNCPTR (gst_flac_parse_start);
|
||||||
baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_flac_parse_stop);
|
baseparse_class->stop = GST_DEBUG_FUNCPTR (gst_flac_parse_stop);
|
||||||
baseparse_class->check_valid_frame =
|
baseparse_class->handle_frame =
|
||||||
GST_DEBUG_FUNCPTR (gst_flac_parse_check_valid_frame);
|
GST_DEBUG_FUNCPTR (gst_flac_parse_handle_frame);
|
||||||
baseparse_class->parse_frame = GST_DEBUG_FUNCPTR (gst_flac_parse_parse_frame);
|
|
||||||
baseparse_class->pre_push_frame =
|
baseparse_class->pre_push_frame =
|
||||||
GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
|
GST_DEBUG_FUNCPTR (gst_flac_parse_pre_push_frame);
|
||||||
baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert);
|
baseparse_class->convert = GST_DEBUG_FUNCPTR (gst_flac_parse_convert);
|
||||||
@ -704,17 +703,21 @@ cleanup:
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static GstFlowReturn
|
||||||
gst_flac_parse_check_valid_frame (GstBaseParse * parse,
|
gst_flac_parse_handle_frame (GstBaseParse * parse,
|
||||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
GstBaseParseFrame * frame, gint * skipsize)
|
||||||
{
|
{
|
||||||
GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
|
GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
|
||||||
GstBuffer *buffer = frame->buffer;
|
GstBuffer *buffer = frame->buffer;
|
||||||
GstMapInfo map;
|
GstMapInfo map;
|
||||||
gboolean result = TRUE;
|
gboolean result = TRUE;
|
||||||
|
GstFlowReturn ret = GST_FLOW_OK;
|
||||||
|
guint framesize;
|
||||||
|
|
||||||
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||||
|
|
||||||
|
*skipsize = 1;
|
||||||
|
|
||||||
if (G_UNLIKELY (map.size < 4)) {
|
if (G_UNLIKELY (map.size < 4)) {
|
||||||
result = FALSE;
|
result = FALSE;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
@ -723,7 +726,7 @@ gst_flac_parse_check_valid_frame (GstBaseParse * parse,
|
|||||||
if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
|
if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
|
||||||
if (memcmp (map.data, "fLaC", 4) == 0) {
|
if (memcmp (map.data, "fLaC", 4) == 0) {
|
||||||
GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
|
GST_DEBUG_OBJECT (flacparse, "fLaC marker found");
|
||||||
*framesize = 4;
|
framesize = 4;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
if (map.data[0] == 0xff && (map.data[1] >> 2) == 0x3e) {
|
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]));
|
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);
|
GST_DEBUG_OBJECT (flacparse, "Found metadata block of size %u", size);
|
||||||
*framesize = size;
|
framesize = size;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -759,7 +762,7 @@ gst_flac_parse_check_valid_frame (GstBaseParse * parse,
|
|||||||
GST_DEBUG_OBJECT (flacparse, "Found sync code");
|
GST_DEBUG_OBJECT (flacparse, "Found sync code");
|
||||||
ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
|
ret = gst_flac_parse_frame_is_valid (flacparse, frame, &next);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
*framesize = next;
|
framesize = next;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
} 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! */
|
||||||
@ -809,7 +812,21 @@ gst_flac_parse_check_valid_frame (GstBaseParse * parse,
|
|||||||
|
|
||||||
cleanup:
|
cleanup:
|
||||||
gst_buffer_unmap (buffer, &map);
|
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
|
static gboolean
|
||||||
@ -1166,6 +1183,7 @@ push_headers:
|
|||||||
res = FALSE;
|
res = FALSE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
gst_base_parse_frame_free (&frame);
|
||||||
}
|
}
|
||||||
g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
|
g_list_foreach (flacparse->headers, (GFunc) gst_mini_object_unref, NULL);
|
||||||
g_list_free (flacparse->headers);
|
g_list_free (flacparse->headers);
|
||||||
@ -1291,27 +1309,28 @@ gst_flac_parse_generate_headers (GstFlacParse * flacparse)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static GstFlowReturn
|
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);
|
GstFlacParse *flacparse = GST_FLAC_PARSE (parse);
|
||||||
GstBuffer *buffer = frame->buffer;
|
GstBuffer *buffer = frame->buffer, *sbuffer;
|
||||||
GstMapInfo map;
|
GstMapInfo map;
|
||||||
GstFlowReturn res = GST_FLOW_ERROR;
|
GstFlowReturn res = GST_FLOW_ERROR;
|
||||||
|
|
||||||
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
gst_buffer_map (buffer, &map, GST_MAP_READ);
|
||||||
|
|
||||||
if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
|
if (flacparse->state == GST_FLAC_PARSE_STATE_INIT) {
|
||||||
GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
|
sbuffer = gst_buffer_copy_region (buffer, GST_BUFFER_COPY_ALL, 0, size);
|
||||||
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
|
GST_BUFFER_TIMESTAMP (sbuffer) = GST_CLOCK_TIME_NONE;
|
||||||
GST_BUFFER_OFFSET (buffer) = 0;
|
GST_BUFFER_DURATION (sbuffer) = GST_CLOCK_TIME_NONE;
|
||||||
GST_BUFFER_OFFSET_END (buffer) = 0;
|
GST_BUFFER_OFFSET (sbuffer) = 0;
|
||||||
|
GST_BUFFER_OFFSET_END (sbuffer) = 0;
|
||||||
|
|
||||||
/* 32 bits metadata block */
|
/* 32 bits metadata block */
|
||||||
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
|
gst_base_parse_set_min_frame_size (GST_BASE_PARSE (flacparse), 4);
|
||||||
flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
|
flacparse->state = GST_FLAC_PARSE_STATE_HEADERS;
|
||||||
|
|
||||||
flacparse->headers =
|
flacparse->headers = g_list_append (flacparse->headers, sbuffer);
|
||||||
g_list_append (flacparse->headers, gst_buffer_ref (buffer));
|
|
||||||
|
|
||||||
res = GST_BASE_PARSE_FLOW_DROPPED;
|
res = GST_BASE_PARSE_FLOW_DROPPED;
|
||||||
} else if (flacparse->state == GST_FLAC_PARSE_STATE_HEADERS) {
|
} 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);
|
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) {
|
switch (type) {
|
||||||
case 0: /* STREAMINFO */
|
case 0: /* STREAMINFO */
|
||||||
if (!gst_flac_parse_handle_streaminfo (flacparse, buffer))
|
if (!gst_flac_parse_handle_streaminfo (flacparse, sbuffer))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
break;
|
break;
|
||||||
case 3: /* SEEKTABLE */
|
case 3: /* SEEKTABLE */
|
||||||
if (!gst_flac_parse_handle_seektable (flacparse, buffer))
|
if (!gst_flac_parse_handle_seektable (flacparse, sbuffer))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
break;
|
break;
|
||||||
case 4: /* VORBIS_COMMENT */
|
case 4: /* VORBIS_COMMENT */
|
||||||
if (!gst_flac_parse_handle_vorbiscomment (flacparse, buffer))
|
if (!gst_flac_parse_handle_vorbiscomment (flacparse, sbuffer))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
break;
|
break;
|
||||||
case 6: /* PICTURE */
|
case 6: /* PICTURE */
|
||||||
if (!gst_flac_parse_handle_picture (flacparse, buffer))
|
if (!gst_flac_parse_handle_picture (flacparse, sbuffer))
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
break;
|
break;
|
||||||
case 1: /* PADDING */
|
case 1: /* PADDING */
|
||||||
@ -1350,13 +1371,12 @@ gst_flac_parse_parse_frame (GstBaseParse * parse, GstBaseParseFrame * frame)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
GST_BUFFER_TIMESTAMP (buffer) = GST_CLOCK_TIME_NONE;
|
GST_BUFFER_TIMESTAMP (sbuffer) = GST_CLOCK_TIME_NONE;
|
||||||
GST_BUFFER_DURATION (buffer) = GST_CLOCK_TIME_NONE;
|
GST_BUFFER_DURATION (sbuffer) = GST_CLOCK_TIME_NONE;
|
||||||
GST_BUFFER_OFFSET (buffer) = 0;
|
GST_BUFFER_OFFSET (sbuffer) = 0;
|
||||||
GST_BUFFER_OFFSET_END (buffer) = 0;
|
GST_BUFFER_OFFSET_END (sbuffer) = 0;
|
||||||
|
|
||||||
flacparse->headers =
|
flacparse->headers = g_list_append (flacparse->headers, sbuffer);
|
||||||
g_list_append (flacparse->headers, gst_buffer_ref (buffer));
|
|
||||||
|
|
||||||
if (is_last) {
|
if (is_last) {
|
||||||
if (!gst_flac_parse_handle_headers (flacparse))
|
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_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 GstFlowReturn gst_mpeg_audio_parse_handle_frame (GstBaseParse * parse,
|
||||||
GstBaseParseFrame * frame, guint * size, gint * skipsize);
|
GstBaseParseFrame * frame, gint * skipsize);
|
||||||
static GstFlowReturn gst_mpeg_audio_parse_parse_frame (GstBaseParse * parse,
|
|
||||||
GstBaseParseFrame * frame);
|
|
||||||
static GstFlowReturn gst_mpeg_audio_parse_pre_push_frame (GstBaseParse * parse,
|
static GstFlowReturn gst_mpeg_audio_parse_pre_push_frame (GstBaseParse * parse,
|
||||||
GstBaseParseFrame * frame);
|
GstBaseParseFrame * frame);
|
||||||
static gboolean gst_mpeg_audio_parse_convert (GstBaseParse * parse,
|
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,
|
static GstCaps *gst_mpeg_audio_parse_get_sink_caps (GstBaseParse * parse,
|
||||||
GstCaps * filter);
|
GstCaps * filter);
|
||||||
|
|
||||||
|
static void gst_mpeg_audio_parse_handle_first_frame (GstMpegAudioParse *
|
||||||
|
mp3parse, GstBuffer * buf);
|
||||||
|
|
||||||
#define gst_mpeg_audio_parse_parent_class parent_class
|
#define gst_mpeg_audio_parse_parent_class parent_class
|
||||||
G_DEFINE_TYPE (GstMpegAudioParse, gst_mpeg_audio_parse, GST_TYPE_BASE_PARSE);
|
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->start = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_start);
|
||||||
parse_class->stop = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_stop);
|
parse_class->stop = GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_stop);
|
||||||
parse_class->check_valid_frame =
|
parse_class->handle_frame =
|
||||||
GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_check_valid_frame);
|
GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_handle_frame);
|
||||||
parse_class->parse_frame =
|
|
||||||
GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_parse_frame);
|
|
||||||
parse_class->pre_push_frame =
|
parse_class->pre_push_frame =
|
||||||
GST_DEBUG_FUNCPTR (gst_mpeg_audio_parse_pre_push_frame);
|
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);
|
||||||
@ -485,9 +484,9 @@ gst_mpeg_audio_parse_head_check (GstMpegAudioParse * mp3parse,
|
|||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static GstFlowReturn
|
||||||
gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
|
gst_mpeg_audio_parse_handle_frame (GstBaseParse * parse,
|
||||||
GstBaseParseFrame * frame, guint * framesize, gint * skipsize)
|
GstBaseParseFrame * frame, gint * skipsize)
|
||||||
{
|
{
|
||||||
GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
|
GstMpegAudioParse *mp3parse = GST_MPEG_AUDIO_PARSE (parse);
|
||||||
GstBuffer *buf = frame->buffer;
|
GstBuffer *buf = frame->buffer;
|
||||||
@ -500,8 +499,10 @@ gst_mpeg_audio_parse_check_valid_frame (GstBaseParse * parse,
|
|||||||
gboolean res = FALSE;
|
gboolean res = FALSE;
|
||||||
|
|
||||||
gst_buffer_map (buf, &map, GST_MAP_READ);
|
gst_buffer_map (buf, &map, GST_MAP_READ);
|
||||||
if (G_UNLIKELY (map.size < 6))
|
if (G_UNLIKELY (map.size < 6)) {
|
||||||
|
*skipsize = 1;
|
||||||
goto cleanup;
|
goto cleanup;
|
||||||
|
}
|
||||||
|
|
||||||
gst_byte_reader_init (&reader, map.data, map.size);
|
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 */
|
/* restore default minimum */
|
||||||
gst_base_parse_set_min_frame_size (parse, MIN_FRAME_SIZE);
|
gst_base_parse_set_min_frame_size (parse, MIN_FRAME_SIZE);
|
||||||
|
|
||||||
*framesize = bpf;
|
|
||||||
res = TRUE;
|
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:
|
cleanup:
|
||||||
gst_buffer_unmap (buf, &map);
|
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
|
static void
|
||||||
@ -977,94 +1033,6 @@ cleanup:
|
|||||||
gst_buffer_unmap (buf, &map);
|
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
|
static gboolean
|
||||||
gst_mpeg_audio_parse_time_to_bytepos (GstMpegAudioParse * mp3parse,
|
gst_mpeg_audio_parse_time_to_bytepos (GstMpegAudioParse * mp3parse,
|
||||||
GstClockTime ts, gint64 * bytepos)
|
GstClockTime ts, gint64 * bytepos)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user