Loading media/libstagefright/codecs/mp3dec/MP3Decoder.cpp +378 −10 Original line number Diff line number Diff line Loading @@ -22,9 +22,183 @@ #include <media/stagefright/MediaDebug.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MetaData.h> #include <media/stagefright/Utils.h> namespace android { // Everything must match except for // protection, bitrate, padding, private bits, mode extension, // copyright bit, original bit and emphasis. // Yes ... there are things that must indeed match... static const uint32_t kMask = 0xfffe0cc0; static bool get_mp3_frame_size( uint32_t header, size_t *frame_size, int *out_sampling_rate = NULL, int *out_channels = NULL, int *out_bitrate = NULL) { *frame_size = 0; if (out_sampling_rate) { *out_sampling_rate = 0; } if (out_channels) { *out_channels = 0; } if (out_bitrate) { *out_bitrate = 0; } if ((header & 0xffe00000) != 0xffe00000) { return false; } unsigned version = (header >> 19) & 3; if (version == 0x01) { return false; } unsigned layer = (header >> 17) & 3; if (layer == 0x00) { return false; } unsigned protection = (header >> 16) & 1; unsigned bitrate_index = (header >> 12) & 0x0f; if (bitrate_index == 0 || bitrate_index == 0x0f) { // Disallow "free" bitrate. return false; } unsigned sampling_rate_index = (header >> 10) & 3; if (sampling_rate_index == 3) { return false; } static const int kSamplingRateV1[] = { 44100, 48000, 32000 }; int sampling_rate = kSamplingRateV1[sampling_rate_index]; if (version == 2 /* V2 */) { sampling_rate /= 2; } else if (version == 0 /* V2.5 */) { sampling_rate /= 4; } unsigned padding = (header >> 9) & 1; if (layer == 3) { // layer I static const int kBitrateV1[] = { 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 }; static const int kBitrateV2[] = { 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 }; int bitrate = (version == 3 /* V1 */) ? kBitrateV1[bitrate_index - 1] : kBitrateV2[bitrate_index - 1]; if (out_bitrate) { *out_bitrate = bitrate; } *frame_size = (12000 * bitrate / sampling_rate + padding) * 4; } else { // layer II or III static const int kBitrateV1L2[] = { 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 }; static const int kBitrateV1L3[] = { 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 }; static const int kBitrateV2[] = { 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 }; int bitrate; if (version == 3 /* V1 */) { bitrate = (layer == 2 /* L2 */) ? kBitrateV1L2[bitrate_index - 1] : kBitrateV1L3[bitrate_index - 1]; } else { // V2 (or 2.5) bitrate = kBitrateV2[bitrate_index - 1]; } if (out_bitrate) { *out_bitrate = bitrate; } if (version == 3 /* V1 */) { *frame_size = 144000 * bitrate / sampling_rate + padding; } else { // V2 or V2.5 *frame_size = 72000 * bitrate / sampling_rate + padding; } } if (out_sampling_rate) { *out_sampling_rate = sampling_rate; } if (out_channels) { int channel_mode = (header >> 6) & 3; *out_channels = (channel_mode == 3) ? 1 : 2; } return true; } static bool resync( uint8_t *data, uint32_t size, uint32_t match_header, off_t *out_pos) { bool valid = false; off_t pos = 0; *out_pos = 0; do { if (pos + 4 > size) { // Don't scan forever. LOGV("no dice, no valid sequence of frames found."); break; } uint32_t header = U32_AT(data + pos); if (match_header != 0 && (header & kMask) != (match_header & kMask)) { ++pos; continue; } LOGV("found possible frame at %ld (header = 0x%08x)", pos, header); // We found what looks like a valid frame, valid = true; *out_pos = pos; } while (!valid); return valid; } MP3Decoder::MP3Decoder(const sp<MediaSource> &source) : mSource(source), mNumChannels(0), Loading @@ -34,7 +208,9 @@ MP3Decoder::MP3Decoder(const sp<MediaSource> &source) mDecoderBuf(NULL), mAnchorTimeUs(0), mNumFramesOutput(0), mInputBuffer(NULL) { mInputBuffer(NULL), mPartialBuffer(NULL), mFixedHeader(0) { init(); } Loading Loading @@ -115,11 +291,120 @@ sp<MetaData> MP3Decoder::getFormat() { return mMeta; } status_t MP3Decoder::updatePartialFrame() { status_t err = OK; if (mPartialBuffer == NULL) { return err; } size_t frameSize = 0; uint32_t partialBufLen = mPartialBuffer->range_length(); uint32_t inputBufLen = mInputBuffer->range_length(); uint8_t frameHeader[4]; uint8_t *frmHdr; uint32_t header; // Look at the frame size and complete the partial frame // Also check if a vaild header is found after the partial frame if (partialBufLen < 4) { // check if partial frame has the 4 bytes header if (inputBufLen < (4 - partialBufLen)) { // input buffer does not have the frame header bytes // bail out TODO LOGE("MP3Decoder::updatePartialFrame buffer to small header not found" " partial buffer len %d, input buffer len %d", partialBufLen, inputBufLen); //mPartialBuffer->release(); //mPartialBuffer = NULL; return UNKNOWN_ERROR; } // copy the header bytes to frameHeader memcpy (frameHeader, mPartialBuffer->data(), partialBufLen); memcpy (frameHeader + partialBufLen, mInputBuffer->data(), (4 - partialBufLen)); // get the first 4 bytes of the buffer header = U32_AT((uint8_t *)frameHeader); frmHdr = frameHeader; } else { frmHdr = (uint8_t *)mPartialBuffer->data(); } // check if its a good frame, and the frame size // get the first 4 bytes of the buffer header = U32_AT(frmHdr); bool curFrame = get_mp3_frame_size(header,&frameSize); if (!curFrame) { LOGE("MP3Decoder::read - partial frame does not have a vaild header 0x%x", header); return UNKNOWN_ERROR; } // check if the following frame is good uint32_t nextFrameOffset = frameSize - partialBufLen; if ((nextFrameOffset + 4) <= inputBufLen) { header = U32_AT((uint8_t *)mInputBuffer->data() + nextFrameOffset); if ((header & 0xffe00000) != 0xffe00000) { // next frame does not have a valid header, // this may not be the next buffer, bail out. LOGE("MP3Decoder::read - next frame does not have a vaild header 0x%x", header); return UNKNOWN_ERROR; } } else { // next frame header is out of range // assume good header for now LOGE("MP3Decoder::read - assuming next frame is good"); } // check if the input buffer has the remaining partial frame if (frameSize > (partialBufLen + inputBufLen)) { // input buffer does not have the remaining partial frame, // discard data here as frame split in 3 buffers not supported LOGE("MP3Decoder::updatePartialFrame - input buffer does not have the complete frame." " frame size %d, saved partial buffer len %d," " input buffer len %d", frameSize, partialBufLen, inputBufLen); return UNKNOWN_ERROR; } // check if the mPartialBuffer can fit the remaining frame if ((mPartialBuffer->size() - partialBufLen) < (frameSize - partialBufLen)) { // mPartialBuffer is small to hold the reaming frame //TODO LOGE("MP3Decoder::updatePartialFrame - mPartialBuffer is small, size %d, required &d", (mPartialBuffer->size() - partialBufLen), (frameSize - partialBufLen)); return UNKNOWN_ERROR; } // done with error checks // copy the partial frames to from a complete frame // Copy the remaining frame from input buffer uint32_t bytesRemaining = frameSize - mPartialBuffer->range_length(); memcpy ((uint8_t *)mPartialBuffer->data() + mPartialBuffer->range_length(), (uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset(), bytesRemaining); // mark the bytes as consumed from input buffer mInputBuffer->set_range( mInputBuffer->range_offset() + bytesRemaining, mInputBuffer->range_length() - bytesRemaining); // set the range and length of mPartialBuffer mPartialBuffer->set_range(0, mPartialBuffer->range_length() + bytesRemaining); LOGE("MP3Decoder::updatePartialFrame - copied the partial frame %d, input buffer length %d", bytesRemaining, mInputBuffer->range_length()); return err; } status_t MP3Decoder::read( MediaBuffer **out, const ReadOptions *options) { status_t err; *out = NULL; bool usedPartialFrame = false; bool seekSource = false; int64_t seekTimeUs; ReadOptions::SeekMode mode; Loading @@ -127,12 +412,18 @@ status_t MP3Decoder::read( CHECK(seekTimeUs >= 0); mNumFramesOutput = 0; seekSource = true; if (mInputBuffer) { mInputBuffer->release(); mInputBuffer = NULL; } if (mPartialBuffer) { mPartialBuffer->release(); mPartialBuffer = NULL; } // Make sure that the next buffer output does not still // depend on fragments from the last one decoded. pvmp3_InitDecoder(mConfig, mDecoderBuf); Loading @@ -147,6 +438,26 @@ status_t MP3Decoder::read( return err; } if ((mFixedHeader == 0) && (mInputBuffer->range_length() > 4)) { //save the first 4 bytes as fixed header for the reset of the file mFixedHeader = U32_AT((uint8_t *)mInputBuffer->data()); } if (seekSource == true) { off_t syncOffset = 0; bool valid = resync((uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset() ,mInputBuffer->range_length(), mFixedHeader, &syncOffset); if (valid) { // consume these bytes, we might find a frame header in next buffer mInputBuffer->set_range( mInputBuffer->range_offset() + syncOffset, mInputBuffer->range_length() - syncOffset); LOGV("mp3 decoder found a sync point after seek syncOffset %d", syncOffset); } else { LOGV("NO SYNC POINT found, buffer length %d",mInputBuffer->range_length()); } } int64_t timeUs; if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { mAnchorTimeUs = timeUs; Loading @@ -155,15 +466,33 @@ status_t MP3Decoder::read( // We must have a new timestamp after seeking. CHECK(seekTimeUs < 0); } // check for partial frame if (mPartialBuffer != NULL) { err = updatePartialFrame(); if (err != OK) { // updating partial frame failed, discard the previously // saved partial frame and continue mPartialBuffer->release(); mPartialBuffer = NULL; err = OK; } } } MediaBuffer *buffer; CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK); if (mPartialBuffer != NULL) { mConfig->pInputBuffer = (uint8_t *)mPartialBuffer->data() + mPartialBuffer->range_offset(); mConfig->inputBufferCurrentLength = mPartialBuffer->range_length(); usedPartialFrame = true; } else { mConfig->pInputBuffer = (uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset(); mConfig->inputBufferCurrentLength = mInputBuffer->range_length(); } mConfig->inputBufferMaxLength = 0; mConfig->inputBufferUsedLength = 0; Loading @@ -175,28 +504,67 @@ status_t MP3Decoder::read( != NO_DECODING_ERROR) { LOGV("mp3 decoder returned error %d", decoderErr); if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR) { if ((decoderErr != NO_ENOUGH_MAIN_DATA_ERROR) && (decoderErr != SYNCH_LOST_ERROR)) { buffer->release(); buffer = NULL; mInputBuffer->release(); mInputBuffer = NULL; if (mPartialBuffer) { mPartialBuffer->release(); mPartialBuffer = NULL; } LOGE("mp3 decoder returned UNKNOWN_ERROR"); return UNKNOWN_ERROR; } if ((mPartialBuffer == NULL) && (decoderErr == NO_ENOUGH_MAIN_DATA_ERROR)) { // Might be a partial frame, save it mPartialBuffer = new MediaBuffer(mInputBuffer->size()); memcpy ((uint8_t *)mPartialBuffer->data(), mConfig->pInputBuffer, mConfig->inputBufferCurrentLength); mPartialBuffer->set_range(0, mConfig->inputBufferCurrentLength); // set output buffer to 0 mConfig->outputFrameSize = 0; // consume the copied bytes from input mConfig->inputBufferUsedLength = mConfig->inputBufferCurrentLength; } else if(decoderErr == SYNCH_LOST_ERROR) { // Try to find the mp3 frame header in the current buffer off_t syncOffset = 0; bool valid = resync(mConfig->pInputBuffer, mConfig->inputBufferCurrentLength, mFixedHeader, &syncOffset); if (!valid) { // consume these bytes, we might find a frame header in next buffer syncOffset = mConfig->inputBufferCurrentLength; } // set output buffer to 0 mConfig->outputFrameSize = 0; // consume the junk bytes from input buffer mConfig->inputBufferUsedLength = syncOffset; } else { // This is recoverable, just ignore the current frame and // play silence instead. memset(buffer->data(), 0, mConfig->outputFrameSize * sizeof(int16_t)); mConfig->inputBufferUsedLength = mInputBuffer->range_length(); } } buffer->set_range( 0, mConfig->outputFrameSize * sizeof(int16_t)); if ((mPartialBuffer != NULL) && usedPartialFrame) { mPartialBuffer->set_range( mPartialBuffer->range_offset() + mConfig->inputBufferUsedLength, mPartialBuffer->range_length() - mConfig->inputBufferUsedLength); mPartialBuffer->release(); mPartialBuffer = NULL; } else { mInputBuffer->set_range( mInputBuffer->range_offset() + mConfig->inputBufferUsedLength, mInputBuffer->range_length() - mConfig->inputBufferUsedLength); } if (mInputBuffer->range_length() == 0) { mInputBuffer->release(); Loading media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -125,7 +125,7 @@ ERROR_CODE pvmp3_decode_header(tmp3Bits *inputStream, * Note that SYNC_WORD_LNGTH is in unit of bits, but inputBufferCurrentLength * is in unit of bytes. */ if (inputStream->inputBufferCurrentLength < ((SYNC_WORD_LNGTH + 21) >> 3)) if (inputStream->inputBufferCurrentLength < ((SYNC_WORD_LNGTH + 25) >> 3)) { return NO_ENOUGH_MAIN_DATA_ERROR; } Loading media/libstagefright/include/MP3Decoder.h +3 −0 Original line number Diff line number Diff line Loading @@ -53,13 +53,16 @@ private: void *mDecoderBuf; int64_t mAnchorTimeUs; int64_t mNumFramesOutput; uint32_t mFixedHeader; MediaBuffer *mInputBuffer; MediaBuffer *mPartialBuffer; void init(); MP3Decoder(const MP3Decoder &); MP3Decoder &operator=(const MP3Decoder &); status_t updatePartialFrame(); }; } // namespace android Loading Loading
media/libstagefright/codecs/mp3dec/MP3Decoder.cpp +378 −10 Original line number Diff line number Diff line Loading @@ -22,9 +22,183 @@ #include <media/stagefright/MediaDebug.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MetaData.h> #include <media/stagefright/Utils.h> namespace android { // Everything must match except for // protection, bitrate, padding, private bits, mode extension, // copyright bit, original bit and emphasis. // Yes ... there are things that must indeed match... static const uint32_t kMask = 0xfffe0cc0; static bool get_mp3_frame_size( uint32_t header, size_t *frame_size, int *out_sampling_rate = NULL, int *out_channels = NULL, int *out_bitrate = NULL) { *frame_size = 0; if (out_sampling_rate) { *out_sampling_rate = 0; } if (out_channels) { *out_channels = 0; } if (out_bitrate) { *out_bitrate = 0; } if ((header & 0xffe00000) != 0xffe00000) { return false; } unsigned version = (header >> 19) & 3; if (version == 0x01) { return false; } unsigned layer = (header >> 17) & 3; if (layer == 0x00) { return false; } unsigned protection = (header >> 16) & 1; unsigned bitrate_index = (header >> 12) & 0x0f; if (bitrate_index == 0 || bitrate_index == 0x0f) { // Disallow "free" bitrate. return false; } unsigned sampling_rate_index = (header >> 10) & 3; if (sampling_rate_index == 3) { return false; } static const int kSamplingRateV1[] = { 44100, 48000, 32000 }; int sampling_rate = kSamplingRateV1[sampling_rate_index]; if (version == 2 /* V2 */) { sampling_rate /= 2; } else if (version == 0 /* V2.5 */) { sampling_rate /= 4; } unsigned padding = (header >> 9) & 1; if (layer == 3) { // layer I static const int kBitrateV1[] = { 32, 64, 96, 128, 160, 192, 224, 256, 288, 320, 352, 384, 416, 448 }; static const int kBitrateV2[] = { 32, 48, 56, 64, 80, 96, 112, 128, 144, 160, 176, 192, 224, 256 }; int bitrate = (version == 3 /* V1 */) ? kBitrateV1[bitrate_index - 1] : kBitrateV2[bitrate_index - 1]; if (out_bitrate) { *out_bitrate = bitrate; } *frame_size = (12000 * bitrate / sampling_rate + padding) * 4; } else { // layer II or III static const int kBitrateV1L2[] = { 32, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320, 384 }; static const int kBitrateV1L3[] = { 32, 40, 48, 56, 64, 80, 96, 112, 128, 160, 192, 224, 256, 320 }; static const int kBitrateV2[] = { 8, 16, 24, 32, 40, 48, 56, 64, 80, 96, 112, 128, 144, 160 }; int bitrate; if (version == 3 /* V1 */) { bitrate = (layer == 2 /* L2 */) ? kBitrateV1L2[bitrate_index - 1] : kBitrateV1L3[bitrate_index - 1]; } else { // V2 (or 2.5) bitrate = kBitrateV2[bitrate_index - 1]; } if (out_bitrate) { *out_bitrate = bitrate; } if (version == 3 /* V1 */) { *frame_size = 144000 * bitrate / sampling_rate + padding; } else { // V2 or V2.5 *frame_size = 72000 * bitrate / sampling_rate + padding; } } if (out_sampling_rate) { *out_sampling_rate = sampling_rate; } if (out_channels) { int channel_mode = (header >> 6) & 3; *out_channels = (channel_mode == 3) ? 1 : 2; } return true; } static bool resync( uint8_t *data, uint32_t size, uint32_t match_header, off_t *out_pos) { bool valid = false; off_t pos = 0; *out_pos = 0; do { if (pos + 4 > size) { // Don't scan forever. LOGV("no dice, no valid sequence of frames found."); break; } uint32_t header = U32_AT(data + pos); if (match_header != 0 && (header & kMask) != (match_header & kMask)) { ++pos; continue; } LOGV("found possible frame at %ld (header = 0x%08x)", pos, header); // We found what looks like a valid frame, valid = true; *out_pos = pos; } while (!valid); return valid; } MP3Decoder::MP3Decoder(const sp<MediaSource> &source) : mSource(source), mNumChannels(0), Loading @@ -34,7 +208,9 @@ MP3Decoder::MP3Decoder(const sp<MediaSource> &source) mDecoderBuf(NULL), mAnchorTimeUs(0), mNumFramesOutput(0), mInputBuffer(NULL) { mInputBuffer(NULL), mPartialBuffer(NULL), mFixedHeader(0) { init(); } Loading Loading @@ -115,11 +291,120 @@ sp<MetaData> MP3Decoder::getFormat() { return mMeta; } status_t MP3Decoder::updatePartialFrame() { status_t err = OK; if (mPartialBuffer == NULL) { return err; } size_t frameSize = 0; uint32_t partialBufLen = mPartialBuffer->range_length(); uint32_t inputBufLen = mInputBuffer->range_length(); uint8_t frameHeader[4]; uint8_t *frmHdr; uint32_t header; // Look at the frame size and complete the partial frame // Also check if a vaild header is found after the partial frame if (partialBufLen < 4) { // check if partial frame has the 4 bytes header if (inputBufLen < (4 - partialBufLen)) { // input buffer does not have the frame header bytes // bail out TODO LOGE("MP3Decoder::updatePartialFrame buffer to small header not found" " partial buffer len %d, input buffer len %d", partialBufLen, inputBufLen); //mPartialBuffer->release(); //mPartialBuffer = NULL; return UNKNOWN_ERROR; } // copy the header bytes to frameHeader memcpy (frameHeader, mPartialBuffer->data(), partialBufLen); memcpy (frameHeader + partialBufLen, mInputBuffer->data(), (4 - partialBufLen)); // get the first 4 bytes of the buffer header = U32_AT((uint8_t *)frameHeader); frmHdr = frameHeader; } else { frmHdr = (uint8_t *)mPartialBuffer->data(); } // check if its a good frame, and the frame size // get the first 4 bytes of the buffer header = U32_AT(frmHdr); bool curFrame = get_mp3_frame_size(header,&frameSize); if (!curFrame) { LOGE("MP3Decoder::read - partial frame does not have a vaild header 0x%x", header); return UNKNOWN_ERROR; } // check if the following frame is good uint32_t nextFrameOffset = frameSize - partialBufLen; if ((nextFrameOffset + 4) <= inputBufLen) { header = U32_AT((uint8_t *)mInputBuffer->data() + nextFrameOffset); if ((header & 0xffe00000) != 0xffe00000) { // next frame does not have a valid header, // this may not be the next buffer, bail out. LOGE("MP3Decoder::read - next frame does not have a vaild header 0x%x", header); return UNKNOWN_ERROR; } } else { // next frame header is out of range // assume good header for now LOGE("MP3Decoder::read - assuming next frame is good"); } // check if the input buffer has the remaining partial frame if (frameSize > (partialBufLen + inputBufLen)) { // input buffer does not have the remaining partial frame, // discard data here as frame split in 3 buffers not supported LOGE("MP3Decoder::updatePartialFrame - input buffer does not have the complete frame." " frame size %d, saved partial buffer len %d," " input buffer len %d", frameSize, partialBufLen, inputBufLen); return UNKNOWN_ERROR; } // check if the mPartialBuffer can fit the remaining frame if ((mPartialBuffer->size() - partialBufLen) < (frameSize - partialBufLen)) { // mPartialBuffer is small to hold the reaming frame //TODO LOGE("MP3Decoder::updatePartialFrame - mPartialBuffer is small, size %d, required &d", (mPartialBuffer->size() - partialBufLen), (frameSize - partialBufLen)); return UNKNOWN_ERROR; } // done with error checks // copy the partial frames to from a complete frame // Copy the remaining frame from input buffer uint32_t bytesRemaining = frameSize - mPartialBuffer->range_length(); memcpy ((uint8_t *)mPartialBuffer->data() + mPartialBuffer->range_length(), (uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset(), bytesRemaining); // mark the bytes as consumed from input buffer mInputBuffer->set_range( mInputBuffer->range_offset() + bytesRemaining, mInputBuffer->range_length() - bytesRemaining); // set the range and length of mPartialBuffer mPartialBuffer->set_range(0, mPartialBuffer->range_length() + bytesRemaining); LOGE("MP3Decoder::updatePartialFrame - copied the partial frame %d, input buffer length %d", bytesRemaining, mInputBuffer->range_length()); return err; } status_t MP3Decoder::read( MediaBuffer **out, const ReadOptions *options) { status_t err; *out = NULL; bool usedPartialFrame = false; bool seekSource = false; int64_t seekTimeUs; ReadOptions::SeekMode mode; Loading @@ -127,12 +412,18 @@ status_t MP3Decoder::read( CHECK(seekTimeUs >= 0); mNumFramesOutput = 0; seekSource = true; if (mInputBuffer) { mInputBuffer->release(); mInputBuffer = NULL; } if (mPartialBuffer) { mPartialBuffer->release(); mPartialBuffer = NULL; } // Make sure that the next buffer output does not still // depend on fragments from the last one decoded. pvmp3_InitDecoder(mConfig, mDecoderBuf); Loading @@ -147,6 +438,26 @@ status_t MP3Decoder::read( return err; } if ((mFixedHeader == 0) && (mInputBuffer->range_length() > 4)) { //save the first 4 bytes as fixed header for the reset of the file mFixedHeader = U32_AT((uint8_t *)mInputBuffer->data()); } if (seekSource == true) { off_t syncOffset = 0; bool valid = resync((uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset() ,mInputBuffer->range_length(), mFixedHeader, &syncOffset); if (valid) { // consume these bytes, we might find a frame header in next buffer mInputBuffer->set_range( mInputBuffer->range_offset() + syncOffset, mInputBuffer->range_length() - syncOffset); LOGV("mp3 decoder found a sync point after seek syncOffset %d", syncOffset); } else { LOGV("NO SYNC POINT found, buffer length %d",mInputBuffer->range_length()); } } int64_t timeUs; if (mInputBuffer->meta_data()->findInt64(kKeyTime, &timeUs)) { mAnchorTimeUs = timeUs; Loading @@ -155,15 +466,33 @@ status_t MP3Decoder::read( // We must have a new timestamp after seeking. CHECK(seekTimeUs < 0); } // check for partial frame if (mPartialBuffer != NULL) { err = updatePartialFrame(); if (err != OK) { // updating partial frame failed, discard the previously // saved partial frame and continue mPartialBuffer->release(); mPartialBuffer = NULL; err = OK; } } } MediaBuffer *buffer; CHECK_EQ(mBufferGroup->acquire_buffer(&buffer), OK); if (mPartialBuffer != NULL) { mConfig->pInputBuffer = (uint8_t *)mPartialBuffer->data() + mPartialBuffer->range_offset(); mConfig->inputBufferCurrentLength = mPartialBuffer->range_length(); usedPartialFrame = true; } else { mConfig->pInputBuffer = (uint8_t *)mInputBuffer->data() + mInputBuffer->range_offset(); mConfig->inputBufferCurrentLength = mInputBuffer->range_length(); } mConfig->inputBufferMaxLength = 0; mConfig->inputBufferUsedLength = 0; Loading @@ -175,28 +504,67 @@ status_t MP3Decoder::read( != NO_DECODING_ERROR) { LOGV("mp3 decoder returned error %d", decoderErr); if (decoderErr != NO_ENOUGH_MAIN_DATA_ERROR) { if ((decoderErr != NO_ENOUGH_MAIN_DATA_ERROR) && (decoderErr != SYNCH_LOST_ERROR)) { buffer->release(); buffer = NULL; mInputBuffer->release(); mInputBuffer = NULL; if (mPartialBuffer) { mPartialBuffer->release(); mPartialBuffer = NULL; } LOGE("mp3 decoder returned UNKNOWN_ERROR"); return UNKNOWN_ERROR; } if ((mPartialBuffer == NULL) && (decoderErr == NO_ENOUGH_MAIN_DATA_ERROR)) { // Might be a partial frame, save it mPartialBuffer = new MediaBuffer(mInputBuffer->size()); memcpy ((uint8_t *)mPartialBuffer->data(), mConfig->pInputBuffer, mConfig->inputBufferCurrentLength); mPartialBuffer->set_range(0, mConfig->inputBufferCurrentLength); // set output buffer to 0 mConfig->outputFrameSize = 0; // consume the copied bytes from input mConfig->inputBufferUsedLength = mConfig->inputBufferCurrentLength; } else if(decoderErr == SYNCH_LOST_ERROR) { // Try to find the mp3 frame header in the current buffer off_t syncOffset = 0; bool valid = resync(mConfig->pInputBuffer, mConfig->inputBufferCurrentLength, mFixedHeader, &syncOffset); if (!valid) { // consume these bytes, we might find a frame header in next buffer syncOffset = mConfig->inputBufferCurrentLength; } // set output buffer to 0 mConfig->outputFrameSize = 0; // consume the junk bytes from input buffer mConfig->inputBufferUsedLength = syncOffset; } else { // This is recoverable, just ignore the current frame and // play silence instead. memset(buffer->data(), 0, mConfig->outputFrameSize * sizeof(int16_t)); mConfig->inputBufferUsedLength = mInputBuffer->range_length(); } } buffer->set_range( 0, mConfig->outputFrameSize * sizeof(int16_t)); if ((mPartialBuffer != NULL) && usedPartialFrame) { mPartialBuffer->set_range( mPartialBuffer->range_offset() + mConfig->inputBufferUsedLength, mPartialBuffer->range_length() - mConfig->inputBufferUsedLength); mPartialBuffer->release(); mPartialBuffer = NULL; } else { mInputBuffer->set_range( mInputBuffer->range_offset() + mConfig->inputBufferUsedLength, mInputBuffer->range_length() - mConfig->inputBufferUsedLength); } if (mInputBuffer->range_length() == 0) { mInputBuffer->release(); Loading
media/libstagefright/codecs/mp3dec/src/pvmp3_decode_header.cpp +1 −1 Original line number Diff line number Diff line Loading @@ -125,7 +125,7 @@ ERROR_CODE pvmp3_decode_header(tmp3Bits *inputStream, * Note that SYNC_WORD_LNGTH is in unit of bits, but inputBufferCurrentLength * is in unit of bytes. */ if (inputStream->inputBufferCurrentLength < ((SYNC_WORD_LNGTH + 21) >> 3)) if (inputStream->inputBufferCurrentLength < ((SYNC_WORD_LNGTH + 25) >> 3)) { return NO_ENOUGH_MAIN_DATA_ERROR; } Loading
media/libstagefright/include/MP3Decoder.h +3 −0 Original line number Diff line number Diff line Loading @@ -53,13 +53,16 @@ private: void *mDecoderBuf; int64_t mAnchorTimeUs; int64_t mNumFramesOutput; uint32_t mFixedHeader; MediaBuffer *mInputBuffer; MediaBuffer *mPartialBuffer; void init(); MP3Decoder(const MP3Decoder &); MP3Decoder &operator=(const MP3Decoder &); status_t updatePartialFrame(); }; } // namespace android Loading