XINGSeeker.cpp revision 5102400104ce1f0a6de7bf913381a91e4f18a22a
14456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber/*
24456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber * Copyright (C) 2010 The Android Open Source Project
34456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber *
44456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber * Licensed under the Apache License, Version 2.0 (the "License");
54456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber * you may not use this file except in compliance with the License.
64456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber * You may obtain a copy of the License at
74456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber *
84456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber *      http://www.apache.org/licenses/LICENSE-2.0
94456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber *
104456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber * Unless required by applicable law or agreed to in writing, software
114456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber * distributed under the License is distributed on an "AS IS" BASIS,
124456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
134456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber * See the License for the specific language governing permissions and
144456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber * limitations under the License.
154456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber */
164456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
174456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber#include "include/XINGSeeker.h"
184456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
194456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber#include <media/stagefright/DataSource.h>
204456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber#include <media/stagefright/Utils.h>
214456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
224456da54bcd206ed1f518c69cc959ca65a179c83Andreas Hubernamespace android {
234456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
244456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huberstatic bool parse_xing_header(
25c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        const sp<DataSource> &source, off64_t first_frame_pos,
264456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        int32_t *frame_number = NULL, int32_t *byte_number = NULL,
275102400104ce1f0a6de7bf913381a91e4f18a22aMarco Nelissen        unsigned char *table_of_contents = NULL, bool *toc_is_valid = NULL,
286fb40672ac0f0b2f479367fa0ba4e8944df06dadGloria Wang        int32_t *quality_indicator = NULL, int64_t *duration = NULL);
294456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
304456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber// static
314456da54bcd206ed1f518c69cc959ca65a179c83Andreas Hubersp<XINGSeeker> XINGSeeker::CreateFromSource(
32c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        const sp<DataSource> &source, off64_t first_frame_pos) {
334456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    sp<XINGSeeker> seeker = new XINGSeeker;
344456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
354456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    seeker->mFirstFramePos = first_frame_pos;
364456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
374456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if (!parse_xing_header(
384456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber                source, first_frame_pos,
395102400104ce1f0a6de7bf913381a91e4f18a22aMarco Nelissen                NULL, &seeker->mSizeBytes, seeker->mTOC, &seeker->mTOCValid,
404456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber                NULL, &seeker->mDurationUs)) {
414456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        return NULL;
424456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
434456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
444456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    return seeker;
454456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber}
464456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
474456da54bcd206ed1f518c69cc959ca65a179c83Andreas HuberXINGSeeker::XINGSeeker()
484456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    : mDurationUs(-1),
494456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber      mSizeBytes(0) {
504456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber}
514456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
524456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huberbool XINGSeeker::getDuration(int64_t *durationUs) {
534456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if (mDurationUs < 0) {
544456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        return false;
554456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
564456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
574456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    *durationUs = mDurationUs;
584456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
594456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    return true;
604456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber}
614456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
62c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dongbool XINGSeeker::getOffsetForTime(int64_t *timeUs, off64_t *pos) {
635102400104ce1f0a6de7bf913381a91e4f18a22aMarco Nelissen    if (mSizeBytes == 0 || !mTOCValid || mDurationUs < 0) {
644456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        return false;
654456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
664456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
674456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    float percent = (float)(*timeUs) * 100 / mDurationUs;
684456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    float fx;
694456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if( percent <= 0.0f ) {
704456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        fx = 0.0f;
714456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    } else if( percent >= 100.0f ) {
724456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        fx = 256.0f;
734456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    } else {
744456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        int a = (int)percent;
754456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        float fa, fb;
764456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        if ( a == 0 ) {
774456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            fa = 0.0f;
784456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        } else {
795102400104ce1f0a6de7bf913381a91e4f18a22aMarco Nelissen            fa = (float)mTOC[a-1];
804456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        }
814456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        if ( a < 99 ) {
825102400104ce1f0a6de7bf913381a91e4f18a22aMarco Nelissen            fb = (float)mTOC[a];
834456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        } else {
844456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            fb = 256.0f;
854456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        }
864456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        fx = fa + (fb-fa)*(percent-a);
874456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
884456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
894456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    *pos = (int)((1.0f/256.0f)*fx*mSizeBytes) + mFirstFramePos;
904456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
914456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    return true;
924456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber}
934456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
944456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huberstatic bool parse_xing_header(
95c7fc37a3dab9bd1f96713649f351b5990e6316ffJames Dong        const sp<DataSource> &source, off64_t first_frame_pos,
964456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        int32_t *frame_number, int32_t *byte_number,
975102400104ce1f0a6de7bf913381a91e4f18a22aMarco Nelissen        unsigned char *table_of_contents, bool *toc_valid,
985102400104ce1f0a6de7bf913381a91e4f18a22aMarco Nelissen        int32_t *quality_indicator,
994456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        int64_t *duration) {
1004456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if (frame_number) {
1014456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        *frame_number = 0;
1024456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
1034456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if (byte_number) {
1044456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        *byte_number = 0;
1054456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
1065102400104ce1f0a6de7bf913381a91e4f18a22aMarco Nelissen    if (toc_valid) {
1075102400104ce1f0a6de7bf913381a91e4f18a22aMarco Nelissen        *toc_valid = false;
1084456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
1094456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if (quality_indicator) {
1104456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        *quality_indicator = 0;
1114456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
1124456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if (duration) {
1134456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        *duration = 0;
1144456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
1154456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
1164456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    uint8_t buffer[4];
1174456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    int offset = first_frame_pos;
1184456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if (source->readAt(offset, &buffer, 4) < 4) { // get header
1194456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        return false;
1204456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
1214456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    offset += 4;
1224456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
1234456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    uint8_t id, layer, sr_index, mode;
1244456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    layer = (buffer[1] >> 1) & 3;
1254456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    id = (buffer[1] >> 3) & 3;
1264456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    sr_index = (buffer[2] >> 2) & 3;
1274456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    mode = (buffer[3] >> 6) & 3;
1284456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if (layer == 0) {
1294456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        return false;
1304456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
1314456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if (id == 1) {
1324456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        return false;
1334456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
1344456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if (sr_index == 3) {
1354456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        return false;
1364456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
1374456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    // determine offset of XING header
1384456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if(id&1) { // mpeg1
1394456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        if (mode != 3) offset += 32;
1404456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        else offset += 17;
1414456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    } else { // mpeg2
1424456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        if (mode != 3) offset += 17;
1434456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        else offset += 9;
1444456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
1454456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
1464456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if (source->readAt(offset, &buffer, 4) < 4) { // XING header ID
1474456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        return false;
1484456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
1494456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    offset += 4;
1504456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    // Check XING ID
1514456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if ((buffer[0] != 'X') || (buffer[1] != 'i')
1524456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber                || (buffer[2] != 'n') || (buffer[3] != 'g')) {
1534456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        if ((buffer[0] != 'I') || (buffer[1] != 'n')
1544456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber                    || (buffer[2] != 'f') || (buffer[3] != 'o')) {
1554456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            return false;
1564456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        }
1574456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
1584456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
1594456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if (source->readAt(offset, &buffer, 4) < 4) { // flags
1604456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        return false;
1614456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
1624456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    offset += 4;
1634456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    uint32_t flags = U32_AT(buffer);
1644456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
1654456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if (flags & 0x0001) {  // Frames field is present
1664456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        if (source->readAt(offset, buffer, 4) < 4) {
1674456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber             return false;
1684456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        }
1694456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        if (frame_number) {
1704456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber           *frame_number = U32_AT(buffer);
1714456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        }
1724456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        int32_t frame = U32_AT(buffer);
1734456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        // Samples per Frame: 1. index = MPEG Version ID, 2. index = Layer
1744456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        const int samplesPerFrames[2][3] =
1754456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        {
1764456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            { 384, 1152, 576  }, // MPEG 2, 2.5: layer1, layer2, layer3
1774456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            { 384, 1152, 1152 }, // MPEG 1: layer1, layer2, layer3
1784456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        };
1794456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        // sampling rates in hertz: 1. index = MPEG Version ID, 2. index = sampling rate index
1804456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        const int samplingRates[4][3] =
1814456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        {
1824456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            { 11025, 12000, 8000,  },    // MPEG 2.5
1834456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            { 0,     0,     0,     },    // reserved
1844456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            { 22050, 24000, 16000, },    // MPEG 2
1854456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            { 44100, 48000, 32000, }     // MPEG 1
1864456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        };
1874456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        if (duration) {
1884456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            *duration = (int64_t)frame * samplesPerFrames[id&1][3-layer] * 1000000LL
1894456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber                / samplingRates[id][sr_index];
1904456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        }
1914456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        offset += 4;
1924456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
1934456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if (flags & 0x0002) {  // Bytes field is present
1944456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        if (byte_number) {
1954456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            if (source->readAt(offset, buffer, 4) < 4) {
1964456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber                return false;
1974456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            }
1984456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            *byte_number = U32_AT(buffer);
1994456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        }
2004456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        offset += 4;
2014456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
2024456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if (flags & 0x0004) {  // TOC field is present
2035102400104ce1f0a6de7bf913381a91e4f18a22aMarco Nelissen        if (table_of_contents) {
2044456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            if (source->readAt(offset + 1, table_of_contents, 99) < 99) {
2054456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber                return false;
2064456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            }
2075102400104ce1f0a6de7bf913381a91e4f18a22aMarco Nelissen            if (toc_valid) {
2085102400104ce1f0a6de7bf913381a91e4f18a22aMarco Nelissen                *toc_valid = true;
2095102400104ce1f0a6de7bf913381a91e4f18a22aMarco Nelissen            }
2104456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        }
2114456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        offset += 100;
2124456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
2134456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    if (flags & 0x0008) {  // Quality indicator field is present
2144456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        if (quality_indicator) {
2154456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            if (source->readAt(offset, buffer, 4) < 4) {
2164456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber                return false;
2174456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            }
2184456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber            *quality_indicator = U32_AT(buffer);
2194456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber        }
2204456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    }
2214456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber    return true;
2224456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber}
2234456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
2244456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber}  // namespace android
2254456da54bcd206ed1f518c69cc959ca65a179c83Andreas Huber
226