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