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