TimedTextDriver.cpp revision 25736fd247ba757feefe15d3071f7e747c64fea4
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/mediaplayer.h> 24#include <media/MediaPlayerInterface.h> 25#include <media/stagefright/DataSource.h> 26#include <media/stagefright/FileSource.h> 27#include <media/stagefright/MediaDefs.h> 28#include <media/stagefright/MediaErrors.h> 29#include <media/stagefright/MediaSource.h> 30#include <media/stagefright/MetaData.h> 31#include <media/stagefright/Utils.h> 32#include <media/stagefright/foundation/ADebug.h> 33#include <media/stagefright/foundation/ALooper.h> 34#include <media/stagefright/timedtext/TimedTextDriver.h> 35 36#include "TextDescriptions.h" 37#include "TimedTextPlayer.h" 38#include "TimedTextSource.h" 39 40namespace android { 41 42TimedTextDriver::TimedTextDriver( 43 const wp<MediaPlayerBase> &listener) 44 : mLooper(new ALooper), 45 mListener(listener), 46 mState(UNINITIALIZED) { 47 mLooper->setName("TimedTextDriver"); 48 mLooper->start(); 49 mPlayer = new TimedTextPlayer(listener); 50 mLooper->registerHandler(mPlayer); 51} 52 53TimedTextDriver::~TimedTextDriver() { 54 mTextSourceVector.clear(); 55 mLooper->stop(); 56} 57 58status_t TimedTextDriver::selectTrack_l(int32_t index) { 59 if (index >= (int)(mTextSourceVector.size())) { 60 return BAD_VALUE; 61 } 62 63 sp<TimedTextSource> source; 64 source = mTextSourceVector.itemAt(index); 65 mPlayer->setDataSource(source); 66 if (mState == UNINITIALIZED) { 67 mState = PAUSED; 68 } 69 mCurrentTrackIndex = index; 70 return OK; 71} 72 73status_t TimedTextDriver::start() { 74 Mutex::Autolock autoLock(mLock); 75 switch (mState) { 76 case UNINITIALIZED: 77 return INVALID_OPERATION; 78 case PLAYING: 79 return OK; 80 case PAUSED: 81 mPlayer->start(); 82 break; 83 default: 84 TRESPASS(); 85 } 86 mState = PLAYING; 87 return OK; 88} 89 90// TODO: Test if pause() works properly. 91// Scenario 1: start - pause - resume 92// Scenario 2: start - seek 93// Scenario 3: start - pause - seek - resume 94status_t TimedTextDriver::pause() { 95 Mutex::Autolock autoLock(mLock); 96 switch (mState) { 97 case UNINITIALIZED: 98 return INVALID_OPERATION; 99 case PLAYING: 100 mPlayer->pause(); 101 break; 102 case PAUSED: 103 return OK; 104 default: 105 TRESPASS(); 106 } 107 mState = PAUSED; 108 return OK; 109} 110 111status_t TimedTextDriver::selectTrack(int32_t index) { 112 status_t ret = OK; 113 Mutex::Autolock autoLock(mLock); 114 switch (mState) { 115 case UNINITIALIZED: 116 case PAUSED: 117 ret = selectTrack_l(index); 118 break; 119 case PLAYING: 120 mPlayer->pause(); 121 ret = selectTrack_l(index); 122 if (ret != OK) { 123 break; 124 } 125 mPlayer->start(); 126 break; 127 defaut: 128 TRESPASS(); 129 } 130 return ret; 131} 132 133status_t TimedTextDriver::unselectTrack(int32_t index) { 134 if (mCurrentTrackIndex != index) { 135 return INVALID_OPERATION; 136 } 137 status_t err = pause(); 138 if (err != OK) { 139 return err; 140 } 141 Mutex::Autolock autoLock(mLock); 142 mState = UNINITIALIZED; 143 return OK; 144} 145 146status_t TimedTextDriver::seekToAsync(int64_t timeUs) { 147 mPlayer->seekToAsync(timeUs); 148 return OK; 149} 150 151status_t TimedTextDriver::addInBandTextSource( 152 const sp<MediaSource>& mediaSource) { 153 sp<TimedTextSource> source = 154 TimedTextSource::CreateTimedTextSource(mediaSource); 155 if (source == NULL) { 156 return ERROR_UNSUPPORTED; 157 } 158 Mutex::Autolock autoLock(mLock); 159 mTextSourceVector.add(source); 160 return OK; 161} 162 163status_t TimedTextDriver::addOutOfBandTextSource( 164 const char *uri, const char *mimeType) { 165 // To support local subtitle file only for now 166 if (strncasecmp("file://", uri, 7)) { 167 ALOGE("uri('%s') is not a file", uri); 168 return ERROR_UNSUPPORTED; 169 } 170 171 sp<DataSource> dataSource = 172 DataSource::CreateFromURI(uri); 173 return createOutOfBandTextSource(mimeType, dataSource); 174} 175 176status_t TimedTextDriver::addOutOfBandTextSource( 177 int fd, off64_t offset, off64_t length, const char *mimeType) { 178 179 if (fd < 0) { 180 ALOGE("Invalid file descriptor: %d", fd); 181 return ERROR_UNSUPPORTED; 182 } 183 184 sp<DataSource> dataSource = new FileSource(dup(fd), offset, length); 185 return createOutOfBandTextSource(mimeType, dataSource); 186} 187 188status_t TimedTextDriver::createOutOfBandTextSource( 189 const char *mimeType, const sp<DataSource>& dataSource) { 190 191 if (dataSource == NULL) { 192 return ERROR_UNSUPPORTED; 193 } 194 195 sp<TimedTextSource> source; 196 if (strcasecmp(mimeType, MEDIA_MIMETYPE_TEXT_SUBRIP) == 0) { 197 source = TimedTextSource::CreateTimedTextSource( 198 dataSource, TimedTextSource::OUT_OF_BAND_FILE_SRT); 199 } 200 201 if (source == NULL) { 202 return ERROR_UNSUPPORTED; 203 } 204 205 Mutex::Autolock autoLock(mLock); 206 mTextSourceVector.add(source); 207 return OK; 208} 209 210void TimedTextDriver::getTrackInfo(Parcel *parcel) { 211 Mutex::Autolock autoLock(mLock); 212 Vector<sp<TimedTextSource> >::const_iterator iter; 213 parcel->writeInt32(mTextSourceVector.size()); 214 for (iter = mTextSourceVector.begin(); 215 iter != mTextSourceVector.end(); ++iter) { 216 sp<MetaData> meta = (*iter)->getFormat(); 217 218 // There are two fields. 219 parcel->writeInt32(2); 220 221 // track type. 222 parcel->writeInt32(MEDIA_TRACK_TYPE_TIMEDTEXT); 223 224 const char *lang = "und"; 225 if (meta != NULL) { 226 meta->findCString(kKeyMediaLanguage, &lang); 227 } 228 parcel->writeString16(String16(lang)); 229 } 230} 231 232} // namespace android 233