TimedTextPlayer.cpp revision 3b573f7bf1c5736d500e39013b8d32478a1429e6
17a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang /*
27a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * Copyright (C) 2011 The Android Open Source Project
37a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang *
47a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * Licensed under the Apache License, Version 2.0 (the "License");
57a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * you may not use this file except in compliance with the License.
67a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * You may obtain a copy of the License at
77a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang *
87a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang *      http://www.apache.org/licenses/LICENSE-2.0
97a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang *
107a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * Unless required by applicable law or agreed to in writing, software
117a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * distributed under the License is distributed on an "AS IS" BASIS,
127a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
137a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * See the License for the specific language governing permissions and
147a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang * limitations under the License.
157a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang */
167a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
177a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang//#define LOG_NDEBUG 0
187a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#define LOG_TAG "TimedTextPlayer"
197a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include <utils/Log.h>
207a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
217a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include <binder/IPCThreadState.h>
223b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
237a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include <media/stagefright/MediaDebug.h>
247a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include <media/stagefright/MediaDefs.h>
257a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include <media/stagefright/MediaErrors.h>
267a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include <media/stagefright/MediaSource.h>
277a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include <media/stagefright/MetaData.h>
287a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include <media/stagefright/MediaBuffer.h>
29965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang#include <media/stagefright/FileSource.h>
307a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include <media/stagefright/Utils.h>
313b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
327a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang#include "include/AwesomePlayer.h"
33965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang#include "TimedTextPlayer.h"
34965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang#include "TimedTextParser.h"
353b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang#include "TextDescriptions.h"
367a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
377a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wangnamespace android {
387a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
397a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wangstruct TimedTextEvent : public TimedEventQueue::Event {
407a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    TimedTextEvent(
417a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            TimedTextPlayer *player,
427a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            void (TimedTextPlayer::*method)())
437a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        : mPlayer(player),
447a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang          mMethod(method) {
457a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    }
467a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
477a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wangprotected:
487a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    virtual ~TimedTextEvent() {}
497a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
507a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    virtual void fire(TimedEventQueue *queue, int64_t /* now_us */) {
517a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        (mPlayer->*mMethod)();
527a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    }
537a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
547a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wangprivate:
557a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    TimedTextPlayer *mPlayer;
567a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    void (TimedTextPlayer::*mMethod)();
577a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
587a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    TimedTextEvent(const TimedTextEvent &);
597a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    TimedTextEvent &operator=(const TimedTextEvent &);
607a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang};
617a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
627a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria WangTimedTextPlayer::TimedTextPlayer(
637a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        AwesomePlayer *observer,
647a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        const wp<MediaPlayerBase> &listener,
657a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        TimedEventQueue *queue)
667a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    : mSource(NULL),
67965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang      mOutOfBandSource(NULL),
687a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang      mSeekTimeUs(0),
697a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang      mStarted(false),
707a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang      mTextEventPending(false),
717a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang      mQueue(queue),
727a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang      mListener(listener),
737a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang      mObserver(observer),
74965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang      mTextBuffer(NULL),
75965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang      mTextParser(NULL),
76965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang      mTextType(kNoText) {
777a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    mTextEvent = new TimedTextEvent(this, &TimedTextPlayer::onTextEvent);
787a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang}
797a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
807a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria WangTimedTextPlayer::~TimedTextPlayer() {
817a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    if (mStarted) {
827a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        reset();
837a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    }
847a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
857a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    mTextTrackVector.clear();
86965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    mTextOutOfBandVector.clear();
877a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang}
887a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
897a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wangstatus_t TimedTextPlayer::start(uint8_t index) {
907a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    CHECK(!mStarted);
917a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
92965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    if (index >=
93965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            mTextTrackVector.size() + mTextOutOfBandVector.size()) {
94965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        LOGE("Incorrect text track index: %d", index);
957a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        return BAD_VALUE;
967a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    }
977a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
983b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    status_t err;
99965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    if (index < mTextTrackVector.size()) { // start an in-band text
100965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        mSource = mTextTrackVector.itemAt(index);
1017a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1023b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        err = mSource->start();
1037a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
104965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        if (err != OK) {
105965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            return err;
106965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        }
107965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        mTextType = kInBandText;
108965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    } else { // start an out-of-band text
109965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        OutOfBandText text =
110965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            mTextOutOfBandVector.itemAt(index - mTextTrackVector.size());
111965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
112965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        mOutOfBandSource = text.source;
113965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        TimedTextParser::FileType fileType = text.type;
114965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
115965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        if (mTextParser == NULL) {
116965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            mTextParser = new TimedTextParser();
117965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        }
118965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
119965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        if ((err = mTextParser->init(mOutOfBandSource, fileType)) != OK) {
120965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            return err;
121965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        }
122965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        mTextType = kOutOfBandText;
1237a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    }
1247a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1253b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    // send sample description format
1263b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    if ((err = extractAndSendGlobalDescriptions()) != OK) {
1273b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        return err;
1283b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    }
1293b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
1307a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    int64_t positionUs;
1317a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    mObserver->getPosition(&positionUs);
1327a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    seekTo(positionUs);
1337a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1347a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    postTextEvent();
1357a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1367a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    mStarted = true;
1377a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1387a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    return OK;
1397a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang}
1407a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1417a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wangvoid TimedTextPlayer::pause() {
1427a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    CHECK(mStarted);
1437a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1447a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    cancelTextEvent();
1457a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang}
1467a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1477a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wangvoid TimedTextPlayer::resume() {
1487a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    CHECK(mStarted);
1497a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1507a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    postTextEvent();
1517a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang}
1527a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1537a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wangvoid TimedTextPlayer::reset() {
1547a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    CHECK(mStarted);
1557a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1567a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    // send an empty text to clear the screen
1577a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    notifyListener(MEDIA_TIMED_TEXT);
1587a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1597a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    cancelTextEvent();
1607a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1617a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    mSeeking = false;
1627a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    mStarted = false;
1637a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
164965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    if (mTextType == kInBandText) {
165965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        if (mTextBuffer != NULL) {
166965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            mTextBuffer->release();
167965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            mTextBuffer = NULL;
168965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        }
1697a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
170965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        if (mSource != NULL) {
171965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            mSource->stop();
172965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            mSource.clear();
173965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            mSource = NULL;
174965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        }
175965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    } else {
176965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        if (mTextParser != NULL) {
177965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            mTextParser.clear();
178965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            mTextParser = NULL;
179965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        }
180965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        if (mOutOfBandSource != NULL) {
181965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            mOutOfBandSource.clear();
182965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            mOutOfBandSource = NULL;
183965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        }
1847a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    }
1857a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang}
1867a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1877a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wangstatus_t TimedTextPlayer::seekTo(int64_t time_us) {
1887a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    Mutex::Autolock autoLock(mLock);
1897a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1907a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    mSeeking = true;
1917a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    mSeekTimeUs = time_us;
1927a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
193965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    postTextEvent();
194965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
1957a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    return OK;
1967a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang}
1977a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
1987a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wangstatus_t TimedTextPlayer::setTimedTextTrackIndex(int32_t index) {
199965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    if (index >=
200965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            (int)(mTextTrackVector.size() + mTextOutOfBandVector.size())) {
2017a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        return BAD_VALUE;
2027a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    }
2037a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
2047a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    if (mStarted) {
2057a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        reset();
2067a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    }
2077a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
2087a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    if (index >= 0) {
2097a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        return start(index);
2107a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    }
2117a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    return OK;
2127a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang}
2137a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
2147a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wangvoid TimedTextPlayer::onTextEvent() {
2157a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    Mutex::Autolock autoLock(mLock);
2167a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
2177a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    if (!mTextEventPending) {
2187a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        return;
2197a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    }
2207a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    mTextEventPending = false;
2217a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
2223b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    if (mData.dataSize() > 0) {
2233b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        notifyListener(MEDIA_TIMED_TEXT, &mData);
2243b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        mData.freeData();
2253b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    }
2263b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
2277a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    MediaSource::ReadOptions options;
2287a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    if (mSeeking) {
2297a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        options.setSeekTo(mSeekTimeUs,
2307a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
2317a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        mSeeking = false;
2327a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
2337a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        notifyListener(MEDIA_TIMED_TEXT); //empty text to clear the screen
2347a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    }
2357a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
236965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    int64_t positionUs, timeUs;
237965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    mObserver->getPosition(&positionUs);
2387a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
239965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    if (mTextType == kInBandText) {
240965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        if (mSource->read(&mTextBuffer, &options) != OK) {
241965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            return;
242965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        }
243965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
244965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        mTextBuffer->meta_data()->findInt64(kKeyTime, &timeUs);
245965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    } else {
246965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        int64_t endTimeUs;
247965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        if (mTextParser->getText(
248965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang                    &mText, &timeUs, &endTimeUs, &options) != OK) {
249965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            return;
250965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        }
251965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    }
2527a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
2533b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    if (timeUs > 0) {
2543b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        extractAndAppendLocalDescriptions(timeUs);
2553b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    }
2563b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
2573b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    if (mTextType == kInBandText) {
2583b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        if (mTextBuffer != NULL) {
2593b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            mTextBuffer->release();
2603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            mTextBuffer = NULL;
2613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
2623b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    } else {
2633b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        mText.clear();
2643b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    }
2653b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
2667a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    //send the text now
2677a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    if (timeUs <= positionUs + 100000ll) {
2687a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        postTextEvent();
2697a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    } else {
2707a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        postTextEvent(timeUs - positionUs - 100000ll);
2717a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    }
2727a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang}
2737a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
2747a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wangvoid TimedTextPlayer::postTextEvent(int64_t delayUs) {
2757a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    if (mTextEventPending) {
2767a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        return;
2777a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    }
2787a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
2797a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    mTextEventPending = true;
2807a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    mQueue->postEventWithDelay(mTextEvent, delayUs < 0 ? 10000 : delayUs);
2817a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang}
2827a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
2837a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wangvoid TimedTextPlayer::cancelTextEvent() {
2847a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    mQueue->cancelEvent(mTextEvent->eventID());
2857a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    mTextEventPending = false;
2867a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang}
2877a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
2887a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wangvoid TimedTextPlayer::addTextSource(sp<MediaSource> source) {
289965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    Mutex::Autolock autoLock(mLock);
2907a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    mTextTrackVector.add(source);
2917a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang}
2927a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
293965d08ba16ee82bc85f69546360c18e7da907406Gloria Wangstatus_t TimedTextPlayer::setParameter(int key, const Parcel &request) {
294965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    Mutex::Autolock autoLock(mLock);
295965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
296965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    if (key == KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE) {
2973b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        const String16 uri16 = request.readString16();
2983b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        String8 uri = String8(uri16);
299965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        KeyedVector<String8, String8> headers;
300965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
301965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        // To support local subtitle file only for now
302965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        if (strncasecmp("file://", uri.string(), 7)) {
303965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            return INVALID_OPERATION;
304965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        }
305965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        sp<DataSource> dataSource =
306965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            DataSource::CreateFromURI(uri, &headers);
307965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        status_t err = dataSource->initCheck();
308965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
309965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        if (err != OK) {
310965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            return err;
311965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        }
312965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
313965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        OutOfBandText text;
314965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        text.source = dataSource;
315965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        if (uri.getPathExtension() == String8(".srt")) {
316965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            text.type = TimedTextParser::OUT_OF_BAND_FILE_SRT;
317965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        } else {
318965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang            return ERROR_UNSUPPORTED;
319965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        }
320965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
321965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        mTextOutOfBandVector.add(text);
322965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
323965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang        return OK;
324965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    }
325965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang    return INVALID_OPERATION;
326965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang}
327965d08ba16ee82bc85f69546360c18e7da907406Gloria Wang
3283b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wangvoid TimedTextPlayer::notifyListener(int msg, const Parcel *parcel) {
3297a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    if (mListener != NULL) {
3307a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        sp<MediaPlayerBase> listener = mListener.promote();
3317a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang
3327a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        if (listener != NULL) {
3333b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (parcel && (parcel->dataSize() > 0)) {
3343b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                listener->sendEvent(msg, 0, 0, parcel);
3357a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            } else { // send an empty timed text to clear the screen
3367a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang                listener->sendEvent(msg);
3377a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang            }
3387a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang        }
3397a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang    }
3407a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang}
3413b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
3423b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang// Each text sample consists of a string of text, optionally with sample
3433b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang// modifier description. The modifier description could specify a new
3443b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang// text style for the string of text. These descriptions are present only
3453b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang// if they are needed. This method is used to extract the modifier
3463b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang// description and append it at the end of the text.
3473b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wangstatus_t TimedTextPlayer::extractAndAppendLocalDescriptions(int64_t timeUs) {
3483b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    const void *data;
3493b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    size_t size = 0;
3503b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    int32_t flag = TextDescriptions::LOCAL_DESCRIPTIONS;
3513b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
3523b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    if (mTextType == kInBandText) {
3533b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        const char *mime;
3543b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
3553b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
3563b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
3573b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            flag |= TextDescriptions::IN_BAND_TEXT_3GPP;
3583b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            data = mTextBuffer->data();
3593b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            size = mTextBuffer->size();
3603b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        } else {
3613b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            // support 3GPP only for now
3623b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            return ERROR_UNSUPPORTED;
3633b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
3643b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    } else {
3653b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        data = mText.c_str();
3663b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        size = mText.size();
3673b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        flag |= TextDescriptions::OUT_OF_BAND_TEXT_SRT;
3683b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    }
3693b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
3703b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    if ((size > 0) && (flag != TextDescriptions::LOCAL_DESCRIPTIONS)) {
3713b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        mData.freeData();
3723b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        return TextDescriptions::getParcelOfDescriptions(
3733b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                (const uint8_t *)data, size, flag, timeUs / 1000, &mData);
3743b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    }
3753b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
3763b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    return OK;
3773b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang}
3783b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
3793b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang// To extract and send the global text descriptions for all the text samples
3803b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang// in the text track or text file.
3813b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wangstatus_t TimedTextPlayer::extractAndSendGlobalDescriptions() {
3823b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    const void *data;
3833b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    size_t size = 0;
3843b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    int32_t flag = TextDescriptions::GLOBAL_DESCRIPTIONS;
3853b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
3863b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    if (mTextType == kInBandText) {
3873b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        const char *mime;
3883b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime));
3893b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
3903b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        // support 3GPP only for now
3913b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
3923b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            uint32_t type;
3933b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            // get the 'tx3g' box content. This box contains the text descriptions
3943b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            // used to render the text track
3953b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (!mSource->getFormat()->findData(
3963b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                        kKeyTextFormatData, &type, &data, &size)) {
3973b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                return ERROR_MALFORMED;
3983b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
3993b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
4003b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            flag |= TextDescriptions::IN_BAND_TEXT_3GPP;
4013b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
4023b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    }
4033b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
4043b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    if ((size > 0) && (flag != TextDescriptions::GLOBAL_DESCRIPTIONS)) {
4053b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        Parcel parcel;
4063b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        if (TextDescriptions::getParcelOfDescriptions(
4073b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                (const uint8_t *)data, size, flag, 0, &parcel) == OK) {
4083b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            if (parcel.dataSize() > 0) {
4093b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang                notifyListener(MEDIA_TIMED_TEXT, &parcel);
4103b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang            }
4113b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang        }
4123b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    }
4133b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang
4143b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang    return OK;
4153b573f7bf1c5736d500e39013b8d32478a1429e6Gloria Wang}
4167a1e3e81264189e23a1db2b174e1b5a5d4c7d1c3Gloria Wang}
417