diff options
author | Robert Shih <robertshih@google.com> | 2014-07-23 15:53:14 -0700 |
---|---|---|
committer | Robert Shih <robertshih@google.com> | 2014-07-25 18:09:14 -0700 |
commit | eb1735e343a93830df259ae8882160bb0d79dcb5 (patch) | |
tree | 5c2c154082effb530ecd7bfbd1c5a61986b6182a /media/libmediaplayerservice/nuplayer | |
parent | ec3c71ed320e5e2252a84aa8b35ac4b9a6f92712 (diff) | |
download | frameworks_av-eb1735e343a93830df259ae8882160bb0d79dcb5.zip frameworks_av-eb1735e343a93830df259ae8882160bb0d79dcb5.tar.gz frameworks_av-eb1735e343a93830df259ae8882160bb0d79dcb5.tar.bz2 |
GenericSource: timed text support
Bug: 16385674
Change-Id: I954cc463b55af4b93c6a6e714115db4fda729dc8
Diffstat (limited to 'media/libmediaplayerservice/nuplayer')
-rw-r--r-- | media/libmediaplayerservice/nuplayer/GenericSource.cpp | 255 | ||||
-rw-r--r-- | media/libmediaplayerservice/nuplayer/GenericSource.h | 13 |
2 files changed, 195 insertions, 73 deletions
diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp index 63a907c..4c6a59c 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp +++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp @@ -42,6 +42,7 @@ NuPlayer::GenericSource::GenericSource( uid_t uid) : Source(notify), mFetchSubtitleDataGeneration(0), + mFetchTimedTextDataGeneration(0), mDurationUs(0ll), mAudioIsVorbis(false), mIsWidevine(isWidevine), @@ -61,6 +62,7 @@ NuPlayer::GenericSource::GenericSource( int fd, int64_t offset, int64_t length) : Source(notify), mFetchSubtitleDataGeneration(0), + mFetchTimedTextDataGeneration(0), mDurationUs(0ll), mAudioIsVorbis(false) { DataSource::RegisterDefaultSniffers(); @@ -204,66 +206,29 @@ void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) { switch (msg->what()) { case kWhatFetchSubtitleData: { - int32_t generation; - CHECK(msg->findInt32("generation", &generation)); - if (generation != mFetchSubtitleDataGeneration) { - // stale - break; - } - - int32_t avail; - if (mSubtitleTrack.mPackets->hasBufferAvailable(&avail)) { - break; - } - - int64_t timeUs; - CHECK(msg->findInt64("timeUs", &timeUs)); - - int64_t subTimeUs; - readBuffer(MEDIA_TRACK_TYPE_SUBTITLE, timeUs, &subTimeUs); - - const int64_t oneSecUs = 1000000ll; - const int64_t delayUs = subTimeUs - timeUs - oneSecUs; - sp<AMessage> msg2 = new AMessage(kWhatSendSubtitleData, id()); - msg2->setInt32("generation", generation); - msg2->post(delayUs < 0 ? 0 : delayUs); - ALOGV("kWhatFetchSubtitleData generation %d, delayUs %lld", - mFetchSubtitleDataGeneration, delayUs); + fetchTextData(kWhatSendSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE, + mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg); + break; + } + case kWhatFetchTimedTextData: + { + fetchTextData(kWhatSendTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT, + mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg); break; } case kWhatSendSubtitleData: { - int32_t generation; - CHECK(msg->findInt32("generation", &generation)); - if (generation != mFetchSubtitleDataGeneration) { - // stale - break; - } - - int64_t subTimeUs; - if (mSubtitleTrack.mPackets->nextBufferTime(&subTimeUs) != OK) { - break; - } - - int64_t nextSubTimeUs; - readBuffer(MEDIA_TRACK_TYPE_SUBTITLE, -1, &nextSubTimeUs); - - sp<ABuffer> buffer; - status_t dequeueStatus = mSubtitleTrack.mPackets->dequeueAccessUnit(&buffer); - if (dequeueStatus != OK) { - ALOGE("kWhatSendSubtitleData dequeueAccessUnit: %d", dequeueStatus); - } else { - sp<AMessage> notify = dupNotify(); - notify->setInt32("what", kWhatSubtitleData); - notify->setBuffer("buffer", buffer); - notify->post(); - - const int64_t delayUs = nextSubTimeUs - subTimeUs; - msg->post(delayUs < 0 ? 0 : delayUs); - } + sendTextData(kWhatSubtitleData, MEDIA_TRACK_TYPE_SUBTITLE, + mFetchSubtitleDataGeneration, mSubtitleTrack.mPackets, msg); + break; + } + case kWhatSendTimedTextData: + { + sendTextData(kWhatTimedTextData, MEDIA_TRACK_TYPE_TIMEDTEXT, + mFetchTimedTextDataGeneration, mTimedTextTrack.mPackets, msg); break; } @@ -317,6 +282,74 @@ void NuPlayer::GenericSource::onMessageReceived(const sp<AMessage> &msg) { } } +void NuPlayer::GenericSource::fetchTextData( + uint32_t sendWhat, + media_track_type type, + int32_t curGen, + sp<AnotherPacketSource> packets, + sp<AMessage> msg) { + int32_t msgGeneration; + CHECK(msg->findInt32("generation", &msgGeneration)); + if (msgGeneration != curGen) { + // stale + return; + } + + int32_t avail; + if (packets->hasBufferAvailable(&avail)) { + return; + } + + int64_t timeUs; + CHECK(msg->findInt64("timeUs", &timeUs)); + + int64_t subTimeUs; + readBuffer(type, timeUs, &subTimeUs); + + int64_t delayUs = subTimeUs - timeUs; + if (msg->what() == kWhatFetchSubtitleData) { + const int64_t oneSecUs = 1000000ll; + delayUs -= oneSecUs; + } + sp<AMessage> msg2 = new AMessage(sendWhat, id()); + msg2->setInt32("generation", msgGeneration); + msg2->post(delayUs < 0 ? 0 : delayUs); +} + +void NuPlayer::GenericSource::sendTextData( + uint32_t what, + media_track_type type, + int32_t curGen, + sp<AnotherPacketSource> packets, + sp<AMessage> msg) { + int32_t msgGeneration; + CHECK(msg->findInt32("generation", &msgGeneration)); + if (msgGeneration != curGen) { + // stale + return; + } + + int64_t subTimeUs; + if (packets->nextBufferTime(&subTimeUs) != OK) { + return; + } + + int64_t nextSubTimeUs; + readBuffer(type, -1, &nextSubTimeUs); + + sp<ABuffer> buffer; + status_t dequeueStatus = packets->dequeueAccessUnit(&buffer); + if (dequeueStatus == OK) { + sp<AMessage> notify = dupNotify(); + notify->setInt32("what", what); + notify->setBuffer("buffer", buffer); + notify->post(); + + const int64_t delayUs = nextSubTimeUs - subTimeUs; + msg->post(delayUs < 0 ? 0 : delayUs); + } +} + sp<MetaData> NuPlayer::GenericSource::getFormatMeta(bool audio) { sp<MediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource; @@ -351,27 +384,49 @@ status_t NuPlayer::GenericSource::dequeueAccessUnit( readBuffer(audio? MEDIA_TRACK_TYPE_AUDIO : MEDIA_TRACK_TYPE_VIDEO, -1ll); } - if (mSubtitleTrack.mSource == NULL) { + if (mSubtitleTrack.mSource == NULL && mTimedTextTrack.mSource == NULL) { return result; } - CHECK(mSubtitleTrack.mPackets != NULL); + if (mSubtitleTrack.mSource != NULL) { + CHECK(mSubtitleTrack.mPackets != NULL); + } + if (mTimedTextTrack.mSource != NULL) { + CHECK(mTimedTextTrack.mPackets != NULL); + } + if (result != OK) { - mSubtitleTrack.mPackets->clear(); - mFetchSubtitleDataGeneration++; + if (mSubtitleTrack.mSource != NULL) { + mSubtitleTrack.mPackets->clear(); + mFetchSubtitleDataGeneration++; + } + if (mTimedTextTrack.mSource != NULL) { + mTimedTextTrack.mPackets->clear(); + mFetchTimedTextDataGeneration++; + } return result; } int64_t timeUs; status_t eosResult; // ignored CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs)); - if (!mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) { + + if (mSubtitleTrack.mSource != NULL + && !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) { sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, id()); msg->setInt64("timeUs", timeUs); msg->setInt32("generation", mFetchSubtitleDataGeneration); msg->post(); } + if (mTimedTextTrack.mSource != NULL + && !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) { + sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, id()); + msg->setInt64("timeUs", timeUs); + msg->setInt32("generation", mFetchTimedTextDataGeneration); + msg->post(); + } + return result; } @@ -430,19 +485,52 @@ sp<AMessage> NuPlayer::GenericSource::getTrackInfo(size_t trackIndex) const { return format; } +ssize_t NuPlayer::GenericSource::getSelectedTrack(media_track_type type) const { + const Track *track = NULL; + switch (type) { + case MEDIA_TRACK_TYPE_VIDEO: + track = &mVideoTrack; + break; + case MEDIA_TRACK_TYPE_AUDIO: + track = &mAudioTrack; + break; + case MEDIA_TRACK_TYPE_TIMEDTEXT: + track = &mTimedTextTrack; + break; + case MEDIA_TRACK_TYPE_SUBTITLE: + track = &mSubtitleTrack; + break; + default: + break; + } + + if (track != NULL && track->mSource != NULL) { + return track->mIndex; + } + + return -1; +} + status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select) { - ALOGV("selectTrack: %zu", trackIndex); + ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex); if (trackIndex >= mSources.size()) { return BAD_INDEX; } if (!select) { - if (mSubtitleTrack.mSource == NULL || trackIndex != mSubtitleTrack.mIndex) { + Track* track = NULL; + if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) { + track = &mSubtitleTrack; + mFetchSubtitleDataGeneration++; + } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) { + track = &mTimedTextTrack; + mFetchTimedTextDataGeneration++; + } + if (track == NULL) { return INVALID_OPERATION; } - mSubtitleTrack.mSource = NULL; - mSubtitleTrack.mPackets->clear(); - mFetchSubtitleDataGeneration++; + track->mSource = NULL; + track->mPackets->clear(); return OK; } @@ -451,18 +539,27 @@ status_t NuPlayer::GenericSource::selectTrack(size_t trackIndex, bool select) { const char *mime; CHECK(meta->findCString(kKeyMIMEType, &mime)); if (!strncasecmp(mime, "text/", 5)) { - if (mSubtitleTrack.mSource != NULL && mSubtitleTrack.mIndex == trackIndex) { + bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP); + Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack; + if (track->mSource != NULL && track->mIndex == trackIndex) { return OK; } - mSubtitleTrack.mIndex = trackIndex; - mSubtitleTrack.mSource = mSources.itemAt(trackIndex); - if (mSubtitleTrack.mPackets == NULL) { - mSubtitleTrack.mPackets = new AnotherPacketSource(mSubtitleTrack.mSource->getFormat()); + track->mIndex = trackIndex; + track->mSource = mSources.itemAt(trackIndex); + if (track->mPackets == NULL) { + track->mPackets = new AnotherPacketSource(track->mSource->getFormat()); } else { - mSubtitleTrack.mPackets->clear(); + track->mPackets->clear(); + track->mPackets->setFormat(track->mSource->getFormat()); } - mFetchSubtitleDataGeneration++; + + if (isSubtitle) { + mFetchSubtitleDataGeneration++; + } else { + mFetchTimedTextDataGeneration++; + } + return OK; } else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) { bool audio = !strncasecmp(mime, "audio/", 6); @@ -529,12 +626,19 @@ sp<ABuffer> NuPlayer::GenericSource::mediaBufferToABuffer( memcpy(abEnd, &numPageSamples, sizeof(numPageSamples)); } + sp<AMessage> meta = ab->meta(); + int64_t timeUs; CHECK(mb->meta_data()->findInt64(kKeyTime, &timeUs)); - - sp<AMessage> meta = ab->meta(); meta->setInt64("timeUs", timeUs); + if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) { + const char *mime; + CHECK(mTimedTextTrack.mSource != NULL + && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime)); + meta->setString("mime", mime); + } + int64_t durationUs; if (mb->meta_data()->findInt64(kKeyDuration, &durationUs)) { meta->setInt64("durationUs", durationUs); @@ -567,6 +671,9 @@ void NuPlayer::GenericSource::readBuffer( case MEDIA_TRACK_TYPE_SUBTITLE: track = &mSubtitleTrack; break; + case MEDIA_TRACK_TYPE_TIMEDTEXT: + track = &mTimedTextTrack; + break; default: TRESPASS(); } @@ -602,7 +709,9 @@ void NuPlayer::GenericSource::readBuffer( // formatChange && seeking: track whose source is changed during selection // formatChange && !seeking: track whose source is not changed during selection // !formatChange: normal seek - if ((seeking || formatChange) && trackType != MEDIA_TRACK_TYPE_SUBTITLE) { + if ((seeking || formatChange) + && (trackType == MEDIA_TRACK_TYPE_AUDIO + || trackType == MEDIA_TRACK_TYPE_VIDEO)) { ATSParser::DiscontinuityType type = formatChange ? (seeking ? ATSParser::DISCONTINUITY_FORMATCHANGE diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h index 4e25d55..3c5f55c 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.h +++ b/media/libmediaplayerservice/nuplayer/GenericSource.h @@ -58,6 +58,7 @@ struct NuPlayer::GenericSource : public NuPlayer::Source { virtual status_t getDuration(int64_t *durationUs); virtual size_t getTrackCount() const; virtual sp<AMessage> getTrackInfo(size_t trackIndex) const; + virtual ssize_t getSelectedTrack(media_track_type type) const; virtual status_t selectTrack(size_t trackIndex, bool select); virtual status_t seekTo(int64_t seekTimeUs); @@ -73,7 +74,9 @@ protected: private: enum { kWhatFetchSubtitleData, + kWhatFetchTimedTextData, kWhatSendSubtitleData, + kWhatSendTimedTextData, kWhatChangeAVSource, }; @@ -88,8 +91,10 @@ private: Track mAudioTrack; Track mVideoTrack; Track mSubtitleTrack; + Track mTimedTextTrack; int32_t mFetchSubtitleDataGeneration; + int32_t mFetchTimedTextDataGeneration; int64_t mDurationUs; bool mAudioIsVorbis; bool mIsWidevine; @@ -98,6 +103,14 @@ private: void initFromDataSource(const sp<DataSource> &dataSource); + void fetchTextData( + uint32_t what, media_track_type type, + int32_t curGen, sp<AnotherPacketSource> packets, sp<AMessage> msg); + + void sendTextData( + uint32_t what, media_track_type type, + int32_t curGen, sp<AnotherPacketSource> packets, sp<AMessage> msg); + sp<ABuffer> mediaBufferToABuffer( MediaBuffer *mbuf, media_track_type trackType, |