summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorGloria Wang <gwang@google.com>2011-05-11 11:24:09 -0700
committerGloria Wang <gwang@google.com>2011-05-25 17:53:29 -0700
commit965d08ba16ee82bc85f69546360c18e7da907406 (patch)
treef581723790736b2ded3529c33d16a7b39701fbbe /media
parent162f7d15ac5c8c23d1c3de171239f3a4e6e06b2a (diff)
downloadframeworks_av-965d08ba16ee82bc85f69546360c18e7da907406.zip
frameworks_av-965d08ba16ee82bc85f69546360c18e7da907406.tar.gz
frameworks_av-965d08ba16ee82bc85f69546360c18e7da907406.tar.bz2
For out of band timed text support (timed text in a separate file).
Change-Id: I9e024a63eb9bf6f839deee3c7766a66e63126c96
Diffstat (limited to 'media')
-rw-r--r--media/libstagefright/Android.mk2
-rw-r--r--media/libstagefright/AwesomePlayer.cpp26
-rw-r--r--media/libstagefright/MPEG4Extractor.cpp2
-rw-r--r--media/libstagefright/include/AwesomePlayer.h1
-rw-r--r--media/libstagefright/timedtext/Android.mk16
-rw-r--r--media/libstagefright/timedtext/TimedTextParser.cpp257
-rw-r--r--media/libstagefright/timedtext/TimedTextParser.h75
-rw-r--r--media/libstagefright/timedtext/TimedTextPlayer.cpp (renamed from media/libstagefright/TimedTextPlayer.cpp)165
-rw-r--r--media/libstagefright/timedtext/TimedTextPlayer.h (renamed from media/libstagefright/include/TimedTextPlayer.h)23
9 files changed, 526 insertions, 41 deletions
diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk
index f731dfb..8c4b274 100644
--- a/media/libstagefright/Android.mk
+++ b/media/libstagefright/Android.mk
@@ -50,7 +50,6 @@ LOCAL_SRC_FILES:= \
ThrottledSource.cpp \
TimeSource.cpp \
TimedEventQueue.cpp \
- TimedTextPlayer.cpp \
Utils.cpp \
VBRISeeker.cpp \
WAVExtractor.cpp \
@@ -89,6 +88,7 @@ LOCAL_STATIC_LIBRARIES := \
libstagefright_avcenc \
libstagefright_m4vh263enc \
libstagefright_matroska \
+ libstagefright_timedtext \
libvpx \
libstagefright_mpeg2ts \
libstagefright_httplive \
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index fb7a871..a4bba4b 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -29,9 +29,10 @@
#include "include/NuCachedSource2.h"
#include "include/ThrottledSource.h"
#include "include/MPEG2TSExtractor.h"
-#include "include/TimedTextPlayer.h"
#include "include/WVMExtractor.h"
+#include "timedtext/TimedTextPlayer.h"
+
#include <binder/IPCThreadState.h>
#include <binder/IServiceManager.h>
#include <media/IMediaPlayerService.h>
@@ -1277,6 +1278,7 @@ void AwesomePlayer::setAudioSource(sp<MediaSource> source) {
}
void AwesomePlayer::addTextSource(sp<MediaSource> source) {
+ Mutex::Autolock autoLock(mTimedTextLock);
CHECK(source != NULL);
if (mTextPlayer == NULL) {
@@ -2061,10 +2063,26 @@ void AwesomePlayer::postAudioSeekComplete_l() {
}
status_t AwesomePlayer::setParameter(int key, const Parcel &request) {
- if (key == KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX) {
- return setTimedTextTrackIndex(request.readInt32());
+ switch (key) {
+ case KEY_PARAMETER_TIMED_TEXT_TRACK_INDEX:
+ {
+ Mutex::Autolock autoLock(mTimedTextLock);
+ return setTimedTextTrackIndex(request.readInt32());
+ }
+ case KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE:
+ {
+ Mutex::Autolock autoLock(mTimedTextLock);
+ if (mTextPlayer == NULL) {
+ mTextPlayer = new TimedTextPlayer(this, mListener, &mQueue);
+ }
+
+ return mTextPlayer->setParameter(key, request);
+ }
+ default:
+ {
+ return ERROR_UNSUPPORTED;
+ }
}
- return ERROR_UNSUPPORTED;
}
status_t AwesomePlayer::getParameter(int key, Parcel *reply) {
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 6692809..98ac044 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -20,7 +20,7 @@
#include "include/MPEG4Extractor.h"
#include "include/SampleTable.h"
#include "include/ESDS.h"
-#include "include/TimedTextPlayer.h"
+#include "timedtext/TimedTextPlayer.h"
#include <arpa/inet.h>
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 3c9a121..a9e8e95 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -231,6 +231,7 @@ private:
int64_t mLastVideoTimeUs;
TimedTextPlayer *mTextPlayer;
+ mutable Mutex mTimedTextLock;
sp<WVMExtractor> mWVMExtractor;
diff --git a/media/libstagefright/timedtext/Android.mk b/media/libstagefright/timedtext/Android.mk
new file mode 100644
index 0000000..9a6062c
--- /dev/null
+++ b/media/libstagefright/timedtext/Android.mk
@@ -0,0 +1,16 @@
+LOCAL_PATH:= $(call my-dir)
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES:= \
+ TimedTextParser.cpp \
+ TimedTextPlayer.cpp
+
+LOCAL_CFLAGS += -Wno-multichar
+LOCAL_C_INCLUDES:= \
+ $(JNI_H_INCLUDE) \
+ $(TOP)/frameworks/base/media/libstagefright \
+ $(TOP)/frameworks/base/include/media/stagefright/openmax
+
+LOCAL_MODULE:= libstagefright_timedtext
+
+include $(BUILD_STATIC_LIBRARY)
diff --git a/media/libstagefright/timedtext/TimedTextParser.cpp b/media/libstagefright/timedtext/TimedTextParser.cpp
new file mode 100644
index 0000000..0bada16
--- /dev/null
+++ b/media/libstagefright/timedtext/TimedTextParser.cpp
@@ -0,0 +1,257 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "TimedTextParser.h"
+#include <media/stagefright/DataSource.h>
+
+namespace android {
+
+TimedTextParser::TimedTextParser()
+ : mDataSource(NULL),
+ mOffset(0),
+ mIndex(0) {
+}
+
+TimedTextParser::~TimedTextParser() {
+ reset();
+}
+
+status_t TimedTextParser::init(
+ const sp<DataSource> &dataSource, FileType fileType) {
+ mDataSource = dataSource;
+ mFileType = fileType;
+
+ status_t err;
+ if ((err = scanFile()) != OK) {
+ reset();
+ return err;
+ }
+
+ return OK;
+}
+
+void TimedTextParser::reset() {
+ mDataSource.clear();
+ mTextVector.clear();
+ mOffset = 0;
+ mIndex = 0;
+}
+
+// scan the text file to get start/stop time and the
+// offset of each piece of text content
+status_t TimedTextParser::scanFile() {
+ if (mFileType != OUT_OF_BAND_FILE_SRT) {
+ return ERROR_UNSUPPORTED;
+ }
+
+ off64_t offset = 0;
+ int64_t startTimeUs;
+ bool endOfFile = false;
+
+ while (!endOfFile) {
+ TextInfo info;
+ status_t err = getNextInSrtFileFormat(&offset, &startTimeUs, &info);
+
+ if (err != OK) {
+ if (err == ERROR_END_OF_STREAM) {
+ endOfFile = true;
+ } else {
+ return err;
+ }
+ } else {
+ mTextVector.add(startTimeUs, info);
+ }
+ }
+
+ if (mTextVector.isEmpty()) {
+ return ERROR_MALFORMED;
+ }
+ return OK;
+}
+
+// read one line started from *offset and store it into data.
+status_t TimedTextParser::readNextLine(off64_t *offset, AString *data) {
+ char character;
+
+ data->clear();
+
+ while (true) {
+ ssize_t err;
+ if ((err = mDataSource->readAt(*offset, &character, 1)) < 1) {
+ if (err == 0) {
+ return ERROR_END_OF_STREAM;
+ }
+ return ERROR_IO;
+ }
+
+ (*offset) ++;
+
+ // a line could end with CR, LF or CR + LF
+ if (character == 10) {
+ break;
+ } else if (character == 13) {
+ if ((err = mDataSource->readAt(*offset, &character, 1)) < 1) {
+ if (err == 0) { // end of the stream
+ return OK;
+ }
+ return ERROR_IO;
+ }
+
+ (*offset) ++;
+
+ if (character != 10) {
+ (*offset) --;
+ }
+ break;
+ }
+
+ data->append(character);
+ }
+
+ return OK;
+}
+
+/* SRT format:
+ * Subtitle number
+ * Start time --> End time
+ * Text of subtitle (one or more lines)
+ * Blank line
+ *
+ * .srt file example:
+ * 1
+ * 00:00:20,000 --> 00:00:24,400
+ * Altocumulus clouds occur between six thousand
+ *
+ * 2
+ * 00:00:24,600 --> 00:00:27,800
+ * and twenty thousand feet above ground level.
+ */
+status_t TimedTextParser::getNextInSrtFileFormat(
+ off64_t *offset, int64_t *startTimeUs, TextInfo *info) {
+ AString data;
+ status_t err;
+ if ((err = readNextLine(offset, &data)) != OK) {
+ return err;
+ }
+
+ // to skip the first line
+ if ((err = readNextLine(offset, &data)) != OK) {
+ return err;
+ }
+
+ int hour1, hour2, min1, min2, sec1, sec2, msec1, msec2;
+ // the start time format is: hours:minutes:seconds,milliseconds
+ // 00:00:24,600 --> 00:00:27,800
+ if (sscanf(data.c_str(), "%02d:%02d:%02d,%03d --> %02d:%02d:%02d,%03d",
+ &hour1, &min1, &sec1, &msec1, &hour2, &min2, &sec2, &msec2) != 8) {
+ return ERROR_MALFORMED;
+ }
+
+ *startTimeUs = ((hour1 * 3600 + min1 * 60 + sec1) * 1000 + msec1) * 1000ll;
+ info->endTimeUs = ((hour2 * 3600 + min2 * 60 + sec2) * 1000 + msec2) * 1000ll;
+ if (info->endTimeUs <= *startTimeUs) {
+ return ERROR_MALFORMED;
+ }
+
+ info->offset = *offset;
+
+ bool needMoreData = true;
+ while (needMoreData) {
+ if ((err = readNextLine(offset, &data)) != OK) {
+ if (err == ERROR_END_OF_STREAM) {
+ needMoreData = false;
+ } else {
+ return err;
+ }
+ }
+
+ if (needMoreData) {
+ data.trim();
+ if (data.empty()) {
+ // it's an empty line used to separate two subtitles
+ needMoreData = false;
+ }
+ }
+ }
+
+ info->textLen = *offset - info->offset;
+
+ return OK;
+}
+
+status_t TimedTextParser::getText(
+ AString *text, int64_t *startTimeUs, int64_t *endTimeUs,
+ const MediaSource::ReadOptions *options) {
+ Mutex::Autolock autoLock(mLock);
+
+ text->clear();
+
+ int64_t seekTimeUs;
+ MediaSource::ReadOptions::SeekMode mode;
+ if (options && options->getSeekTo(&seekTimeUs, &mode)) {
+ int64_t lastEndTimeUs = mTextVector.valueAt(mTextVector.size() - 1).endTimeUs;
+ int64_t firstStartTimeUs = mTextVector.keyAt(0);
+
+ if (seekTimeUs < 0 || seekTimeUs > lastEndTimeUs) {
+ return ERROR_OUT_OF_RANGE;
+ } else if (seekTimeUs < firstStartTimeUs) {
+ mIndex = 0;
+ } else {
+ // binary search
+ ssize_t low = 0;
+ ssize_t high = mTextVector.size() - 1;
+ ssize_t mid = 0;
+ int64_t currTimeUs;
+
+ while (low <= high) {
+ mid = low + (high - low)/2;
+ currTimeUs = mTextVector.keyAt(mid);
+ const int diff = currTimeUs - seekTimeUs;
+
+ if (diff == 0) {
+ break;
+ } else if (diff < 0) {
+ low = mid + 1;
+ } else {
+ if ((high == mid + 1)
+ && (seekTimeUs < mTextVector.keyAt(high))) {
+ break;
+ }
+ high = mid - 1;
+ }
+ }
+
+ mIndex = mid;
+ }
+ }
+
+ TextInfo info = mTextVector.valueAt(mIndex);
+ *startTimeUs = mTextVector.keyAt(mIndex);
+ *endTimeUs = info.endTimeUs;
+ mIndex ++;
+
+ char *str = new char[info.textLen];
+ if (mDataSource->readAt(info.offset, str, info.textLen) < info.textLen) {
+ delete[] str;
+ return ERROR_IO;
+ }
+
+ text->append(str, info.textLen);
+ delete[] str;
+ return OK;
+}
+
+} // namespace android
diff --git a/media/libstagefright/timedtext/TimedTextParser.h b/media/libstagefright/timedtext/TimedTextParser.h
new file mode 100644
index 0000000..44774c2
--- /dev/null
+++ b/media/libstagefright/timedtext/TimedTextParser.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef TIMED_TEXT_PARSER_H_
+
+#define TIMED_TEXT_PARSER_H_
+
+#include <media/MediaPlayerInterface.h>
+#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AString.h>
+#include <media/stagefright/MediaSource.h>
+
+namespace android {
+
+class DataSource;
+
+class TimedTextParser : public RefBase {
+public:
+ TimedTextParser();
+ virtual ~TimedTextParser();
+
+ enum FileType {
+ OUT_OF_BAND_FILE_SRT = 1,
+ };
+
+ status_t getText(AString *text, int64_t *startTimeUs, int64_t *endTimeUs,
+ const MediaSource::ReadOptions *options = NULL);
+ status_t init(const sp<DataSource> &dataSource, FileType fileType);
+ void reset();
+
+private:
+ Mutex mLock;
+
+ sp<DataSource> mDataSource;
+ off64_t mOffset;
+
+ struct TextInfo {
+ int64_t endTimeUs;
+ // the offset of the text in the original file
+ off64_t offset;
+ int textLen;
+ };
+
+ int mIndex;
+ FileType mFileType;
+
+ // the key indicated the start time of the text
+ KeyedVector<int64_t, TextInfo> mTextVector;
+
+ status_t getNextInSrtFileFormat(
+ off64_t *offset, int64_t *startTimeUs, TextInfo *info);
+ status_t readNextLine(off64_t *offset, AString *data);
+
+ status_t scanFile();
+
+ DISALLOW_EVIL_CONSTRUCTORS(TimedTextParser);
+};
+
+} // namespace android
+
+#endif // TIMED_TEXT_PARSER_H_
+
diff --git a/media/libstagefright/TimedTextPlayer.cpp b/media/libstagefright/timedtext/TimedTextPlayer.cpp
index 1ac22cb..50bb16d 100644
--- a/media/libstagefright/TimedTextPlayer.cpp
+++ b/media/libstagefright/timedtext/TimedTextPlayer.cpp
@@ -25,9 +25,11 @@
#include <media/stagefright/MediaSource.h>
#include <media/stagefright/MetaData.h>
#include <media/stagefright/MediaBuffer.h>
+#include <media/stagefright/FileSource.h>
#include <media/stagefright/Utils.h>
#include "include/AwesomePlayer.h"
-#include "include/TimedTextPlayer.h"
+#include "TimedTextPlayer.h"
+#include "TimedTextParser.h"
namespace android {
@@ -59,13 +61,16 @@ TimedTextPlayer::TimedTextPlayer(
const wp<MediaPlayerBase> &listener,
TimedEventQueue *queue)
: mSource(NULL),
+ mOutOfBandSource(NULL),
mSeekTimeUs(0),
mStarted(false),
mTextEventPending(false),
mQueue(queue),
mListener(listener),
mObserver(observer),
- mTextBuffer(NULL) {
+ mTextBuffer(NULL),
+ mTextParser(NULL),
+ mTextType(kNoText) {
mTextEvent = new TimedTextEvent(this, &TimedTextPlayer::onTextEvent);
}
@@ -75,22 +80,43 @@ TimedTextPlayer::~TimedTextPlayer() {
}
mTextTrackVector.clear();
+ mTextOutOfBandVector.clear();
}
status_t TimedTextPlayer::start(uint8_t index) {
CHECK(!mStarted);
- if (index >= mTextTrackVector.size()) {
- LOGE("Incorrect text track index");
+ if (index >=
+ mTextTrackVector.size() + mTextOutOfBandVector.size()) {
+ LOGE("Incorrect text track index: %d", index);
return BAD_VALUE;
}
- mSource = mTextTrackVector.itemAt(index);
+ if (index < mTextTrackVector.size()) { // start an in-band text
+ mSource = mTextTrackVector.itemAt(index);
- status_t err = mSource->start();
+ status_t err = mSource->start();
- if (err != OK) {
- return err;
+ if (err != OK) {
+ return err;
+ }
+ mTextType = kInBandText;
+ } else { // start an out-of-band text
+ OutOfBandText text =
+ mTextOutOfBandVector.itemAt(index - mTextTrackVector.size());
+
+ mOutOfBandSource = text.source;
+ TimedTextParser::FileType fileType = text.type;
+
+ if (mTextParser == NULL) {
+ mTextParser = new TimedTextParser();
+ }
+
+ status_t err;
+ if ((err = mTextParser->init(mOutOfBandSource, fileType)) != OK) {
+ return err;
+ }
+ mTextType = kOutOfBandText;
}
int64_t positionUs;
@@ -127,15 +153,26 @@ void TimedTextPlayer::reset() {
mSeeking = false;
mStarted = false;
- if (mTextBuffer != NULL) {
- mTextBuffer->release();
- mTextBuffer = NULL;
- }
+ if (mTextType == kInBandText) {
+ if (mTextBuffer != NULL) {
+ mTextBuffer->release();
+ mTextBuffer = NULL;
+ }
- if (mSource != NULL) {
- mSource->stop();
- mSource.clear();
- mSource = NULL;
+ if (mSource != NULL) {
+ mSource->stop();
+ mSource.clear();
+ mSource = NULL;
+ }
+ } else {
+ if (mTextParser != NULL) {
+ mTextParser.clear();
+ mTextParser = NULL;
+ }
+ if (mOutOfBandSource != NULL) {
+ mOutOfBandSource.clear();
+ mOutOfBandSource = NULL;
+ }
}
}
@@ -145,11 +182,14 @@ status_t TimedTextPlayer::seekTo(int64_t time_us) {
mSeeking = true;
mSeekTimeUs = time_us;
+ postTextEvent();
+
return OK;
}
status_t TimedTextPlayer::setTimedTextTrackIndex(int32_t index) {
- if (index >= (int)(mTextTrackVector.size())) {
+ if (index >=
+ (int)(mTextTrackVector.size() + mTextOutOfBandVector.size())) {
return BAD_VALUE;
}
@@ -177,34 +217,54 @@ void TimedTextPlayer::onTextEvent() {
MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC);
mSeeking = false;
- if (mTextBuffer != NULL) {
- mTextBuffer->release();
- mTextBuffer = NULL;
+ if (mTextType == kInBandText) {
+ if (mTextBuffer != NULL) {
+ mTextBuffer->release();
+ mTextBuffer = NULL;
+ }
+ } else {
+ mText.clear();
}
notifyListener(MEDIA_TIMED_TEXT); //empty text to clear the screen
}
- if (mTextBuffer != NULL) {
- uint8_t *tmp = (uint8_t *)(mTextBuffer->data());
- size_t len = (*tmp) << 8 | (*(tmp + 1));
+ int64_t positionUs, timeUs;
+ mObserver->getPosition(&positionUs);
- notifyListener(MEDIA_TIMED_TEXT,
- tmp + 2,
- len);
+ if (mTextType == kInBandText) {
+ if (mTextBuffer != NULL) {
+ uint8_t *tmp = (uint8_t *)(mTextBuffer->data());
+ size_t len = (*tmp) << 8 | (*(tmp + 1));
- mTextBuffer->release();
- mTextBuffer = NULL;
+ notifyListener(MEDIA_TIMED_TEXT,
+ tmp + 2,
+ len);
- }
+ mTextBuffer->release();
+ mTextBuffer = NULL;
- if (mSource->read(&mTextBuffer, &options) != OK) {
- return;
- }
+ }
- int64_t positionUs, timeUs;
- mObserver->getPosition(&positionUs);
- mTextBuffer->meta_data()->findInt64(kKeyTime, &timeUs);
+ if (mSource->read(&mTextBuffer, &options) != OK) {
+ return;
+ }
+
+ mTextBuffer->meta_data()->findInt64(kKeyTime, &timeUs);
+ } else {
+ if (mText.size() > 0) {
+ notifyListener(MEDIA_TIMED_TEXT,
+ mText.c_str(),
+ mText.size());
+ mText.clear();
+ }
+
+ int64_t endTimeUs;
+ if (mTextParser->getText(
+ &mText, &timeUs, &endTimeUs, &options) != OK) {
+ return;
+ }
+ }
//send the text now
if (timeUs <= positionUs + 100000ll) {
@@ -229,9 +289,44 @@ void TimedTextPlayer::cancelTextEvent() {
}
void TimedTextPlayer::addTextSource(sp<MediaSource> source) {
+ Mutex::Autolock autoLock(mLock);
mTextTrackVector.add(source);
}
+status_t TimedTextPlayer::setParameter(int key, const Parcel &request) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (key == KEY_PARAMETER_TIMED_TEXT_ADD_OUT_OF_BAND_SOURCE) {
+ String8 uri = request.readString8();
+ KeyedVector<String8, String8> headers;
+
+ // To support local subtitle file only for now
+ if (strncasecmp("file://", uri.string(), 7)) {
+ return INVALID_OPERATION;
+ }
+ sp<DataSource> dataSource =
+ DataSource::CreateFromURI(uri, &headers);
+ status_t err = dataSource->initCheck();
+
+ if (err != OK) {
+ return err;
+ }
+
+ OutOfBandText text;
+ text.source = dataSource;
+ if (uri.getPathExtension() == String8(".srt")) {
+ text.type = TimedTextParser::OUT_OF_BAND_FILE_SRT;
+ } else {
+ return ERROR_UNSUPPORTED;
+ }
+
+ mTextOutOfBandVector.add(text);
+
+ return OK;
+ }
+ return INVALID_OPERATION;
+}
+
void TimedTextPlayer::notifyListener(
int msg, const void *data, size_t size) {
if (mListener != NULL) {
diff --git a/media/libstagefright/include/TimedTextPlayer.h b/media/libstagefright/timedtext/TimedTextPlayer.h
index ac41b4f..590760b 100644
--- a/media/libstagefright/include/TimedTextPlayer.h
+++ b/media/libstagefright/timedtext/TimedTextPlayer.h
@@ -20,8 +20,10 @@
#include <media/MediaPlayerInterface.h>
#include <media/stagefright/foundation/ABase.h>
+#include <media/stagefright/foundation/AString.h>
#include "include/TimedEventQueue.h"
+#include "TimedTextParser.h"
namespace android {
@@ -50,11 +52,19 @@ public:
void addTextSource(sp<MediaSource> source);
status_t setTimedTextTrackIndex(int32_t index);
+ status_t setParameter(int key, const Parcel &request);
private:
+ enum TextType {
+ kNoText = 0,
+ kInBandText = 1,
+ kOutOfBandText = 2,
+ };
+
Mutex mLock;
sp<MediaSource> mSource;
+ sp<DataSource> mOutOfBandSource;
bool mSeeking;
int64_t mSeekTimeUs;
@@ -72,8 +82,21 @@ private:
MediaBuffer *mTextBuffer;
Parcel mData;
+ // for in-band timed text
Vector<sp<MediaSource> > mTextTrackVector;
+ // for out-of-band timed text
+ struct OutOfBandText {
+ TimedTextParser::FileType type;
+ sp<DataSource> source;
+ };
+ Vector<OutOfBandText > mTextOutOfBandVector;
+
+ sp<TimedTextParser> mTextParser;
+ AString mText;
+
+ TextType mTextType;
+
void reset();
void onTextEvent();