TimedTextDriver.cpp revision 3254b25e8b0f674ccc2226609e01dd86a600802e
1 /* 2 * Copyright (C) 2012 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17//#define LOG_NDEBUG 0 18#define LOG_TAG "TimedTextDriver" 19#include <utils/Log.h> 20 21#include <binder/IPCThreadState.h> 22 23#include <media/MediaPlayerInterface.h> 24#include <media/stagefright/MediaErrors.h> 25#include <media/stagefright/MediaSource.h> 26#include <media/stagefright/DataSource.h> 27#include <media/stagefright/Utils.h> 28#include <media/stagefright/foundation/ADebug.h> 29#include <media/stagefright/foundation/ALooper.h> 30#include <media/stagefright/timedtext/TimedTextDriver.h> 31 32#include "TextDescriptions.h" 33#include "TimedTextPlayer.h" 34#include "TimedTextSource.h" 35 36namespace android { 37 38TimedTextDriver::TimedTextDriver( 39 const wp<MediaPlayerBase> &listener) 40 : mLooper(new ALooper), 41 mListener(listener), 42 mState(UNINITIALIZED) { 43 mLooper->setName("TimedTextDriver"); 44 mLooper->start(); 45 mPlayer = new TimedTextPlayer(listener); 46 mLooper->registerHandler(mPlayer); 47} 48 49TimedTextDriver::~TimedTextDriver() { 50 mTextInBandVector.clear(); 51 mTextOutOfBandVector.clear(); 52 mLooper->stop(); 53} 54 55status_t TimedTextDriver::setTimedTextTrackIndex_l(int32_t index) { 56 if (index >= 57 (int)(mTextInBandVector.size() + mTextOutOfBandVector.size())) { 58 return BAD_VALUE; 59 } 60 61 sp<TimedTextSource> source; 62 if (index < mTextInBandVector.size()) { 63 source = mTextInBandVector.itemAt(index); 64 } else { 65 source = mTextOutOfBandVector.itemAt(index - mTextInBandVector.size()); 66 } 67 mPlayer->setDataSource(source); 68 return OK; 69} 70 71status_t TimedTextDriver::start() { 72 Mutex::Autolock autoLock(mLock); 73 switch (mState) { 74 case UNINITIALIZED: 75 return INVALID_OPERATION; 76 case STOPPED: 77 mPlayer->start(); 78 break; 79 case PLAYING: 80 return OK; 81 case PAUSED: 82 mPlayer->resume(); 83 break; 84 default: 85 TRESPASS(); 86 } 87 mState = PLAYING; 88 return OK; 89} 90 91status_t TimedTextDriver::stop() { 92 return pause(); 93} 94 95// TODO: Test if pause() works properly. 96// Scenario 1: start - pause - resume 97// Scenario 2: start - seek 98// Scenario 3: start - pause - seek - resume 99status_t TimedTextDriver::pause() { 100 Mutex::Autolock autoLock(mLock); 101 switch (mState) { 102 case UNINITIALIZED: 103 return INVALID_OPERATION; 104 case STOPPED: 105 return OK; 106 case PLAYING: 107 mPlayer->pause(); 108 break; 109 case PAUSED: 110 return OK; 111 default: 112 TRESPASS(); 113 } 114 mState = PAUSED; 115 return OK; 116} 117 118status_t TimedTextDriver::resume() { 119 return start(); 120} 121 122status_t TimedTextDriver::seekToAsync(int64_t timeUs) { 123 mPlayer->seekToAsync(timeUs); 124 return OK; 125} 126 127status_t TimedTextDriver::setTimedTextTrackIndex(int32_t index) { 128 // TODO: This is current implementation for MediaPlayer::disableTimedText(). 129 // Find better way for readability. 130 if (index < 0) { 131 mPlayer->pause(); 132 return OK; 133 } 134 135 status_t ret = OK; 136 Mutex::Autolock autoLock(mLock); 137 switch (mState) { 138 case UNINITIALIZED: 139 ret = INVALID_OPERATION; 140 break; 141 case PAUSED: 142 ret = setTimedTextTrackIndex_l(index); 143 break; 144 case PLAYING: 145 mPlayer->pause(); 146 ret = setTimedTextTrackIndex_l(index); 147 if (ret != OK) { 148 break; 149 } 150 mPlayer->start(); 151 break; 152 case STOPPED: 153 // TODO: The only difference between STOPPED and PAUSED is this 154 // part. Revise the flow from "MediaPlayer::enableTimedText()" and 155 // remove one of the status, PAUSED and STOPPED, if possible. 156 ret = setTimedTextTrackIndex_l(index); 157 if (ret != OK) { 158 break; 159 } 160 mPlayer->start(); 161 break; 162 defaut: 163 TRESPASS(); 164 } 165 return ret; 166} 167 168status_t TimedTextDriver::addInBandTextSource( 169 const sp<MediaSource>& mediaSource) { 170 sp<TimedTextSource> source = 171 TimedTextSource::CreateTimedTextSource(mediaSource); 172 if (source == NULL) { 173 return ERROR_UNSUPPORTED; 174 } 175 Mutex::Autolock autoLock(mLock); 176 mTextInBandVector.add(source); 177 if (mState == UNINITIALIZED) { 178 mState = STOPPED; 179 } 180 return OK; 181} 182 183status_t TimedTextDriver::addOutOfBandTextSource( 184 const Parcel &request) { 185 // TODO: Define "TimedTextSource::CreateFromURI(uri)" 186 // and move below lines there..? 187 188 // String values written in Parcel are UTF-16 values. 189 const String16 uri16 = request.readString16(); 190 String8 uri = String8(request.readString16()); 191 192 uri.toLower(); 193 // To support local subtitle file only for now 194 if (strncasecmp("file://", uri.string(), 7)) { 195 return ERROR_UNSUPPORTED; 196 } 197 sp<DataSource> dataSource = 198 DataSource::CreateFromURI(uri); 199 if (dataSource == NULL) { 200 return ERROR_UNSUPPORTED; 201 } 202 203 sp<TimedTextSource> source; 204 if (uri.getPathExtension() == String8(".srt")) { 205 source = TimedTextSource::CreateTimedTextSource( 206 dataSource, TimedTextSource::OUT_OF_BAND_FILE_SRT); 207 } 208 209 if (source == NULL) { 210 return ERROR_UNSUPPORTED; 211 } 212 213 Mutex::Autolock autoLock(mLock); 214 215 mTextOutOfBandVector.add(source); 216 if (mState == UNINITIALIZED) { 217 mState = STOPPED; 218 } 219 return OK; 220} 221 222} // namespace android 223