TimedTextDriver.cpp revision 6655174826330afe66ef766258181ae8c11f3f6c
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 31#include "TimedTextDriver.h" 32 33#include "TextDescriptions.h" 34#include "TimedTextPlayer.h" 35#include "TimedTextSource.h" 36 37namespace android { 38 39TimedTextDriver::TimedTextDriver( 40 const wp<MediaPlayerBase> &listener) 41 : mLooper(new ALooper), 42 mListener(listener), 43 mState(UNINITIALIZED) { 44 mLooper->setName("TimedTextDriver"); 45 mLooper->start(); 46 mPlayer = new TimedTextPlayer(listener); 47 mLooper->registerHandler(mPlayer); 48} 49 50TimedTextDriver::~TimedTextDriver() { 51 mTextInBandVector.clear(); 52 mTextOutOfBandVector.clear(); 53 mLooper->stop(); 54} 55 56status_t TimedTextDriver::setTimedTextTrackIndex_l(int32_t index) { 57 if (index >= 58 (int)(mTextInBandVector.size() + mTextOutOfBandVector.size())) { 59 return BAD_VALUE; 60 } 61 62 sp<TimedTextSource> source; 63 if (index < mTextInBandVector.size()) { 64 source = mTextInBandVector.itemAt(index); 65 } else { 66 source = mTextOutOfBandVector.itemAt(index - mTextInBandVector.size()); 67 } 68 mPlayer->setDataSource(source); 69 return OK; 70} 71 72status_t TimedTextDriver::start() { 73 Mutex::Autolock autoLock(mLock); 74 switch (mState) { 75 case UNINITIALIZED: 76 return INVALID_OPERATION; 77 case STOPPED: 78 mPlayer->start(); 79 break; 80 case PLAYING: 81 return OK; 82 case PAUSED: 83 mPlayer->resume(); 84 break; 85 default: 86 TRESPASS(); 87 } 88 mState = PLAYING; 89 return OK; 90} 91 92status_t TimedTextDriver::stop() { 93 return pause(); 94} 95 96// TODO: Test if pause() works properly. 97// Scenario 1: start - pause - resume 98// Scenario 2: start - seek 99// Scenario 3: start - pause - seek - resume 100status_t TimedTextDriver::pause() { 101 Mutex::Autolock autoLock(mLock); 102 switch (mState) { 103 case UNINITIALIZED: 104 return INVALID_OPERATION; 105 case STOPPED: 106 return OK; 107 case PLAYING: 108 mPlayer->pause(); 109 break; 110 case PAUSED: 111 return OK; 112 default: 113 TRESPASS(); 114 } 115 mState = PAUSED; 116 return OK; 117} 118 119status_t TimedTextDriver::resume() { 120 return start(); 121} 122 123status_t TimedTextDriver::seekToAsync(int64_t timeUs) { 124 mPlayer->seekToAsync(timeUs); 125 return OK; 126} 127 128status_t TimedTextDriver::setTimedTextTrackIndex(int32_t index) { 129 // TODO: This is current implementation for MediaPlayer::disableTimedText(). 130 // Find better way for readability. 131 if (index < 0) { 132 mPlayer->pause(); 133 return OK; 134 } 135 136 status_t ret = OK; 137 Mutex::Autolock autoLock(mLock); 138 switch (mState) { 139 case UNINITIALIZED: 140 ret = INVALID_OPERATION; 141 break; 142 case PAUSED: 143 ret = setTimedTextTrackIndex_l(index); 144 break; 145 case PLAYING: 146 mPlayer->pause(); 147 ret = setTimedTextTrackIndex_l(index); 148 if (ret != OK) { 149 break; 150 } 151 mPlayer->start(); 152 break; 153 case STOPPED: 154 // TODO: The only difference between STOPPED and PAUSED is this 155 // part. Revise the flow from "MediaPlayer::enableTimedText()" and 156 // remove one of the status, PAUSED and STOPPED, if possible. 157 ret = setTimedTextTrackIndex_l(index); 158 if (ret != OK) { 159 break; 160 } 161 mPlayer->start(); 162 break; 163 defaut: 164 TRESPASS(); 165 } 166 return ret; 167} 168 169status_t TimedTextDriver::addInBandTextSource( 170 const sp<MediaSource>& mediaSource) { 171 sp<TimedTextSource> source = 172 TimedTextSource::CreateTimedTextSource(mediaSource); 173 if (source == NULL) { 174 return ERROR_UNSUPPORTED; 175 } 176 Mutex::Autolock autoLock(mLock); 177 mTextInBandVector.add(source); 178 if (mState == UNINITIALIZED) { 179 mState = STOPPED; 180 } 181 return OK; 182} 183 184status_t TimedTextDriver::addOutOfBandTextSource( 185 const Parcel &request) { 186 // TODO: Define "TimedTextSource::CreateFromURI(uri)" 187 // and move below lines there..? 188 189 // String values written in Parcel are UTF-16 values. 190 const String16 uri16 = request.readString16(); 191 String8 uri = String8(request.readString16()); 192 193 uri.toLower(); 194 // To support local subtitle file only for now 195 if (strncasecmp("file://", uri.string(), 7)) { 196 return ERROR_UNSUPPORTED; 197 } 198 sp<DataSource> dataSource = 199 DataSource::CreateFromURI(uri); 200 if (dataSource == NULL) { 201 return ERROR_UNSUPPORTED; 202 } 203 204 sp<TimedTextSource> source; 205 if (uri.getPathExtension() == String8(".srt")) { 206 source = TimedTextSource::CreateTimedTextSource( 207 dataSource, TimedTextSource::OUT_OF_BAND_FILE_SRT); 208 } 209 210 if (source == NULL) { 211 return ERROR_UNSUPPORTED; 212 } 213 214 Mutex::Autolock autoLock(mLock); 215 216 mTextOutOfBandVector.add(source); 217 if (mState == UNINITIALIZED) { 218 mState = STOPPED; 219 } 220 return OK; 221} 222 223} // namespace android 224