/* * FLUENDO S.A. * Copyright (C) <2005 - 2011> */ /********************************************************************* * Adapted from dist10 reference code and used under the license therein: * ISO MPEG Audio Subgroup Software Simulation Group (1996) * ISO 13818-3 MPEG-2 Audio Decoder - Lower Sampling Frequency Extension **********************************************************************/ #ifdef HAVE_CONFIG_H #include "config.h" #endif #include #include "mp3tl.h" #include "mp3tl-priv.h" #include "decode.h" GST_DEBUG_CATEGORY_EXTERN (flump3debug); #define GST_CAT_DEFAULT flump3debug /* Minimum size in bytes of an MP3 frame */ #define MIN_FRAME_SIZE 24 mp3tl * mp3tl_new (Bit_stream_struc * bs, Mp3TlMode mode) { mp3tl *tl; void *alloc_memory; g_return_val_if_fail (bs != NULL, NULL); g_return_val_if_fail (mode == MP3TL_MODE_16BIT, NULL); alloc_memory = g_malloc0 (sizeof (mp3tl) + __CACHE_LINE_BYTES); tl = (mp3tl *) __CACHE_LINE_ALIGN(alloc_memory); g_return_val_if_fail (tl != NULL, NULL); tl->alloc_memory = alloc_memory; tl->bs = bs; tl->need_sync = TRUE; tl->need_header = TRUE; tl->at_eos = FALSE; tl->lost_sync = TRUE; tl->sample_size = 16; tl->sample_buf = NULL; tl->sample_w = 0; tl->stream_layer = 0; tl->error_count = 0; tl->fr_ps.alloc = NULL; init_syn_filter (&tl->fr_ps); tl->free_first = TRUE; #ifdef USE_IPP if (!mp3_ipp_init (tl)) { g_free (tl); return NULL; } #endif if (!mp3_c_init (tl)) { g_free (tl); return NULL; } return tl; } void mp3tl_free (mp3tl * tl) { g_return_if_fail (tl != NULL); #ifdef USE_IPP mp3_ipp_close (tl); #endif g_free (tl->alloc_memory); }; void mp3tl_set_eos (mp3tl * tl, gboolean is_eos) { tl->at_eos = is_eos; } Mp3TlRetcode mp3tl_sync (mp3tl * tl) { g_return_val_if_fail (tl != NULL, FALSE); if (tl->need_sync) { guint64 sync_start; /* Find a sync word, with valid header */ bs_reset (tl->bs); /* Need at least sync word + header bits */ if (bs_bits_avail (tl->bs) < SYNC_WORD_LNGTH + HEADER_LNGTH) return MP3TL_ERR_NO_SYNC; sync_start = bs_pos (tl->bs); GST_LOG ("Starting sync search at %" G_GUINT64_FORMAT " (byte %" G_GUINT64_FORMAT ")", sync_start, sync_start / 8); do { gboolean sync; guint64 offset; guint64 frame_start; fr_header *hdr = &tl->fr_ps.header; gboolean valid = TRUE; guint64 total_offset; sync = bs_seek_sync (tl->bs); offset = bs_read_pos (tl->bs) - bs_pos (tl->bs); total_offset = bs_read_pos (tl->bs) - sync_start; if (!sync) { /* Leave the last byte in the stream, as it might be the first byte * of our sync word later */ if (offset > 8) bs_consume (tl->bs, (guint32) (offset - 8)); tl->lost_sync = TRUE; GST_LOG ("Not enough data in buffer for a sync sequence"); return MP3TL_ERR_NO_SYNC; } g_assert (offset >= SYNC_WORD_LNGTH); /* Check if we skipped any data to find the sync word */ if (offset != SYNC_WORD_LNGTH) { GST_DEBUG ("Skipped %" G_GUINT64_FORMAT " bits to find sync", offset); tl->lost_sync = TRUE; } /* Remember the start of frame */ frame_start = bs_read_pos (tl->bs) - SYNC_WORD_LNGTH; /* Look ahead and check the header details */ if (bs_bits_avail (tl->bs) < 20) { /* Consume bytes to the start of sync word and go get more data */ bs_consume (tl->bs, (guint32) (offset - SYNC_WORD_LNGTH)); tl->lost_sync = TRUE; GST_LOG ("Not enough data in buffer to read header"); return MP3TL_ERR_NO_SYNC; } /* Read header bits */ GST_LOG ("Reading header at %" G_GUINT64_FORMAT " (byte %" G_GUINT64_FORMAT ")", bs_read_pos (tl->bs), bs_read_pos (tl->bs) / 8); if (!read_header (tl, hdr)) { valid = FALSE; GST_LOG ("Bad header"); } else { /* Fill out the derived header details */ hdr->sample_size = tl->sample_size; if (!set_hdr_data_slots (hdr)) { GST_LOG ("Bad header (slots)"); valid = FALSE; } /* Data is not allowed to suddenly change to a different layer */ if (tl->stream_layer != 0 && hdr->layer != tl->stream_layer) { GST_LOG ("Bad header (layer changed)"); valid = FALSE; } } /* FIXME: Could check the CRC to confirm a sync point */ /* If we skipped any to find the sync, and we have enough data, * jump ahead to where we expect the next frame to be and confirm * that there is a sync word there */ if (valid && tl->lost_sync) { gint64 remain; remain = hdr->frame_bits - (bs_read_pos (tl->bs) - frame_start); if (hdr->frame_bits < (8 * MIN_FRAME_SIZE)) { GST_LOG ("Header indicates a frame too small to be correct"); valid = FALSE; } else if (bs_bits_avail (tl->bs) >= hdr->frame_bits) { guint32 sync_word; fr_header next_hdr; GST_DEBUG ("Peeking ahead %u bits to check sync (%" G_GINT64_FORMAT ", %" G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT ")", hdr->frame_bits, remain, (guint64) bs_read_pos (tl->bs), (guint64) frame_start); /* Skip 'remain' bits */ bs_skipbits (tl->bs, (guint32) (remain - 1)); /* Read a sync word and check */ sync_word = bs_getbits_aligned (tl->bs, SYNC_WORD_LNGTH); if (sync_word != SYNC_WORD) { valid = FALSE; GST_LOG ("No next sync word %u bits later @ %" G_GUINT64_FORMAT ". Got 0x%03x", hdr->frame_bits, bs_read_pos (tl->bs) - SYNC_WORD_LNGTH, sync_word); } else if (!read_header (tl, &next_hdr)) { GST_LOG ("Invalid header at next indicated frame"); valid = FALSE; } else { /* Check that the samplerate and layer for the next header is * the same */ if ((hdr->layer != next_hdr.layer) || (hdr->sample_rate != next_hdr.sample_rate) || (hdr->copyright != next_hdr.copyright) || (hdr->original != next_hdr.original) || (hdr->emphasis != next_hdr.emphasis)) { valid = FALSE; GST_LOG ("Invalid header at next indicated frame"); } } if (valid) GST_LOG ("Good - found a valid frame %u bits later.", hdr->frame_bits); } else if (!tl->at_eos) { GST_LOG ("Not enough data in buffer to test next header"); /* Not at the end of stream, so wait for more data to validate the * frame with */ /* Consume bytes to the start of sync word and go get more data */ bs_consume (tl->bs, (guint32) (offset - SYNC_WORD_LNGTH)); return MP3TL_ERR_NO_SYNC; } } if (!valid) { /* Move past the first byte of the sync word and keep looking */ bs_consume (tl->bs, (guint32) (offset - SYNC_WORD_LNGTH + 8)); } else { /* Consume everything up to the start of sync word */ if (offset > SYNC_WORD_LNGTH) bs_consume (tl->bs, (guint32) (offset - SYNC_WORD_LNGTH)); tl->need_sync = FALSE; GST_DEBUG ("OK after %" G_GUINT64_FORMAT " offset", total_offset - SYNC_WORD_LNGTH); } } while (tl->need_sync); if (bs_pos (tl->bs) != sync_start) GST_DEBUG ("Skipped %" G_GUINT64_FORMAT " bits, found sync", bs_pos (tl->bs) - sync_start); } return MP3TL_ERR_OK; } Mp3TlRetcode mp3tl_decode_header (mp3tl * tl, const fr_header ** ret_hdr) { fr_header *hdr; Mp3TlRetcode ret; g_return_val_if_fail (tl != NULL, FALSE); hdr = &tl->fr_ps.header; if (G_LIKELY (ret_hdr != NULL)) *ret_hdr = hdr; if (!tl->need_header) return MP3TL_ERR_OK; if ((ret = mp3tl_sync (tl)) != MP3TL_ERR_OK) return ret; /* Restart the read ptr and move past the sync word */ bs_reset (tl->bs); bs_getbits (tl->bs, SYNC_WORD_LNGTH); /* If there are less than header bits available, something went * wrong in the sync */ g_assert (bs_bits_avail (tl->bs) >= HEADER_LNGTH); GST_DEBUG ("Frame is %d bytes (%d bits)", hdr->frame_bits / 8, hdr->frame_bits); /* Consume the header and sync word */ bs_consume (tl->bs, SYNC_WORD_LNGTH + HEADER_LNGTH); tl->need_header = FALSE; return MP3TL_ERR_OK; } Mp3TlRetcode mp3tl_gather_frame (mp3tl * tl, gint * _offset, gint * _length) { guint64 sync_start; gboolean sync; guint64 offset; guint64 frame_start; fr_header *hdr; gboolean valid = TRUE; /* Find a sync word, with valid header */ bs_reset (tl->bs); /* Need at least sync word + header bits */ if (bs_bits_avail (tl->bs) < SYNC_WORD_LNGTH + HEADER_LNGTH) return MP3TL_ERR_NO_SYNC; sync_start = bs_pos (tl->bs); GST_LOG ("Starting sync search at %" G_GUINT64_FORMAT " (byte %" G_GUINT64_FORMAT ")", sync_start, sync_start / 8); hdr = &tl->fr_ps.header; sync = bs_seek_sync (tl->bs); offset = bs_read_pos (tl->bs) - bs_pos (tl->bs); if (!sync) { GST_LOG ("Not enough data for a sync sequence"); return MP3TL_ERR_NO_SYNC; } /* Check if we skipped any data to find the sync word */ if (offset != SYNC_WORD_LNGTH) { GST_DEBUG ("Skipped %" G_GUINT64_FORMAT " bits to find sync", offset); } /* Remember the start of frame */ frame_start = bs_read_pos (tl->bs) - SYNC_WORD_LNGTH; /* Look ahead and check the header details */ if (bs_bits_avail (tl->bs) < 20) { GST_LOG ("Not enough data to read header"); return MP3TL_ERR_NO_SYNC; } /* Read header bits */ GST_LOG ("Reading header at %" G_GUINT64_FORMAT " (byte %" G_GUINT64_FORMAT ")", bs_read_pos (tl->bs), bs_read_pos (tl->bs) / 8); if (!read_header (tl, hdr)) { valid = FALSE; GST_LOG ("Bad header"); } else { /* Fill out the derived header details */ hdr->sample_size = tl->sample_size; if (!set_hdr_data_slots (hdr)) { GST_LOG ("Bad header (slots)"); valid = FALSE; } /* Data is not allowed to suddenly change to a different layer */ if (tl->stream_layer != 0 && hdr->layer != tl->stream_layer) { GST_LOG ("Bad header (layer changed)"); valid = FALSE; } } /* If we skipped any to find the sync, and we have enough data, * jump ahead to where we expect the next frame to be and confirm * that there is a sync word there */ if (valid) { gint64 remain; remain = hdr->frame_bits - (bs_read_pos (tl->bs) - frame_start); if (hdr->frame_bits < (8 * MIN_FRAME_SIZE)) { GST_LOG ("Header indicates a frame too small to be correct"); } else if (bs_bits_avail (tl->bs) >= hdr->frame_bits) { guint32 sync_word; fr_header next_hdr; GST_DEBUG ("Peeking ahead %u bits to check sync (%" G_GINT64_FORMAT ", %" G_GUINT64_FORMAT ", %" G_GUINT64_FORMAT ")", hdr->frame_bits, remain, (guint64) bs_read_pos (tl->bs), (guint64) frame_start); /* Skip 'remain' bits */ bs_skipbits (tl->bs, (guint32) (remain - 1)); /* Read a sync word and check */ sync_word = bs_getbits_aligned (tl->bs, SYNC_WORD_LNGTH); if (sync_word != SYNC_WORD) { valid = FALSE; GST_LOG ("No next sync word %u bits later @ %" G_GUINT64_FORMAT ". Got 0x%03x", hdr->frame_bits, bs_read_pos (tl->bs) - SYNC_WORD_LNGTH, sync_word); } else if (!read_header (tl, &next_hdr)) { GST_LOG ("Invalid header at next indicated frame"); valid = FALSE; } else { /* Check that the samplerate and layer for the next header is * the same */ if ((hdr->layer != next_hdr.layer) || (hdr->sample_rate != next_hdr.sample_rate) || (hdr->copyright != next_hdr.copyright) || (hdr->original != next_hdr.original) || (hdr->emphasis != next_hdr.emphasis)) { valid = FALSE; GST_LOG ("Invalid header at next indicated frame"); } } if (valid) { GST_LOG ("Good - found a valid frame %u bits later.", hdr->frame_bits); } } else if (!tl->at_eos) { GST_LOG ("Not enough data in buffer to test next header"); /* Not at the end of stream, so wait for more data to validate the * frame with */ return MP3TL_ERR_NO_SYNC; } *_offset = frame_start >> 3; *_length = hdr->frame_bits >> 3; tl->lost_sync = FALSE; } else { *_offset = (frame_start + SYNC_WORD_LNGTH) >> 3; return MP3TL_ERR_NO_SYNC; } return MP3TL_ERR_OK; } /********************************************************************* * Decode the current frame into the samples buffer *********************************************************************/ Mp3TlRetcode mp3tl_decode_frame (mp3tl * tl, guint8 * samples, guint bufsize) { fr_header *hdr; int i, j; int error_protection; guint new_crc; Mp3TlRetcode ret; gint64 frame_start_pos; g_return_val_if_fail (tl != NULL, MP3TL_ERR_PARAM); g_return_val_if_fail (samples != NULL, MP3TL_ERR_PARAM); hdr = &tl->fr_ps.header; if ((ret = mp3tl_decode_header (tl, NULL)) != MP3TL_ERR_OK) return ret; /* Check that the buffer is big enough to hold the decoded samples */ if (bufsize < hdr->frame_samples * (hdr->sample_size / 8) * hdr->channels) return MP3TL_ERR_PARAM; bs_reset (tl->bs); GST_LOG ("Starting decode of frame size %u bits, with %u bits in buffer", hdr->frame_bits, bs_bits_avail (tl->bs)); /* Got enough bits for the decode? (exclude the header) */ if (bs_bits_avail (tl->bs) < hdr->frame_bits - (SYNC_WORD_LNGTH + HEADER_LNGTH)) return MP3TL_ERR_NEED_DATA; hdr_to_frps (&tl->fr_ps); if (hdr->version == MPEG_VERSION_1) tl->n_granules = 2; else tl->n_granules = 1; tl->stream_layer = hdr->layer; error_protection = hdr->error_protection; /* We're about to start reading bits out of the stream, * after which we'll need a new sync and header */ tl->need_sync = TRUE; tl->need_header = TRUE; /* Set up the output buffer */ tl->sample_w = 0; tl->sample_buf = (gint16 *) samples; /* Remember the start of the frame */ frame_start_pos = bs_read_pos (tl->bs) - (SYNC_WORD_LNGTH + HEADER_LNGTH); /* Retrieve the CRC from the stream */ if (error_protection) buffer_CRC (tl->bs, &tl->old_crc); switch (hdr->layer) { case 1:{ guint bit_alloc[2][SBLIMIT], scale_index[2][3][SBLIMIT]; guint ch; I_decode_bitalloc (tl->bs, bit_alloc, &tl->fr_ps); I_decode_scale (tl->bs, bit_alloc, scale_index, &tl->fr_ps); /* Compute and check the CRC */ if (error_protection) { I_CRC_calc (&tl->fr_ps, bit_alloc, &new_crc); if (new_crc != tl->old_crc) { tl->error_count++; GST_DEBUG ("CRC mismatch - Bad frame"); return MP3TL_ERR_BAD_FRAME; } } for (i = 0; i < SCALE_BLOCK; i++) { I_buffer_sample (tl->bs, tl->sample, bit_alloc, &tl->fr_ps); I_dequant_and_scale_sample (tl->sample, tl->fraction, bit_alloc, scale_index, &tl->fr_ps); for (ch = 0; ch < hdr->channels; ch++) { mp3_SubBandSynthesis (tl, &tl->fr_ps, &(tl->fraction[ch][0][0]), ch, &((tl->pcm_sample)[ch][0][0])); } out_fifo (tl->pcm_sample, 1, &tl->fr_ps, tl->sample_buf, &tl->sample_w, SAMPLE_BUF_SIZE); } break; } case 2:{ guint bit_alloc[2][SBLIMIT], scfsi[2][SBLIMIT], scale_index[2][3][SBLIMIT]; guint ch; /* Choose bit allocations table */ II_pick_table (&tl->fr_ps); /* Read band bit allocations from the data and scale */ II_decode_bitalloc (tl->bs, bit_alloc, &tl->fr_ps); II_decode_scale (tl->bs, scfsi, bit_alloc, scale_index, &tl->fr_ps); if (error_protection) { II_CRC_calc (&tl->fr_ps, bit_alloc, scfsi, &new_crc); if (new_crc != tl->old_crc) { tl->error_count++; GST_DEBUG ("CRC mismatch - Bad frame"); return MP3TL_ERR_BAD_FRAME; } } for (i = 0; i < SCALE_BLOCK; i++) { II_buffer_sample (tl->bs, (tl->sample), bit_alloc, &tl->fr_ps); II_dequant_and_scale_sample (tl->sample, bit_alloc, tl->fraction, scale_index, i >> 2, &tl->fr_ps); for (j = 0; j < 3; j++) for (ch = 0; ch < hdr->channels; ch++) { mp3_SubBandSynthesis (tl, &tl->fr_ps, &((tl->fraction)[ch][j][0]), ch, &((tl->pcm_sample)[ch][j][0])); } out_fifo (tl->pcm_sample, 3, &tl->fr_ps, tl->sample_buf, &tl->sample_w, SAMPLE_BUF_SIZE); } break; } case 3: /* Decoder specific implementation */ #ifdef USE_IPP if (hdr->version == MPEG_VERSION_2_5) ret = c_decode_mp3 (tl); else ret = ipp_decode_mp3 (tl); #else ret = c_decode_mp3 (tl); #endif if (ret == MP3TL_ERR_BAD_FRAME) { /* Consume the data from our bitreader */ bs_consume (tl->bs, hdr->frame_bits - (SYNC_WORD_LNGTH + HEADER_LNGTH)); return ret; } if (ret != MP3TL_ERR_OK) return ret; break; default: GST_WARNING ("Unknown layer %d, invalid bitstream.", hdr->layer); return MP3TL_ERR_STREAM; } /* skip ancillary data HP 22-nov-95 */ if (hdr->bitrate_idx != 0) { /* if not free-format */ /* Ancillary bits are any left in the frame that didn't get used */ gint64 anc_len = hdr->frame_slots * hdr->bits_per_slot; anc_len -= bs_read_pos (tl->bs) - frame_start_pos; if (anc_len > 0) { GST_DEBUG ("Skipping %" G_GINT64_FORMAT " ancillary bits", anc_len); do { bs_getbits (tl->bs, (guint32) MIN (anc_len, MAX_LENGTH)); anc_len -= MAX_LENGTH; } while (anc_len > 0); } } tl->frame_num++; tl->bits_used += hdr->frame_bits; /* Consume the data */ bs_consume (tl->bs, hdr->frame_bits - (SYNC_WORD_LNGTH + HEADER_LNGTH)); GST_DEBUG ("Used %u bits = %u slots plus %u", hdr->frame_bits, hdr->frame_slots, hdr->frame_bits % hdr->bits_per_slot); GST_DEBUG ("Avg slots/frame so far = %.3f; b/smp = %.2f; br = %.3f kbps", (FLOAT) tl->bits_used / (tl->frame_num * hdr->bits_per_slot), (FLOAT) tl->bits_used / (tl->frame_num * hdr->frame_samples), (FLOAT) (1000 * tl->bits_used) / (tl->frame_num * hdr->frame_samples) * s_rates[hdr->version][hdr->srate_idx]); /* Correctly decoded a frame, so assume we're synchronised */ tl->lost_sync = FALSE; return MP3TL_ERR_OK; } void mp3tl_flush (mp3tl * tl) { GST_LOG ("Flush"); /* Clear out the bytestreams */ bs_flush (tl->bs); tl->need_header = TRUE; tl->need_sync = TRUE; tl->lost_sync = TRUE; init_syn_filter (&tl->fr_ps); tl->sample_buf = NULL; tl->sample_w = 0; memset (tl->pcm_sample, 0, sizeof (tl->pcm_sample)); /* Call decoder specific flush routines */ #ifdef USE_IPP mp3_ipp_flush (tl); #endif mp3_c_flush (tl); } Mp3TlRetcode mp3tl_skip_frame (mp3tl * tl) { fr_header *hdr; Mp3TlRetcode ret; g_return_val_if_fail (tl != NULL, MP3TL_ERR_PARAM); hdr = &tl->fr_ps.header; if ((ret = mp3tl_decode_header (tl, NULL)) != MP3TL_ERR_OK) return ret; bs_reset (tl->bs); /* Got enough bits to consume? (exclude the header) */ if (bs_bits_avail (tl->bs) < hdr->frame_bits - (SYNC_WORD_LNGTH + HEADER_LNGTH)) return MP3TL_ERR_NEED_DATA; hdr_to_frps (&tl->fr_ps); if (hdr->version == MPEG_VERSION_1) tl->n_granules = 2; else tl->n_granules = 1; tl->stream_layer = hdr->layer; /* We're about to start reading bits out of the stream, * after which we'll need a new sync and header */ tl->need_sync = TRUE; tl->need_header = TRUE; tl->frame_num++; tl->bits_used += hdr->frame_bits; /* Consume the data */ bs_consume (tl->bs, hdr->frame_bits - (SYNC_WORD_LNGTH + HEADER_LNGTH)); GST_DEBUG ("Skipped %u bits = %u slots plus %u", hdr->frame_bits, hdr->frame_slots, hdr->frame_bits % hdr->bits_per_slot); GST_DEBUG ("Avg slots/frame so far = %.3f; b/smp = %.2f; br = %.3f kbps", (FLOAT) tl->bits_used / (tl->frame_num * hdr->bits_per_slot), (FLOAT) tl->bits_used / (tl->frame_num * hdr->frame_samples), (FLOAT) (1000 * tl->bits_used) / (tl->frame_num * hdr->frame_samples) * s_rates[hdr->version][hdr->srate_idx]); return MP3TL_ERR_OK; } const char * mp3tl_get_err_reason (mp3tl * tl) { return tl->reason; }