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