16655174826330afe66ef766258181ae8c11f3f6cInsun Kang /*
26655174826330afe66ef766258181ae8c11f3f6cInsun Kang * Copyright (C) 2012 The Android Open Source Project
3965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang *
4965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang * Licensed under the Apache License, Version 2.0 (the "License");
5965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang * you may not use this file except in compliance with the License.
6965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang * You may obtain a copy of the License at
7965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang *
8965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang *      http://www.apache.org/licenses/LICENSE-2.0
9965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang *
10965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang * Unless required by applicable law or agreed to in writing, software
11965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang * distributed under the License is distributed on an "AS IS" BASIS,
12965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang * See the License for the specific language governing permissions and
14965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang * limitations under the License.
15965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang */
16965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
176655174826330afe66ef766258181ae8c11f3f6cInsun Kang//#define LOG_NDEBUG 0
186655174826330afe66ef766258181ae8c11f3f6cInsun Kang#define LOG_TAG "TimedTextSRTSource"
196655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include <utils/Log.h>
206655174826330afe66ef766258181ae8c11f3f6cInsun Kang
216655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include <binder/Parcel.h>
22bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang#include <media/stagefright/foundation/ADebug.h>  // for CHECK_xx
236655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include <media/stagefright/foundation/AString.h>
24965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang#include <media/stagefright/DataSource.h>
25f9d660a5e0196240add5daf0199f128d471e592cInsun Kang#include <media/stagefright/MediaDefs.h>  // for MEDIA_MIMETYPE_xxx
266655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include <media/stagefright/MediaErrors.h>
276655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include <media/stagefright/MediaSource.h>
28f9d660a5e0196240add5daf0199f128d471e592cInsun Kang#include <media/stagefright/MetaData.h>
296655174826330afe66ef766258181ae8c11f3f6cInsun Kang
306655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include "TimedTextSRTSource.h"
316655174826330afe66ef766258181ae8c11f3f6cInsun Kang#include "TextDescriptions.h"
32965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
33965d08ba16ee82bc85f69546360c18e7da907406Gloria Wangnamespace android {
34965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
356655174826330afe66ef766258181ae8c11f3f6cInsun KangTimedTextSRTSource::TimedTextSRTSource(const sp<DataSource>& dataSource)
366655174826330afe66ef766258181ae8c11f3f6cInsun Kang        : mSource(dataSource),
37f9d660a5e0196240add5daf0199f128d471e592cInsun Kang          mMetaData(new MetaData),
386655174826330afe66ef766258181ae8c11f3f6cInsun Kang          mIndex(0) {
39965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang}
40965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
416655174826330afe66ef766258181ae8c11f3f6cInsun KangTimedTextSRTSource::~TimedTextSRTSource() {
42965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang}
43965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
446655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextSRTSource::start() {
456655174826330afe66ef766258181ae8c11f3f6cInsun Kang    status_t err = scanFile();
466655174826330afe66ef766258181ae8c11f3f6cInsun Kang    if (err != OK) {
47965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        reset();
48965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    }
49f9d660a5e0196240add5daf0199f128d471e592cInsun Kang    // TODO: Need to detect the language, because SRT doesn't give language
50f9d660a5e0196240add5daf0199f128d471e592cInsun Kang    // information explicitly.
51f9d660a5e0196240add5daf0199f128d471e592cInsun Kang    mMetaData->setCString(kKeyMediaLanguage, "");
526655174826330afe66ef766258181ae8c11f3f6cInsun Kang    return err;
53965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang}
54965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
556655174826330afe66ef766258181ae8c11f3f6cInsun Kangvoid TimedTextSRTSource::reset() {
56f9d660a5e0196240add5daf0199f128d471e592cInsun Kang    mMetaData->clear();
57965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    mTextVector.clear();
58965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    mIndex = 0;
59965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang}
60965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
616655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextSRTSource::stop() {
626655174826330afe66ef766258181ae8c11f3f6cInsun Kang    reset();
636655174826330afe66ef766258181ae8c11f3f6cInsun Kang    return OK;
646655174826330afe66ef766258181ae8c11f3f6cInsun Kang}
656655174826330afe66ef766258181ae8c11f3f6cInsun Kang
666655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextSRTSource::read(
67bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang        int64_t *startTimeUs,
68bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang        int64_t *endTimeUs,
696655174826330afe66ef766258181ae8c11f3f6cInsun Kang        Parcel *parcel,
706655174826330afe66ef766258181ae8c11f3f6cInsun Kang        const MediaSource::ReadOptions *options) {
716655174826330afe66ef766258181ae8c11f3f6cInsun Kang    AString text;
72bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang    status_t err = getText(options, &text, startTimeUs, endTimeUs);
736655174826330afe66ef766258181ae8c11f3f6cInsun Kang    if (err != OK) {
746655174826330afe66ef766258181ae8c11f3f6cInsun Kang        return err;
756655174826330afe66ef766258181ae8c11f3f6cInsun Kang    }
766655174826330afe66ef766258181ae8c11f3f6cInsun Kang
77bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang    CHECK_GE(*startTimeUs, 0);
78bae00e73c6d1d87cc5fd42b50f95d1d9572162eaInsun Kang    extractAndAppendLocalDescriptions(*startTimeUs, text, parcel);
796655174826330afe66ef766258181ae8c11f3f6cInsun Kang    return OK;
806655174826330afe66ef766258181ae8c11f3f6cInsun Kang}
81965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
82a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kangsp<MetaData> TimedTextSRTSource::getFormat() {
83a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang    return mMetaData;
84a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang}
85a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang
866655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextSRTSource::scanFile() {
87965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    off64_t offset = 0;
88965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    int64_t startTimeUs;
89965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    bool endOfFile = false;
90965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
91965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    while (!endOfFile) {
92965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        TextInfo info;
936655174826330afe66ef766258181ae8c11f3f6cInsun Kang        status_t err = getNextSubtitleInfo(&offset, &startTimeUs, &info);
946655174826330afe66ef766258181ae8c11f3f6cInsun Kang        switch (err) {
956655174826330afe66ef766258181ae8c11f3f6cInsun Kang            case OK:
966655174826330afe66ef766258181ae8c11f3f6cInsun Kang                mTextVector.add(startTimeUs, info);
976655174826330afe66ef766258181ae8c11f3f6cInsun Kang                break;
986655174826330afe66ef766258181ae8c11f3f6cInsun Kang            case ERROR_END_OF_STREAM:
99965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang                endOfFile = true;
1006655174826330afe66ef766258181ae8c11f3f6cInsun Kang                break;
1016655174826330afe66ef766258181ae8c11f3f6cInsun Kang            default:
102965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang                return err;
103965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        }
104965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    }
105965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    if (mTextVector.isEmpty()) {
106965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        return ERROR_MALFORMED;
107965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    }
108965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    return OK;
109965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang}
110965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
111965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang/* SRT format:
1126655174826330afe66ef766258181ae8c11f3f6cInsun Kang *   Subtitle number
1136655174826330afe66ef766258181ae8c11f3f6cInsun Kang *   Start time --> End time
1146655174826330afe66ef766258181ae8c11f3f6cInsun Kang *   Text of subtitle (one or more lines)
1156655174826330afe66ef766258181ae8c11f3f6cInsun Kang *   Blank lines
116965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang *
117965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang * .srt file example:
1186655174826330afe66ef766258181ae8c11f3f6cInsun Kang * 1
1196655174826330afe66ef766258181ae8c11f3f6cInsun Kang * 00:00:20,000 --> 00:00:24,400
1206655174826330afe66ef766258181ae8c11f3f6cInsun Kang * Altocumulus clouds occr between six thousand
121965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang *
1226655174826330afe66ef766258181ae8c11f3f6cInsun Kang * 2
1236655174826330afe66ef766258181ae8c11f3f6cInsun Kang * 00:00:24,600 --> 00:00:27,800
1246655174826330afe66ef766258181ae8c11f3f6cInsun Kang * and twenty thousand feet above ground level.
125965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang */
1266655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextSRTSource::getNextSubtitleInfo(
1276655174826330afe66ef766258181ae8c11f3f6cInsun Kang          off64_t *offset, int64_t *startTimeUs, TextInfo *info) {
128965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    AString data;
129965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    status_t err;
130965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
1310e0c3220ee1c4d57765e2cba3b07923921c55e08Insun Kang    // To skip blank lines.
1320e0c3220ee1c4d57765e2cba3b07923921c55e08Insun Kang    do {
1330e0c3220ee1c4d57765e2cba3b07923921c55e08Insun Kang        if ((err = readNextLine(offset, &data)) != OK) {
1340e0c3220ee1c4d57765e2cba3b07923921c55e08Insun Kang            return err;
1350e0c3220ee1c4d57765e2cba3b07923921c55e08Insun Kang        }
1360e0c3220ee1c4d57765e2cba3b07923921c55e08Insun Kang        data.trim();
1376655174826330afe66ef766258181ae8c11f3f6cInsun Kang    } while (data.empty());
1380e0c3220ee1c4d57765e2cba3b07923921c55e08Insun Kang
1390e0c3220ee1c4d57765e2cba3b07923921c55e08Insun Kang    // Just ignore the first non-blank line which is subtitle sequence number.
140965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    if ((err = readNextLine(offset, &data)) != OK) {
141965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        return err;
142965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    }
143965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    int hour1, hour2, min1, min2, sec1, sec2, msec1, msec2;
144965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    // the start time format is: hours:minutes:seconds,milliseconds
145965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    // 00:00:24,600 --> 00:00:27,800
146965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    if (sscanf(data.c_str(), "%02d:%02d:%02d,%03d --> %02d:%02d:%02d,%03d",
1476655174826330afe66ef766258181ae8c11f3f6cInsun Kang               &hour1, &min1, &sec1, &msec1, &hour2, &min2, &sec2, &msec2) != 8) {
148965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        return ERROR_MALFORMED;
149965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    }
150965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
151965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    *startTimeUs = ((hour1 * 3600 + min1 * 60 + sec1) * 1000 + msec1) * 1000ll;
152965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    info->endTimeUs = ((hour2 * 3600 + min2 * 60 + sec2) * 1000 + msec2) * 1000ll;
153965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    if (info->endTimeUs <= *startTimeUs) {
154965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        return ERROR_MALFORMED;
155965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    }
156965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
157965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    info->offset = *offset;
158965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    bool needMoreData = true;
159965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    while (needMoreData) {
160965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        if ((err = readNextLine(offset, &data)) != OK) {
161965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            if (err == ERROR_END_OF_STREAM) {
162a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang                break;
163965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            } else {
164965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang                return err;
165965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            }
166965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        }
167965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
168a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang        data.trim();
169a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang        if (data.empty()) {
170a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang            // it's an empty line used to separate two subtitles
171a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang            needMoreData = false;
172965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        }
173965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    }
174965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    info->textLen = *offset - info->offset;
175965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    return OK;
176965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang}
177965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
1786655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextSRTSource::readNextLine(off64_t *offset, AString *data) {
1796655174826330afe66ef766258181ae8c11f3f6cInsun Kang    data->clear();
1806655174826330afe66ef766258181ae8c11f3f6cInsun Kang    while (true) {
1816655174826330afe66ef766258181ae8c11f3f6cInsun Kang        ssize_t readSize;
1826655174826330afe66ef766258181ae8c11f3f6cInsun Kang        char character;
1836655174826330afe66ef766258181ae8c11f3f6cInsun Kang        if ((readSize = mSource->readAt(*offset, &character, 1)) < 1) {
1846655174826330afe66ef766258181ae8c11f3f6cInsun Kang            if (readSize == 0) {
1856655174826330afe66ef766258181ae8c11f3f6cInsun Kang                return ERROR_END_OF_STREAM;
1866655174826330afe66ef766258181ae8c11f3f6cInsun Kang            }
1876655174826330afe66ef766258181ae8c11f3f6cInsun Kang            return ERROR_IO;
1886655174826330afe66ef766258181ae8c11f3f6cInsun Kang        }
189965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
1906655174826330afe66ef766258181ae8c11f3f6cInsun Kang        (*offset)++;
191965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
1926655174826330afe66ef766258181ae8c11f3f6cInsun Kang        // a line could end with CR, LF or CR + LF
1936655174826330afe66ef766258181ae8c11f3f6cInsun Kang        if (character == 10) {
1946655174826330afe66ef766258181ae8c11f3f6cInsun Kang            break;
1956655174826330afe66ef766258181ae8c11f3f6cInsun Kang        } else if (character == 13) {
1966655174826330afe66ef766258181ae8c11f3f6cInsun Kang            if ((readSize = mSource->readAt(*offset, &character, 1)) < 1) {
1976655174826330afe66ef766258181ae8c11f3f6cInsun Kang                if (readSize == 0) {  // end of the stream
1986655174826330afe66ef766258181ae8c11f3f6cInsun Kang                    return OK;
1996655174826330afe66ef766258181ae8c11f3f6cInsun Kang                }
2006655174826330afe66ef766258181ae8c11f3f6cInsun Kang                return ERROR_IO;
2016655174826330afe66ef766258181ae8c11f3f6cInsun Kang            }
2026655174826330afe66ef766258181ae8c11f3f6cInsun Kang
2036655174826330afe66ef766258181ae8c11f3f6cInsun Kang            (*offset)++;
2046655174826330afe66ef766258181ae8c11f3f6cInsun Kang            if (character != 10) {
2056655174826330afe66ef766258181ae8c11f3f6cInsun Kang                (*offset)--;
2066655174826330afe66ef766258181ae8c11f3f6cInsun Kang            }
2076655174826330afe66ef766258181ae8c11f3f6cInsun Kang            break;
2086655174826330afe66ef766258181ae8c11f3f6cInsun Kang        }
2096655174826330afe66ef766258181ae8c11f3f6cInsun Kang        data->append(character);
2106655174826330afe66ef766258181ae8c11f3f6cInsun Kang    }
2116655174826330afe66ef766258181ae8c11f3f6cInsun Kang    return OK;
2126655174826330afe66ef766258181ae8c11f3f6cInsun Kang}
2136655174826330afe66ef766258181ae8c11f3f6cInsun Kang
2146655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextSRTSource::getText(
2156655174826330afe66ef766258181ae8c11f3f6cInsun Kang        const MediaSource::ReadOptions *options,
2166655174826330afe66ef766258181ae8c11f3f6cInsun Kang        AString *text, int64_t *startTimeUs, int64_t *endTimeUs) {
2170a2f0e047a2e593c62f54b07b903baf4728b9d0aInsun Kang    if (mTextVector.size() == 0) {
2180a2f0e047a2e593c62f54b07b903baf4728b9d0aInsun Kang        return ERROR_END_OF_STREAM;
2190a2f0e047a2e593c62f54b07b903baf4728b9d0aInsun Kang    }
2206655174826330afe66ef766258181ae8c11f3f6cInsun Kang    text->clear();
221965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    int64_t seekTimeUs;
222965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    MediaSource::ReadOptions::SeekMode mode;
2236655174826330afe66ef766258181ae8c11f3f6cInsun Kang    if (options != NULL && options->getSeekTo(&seekTimeUs, &mode)) {
2246655174826330afe66ef766258181ae8c11f3f6cInsun Kang        int64_t lastEndTimeUs =
2256655174826330afe66ef766258181ae8c11f3f6cInsun Kang                mTextVector.valueAt(mTextVector.size() - 1).endTimeUs;
226a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang        if (seekTimeUs < 0) {
227965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            return ERROR_OUT_OF_RANGE;
228a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang        } else if (seekTimeUs >= lastEndTimeUs) {
229a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang            return ERROR_END_OF_STREAM;
230965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        } else {
231965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            // binary search
2320a2f0e047a2e593c62f54b07b903baf4728b9d0aInsun Kang            size_t low = 0;
2330a2f0e047a2e593c62f54b07b903baf4728b9d0aInsun Kang            size_t high = mTextVector.size() - 1;
2340a2f0e047a2e593c62f54b07b903baf4728b9d0aInsun Kang            size_t mid = 0;
235965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
236965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            while (low <= high) {
237965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang                mid = low + (high - low)/2;
238a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang                int diff = compareExtendedRangeAndTime(mid, seekTimeUs);
239a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang                if (diff == 0) {
240965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang                    break;
241a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang                } else if (diff < 0) {
242965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang                    low = mid + 1;
243965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang                } else {
244965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang                    high = mid - 1;
245965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang                }
246965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            }
247965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            mIndex = mid;
248965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        }
249965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    }
2500a2f0e047a2e593c62f54b07b903baf4728b9d0aInsun Kang
2510a2f0e047a2e593c62f54b07b903baf4728b9d0aInsun Kang    if (mIndex >= mTextVector.size()) {
2520a2f0e047a2e593c62f54b07b903baf4728b9d0aInsun Kang        return ERROR_END_OF_STREAM;
2530a2f0e047a2e593c62f54b07b903baf4728b9d0aInsun Kang    }
254a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang
2556655174826330afe66ef766258181ae8c11f3f6cInsun Kang    const TextInfo &info = mTextVector.valueAt(mIndex);
256965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    *startTimeUs = mTextVector.keyAt(mIndex);
257965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    *endTimeUs = info.endTimeUs;
2586655174826330afe66ef766258181ae8c11f3f6cInsun Kang    mIndex++;
259965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
260965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    char *str = new char[info.textLen];
2616655174826330afe66ef766258181ae8c11f3f6cInsun Kang    if (mSource->readAt(info.offset, str, info.textLen) < info.textLen) {
262965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        delete[] str;
263965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        return ERROR_IO;
264965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    }
265965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    text->append(str, info.textLen);
266965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    delete[] str;
267965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    return OK;
268965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang}
269965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
2706655174826330afe66ef766258181ae8c11f3f6cInsun Kangstatus_t TimedTextSRTSource::extractAndAppendLocalDescriptions(
2716655174826330afe66ef766258181ae8c11f3f6cInsun Kang        int64_t timeUs, const AString &text, Parcel *parcel) {
2726655174826330afe66ef766258181ae8c11f3f6cInsun Kang    const void *data = text.c_str();
2736655174826330afe66ef766258181ae8c11f3f6cInsun Kang    size_t size = text.size();
2746655174826330afe66ef766258181ae8c11f3f6cInsun Kang    int32_t flag = TextDescriptions::LOCAL_DESCRIPTIONS |
2756655174826330afe66ef766258181ae8c11f3f6cInsun Kang                   TextDescriptions::OUT_OF_BAND_TEXT_SRT;
2766655174826330afe66ef766258181ae8c11f3f6cInsun Kang
2776655174826330afe66ef766258181ae8c11f3f6cInsun Kang    if (size > 0) {
2786655174826330afe66ef766258181ae8c11f3f6cInsun Kang        return TextDescriptions::getParcelOfDescriptions(
2796655174826330afe66ef766258181ae8c11f3f6cInsun Kang                (const uint8_t *)data, size, flag, timeUs / 1000, parcel);
2806655174826330afe66ef766258181ae8c11f3f6cInsun Kang    }
2816655174826330afe66ef766258181ae8c11f3f6cInsun Kang    return OK;
2826655174826330afe66ef766258181ae8c11f3f6cInsun Kang}
2836655174826330afe66ef766258181ae8c11f3f6cInsun Kang
284a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kangint TimedTextSRTSource::compareExtendedRangeAndTime(size_t index, int64_t timeUs) {
285a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang    CHECK_LT(index, mTextVector.size());
286a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang    int64_t endTimeUs = mTextVector.valueAt(index).endTimeUs;
287a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang    int64_t startTimeUs = (index > 0) ?
288a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang            mTextVector.valueAt(index - 1).endTimeUs : 0;
289a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang    if (timeUs >= startTimeUs && timeUs < endTimeUs) {
290a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang        return 0;
291a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang    } else if (endTimeUs <= timeUs) {
292a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang        return -1;
293a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang    } else {
294a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang        return 1;
295a3c9d82d0f898d30982840b48d1f00fd0d831e19Insun Kang    }
296f9d660a5e0196240add5daf0199f128d471e592cInsun Kang}
297f9d660a5e0196240add5daf0199f128d471e592cInsun Kang
298965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang}  // namespace android
299