diff options
author | Gloria Wang <gwang@google.com> | 2011-05-31 16:08:47 -0700 |
---|---|---|
committer | Gloria Wang <gwang@google.com> | 2011-06-22 11:32:19 -0700 |
commit | 3b573f7bf1c5736d500e39013b8d32478a1429e6 (patch) | |
tree | 620cf88dc1ca7ffaca6c66819278d669a2e977bd /media/libstagefright/timedtext | |
parent | 6ef9a104959c1d15232fe3a319e4a270eed3ddb5 (diff) | |
download | frameworks_av-3b573f7bf1c5736d500e39013b8d32478a1429e6.zip frameworks_av-3b573f7bf1c5736d500e39013b8d32478a1429e6.tar.gz frameworks_av-3b573f7bf1c5736d500e39013b8d32478a1429e6.tar.bz2 |
Timed text display format support:
1. Extract 3GPP global format descriptions
2. Extract 3GPP local format descriptions
3. Define data structure (TimedText) for applications to
retrieve the format metadata
Change-Id: I6eac2a78df29ee15beee456656331fdd83b24e8e
Diffstat (limited to 'media/libstagefright/timedtext')
-rw-r--r-- | media/libstagefright/timedtext/Android.mk | 1 | ||||
-rw-r--r-- | media/libstagefright/timedtext/TextDescriptions.cpp | 385 | ||||
-rw-r--r-- | media/libstagefright/timedtext/TextDescriptions.h | 84 | ||||
-rw-r--r-- | media/libstagefright/timedtext/TimedTextPlayer.cpp | 147 | ||||
-rw-r--r-- | media/libstagefright/timedtext/TimedTextPlayer.h | 6 |
5 files changed, 582 insertions, 41 deletions
diff --git a/media/libstagefright/timedtext/Android.mk b/media/libstagefright/timedtext/Android.mk index 9a6062c..59d0e15 100644 --- a/media/libstagefright/timedtext/Android.mk +++ b/media/libstagefright/timedtext/Android.mk @@ -2,6 +2,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_SRC_FILES:= \ + TextDescriptions.cpp \ TimedTextParser.cpp \ TimedTextPlayer.cpp diff --git a/media/libstagefright/timedtext/TextDescriptions.cpp b/media/libstagefright/timedtext/TextDescriptions.cpp new file mode 100644 index 0000000..f9c1fe0 --- /dev/null +++ b/media/libstagefright/timedtext/TextDescriptions.cpp @@ -0,0 +1,385 @@ +/* + * 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 "TextDescriptions.h" +#include <media/stagefright/Utils.h> +#include <media/stagefright/MediaErrors.h> + +namespace android { + +TextDescriptions::TextDescriptions() { +} + +status_t TextDescriptions::getParcelOfDescriptions( + const uint8_t *data, ssize_t size, + uint32_t flags, int timeMs, Parcel *parcel) { + parcel->freeData(); + + if (flags & IN_BAND_TEXT_3GPP) { + if (flags & GLOBAL_DESCRIPTIONS) { + return extract3GPPGlobalDescriptions(data, size, parcel, 0); + } else if (flags & LOCAL_DESCRIPTIONS) { + return extract3GPPLocalDescriptions(data, size, timeMs, parcel, 0); + } + } else if (flags & OUT_OF_BAND_TEXT_SRT) { + if (flags & LOCAL_DESCRIPTIONS) { + return extractSRTLocalDescriptions(data, size, timeMs, parcel); + } + } + + return ERROR_UNSUPPORTED; +} + +// Parse the SRT text sample, and store the timing and text sample in a Parcel. +// The Parcel will be sent to MediaPlayer.java through event, and will be +// parsed in TimedText.java. +status_t TextDescriptions::extractSRTLocalDescriptions( + const uint8_t *data, ssize_t size, int timeMs, Parcel *parcel) { + parcel->writeInt32(KEY_LOCAL_SETTING); + parcel->writeInt32(KEY_START_TIME); + parcel->writeInt32(timeMs); + + parcel->writeInt32(KEY_STRUCT_TEXT); + // write the size of the text sample + parcel->writeInt32(size); + // write the text sample as a byte array + parcel->writeInt32(size); + parcel->write(data, size); + + return OK; +} + +// Extract the local 3GPP display descriptions. 3GPP local descriptions +// are appended to the text sample if any. The descriptions could include +// information such as text styles, highlights, karaoke and so on. They +// are contained in different boxes, such as 'styl' box contains text +// styles, and 'krok' box contains karaoke timing and positions. +status_t TextDescriptions::extract3GPPLocalDescriptions( + const uint8_t *data, ssize_t size, + int timeMs, Parcel *parcel, int depth) { + if (depth == 0) { + parcel->writeInt32(KEY_LOCAL_SETTING); + + // write start time to display this text sample + parcel->writeInt32(KEY_START_TIME); + parcel->writeInt32(timeMs); + + ssize_t textLen = (*data) << 8 | (*(data + 1)); + + // write text sample length and text sample itself + parcel->writeInt32(KEY_STRUCT_TEXT); + parcel->writeInt32(textLen); + parcel->writeInt32(textLen); + parcel->write(data + 2, textLen); + + if (size > textLen) { + data += (textLen + 2); + size -= (textLen + 2); + } else { + return OK; + } + } + + const uint8_t *tmpData = data; + ssize_t chunkSize = U32_AT(tmpData); + uint32_t chunkType = U32_AT(tmpData + 4); + + if (chunkSize <= 0) { + return OK; + } + + tmpData += 8; + + switch(chunkType) { + // 'styl' box specifies the style of the text. + case FOURCC('s', 't', 'y', 'l'): + { + uint16_t count = U16_AT(tmpData); + + tmpData += 2; + + for (int i = 0; i < count; i++) { + parcel->writeInt32(KEY_STRUCT_STYLE_LIST); + parcel->writeInt32(KEY_START_CHAR); + parcel->writeInt32(U16_AT(tmpData)); + + parcel->writeInt32(KEY_END_CHAR); + parcel->writeInt32(U16_AT(tmpData + 2)); + + parcel->writeInt32(KEY_FONT_ID); + parcel->writeInt32(U16_AT(tmpData + 4)); + + parcel->writeInt32(KEY_STYLE_FLAGS); + parcel->writeInt32(*(tmpData + 6)); + + parcel->writeInt32(KEY_FONT_SIZE); + parcel->writeInt32(*(tmpData + 7)); + + parcel->writeInt32(KEY_TEXT_COLOR_RGBA); + uint32_t rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16 + | *(tmpData + 10) << 8 | *(tmpData + 11); + parcel->writeInt32(rgba); + + tmpData += 12; + } + + break; + } + // 'krok' box. The number of highlight events is specified, and each + // event is specified by a starting and ending char offset and an end + // time for the event. + case FOURCC('k', 'r', 'o', 'k'): + { + + parcel->writeInt32(KEY_STRUCT_KARAOKE_LIST); + + int startTime = U32_AT(tmpData); + uint16_t count = U16_AT(tmpData + 4); + parcel->writeInt32(count); + + tmpData += 6; + int lastEndTime = 0; + + for (int i = 0; i < count; i++) { + parcel->writeInt32(startTime + lastEndTime); + + lastEndTime = U32_AT(tmpData); + parcel->writeInt32(lastEndTime); + + parcel->writeInt32(U16_AT(tmpData + 4)); + parcel->writeInt32(U16_AT(tmpData + 6)); + + tmpData += 8; + } + + break; + } + // 'hlit' box specifies highlighted text + case FOURCC('h', 'l', 'i', 't'): + { + parcel->writeInt32(KEY_STRUCT_HIGHLIGHT_LIST); + + // the start char offset to highlight + parcel->writeInt32(U16_AT(tmpData)); + // the last char offset to highlight + parcel->writeInt32(U16_AT(tmpData + 2)); + + break; + } + // 'hclr' box specifies the RGBA color: 8 bits each of + // red, green, blue, and an alpha(transparency) value + case FOURCC('h', 'c', 'l', 'r'): + { + parcel->writeInt32(KEY_HIGHLIGHT_COLOR_RGBA); + + uint32_t rgba = *(tmpData) << 24 | *(tmpData + 1) << 16 + | *(tmpData + 2) << 8 | *(tmpData + 3); + parcel->writeInt32(rgba); + + break; + } + // 'dlay' box specifies a delay after a scroll in and/or + // before scroll out. + case FOURCC('d', 'l', 'a', 'y'): + { + parcel->writeInt32(KEY_SCROLL_DELAY); + + uint32_t delay = *(tmpData) << 24 | *(tmpData + 1) << 16 + | *(tmpData + 2) << 8 | *(tmpData + 3); + parcel->writeInt32(delay); + + break; + } + // 'href' box for hyper text link + case FOURCC('h', 'r', 'e', 'f'): + { + parcel->writeInt32(KEY_STRUCT_HYPER_TEXT_LIST); + + // the start offset of the text to be linked + parcel->writeInt32(U16_AT(tmpData)); + // the end offset of the text + parcel->writeInt32(U16_AT(tmpData + 2)); + + // the number of bytes in the following URL + int len = *(tmpData + 4); + parcel->writeInt32(len); + + // the linked-to URL + parcel->writeInt32(len); + parcel->write(tmpData + 5, len); + + tmpData += (5 + len); + + // the number of bytes in the following "alt" string + len = *tmpData; + parcel->writeInt32(len); + + // an "alt" string for user display + parcel->writeInt32(len); + parcel->write(tmpData + 1, len); + + break; + } + // 'tbox' box to indicate the position of the text with values + // of top, left, bottom and right + case FOURCC('t', 'b', 'o', 'x'): + { + parcel->writeInt32(KEY_STRUCT_TEXT_POS); + parcel->writeInt32(U16_AT(tmpData)); + parcel->writeInt32(U16_AT(tmpData + 2)); + parcel->writeInt32(U16_AT(tmpData + 4)); + parcel->writeInt32(U16_AT(tmpData + 6)); + + break; + } + // 'blnk' to specify the char range to be blinked + case FOURCC('b', 'l', 'n', 'k'): + { + parcel->writeInt32(KEY_STRUCT_BLINKING_TEXT_LIST); + + // start char offset + parcel->writeInt32(U16_AT(tmpData)); + // end char offset + parcel->writeInt32(U16_AT(tmpData + 2)); + + break; + } + // 'twrp' box specifies text wrap behavior. If the value if 0x00, + // then no wrap. If it's 0x01, then automatic 'soft' wrap is enabled. + // 0x02-0xff are reserved. + case FOURCC('t', 'w', 'r', 'p'): + { + parcel->writeInt32(KEY_WRAP_TEXT); + parcel->writeInt32(*tmpData); + + break; + } + default: + { + break; + } + } + + if (size > chunkSize) { + data += chunkSize; + size -= chunkSize; + // continue to parse next box + return extract3GPPLocalDescriptions(data, size, 0, parcel, 1); + } + + return OK; +} + +// To extract box 'tx3g' defined in 3GPP TS 26.245, and store it in a Parcel +status_t TextDescriptions::extract3GPPGlobalDescriptions( + const uint8_t *data, ssize_t size, Parcel *parcel, int depth) { + + ssize_t chunkSize = U32_AT(data); + uint32_t chunkType = U32_AT(data + 4); + const uint8_t *tmpData = data; + tmpData += 8; + + if (size < chunkSize) { + return OK; + } + + if (depth == 0) { + parcel->writeInt32(KEY_GLOBAL_SETTING); + } + switch(chunkType) { + case FOURCC('t', 'x', '3', 'g'): + { + tmpData += 8; // skip the first 8 bytes + parcel->writeInt32(KEY_DISPLAY_FLAGS); + parcel->writeInt32(U32_AT(tmpData)); + + parcel->writeInt32(KEY_STRUCT_JUSTIFICATION); + parcel->writeInt32(tmpData[4]); + parcel->writeInt32(tmpData[5]); + + parcel->writeInt32(KEY_BACKGROUND_COLOR_RGBA); + uint32_t rgba = *(tmpData + 6) << 24 | *(tmpData + 7) << 16 + | *(tmpData + 8) << 8 | *(tmpData + 9); + parcel->writeInt32(rgba); + + tmpData += 10; + parcel->writeInt32(KEY_STRUCT_TEXT_POS); + parcel->writeInt32(U16_AT(tmpData)); + parcel->writeInt32(U16_AT(tmpData + 2)); + parcel->writeInt32(U16_AT(tmpData + 4)); + parcel->writeInt32(U16_AT(tmpData + 6)); + + tmpData += 8; + parcel->writeInt32(KEY_STRUCT_STYLE_LIST); + parcel->writeInt32(KEY_START_CHAR); + parcel->writeInt32(U16_AT(tmpData)); + + parcel->writeInt32(KEY_END_CHAR); + parcel->writeInt32(U16_AT(tmpData + 2)); + + parcel->writeInt32(KEY_FONT_ID); + parcel->writeInt32(U16_AT(tmpData + 4)); + + parcel->writeInt32(KEY_STYLE_FLAGS); + parcel->writeInt32(*(tmpData + 6)); + + parcel->writeInt32(KEY_FONT_SIZE); + parcel->writeInt32(*(tmpData + 7)); + + parcel->writeInt32(KEY_TEXT_COLOR_RGBA); + rgba = *(tmpData + 8) << 24 | *(tmpData + 9) << 16 + | *(tmpData + 10) << 8 | *(tmpData + 11); + parcel->writeInt32(rgba); + + tmpData += 12; + parcel->writeInt32(KEY_STRUCT_FONT_LIST); + uint16_t count = U16_AT(tmpData); + parcel->writeInt32(count); + + tmpData += 2; + for (int i = 0; i < count; i++) { + // font ID + parcel->writeInt32(U16_AT(tmpData)); + + // font name length + parcel->writeInt32(*(tmpData + 2)); + + int len = *(tmpData + 2); + + parcel->write(tmpData + 3, len); + tmpData += 3 + len; + } + + break; + } + default: + { + break; + } + } + + data += chunkSize; + size -= chunkSize; + + if (size > 0) { + // continue to extract next 'tx3g' + return extract3GPPGlobalDescriptions(data, size, parcel, 1); + } + + return OK; +} + +} // namespace android diff --git a/media/libstagefright/timedtext/TextDescriptions.h b/media/libstagefright/timedtext/TextDescriptions.h new file mode 100644 index 0000000..0144917 --- /dev/null +++ b/media/libstagefright/timedtext/TextDescriptions.h @@ -0,0 +1,84 @@ + /* + * 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 TEXT_DESCRIPTIONS_H_ + +#define TEXT_DESCRIPTIONS_H_ + +#include <binder/Parcel.h> +#include <media/stagefright/foundation/ABase.h> + +namespace android { + +class TextDescriptions { +public: + enum { + IN_BAND_TEXT_3GPP = 0x01, + OUT_OF_BAND_TEXT_SRT = 0x02, + + GLOBAL_DESCRIPTIONS = 0x100, + LOCAL_DESCRIPTIONS = 0x200, + }; + + static status_t getParcelOfDescriptions( + const uint8_t *data, ssize_t size, + uint32_t flags, int timeMs, Parcel *parcel); +private: + TextDescriptions(); + + enum { + // These keys must be in sync with the keys in TimedText.java + KEY_DISPLAY_FLAGS = 1, // int + KEY_STYLE_FLAGS = 2, // int + KEY_BACKGROUND_COLOR_RGBA = 3, // int + KEY_HIGHLIGHT_COLOR_RGBA = 4, // int + KEY_SCROLL_DELAY = 5, // int + KEY_WRAP_TEXT = 6, // int + KEY_START_TIME = 7, // int + KEY_STRUCT_BLINKING_TEXT_LIST = 8, // List<CharPos> + KEY_STRUCT_FONT_LIST = 9, // List<Font> + KEY_STRUCT_HIGHLIGHT_LIST = 10, // List<CharPos> + KEY_STRUCT_HYPER_TEXT_LIST = 11, // List<HyperText> + KEY_STRUCT_KARAOKE_LIST = 12, // List<Karaoke> + KEY_STRUCT_STYLE_LIST = 13, // List<Style> + KEY_STRUCT_TEXT_POS = 14, // TextPos + KEY_STRUCT_JUSTIFICATION = 15, // Justification + KEY_STRUCT_TEXT = 16, // Text + + KEY_GLOBAL_SETTING = 101, + KEY_LOCAL_SETTING = 102, + KEY_START_CHAR = 103, + KEY_END_CHAR = 104, + KEY_FONT_ID = 105, + KEY_FONT_SIZE = 106, + KEY_TEXT_COLOR_RGBA = 107, + }; + + static status_t extractSRTLocalDescriptions( + const uint8_t *data, ssize_t size, + int timeMs, Parcel *parcel); + static status_t extract3GPPGlobalDescriptions( + const uint8_t *data, ssize_t size, + Parcel *parcel, int depth); + static status_t extract3GPPLocalDescriptions( + const uint8_t *data, ssize_t size, + int timeMs, Parcel *parcel, int depth); + + DISALLOW_EVIL_CONSTRUCTORS(TextDescriptions); +}; + +} // namespace android +#endif // TEXT_DESCRIPTIONS_H_ diff --git a/media/libstagefright/timedtext/TimedTextPlayer.cpp b/media/libstagefright/timedtext/TimedTextPlayer.cpp index 50bb16d..7c8a747 100644 --- a/media/libstagefright/timedtext/TimedTextPlayer.cpp +++ b/media/libstagefright/timedtext/TimedTextPlayer.cpp @@ -19,6 +19,7 @@ #include <utils/Log.h> #include <binder/IPCThreadState.h> + #include <media/stagefright/MediaDebug.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MediaErrors.h> @@ -27,9 +28,11 @@ #include <media/stagefright/MediaBuffer.h> #include <media/stagefright/FileSource.h> #include <media/stagefright/Utils.h> + #include "include/AwesomePlayer.h" #include "TimedTextPlayer.h" #include "TimedTextParser.h" +#include "TextDescriptions.h" namespace android { @@ -92,10 +95,11 @@ status_t TimedTextPlayer::start(uint8_t index) { return BAD_VALUE; } + status_t err; if (index < mTextTrackVector.size()) { // start an in-band text mSource = mTextTrackVector.itemAt(index); - status_t err = mSource->start(); + err = mSource->start(); if (err != OK) { return err; @@ -112,13 +116,17 @@ status_t TimedTextPlayer::start(uint8_t index) { mTextParser = new TimedTextParser(); } - status_t err; if ((err = mTextParser->init(mOutOfBandSource, fileType)) != OK) { return err; } mTextType = kOutOfBandText; } + // send sample description format + if ((err = extractAndSendGlobalDescriptions()) != OK) { + return err; + } + int64_t positionUs; mObserver->getPosition(&positionUs); seekTo(positionUs); @@ -211,21 +219,17 @@ void TimedTextPlayer::onTextEvent() { } mTextEventPending = false; + if (mData.dataSize() > 0) { + notifyListener(MEDIA_TIMED_TEXT, &mData); + mData.freeData(); + } + MediaSource::ReadOptions options; if (mSeeking) { options.setSeekTo(mSeekTimeUs, MediaSource::ReadOptions::SEEK_PREVIOUS_SYNC); mSeeking = false; - if (mTextType == kInBandText) { - if (mTextBuffer != NULL) { - mTextBuffer->release(); - mTextBuffer = NULL; - } - } else { - mText.clear(); - } - notifyListener(MEDIA_TIMED_TEXT); //empty text to clear the screen } @@ -233,32 +237,12 @@ void TimedTextPlayer::onTextEvent() { mObserver->getPosition(&positionUs); if (mTextType == kInBandText) { - if (mTextBuffer != NULL) { - uint8_t *tmp = (uint8_t *)(mTextBuffer->data()); - size_t len = (*tmp) << 8 | (*(tmp + 1)); - - notifyListener(MEDIA_TIMED_TEXT, - tmp + 2, - len); - - mTextBuffer->release(); - mTextBuffer = NULL; - - } - 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) { @@ -266,6 +250,19 @@ void TimedTextPlayer::onTextEvent() { } } + if (timeUs > 0) { + extractAndAppendLocalDescriptions(timeUs); + } + + if (mTextType == kInBandText) { + if (mTextBuffer != NULL) { + mTextBuffer->release(); + mTextBuffer = NULL; + } + } else { + mText.clear(); + } + //send the text now if (timeUs <= positionUs + 100000ll) { postTextEvent(); @@ -297,7 +294,8 @@ 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(); + const String16 uri16 = request.readString16(); + String8 uri = String8(uri16); KeyedVector<String8, String8> headers; // To support local subtitle file only for now @@ -327,21 +325,92 @@ status_t TimedTextPlayer::setParameter(int key, const Parcel &request) { return INVALID_OPERATION; } -void TimedTextPlayer::notifyListener( - int msg, const void *data, size_t size) { +void TimedTextPlayer::notifyListener(int msg, const Parcel *parcel) { if (mListener != NULL) { sp<MediaPlayerBase> listener = mListener.promote(); if (listener != NULL) { - if (size > 0) { - mData.freeData(); - mData.write(data, size); - - listener->sendEvent(msg, 0, 0, &mData); + if (parcel && (parcel->dataSize() > 0)) { + listener->sendEvent(msg, 0, 0, parcel); } else { // send an empty timed text to clear the screen listener->sendEvent(msg); } } } } + +// Each text sample consists of a string of text, optionally with sample +// modifier description. The modifier description could specify a new +// text style for the string of text. These descriptions are present only +// if they are needed. This method is used to extract the modifier +// description and append it at the end of the text. +status_t TimedTextPlayer::extractAndAppendLocalDescriptions(int64_t timeUs) { + const void *data; + size_t size = 0; + int32_t flag = TextDescriptions::LOCAL_DESCRIPTIONS; + + if (mTextType == kInBandText) { + const char *mime; + CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime)); + + if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) { + flag |= TextDescriptions::IN_BAND_TEXT_3GPP; + data = mTextBuffer->data(); + size = mTextBuffer->size(); + } else { + // support 3GPP only for now + return ERROR_UNSUPPORTED; + } + } else { + data = mText.c_str(); + size = mText.size(); + flag |= TextDescriptions::OUT_OF_BAND_TEXT_SRT; + } + + if ((size > 0) && (flag != TextDescriptions::LOCAL_DESCRIPTIONS)) { + mData.freeData(); + return TextDescriptions::getParcelOfDescriptions( + (const uint8_t *)data, size, flag, timeUs / 1000, &mData); + } + + return OK; +} + +// To extract and send the global text descriptions for all the text samples +// in the text track or text file. +status_t TimedTextPlayer::extractAndSendGlobalDescriptions() { + const void *data; + size_t size = 0; + int32_t flag = TextDescriptions::GLOBAL_DESCRIPTIONS; + + if (mTextType == kInBandText) { + const char *mime; + CHECK(mSource->getFormat()->findCString(kKeyMIMEType, &mime)); + + // support 3GPP only for now + if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) { + uint32_t type; + // get the 'tx3g' box content. This box contains the text descriptions + // used to render the text track + if (!mSource->getFormat()->findData( + kKeyTextFormatData, &type, &data, &size)) { + return ERROR_MALFORMED; + } + + flag |= TextDescriptions::IN_BAND_TEXT_3GPP; + } + } + + if ((size > 0) && (flag != TextDescriptions::GLOBAL_DESCRIPTIONS)) { + Parcel parcel; + if (TextDescriptions::getParcelOfDescriptions( + (const uint8_t *)data, size, flag, 0, &parcel) == OK) { + if (parcel.dataSize() > 0) { + notifyListener(MEDIA_TIMED_TEXT, &parcel); + } + } + } + + return OK; +} } diff --git a/media/libstagefright/timedtext/TimedTextPlayer.h b/media/libstagefright/timedtext/TimedTextPlayer.h index 590760b..a744db5 100644 --- a/media/libstagefright/timedtext/TimedTextPlayer.h +++ b/media/libstagefright/timedtext/TimedTextPlayer.h @@ -103,8 +103,10 @@ private: void postTextEvent(int64_t delayUs = -1); void cancelTextEvent(); - void notifyListener( - int msg, const void *data = NULL, size_t size = 0); + void notifyListener(int msg, const Parcel *parcel = NULL); + + status_t extractAndAppendLocalDescriptions(int64_t timeUs); + status_t extractAndSendGlobalDescriptions(); DISALLOW_EVIL_CONSTRUCTORS(TimedTextPlayer); }; |