mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 12:11:13 +00:00
flacdec: we expect framed input now, remove some more code
This commit is contained in:
parent
92361863e6
commit
5ab43cdf91
2 changed files with 32 additions and 120 deletions
|
@ -247,6 +247,19 @@ static gboolean
|
||||||
gst_flac_dec_set_format (GstAudioDecoder * dec, GstCaps * caps)
|
gst_flac_dec_set_format (GstAudioDecoder * dec, GstCaps * caps)
|
||||||
{
|
{
|
||||||
/* if stream headers are present we could process them here already */
|
/* if stream headers are present we could process them here already */
|
||||||
|
#if 0
|
||||||
|
///gst_adapter_push (dec->adapter, gst_buffer_ref (buf)); // for all stream headers
|
||||||
|
/* The first time we get audio data, we know we got all the headers.
|
||||||
|
* We then loop until all the metadata is processed, then do an extra
|
||||||
|
* "process_single" step for the audio frame. */
|
||||||
|
GST_DEBUG_OBJECT (dec,
|
||||||
|
"First audio frame, ensuring all metadata is processed");
|
||||||
|
if (!FLAC__stream_decoder_process_until_end_of_metadata (dec->decoder)) {
|
||||||
|
GST_DEBUG_OBJECT (dec, "process_until_end_of_metadata failed");
|
||||||
|
}
|
||||||
|
GST_DEBUG_OBJECT (dec, "All headers and metadata are now processed");
|
||||||
|
#endif
|
||||||
|
/* FIXME: refuse caps is there are no stream headers */
|
||||||
GST_LOG_OBJECT (dec, "sink caps: %" GST_PTR_FORMAT, caps);
|
GST_LOG_OBJECT (dec, "sink caps: %" GST_PTR_FORMAT, caps);
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
@ -335,6 +348,8 @@ gst_flac_calculate_crc8 (guint8 * data, guint length)
|
||||||
return crc;
|
return crc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* FIXME: for our purposes it's probably enough to just check for the sync
|
||||||
|
* marker - we just want to know if it's a header frame or not */
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_flac_dec_scan_got_frame (GstFlacDec * flacdec, guint8 * data, guint size,
|
gst_flac_dec_scan_got_frame (GstFlacDec * flacdec, guint8 * data, guint size,
|
||||||
gint64 * last_sample_num)
|
gint64 * last_sample_num)
|
||||||
|
@ -684,11 +699,7 @@ gst_flac_dec_write (GstFlacDec * flacdec, const FLAC__Frame * frame,
|
||||||
}
|
}
|
||||||
gst_buffer_unmap (outbuf, data, size);
|
gst_buffer_unmap (outbuf, data, size);
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (flacdec, "pushing %d samples at offset %" G_GINT64_FORMAT
|
GST_DEBUG_OBJECT (flacdec, "pushing %d samples", samples);
|
||||||
" (%" GST_TIME_FORMAT " + %" GST_TIME_FORMAT ")",
|
|
||||||
samples, GST_BUFFER_OFFSET (outbuf),
|
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (outbuf)),
|
|
||||||
GST_TIME_ARGS (GST_BUFFER_DURATION (outbuf)));
|
|
||||||
|
|
||||||
ret = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (flacdec), outbuf, 1);
|
ret = gst_audio_decoder_finish_frame (GST_AUDIO_DECODER (flacdec), outbuf, 1);
|
||||||
|
|
||||||
|
@ -733,58 +744,10 @@ gst_flac_dec_flush (GstAudioDecoder * audio_dec, gboolean hard)
|
||||||
gst_adapter_clear (dec->adapter);
|
gst_adapter_clear (dec->adapter);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
gst_flac_dec_chain_parse_headers (GstFlacDec * dec)
|
|
||||||
{
|
|
||||||
guint8 marker[4];
|
|
||||||
guint avail, off;
|
|
||||||
|
|
||||||
avail = gst_adapter_available (dec->adapter);
|
|
||||||
if (avail < 4)
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
gst_adapter_copy (dec->adapter, marker, 0, 4);
|
|
||||||
if (strncmp ((const gchar *) marker, "fLaC", 4) != 0) {
|
|
||||||
GST_ERROR_OBJECT (dec, "Unexpected header, expected fLaC header");
|
|
||||||
return TRUE; /* abort header parsing */
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (dec, "fLaC header : len 4 @ %7u", 0);
|
|
||||||
|
|
||||||
off = 4;
|
|
||||||
while (avail > (off + 1 + 3)) {
|
|
||||||
gboolean is_last;
|
|
||||||
guint8 mb_hdr[4];
|
|
||||||
guint len, block_type;
|
|
||||||
|
|
||||||
gst_adapter_copy (dec->adapter, mb_hdr, off, 4);
|
|
||||||
|
|
||||||
is_last = ((mb_hdr[0] & 0x80) == 0x80);
|
|
||||||
block_type = mb_hdr[0] & 0x7f;
|
|
||||||
len = GST_READ_UINT24_BE (mb_hdr + 1);
|
|
||||||
GST_DEBUG_OBJECT (dec, "Metadata block type %u: len %7u + 4 @ %7u%s",
|
|
||||||
block_type, len, off, (is_last) ? " (last)" : "");
|
|
||||||
off += 4 + len;
|
|
||||||
|
|
||||||
if (is_last)
|
|
||||||
break;
|
|
||||||
|
|
||||||
if (off >= avail) {
|
|
||||||
GST_LOG_OBJECT (dec, "Need more data: next offset %u > avail %u", off,
|
|
||||||
avail);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* want metadata blocks plus at least one frame */
|
|
||||||
return (off + FLAC__MAX_BLOCK_SIZE >= avail);
|
|
||||||
}
|
|
||||||
|
|
||||||
static GstFlowReturn
|
static GstFlowReturn
|
||||||
gst_flac_dec_handle_frame (GstAudioDecoder * audio_dec, GstBuffer * buf)
|
gst_flac_dec_handle_frame (GstAudioDecoder * audio_dec, GstBuffer * buf)
|
||||||
{
|
{
|
||||||
GstFlacDec *dec;
|
GstFlacDec *dec;
|
||||||
gboolean got_audio_frame;
|
|
||||||
|
|
||||||
dec = GST_FLAC_DEC (audio_dec);
|
dec = GST_FLAC_DEC (audio_dec);
|
||||||
|
|
||||||
|
@ -798,13 +761,9 @@ gst_flac_dec_handle_frame (GstAudioDecoder * audio_dec, GstBuffer * buf)
|
||||||
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_BUFFER_FLAGS (buf),
|
GST_TIME_ARGS (GST_BUFFER_TIMESTAMP (buf)), GST_BUFFER_FLAGS (buf),
|
||||||
gst_buffer_get_size (buf));
|
gst_buffer_get_size (buf));
|
||||||
|
|
||||||
|
/* drop any in-stream headers, we've processed those in set_format already */
|
||||||
if (G_UNLIKELY (!dec->got_headers)) {
|
if (G_UNLIKELY (!dec->got_headers)) {
|
||||||
// FIXME
|
gboolean got_audio_frame;
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: should always be framed */
|
|
||||||
dec->framed = TRUE;
|
|
||||||
if (dec->framed) {
|
|
||||||
gint64 unused;
|
gint64 unused;
|
||||||
guint8 *data;
|
guint8 *data;
|
||||||
gsize size;
|
gsize size;
|
||||||
|
@ -813,8 +772,14 @@ gst_flac_dec_handle_frame (GstAudioDecoder * audio_dec, GstBuffer * buf)
|
||||||
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
|
data = gst_buffer_map (buf, &size, NULL, GST_MAP_READ);
|
||||||
got_audio_frame = gst_flac_dec_scan_got_frame (dec, data, size, &unused);
|
got_audio_frame = gst_flac_dec_scan_got_frame (dec, data, size, &unused);
|
||||||
gst_buffer_unmap (buf, data, size);
|
gst_buffer_unmap (buf, data, size);
|
||||||
} else {
|
|
||||||
got_audio_frame = TRUE;
|
if (!got_audio_frame) {
|
||||||
|
GST_INFO_OBJECT (dec, "dropping in-stream header, %d bytes", size);
|
||||||
|
return GST_FLOW_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_INFO_OBJECT (dec, "first audio frame, got all in-stream headers now");
|
||||||
|
dec->got_headers = TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
gst_adapter_push (dec->adapter, gst_buffer_ref (buf));
|
gst_adapter_push (dec->adapter, gst_buffer_ref (buf));
|
||||||
|
@ -822,65 +787,13 @@ gst_flac_dec_handle_frame (GstAudioDecoder * audio_dec, GstBuffer * buf)
|
||||||
|
|
||||||
dec->last_flow = GST_FLOW_OK;
|
dec->last_flow = GST_FLOW_OK;
|
||||||
|
|
||||||
if (!dec->framed) {
|
|
||||||
if (G_UNLIKELY (!dec->got_headers)) {
|
|
||||||
if (!gst_flac_dec_chain_parse_headers (dec)) {
|
|
||||||
GST_LOG_OBJECT (dec, "don't have metadata blocks yet, need more data");
|
|
||||||
goto out;
|
|
||||||
}
|
|
||||||
GST_INFO_OBJECT (dec, "have all metadata blocks now");
|
|
||||||
dec->got_headers = TRUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* wait until we have at least 64kB because libflac's StreamDecoder
|
|
||||||
* interface is a bit dumb it seems (if we don't have as much data as
|
|
||||||
* it wants it will call our read callback repeatedly and the only
|
|
||||||
* way to stop that is to error out or EOS, which will affect the
|
|
||||||
* decoder state). And the decoder seems to always ask for MAX_BLOCK_SIZE
|
|
||||||
* bytes rather than the max. block size from the header). Requiring
|
|
||||||
* MAX_BLOCK_SIZE bytes here should make sure it always gets enough data
|
|
||||||
* to decode at least one block */
|
|
||||||
while (gst_adapter_available (dec->adapter) >= FLAC__MAX_BLOCK_SIZE &&
|
|
||||||
dec->last_flow == GST_FLOW_OK) {
|
|
||||||
GST_LOG_OBJECT (dec, "%u bytes available",
|
|
||||||
gst_adapter_available (dec->adapter));
|
|
||||||
if (!FLAC__stream_decoder_process_single (dec->decoder)) {
|
|
||||||
GST_DEBUG_OBJECT (dec, "process_single failed");
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (FLAC__stream_decoder_get_state (dec->decoder) ==
|
|
||||||
FLAC__STREAM_DECODER_ABORTED) {
|
|
||||||
GST_WARNING_OBJECT (dec, "Read callback caused internal abort");
|
|
||||||
dec->last_flow = GST_FLOW_ERROR;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if (dec->framed && got_audio_frame) {
|
|
||||||
/* framed - there should always be enough data to decode something */
|
/* framed - there should always be enough data to decode something */
|
||||||
GST_LOG_OBJECT (dec, "%u bytes available",
|
GST_LOG_OBJECT (dec, "%u bytes available",
|
||||||
gst_adapter_available (dec->adapter));
|
gst_adapter_available (dec->adapter));
|
||||||
if (G_UNLIKELY (!dec->got_headers)) {
|
|
||||||
/* The first time we get audio data, we know we got all the headers.
|
|
||||||
* We then loop until all the metadata is processed, then do an extra
|
|
||||||
* "process_single" step for the audio frame. */
|
|
||||||
GST_DEBUG_OBJECT (dec,
|
|
||||||
"First audio frame, ensuring all metadata is processed");
|
|
||||||
if (!FLAC__stream_decoder_process_until_end_of_metadata (dec->decoder)) {
|
|
||||||
GST_DEBUG_OBJECT (dec, "process_until_end_of_metadata failed");
|
|
||||||
}
|
|
||||||
GST_DEBUG_OBJECT (dec,
|
|
||||||
"All metadata is now processed, reading to process audio data");
|
|
||||||
dec->got_headers = TRUE;
|
|
||||||
}
|
|
||||||
if (!FLAC__stream_decoder_process_single (dec->decoder)) {
|
|
||||||
GST_DEBUG_OBJECT (dec, "process_single failed");
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
GST_DEBUG_OBJECT (dec, "don't have all headers yet");
|
|
||||||
}
|
|
||||||
|
|
||||||
out:
|
if (!FLAC__stream_decoder_process_single (dec->decoder)) {
|
||||||
|
GST_INFO_OBJECT (dec, "process_single failed");
|
||||||
|
}
|
||||||
|
|
||||||
return dec->last_flow;
|
return dec->last_flow;
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,9 +44,8 @@ struct _GstFlacDec {
|
||||||
/*< private >*/
|
/*< private >*/
|
||||||
FLAC__StreamDecoder *decoder;
|
FLAC__StreamDecoder *decoder;
|
||||||
GstAdapter *adapter;
|
GstAdapter *adapter;
|
||||||
gboolean framed; // FIXME
|
|
||||||
|
|
||||||
gboolean got_headers; /* if we've parsed the headers */
|
gboolean got_headers; /* have we received all the header buffers yet? */
|
||||||
|
|
||||||
GstTagList *tags;
|
GstTagList *tags;
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue