Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 9dec4911 authored by James Dong's avatar James Dong
Browse files

MP3Extractor and MP3 decoder fixes - DO NOT MERGE

cherry-picked the following patches from HC branch:
o PV's mp3 decoder mistreated inputBufferCurrentLength in unit of bytes as in unit of bits
o Do not enforce the rule in MP3Extractor that all audio frames in an mp3 file must have the same mode
o When the temp buffer wraps around, the next read position should start
    from what have been read to avoid reading the same remaining bytes in
    the buffer again.
o Speed up MP3Extractor using cached reads

bug - 4083532

Change-Id: I7bbd2bd358fd5ee322287866cb8ee0c2bb217fea
parent 0ef63152
Loading
Loading
Loading
Loading
+43 −6
Original line number Diff line number Diff line
@@ -37,10 +37,10 @@
namespace android {

// Everything must match except for
// protection, bitrate, padding, private bits, mode extension,
// protection, bitrate, padding, private bits, mode, mode extension,
// copyright bit, original bit and emphasis.
// Yes ... there are things that must indeed match...
static const uint32_t kMask = 0xfffe0cc0;
static const uint32_t kMask = 0xfffe0c00;

static bool get_mp3_frame_size(
        uint32_t header, size_t *frame_size,
@@ -344,22 +344,55 @@ static bool Resync(

    off_t pos = *inout_pos;
    bool valid = false;

    const size_t kMaxReadBytes = 1024;
    const off_t kMaxBytesChecked = 128 * 1024;
    uint8_t buf[kMaxReadBytes];
    ssize_t bytesToRead = kMaxReadBytes;
    ssize_t totalBytesRead = 0;
    ssize_t remainingBytes = 0;
    bool reachEOS = false;
    uint8_t *tmp = buf;

    do {
        if (pos >= *inout_pos + 128 * 1024) {
        if (pos >= *inout_pos + kMaxBytesChecked) {
            // Don't scan forever.
            LOGV("giving up at offset %ld", pos);
            break;
        }

        uint8_t tmp[4];
        if (source->readAt(pos, tmp, 4) != 4) {
        if (remainingBytes < 4) {
            if (reachEOS) {
                break;
            } else {
                memcpy(buf, tmp, remainingBytes);
                bytesToRead = kMaxReadBytes - remainingBytes;

                /*
                 * The next read position should start from the end of
                 * the last buffer, and thus should include the remaining
                 * bytes in the buffer.
                 */
                totalBytesRead = source->readAt(pos + remainingBytes,
                                                buf + remainingBytes,
                                                bytesToRead);
                if (totalBytesRead <= 0) {
                    break;
                }
                reachEOS = (totalBytesRead != bytesToRead);
                totalBytesRead += remainingBytes;
                remainingBytes = totalBytesRead;
                tmp = buf;
                continue;
            }
        }

        uint32_t header = U32_AT(tmp);

        if (match_header != 0 && (header & kMask) != (match_header & kMask)) {
            ++pos;
            ++tmp;
            --remainingBytes;
            continue;
        }

@@ -368,6 +401,8 @@ static bool Resync(
        if (!get_mp3_frame_size(header, &frame_size,
                               &sample_rate, &num_channels, &bitrate)) {
            ++pos;
            ++tmp;
            --remainingBytes;
            continue;
        }

@@ -417,6 +452,8 @@ static bool Resync(
        }

        ++pos;
        ++tmp;
        --remainingBytes;
    } while (!valid);

    return valid;
+4 −2
Original line number Diff line number Diff line
@@ -122,8 +122,10 @@ ERROR_CODE pvmp3_decode_header(tmp3Bits *inputStream,

    /*
     * Verify that at least the header is complete
     * Note that SYNC_WORD_LNGTH is in unit of bits, but inputBufferCurrentLength
     * is in unit of bytes.
     */
    if (inputStream->inputBufferCurrentLength < (SYNC_WORD_LNGTH + 21))
    if (inputStream->inputBufferCurrentLength < ((SYNC_WORD_LNGTH + 21) >> 3))
    {
        return NO_ENOUGH_MAIN_DATA_ERROR;
    }