Merge "MediaSession2: Update Builder" into pi-dev
diff --git a/media/libmedia/NdkWrapper.cpp b/media/libmedia/NdkWrapper.cpp
index 3b1b413..5418af9 100644
--- a/media/libmedia/NdkWrapper.cpp
+++ b/media/libmedia/NdkWrapper.cpp
@@ -81,11 +81,16 @@
AMEDIAFORMAT_KEY_STRIDE,
AMEDIAFORMAT_KEY_TRACK_ID,
AMEDIAFORMAT_KEY_WIDTH,
+ AMEDIAFORMAT_KEY_DISPLAY_HEIGHT,
+ AMEDIAFORMAT_KEY_DISPLAY_WIDTH,
+ AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID,
+ AMEDIAFORMAT_KEY_TRACK_INDEX,
};
static const char *AMediaFormatKeyGroupInt64[] = {
AMEDIAFORMAT_KEY_DURATION,
AMEDIAFORMAT_KEY_REPEAT_PREVIOUS_FRAME_AFTER,
+ AMEDIAFORMAT_KEY_TIME_US,
};
static const char *AMediaFormatKeyGroupString[] = {
@@ -96,6 +101,14 @@
static const char *AMediaFormatKeyGroupBuffer[] = {
AMEDIAFORMAT_KEY_HDR_STATIC_INFO,
+ AMEDIAFORMAT_KEY_SEI,
+ AMEDIAFORMAT_KEY_MPEG_USER_DATA,
+};
+
+static const char *AMediaFormatKeyGroupCsd[] = {
+ AMEDIAFORMAT_KEY_CSD_0,
+ AMEDIAFORMAT_KEY_CSD_1,
+ AMEDIAFORMAT_KEY_CSD_2,
};
static const char *AMediaFormatKeyGroupRect[] = {
@@ -307,11 +320,19 @@
}
sp<AMessage> AMediaFormatWrapper::toAMessage() const {
+ sp<AMessage> msg;
+ writeToAMessage(msg);
+ return msg;
+}
+
+void AMediaFormatWrapper::writeToAMessage(sp<AMessage> &msg) const {
if (mAMediaFormat == NULL) {
- return NULL;
+ msg = NULL;
}
- sp<AMessage> msg = new AMessage;
+ if (msg == NULL) {
+ msg = new AMessage;
+ }
for (auto& key : AMediaFormatKeyGroupInt32) {
int32_t val;
if (getInt32(key, &val)) {
@@ -338,6 +359,16 @@
msg->setBuffer(key, buffer);
}
}
+ for (auto& key : AMediaFormatKeyGroupCsd) {
+ void *data;
+ size_t size;
+ if (getBuffer(key, &data, &size)) {
+ sp<ABuffer> buffer = ABuffer::CreateAsCopy(data, size);
+ buffer->meta()->setInt32(AMEDIAFORMAT_KEY_CSD, 1);
+ buffer->meta()->setInt64(AMEDIAFORMAT_KEY_TIME_US, 0);
+ msg->setBuffer(key, buffer);
+ }
+ }
for (auto& key : AMediaFormatKeyGroupRect) {
int32_t left, top, right, bottom;
if (getRect(key, &left, &top, &right, &bottom)) {
@@ -355,7 +386,6 @@
}
}
}
- return msg;
}
const char* AMediaFormatWrapper::toString() const {
diff --git a/media/libmedia/include/media/NdkWrapper.h b/media/libmedia/include/media/NdkWrapper.h
index f17d2cc..191665a 100644
--- a/media/libmedia/include/media/NdkWrapper.h
+++ b/media/libmedia/include/media/NdkWrapper.h
@@ -45,6 +45,7 @@
class MetaData;
struct AMediaFormatWrapper : public RefBase {
+
static sp<AMediaFormatWrapper> Create(const sp<AMessage> &message);
AMediaFormatWrapper();
@@ -54,6 +55,7 @@
AMediaFormat *getAMediaFormat() const;
sp<AMessage> toAMessage() const ;
+ void writeToAMessage(sp<AMessage>&) const ;
const char* toString() const ;
status_t release();
diff --git a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
index 936fb20..196b103 100644
--- a/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
+++ b/media/libmediaplayer2/nuplayer2/GenericSource2.cpp
@@ -35,13 +35,13 @@
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSourceFactory.h>
-#include <media/stagefright/FileSource.h>
#include <media/stagefright/InterfaceUtils.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaClock.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaExtractorFactory.h>
#include <media/stagefright/MetaData.h>
+#include <media/stagefright/NdkUtils.h>
#include <media/stagefright/Utils.h>
#include "../../libstagefright/include/NuCachedSource2.h"
#include "../../libstagefright/include/HTTPBase.h"
@@ -161,29 +161,40 @@
}
status_t NuPlayer2::GenericSource2::initFromDataSource() {
- sp<IMediaExtractor> extractor;
- CHECK(mDataSource != NULL);
+ mExtractor = new AMediaExtractorWrapper(AMediaExtractor_new());
+ CHECK(mDataSource != NULL || mFd != -1);
sp<DataSource> dataSource = mDataSource;
+ const int fd = mFd;
+ const int64_t offset = mOffset;
+ const int64_t length = mLength;
mLock.unlock();
// This might take long time if data source is not reliable.
- extractor = MediaExtractorFactory::Create(dataSource, NULL);
+ status_t err;
+ if (dataSource != nullptr) {
+ mDataSourceWrapper = new AMediaDataSourceWrapper(dataSource);
+ err = mExtractor->setDataSource(mDataSourceWrapper->getAMediaDataSource());
+ } else {
+ err = mExtractor->setDataSource(fd, offset, length);
+ }
- if (extractor == NULL) {
- ALOGE("initFromDataSource, cannot create extractor!");
+ if (err != OK) {
+ ALOGE("initFromDataSource, failed to create data source!");
+ mLock.lock();
return UNKNOWN_ERROR;
}
- sp<MetaData> fileMeta = extractor->getMetaData();
-
- size_t numtracks = extractor->countTracks();
+ size_t numtracks = mExtractor->getTrackCount();
if (numtracks == 0) {
ALOGE("initFromDataSource, source has no track!");
+ mLock.lock();
return UNKNOWN_ERROR;
}
mLock.lock();
- mFileMeta = fileMeta;
+ mFd = -1;
+ mDataSource = dataSource;
+ mFileMeta = convertMediaFormatWrapperToMetaData(mExtractor->getFormat());
if (mFileMeta != NULL) {
int64_t duration;
if (mFileMeta->findInt64(kKeyDuration, &duration)) {
@@ -196,18 +207,22 @@
mMimes.clear();
for (size_t i = 0; i < numtracks; ++i) {
- sp<IMediaSource> track = extractor->getTrack(i);
- if (track == NULL) {
- continue;
- }
- sp<MetaData> meta = extractor->getTrackMetaData(i);
- if (meta == NULL) {
+ sp<AMediaFormatWrapper> trackFormat = mExtractor->getTrackFormat(i);
+ if (trackFormat == NULL) {
ALOGE("no metadata for track %zu", i);
return UNKNOWN_ERROR;
}
+ sp<AMediaExtractorWrapper> trackExtractor = new AMediaExtractorWrapper(AMediaExtractor_new());
+ if (mDataSourceWrapper != nullptr) {
+ err = trackExtractor->setDataSource(mDataSourceWrapper->getAMediaDataSource());
+ } else {
+ err = trackExtractor->setDataSource(fd, offset, length);
+ }
+
const char *mime;
+ sp<MetaData> meta = convertMediaFormatWrapperToMetaData(trackFormat);
CHECK(meta->findCString(kKeyMIMEType, &mime));
ALOGV("initFromDataSource track[%zu]: %s", i, mime);
@@ -217,11 +232,11 @@
// extractor operation, some extractors might modify meta
// during getTrack() and make it invalid.
if (!strncasecmp(mime, "audio/", 6)) {
- if (mAudioTrack.mSource == NULL) {
+ if (mAudioTrack.mExtractor == NULL) {
mAudioTrack.mIndex = i;
- mAudioTrack.mSource = track;
- mAudioTrack.mPackets =
- new AnotherPacketSource(mAudioTrack.mSource->getFormat());
+ mAudioTrack.mExtractor = trackExtractor;
+ mAudioTrack.mExtractor->selectTrack(i);
+ mAudioTrack.mPackets = new AnotherPacketSource(meta);
if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_VORBIS)) {
mAudioIsVorbis = true;
@@ -232,18 +247,18 @@
mMimes.add(String8(mime));
}
} else if (!strncasecmp(mime, "video/", 6)) {
- if (mVideoTrack.mSource == NULL) {
+ if (mVideoTrack.mExtractor == NULL) {
mVideoTrack.mIndex = i;
- mVideoTrack.mSource = track;
- mVideoTrack.mPackets =
- new AnotherPacketSource(mVideoTrack.mSource->getFormat());
+ mVideoTrack.mExtractor = trackExtractor;
+ mVideoTrack.mExtractor->selectTrack(i);
+ mVideoTrack.mPackets = new AnotherPacketSource(meta);
// video always at the beginning
mMimes.insertAt(String8(mime), 0);
}
}
- mSources.push(track);
+ mExtractors.push(trackExtractor);
int64_t durationUs;
if (meta->findInt64(kKeyDuration, &durationUs)) {
if (durationUs > mDurationUs) {
@@ -259,10 +274,10 @@
}
}
- ALOGV("initFromDataSource mSources.size(): %zu mIsSecure: %d mime[0]: %s", mSources.size(),
+ ALOGV("initFromDataSource mExtractors.size(): %zu mIsSecure: %d mime[0]: %s", mExtractors.size(),
mIsSecure, (mMimes.isEmpty() ? "NONE" : mMimes[0].string()));
- if (mSources.size() == 0) {
+ if (mExtractors.size() == 0) {
ALOGE("b/23705695");
return UNKNOWN_ERROR;
}
@@ -294,31 +309,10 @@
return OK;
}
-status_t NuPlayer2::GenericSource2::startSources() {
- // Start the selected A/V tracks now before we start buffering.
- // Widevine sources might re-initialize crypto when starting, if we delay
- // this to start(), all data buffered during prepare would be wasted.
- // (We don't actually start reading until start().)
- //
- // TODO: this logic may no longer be relevant after the removal of widevine
- // support
- if (mAudioTrack.mSource != NULL && mAudioTrack.mSource->start() != OK) {
- ALOGE("failed to start audio track!");
- return UNKNOWN_ERROR;
- }
-
- if (mVideoTrack.mSource != NULL && mVideoTrack.mSource->start() != OK) {
- ALOGE("failed to start video track!");
- return UNKNOWN_ERROR;
- }
-
- return OK;
-}
-
int64_t NuPlayer2::GenericSource2::getLastReadPosition() {
- if (mAudioTrack.mSource != NULL) {
+ if (mAudioTrack.mExtractor != NULL) {
return mAudioTimeUs;
- } else if (mVideoTrack.mSource != NULL) {
+ } else if (mVideoTrack.mExtractor != NULL) {
return mVideoTimeUs;
} else {
return 0;
@@ -391,51 +385,16 @@
if (!mDisconnected) {
mDataSource = dataSource;
}
- } else {
- if (property_get_bool("media.stagefright.extractremote", true) &&
- !FileSource::requiresDrm(mFd, mOffset, mLength, nullptr /* mime */)) {
- sp<IBinder> binder =
- defaultServiceManager()->getService(String16("media.extractor"));
- if (binder != nullptr) {
- ALOGD("FileSource remote");
- sp<IMediaExtractorService> mediaExService(
- interface_cast<IMediaExtractorService>(binder));
- sp<IDataSource> source =
- mediaExService->makeIDataSource(mFd, mOffset, mLength);
- ALOGV("IDataSource(FileSource): %p %d %lld %lld",
- source.get(), mFd, (long long)mOffset, (long long)mLength);
- if (source.get() != nullptr) {
- mDataSource = CreateDataSourceFromIDataSource(source);
- if (mDataSource != nullptr) {
- // Close the local file descriptor as it is not needed anymore.
- close(mFd);
- mFd = -1;
- }
- } else {
- ALOGW("extractor service cannot make data source");
- }
- } else {
- ALOGW("extractor service not running");
- }
- }
- if (mDataSource == nullptr) {
- ALOGD("FileSource local");
- mDataSource = new FileSource(mFd, mOffset, mLength);
- }
- // TODO: close should always be done on mFd, see the lines following
- // CreateDataSourceFromIDataSource above,
- // and the FileSource constructor should dup the mFd argument as needed.
- mFd = -1;
}
- if (mDataSource == NULL) {
+ if (mFd == -1 && mDataSource == NULL) {
ALOGE("Failed to create data source!");
notifyPreparedAndCleanup(UNKNOWN_ERROR);
return;
}
}
- if (mDataSource->flags() & DataSource::kIsCachingDataSource) {
+ if (mDataSource != nullptr && mDataSource->flags() & DataSource::kIsCachingDataSource) {
mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get());
}
@@ -452,7 +411,7 @@
return;
}
- if (mVideoTrack.mSource != NULL) {
+ if (mVideoTrack.mExtractor != NULL) {
sp<MetaData> meta = getFormatMeta_l(false /* audio */);
sp<AMessage> msg = new AMessage;
err = convertMetaDataToMessage(meta, &msg);
@@ -479,13 +438,6 @@
void NuPlayer2::GenericSource2::finishPrepareAsync() {
ALOGV("finishPrepareAsync");
- status_t err = startSources();
- if (err != OK) {
- ALOGE("Failed to init start data source!");
- notifyPreparedAndCleanup(err);
- return;
- }
-
if (mIsStreaming) {
mCachedSource->resumeFetchingIfNecessary();
mPreparing = true;
@@ -494,11 +446,11 @@
notifyPrepared();
}
- if (mAudioTrack.mSource != NULL) {
+ if (mAudioTrack.mExtractor != NULL) {
postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
}
- if (mVideoTrack.mSource != NULL) {
+ if (mVideoTrack.mExtractor != NULL) {
postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
}
}
@@ -520,11 +472,11 @@
Mutex::Autolock _l(mLock);
ALOGI("start");
- if (mAudioTrack.mSource != NULL) {
+ if (mAudioTrack.mExtractor != NULL) {
postReadBuffer(MEDIA_TRACK_TYPE_AUDIO);
}
- if (mVideoTrack.mSource != NULL) {
+ if (mVideoTrack.mExtractor != NULL) {
postReadBuffer(MEDIA_TRACK_TYPE_VIDEO);
}
@@ -563,6 +515,9 @@
} else if (httpSource != NULL) {
static_cast<HTTPBase *>(httpSource.get())->disconnect();
}
+
+ mDataSourceWrapper = NULL;
+
}
status_t NuPlayer2::GenericSource2::feedMoreTSData() {
@@ -630,30 +585,27 @@
{
int32_t trackIndex;
CHECK(msg->findInt32("trackIndex", &trackIndex));
- const sp<IMediaSource> source = mSources.itemAt(trackIndex);
+ const sp<AMediaExtractorWrapper> extractor = mExtractors.itemAt(trackIndex);
Track* track;
- const char *mime;
+ AString mime;
media_track_type trackType, counterpartType;
- sp<MetaData> meta = source->getFormat();
- meta->findCString(kKeyMIMEType, &mime);
- if (!strncasecmp(mime, "audio/", 6)) {
+ sp<AMediaFormatWrapper> format = extractor->getTrackFormat(trackIndex);
+ format->getString(AMEDIAFORMAT_KEY_MIME, &mime);
+ if (!strncasecmp(mime.c_str(), "audio/", 6)) {
track = &mAudioTrack;
trackType = MEDIA_TRACK_TYPE_AUDIO;
counterpartType = MEDIA_TRACK_TYPE_VIDEO;;
} else {
- CHECK(!strncasecmp(mime, "video/", 6));
+ CHECK(!strncasecmp(mime.c_str(), "video/", 6));
track = &mVideoTrack;
trackType = MEDIA_TRACK_TYPE_VIDEO;
counterpartType = MEDIA_TRACK_TYPE_AUDIO;;
}
- if (track->mSource != NULL) {
- track->mSource->stop();
- }
- track->mSource = source;
- track->mSource->start();
+ track->mExtractor = extractor;
+ track->mExtractor->selectSingleTrack(trackIndex);
track->mIndex = trackIndex;
++mAudioDataGeneration;
++mVideoDataGeneration;
@@ -786,11 +738,10 @@
return;
}
- uint32_t textType;
- const void *data;
+ void *data = NULL;
size_t size = 0;
- if (mTimedTextTrack.mSource->getFormat()->findData(
- kKeyTextFormatData, &textType, &data, &size)) {
+ if (mTimedTextTrack.mExtractor->getTrackFormat(mTimedTextTrack.mIndex)->getBuffer(
+ "text", &data, &size)) {
mGlobalTimedText = new ABuffer(size);
if (mGlobalTimedText->data()) {
memcpy(mGlobalTimedText->data(), data, size);
@@ -806,19 +757,36 @@
}
}
+sp<AMessage> NuPlayer2::GenericSource2::getFormat(bool audio) {
+ Mutex::Autolock _l(mLock);
+ return getFormat_l(audio);
+}
+
sp<MetaData> NuPlayer2::GenericSource2::getFormatMeta(bool audio) {
Mutex::Autolock _l(mLock);
return getFormatMeta_l(audio);
}
-sp<MetaData> NuPlayer2::GenericSource2::getFormatMeta_l(bool audio) {
- sp<IMediaSource> source = audio ? mAudioTrack.mSource : mVideoTrack.mSource;
+sp<AMessage> NuPlayer2::GenericSource2::getFormat_l(bool audio) {
+ sp<AMediaExtractorWrapper> extractor = audio ? mAudioTrack.mExtractor : mVideoTrack.mExtractor;
+ size_t trackIndex = audio ? mAudioTrack.mIndex : mVideoTrack.mIndex;
- if (source == NULL) {
+ if (extractor == NULL) {
return NULL;
}
- return source->getFormat();
+ return extractor->getTrackFormat(trackIndex)->toAMessage();
+}
+
+sp<MetaData> NuPlayer2::GenericSource2::getFormatMeta_l(bool audio) {
+ sp<AMediaExtractorWrapper> extractor = audio ? mAudioTrack.mExtractor : mVideoTrack.mExtractor;
+ size_t trackIndex = audio ? mAudioTrack.mIndex : mVideoTrack.mIndex;
+
+ if (extractor == NULL) {
+ return NULL;
+ }
+
+ return convertMediaFormatWrapperToMetaData(extractor->getTrackFormat(trackIndex));
}
status_t NuPlayer2::GenericSource2::dequeueAccessUnit(
@@ -833,7 +801,7 @@
Track *track = audio ? &mAudioTrack : &mVideoTrack;
- if (track->mSource == NULL) {
+ if (track->mExtractor == NULL) {
return -EWOULDBLOCK;
}
@@ -878,11 +846,11 @@
}
if (result != OK) {
- if (mSubtitleTrack.mSource != NULL) {
+ if (mSubtitleTrack.mExtractor != NULL) {
mSubtitleTrack.mPackets->clear();
mFetchSubtitleDataGeneration++;
}
- if (mTimedTextTrack.mSource != NULL) {
+ if (mTimedTextTrack.mExtractor != NULL) {
mTimedTextTrack.mPackets->clear();
mFetchTimedTextDataGeneration++;
}
@@ -898,7 +866,7 @@
mVideoLastDequeueTimeUs = timeUs;
}
- if (mSubtitleTrack.mSource != NULL
+ if (mSubtitleTrack.mExtractor != NULL
&& !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
msg->setInt64("timeUs", timeUs);
@@ -906,7 +874,7 @@
msg->post();
}
- if (mTimedTextTrack.mSource != NULL
+ if (mTimedTextTrack.mExtractor != NULL
&& !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
msg->setInt64("timeUs", timeUs);
@@ -925,50 +893,47 @@
size_t NuPlayer2::GenericSource2::getTrackCount() const {
Mutex::Autolock _l(mLock);
- return mSources.size();
+ return mExtractors.size();
}
sp<AMessage> NuPlayer2::GenericSource2::getTrackInfo(size_t trackIndex) const {
Mutex::Autolock _l(mLock);
- size_t trackCount = mSources.size();
+ size_t trackCount = mExtractors.size();
if (trackIndex >= trackCount) {
return NULL;
}
- sp<AMessage> format = new AMessage();
- sp<MetaData> meta = mSources.itemAt(trackIndex)->getFormat();
- if (meta == NULL) {
+ sp<AMessage> format = mExtractors.itemAt(trackIndex)->getTrackFormat(trackIndex)->toAMessage();
+ if (format == NULL) {
ALOGE("no metadata for track %zu", trackIndex);
return NULL;
}
- const char *mime;
- CHECK(meta->findCString(kKeyMIMEType, &mime));
- format->setString("mime", mime);
+ AString mime;
+ CHECK(format->findString(AMEDIAFORMAT_KEY_MIME, &mime));
int32_t trackType;
- if (!strncasecmp(mime, "video/", 6)) {
+ if (!strncasecmp(mime.c_str(), "video/", 6)) {
trackType = MEDIA_TRACK_TYPE_VIDEO;
- } else if (!strncasecmp(mime, "audio/", 6)) {
+ } else if (!strncasecmp(mime.c_str(), "audio/", 6)) {
trackType = MEDIA_TRACK_TYPE_AUDIO;
- } else if (!strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP)) {
+ } else if (!strcasecmp(mime.c_str(), MEDIA_MIMETYPE_TEXT_3GPP)) {
trackType = MEDIA_TRACK_TYPE_TIMEDTEXT;
} else {
trackType = MEDIA_TRACK_TYPE_UNKNOWN;
}
format->setInt32("type", trackType);
- const char *lang;
- if (!meta->findCString(kKeyMediaLanguage, &lang)) {
- lang = "und";
+ AString lang;
+ if (!format->findString("language", &lang)) {
+ format->setString("language", "und");
}
- format->setString("language", lang);
if (trackType == MEDIA_TRACK_TYPE_SUBTITLE) {
int32_t isAutoselect = 1, isDefault = 0, isForced = 0;
- meta->findInt32(kKeyTrackIsAutoselect, &isAutoselect);
- meta->findInt32(kKeyTrackIsDefault, &isDefault);
- meta->findInt32(kKeyTrackIsForced, &isForced);
+ format->findInt32(AMEDIAFORMAT_KEY_IS_AUTOSELECT, &isAutoselect);
+ format->findInt32(AMEDIAFORMAT_KEY_IS_DEFAULT, &isDefault);
+ format->findInt32(AMEDIAFORMAT_KEY_IS_FORCED_SUBTITLE, &isForced);
format->setInt32("auto", !!isAutoselect);
format->setInt32("default", !!isDefault);
@@ -998,7 +963,7 @@
break;
}
- if (track != NULL && track->mSource != NULL) {
+ if (track != NULL && track->mExtractor != NULL) {
return track->mIndex;
}
@@ -1009,49 +974,45 @@
Mutex::Autolock _l(mLock);
ALOGV("%s track: %zu", select ? "select" : "deselect", trackIndex);
- if (trackIndex >= mSources.size()) {
+ if (trackIndex >= mExtractors.size()) {
return BAD_INDEX;
}
if (!select) {
Track* track = NULL;
- if (mSubtitleTrack.mSource != NULL && trackIndex == mSubtitleTrack.mIndex) {
+ if (mSubtitleTrack.mExtractor != NULL && trackIndex == mSubtitleTrack.mIndex) {
track = &mSubtitleTrack;
mFetchSubtitleDataGeneration++;
- } else if (mTimedTextTrack.mSource != NULL && trackIndex == mTimedTextTrack.mIndex) {
+ } else if (mTimedTextTrack.mExtractor != NULL && trackIndex == mTimedTextTrack.mIndex) {
track = &mTimedTextTrack;
mFetchTimedTextDataGeneration++;
}
if (track == NULL) {
return INVALID_OPERATION;
}
- track->mSource->stop();
- track->mSource = NULL;
+ track->mExtractor = NULL;
track->mPackets->clear();
return OK;
}
- const sp<IMediaSource> source = mSources.itemAt(trackIndex);
- sp<MetaData> meta = source->getFormat();
+ const sp<AMediaExtractorWrapper> extractor = mExtractors.itemAt(trackIndex);
+ sp<MetaData> meta = convertMediaFormatWrapperToMetaData(extractor->getTrackFormat(trackIndex));
const char *mime;
CHECK(meta->findCString(kKeyMIMEType, &mime));
if (!strncasecmp(mime, "text/", 5)) {
bool isSubtitle = strcasecmp(mime, MEDIA_MIMETYPE_TEXT_3GPP);
Track *track = isSubtitle ? &mSubtitleTrack : &mTimedTextTrack;
- if (track->mSource != NULL && track->mIndex == trackIndex) {
+ if (track->mExtractor != NULL && track->mIndex == trackIndex) {
return OK;
}
track->mIndex = trackIndex;
- if (track->mSource != NULL) {
- track->mSource->stop();
- }
- track->mSource = mSources.itemAt(trackIndex);
- track->mSource->start();
+ track->mExtractor = mExtractors.itemAt(trackIndex);
+ track->mExtractor->selectSingleTrack(trackIndex);
if (track->mPackets == NULL) {
- track->mPackets = new AnotherPacketSource(track->mSource->getFormat());
+ track->mPackets = new AnotherPacketSource(meta);
} else {
track->mPackets->clear();
- track->mPackets->setFormat(track->mSource->getFormat());
+ track->mPackets->setFormat(meta);
}
@@ -1062,7 +1023,7 @@
}
status_t eosResult; // ignored
- if (mSubtitleTrack.mSource != NULL
+ if (mSubtitleTrack.mExtractor != NULL
&& !mSubtitleTrack.mPackets->hasBufferAvailable(&eosResult)) {
sp<AMessage> msg = new AMessage(kWhatFetchSubtitleData, this);
msg->setInt64("timeUs", timeUs);
@@ -1074,7 +1035,7 @@
msg2->setInt32("generation", mFetchTimedTextDataGeneration);
msg2->post();
- if (mTimedTextTrack.mSource != NULL
+ if (mTimedTextTrack.mExtractor != NULL
&& !mTimedTextTrack.mPackets->hasBufferAvailable(&eosResult)) {
sp<AMessage> msg = new AMessage(kWhatFetchTimedTextData, this);
msg->setInt64("timeUs", timeUs);
@@ -1086,7 +1047,7 @@
} else if (!strncasecmp(mime, "audio/", 6) || !strncasecmp(mime, "video/", 6)) {
bool audio = !strncasecmp(mime, "audio/", 6);
Track *track = audio ? &mAudioTrack : &mVideoTrack;
- if (track->mSource != NULL && track->mIndex == trackIndex) {
+ if (track->mExtractor != NULL && track->mIndex == trackIndex) {
return OK;
}
@@ -1133,7 +1094,7 @@
}
status_t NuPlayer2::GenericSource2::doSeek(int64_t seekTimeUs, MediaPlayer2SeekMode mode) {
- if (mVideoTrack.mSource != NULL) {
+ if (mVideoTrack.mExtractor != NULL) {
++mVideoDataGeneration;
int64_t actualTimeUs;
@@ -1145,18 +1106,18 @@
mVideoLastDequeueTimeUs = actualTimeUs;
}
- if (mAudioTrack.mSource != NULL) {
+ if (mAudioTrack.mExtractor != NULL) {
++mAudioDataGeneration;
readBuffer(MEDIA_TRACK_TYPE_AUDIO, seekTimeUs, MediaPlayer2SeekMode::SEEK_CLOSEST);
mAudioLastDequeueTimeUs = seekTimeUs;
}
- if (mSubtitleTrack.mSource != NULL) {
+ if (mSubtitleTrack.mExtractor != NULL) {
mSubtitleTrack.mPackets->clear();
mFetchSubtitleDataGeneration++;
}
- if (mTimedTextTrack.mSource != NULL) {
+ if (mTimedTextTrack.mExtractor != NULL) {
mTimedTextTrack.mPackets->clear();
mFetchTimedTextDataGeneration++;
}
@@ -1227,10 +1188,12 @@
}
if (trackType == MEDIA_TRACK_TYPE_TIMEDTEXT) {
- const char *mime;
- CHECK(mTimedTextTrack.mSource != NULL
- && mTimedTextTrack.mSource->getFormat()->findCString(kKeyMIMEType, &mime));
- meta->setString("mime", mime);
+ AString mime;
+ sp<AMediaExtractorWrapper> extractor = mTimedTextTrack.mExtractor;
+ size_t trackIndex = mTimedTextTrack.mIndex;
+ CHECK(extractor != NULL
+ && extractor->getTrackFormat(trackIndex)->getString(AMEDIAFORMAT_KEY_MIME, &mime));
+ meta->setString("mime", mime.c_str());
}
int64_t durationUs;
@@ -1327,7 +1290,7 @@
TRESPASS();
}
- if (track->mSource == NULL) {
+ if (track->mExtractor == NULL) {
return;
}
@@ -1335,109 +1298,77 @@
*actualTimeUs = seekTimeUs;
}
- MediaSource::ReadOptions options;
bool seeking = false;
+ sp<AMediaExtractorWrapper> extractor = track->mExtractor;
if (seekTimeUs >= 0) {
- options.setSeekTo(seekTimeUs, mode);
+ extractor->seekTo(seekTimeUs, mode);
seeking = true;
}
- const bool couldReadMultiple = (track->mSource->supportReadMultiple());
-
- if (couldReadMultiple) {
- options.setNonBlocking();
- }
-
int32_t generation = getDataGeneration(trackType);
for (size_t numBuffers = 0; numBuffers < maxBuffers; ) {
- Vector<MediaBufferBase *> mediaBuffers;
- status_t err = NO_ERROR;
+ Vector<sp<ABuffer> > aBuffers;
- sp<IMediaSource> source = track->mSource;
mLock.unlock();
- if (couldReadMultiple) {
- err = source->readMultiple(
- &mediaBuffers, maxBuffers - numBuffers, &options);
- } else {
- MediaBufferBase *mbuf = NULL;
- err = source->read(&mbuf, &options);
- if (err == OK && mbuf != NULL) {
- mediaBuffers.push_back(mbuf);
- }
+
+ sp<AMediaFormatWrapper> format;
+ ssize_t sampleSize = -1;
+ status_t err = extractor->getSampleFormat(format);
+ if (err == OK) {
+ sampleSize = extractor->getSampleSize();
}
+
+ if (err != OK || sampleSize < 0) {
+ mLock.lock();
+ track->mPackets->signalEOS(err != OK ? err : ERROR_END_OF_STREAM);
+ break;
+ }
+
+ sp<ABuffer> abuf = new ABuffer(sampleSize);
+ sampleSize = extractor->readSampleData(abuf);
mLock.lock();
- options.clearNonPersistent();
-
- size_t id = 0;
- size_t count = mediaBuffers.size();
-
// in case track has been changed since we don't have lock for some time.
if (generation != getDataGeneration(trackType)) {
- for (; id < count; ++id) {
- mediaBuffers[id]->release();
- }
break;
}
- for (; id < count; ++id) {
- int64_t timeUs;
- MediaBufferBase *mbuf = mediaBuffers[id];
- if (!mbuf->meta_data().findInt64(kKeyTime, &timeUs)) {
- mbuf->meta_data().dumpToLog();
- track->mPackets->signalEOS(ERROR_MALFORMED);
- break;
- }
- if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
- mAudioTimeUs = timeUs;
- } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
- mVideoTimeUs = timeUs;
- }
-
- queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
-
- sp<ABuffer> buffer = mediaBufferToABuffer(mbuf, trackType);
- if (numBuffers == 0 && actualTimeUs != nullptr) {
- *actualTimeUs = timeUs;
- }
- if (seeking && buffer != nullptr) {
- sp<AMessage> meta = buffer->meta();
- if (meta != nullptr && mode == MediaPlayer2SeekMode::SEEK_CLOSEST
- && seekTimeUs > timeUs) {
- sp<AMessage> extra = new AMessage;
- extra->setInt64("resume-at-mediaTimeUs", seekTimeUs);
- meta->setMessage("extra", extra);
- }
- }
-
- track->mPackets->queueAccessUnit(buffer);
- formatChange = false;
- seeking = false;
- ++numBuffers;
- }
- if (id < count) {
- // Error, some mediaBuffer doesn't have kKeyTime.
- for (; id < count; ++id) {
- mediaBuffers[id]->release();
- }
+ int64_t timeUs = extractor->getSampleTime();
+ if (timeUs < 0) {
+ track->mPackets->signalEOS(ERROR_MALFORMED);
break;
}
- if (err == WOULD_BLOCK) {
- break;
- } else if (err == INFO_FORMAT_CHANGED) {
-#if 0
- track->mPackets->queueDiscontinuity(
- ATSParser::DISCONTINUITY_FORMATCHANGE,
- NULL,
- false /* discard */);
-#endif
- } else if (err != OK) {
- queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
- track->mPackets->signalEOS(err);
- break;
+ sp<AMessage> meta = abuf->meta();
+ format->writeToAMessage(meta);
+ meta->setInt64("timeUs", timeUs);
+ if (trackType == MEDIA_TRACK_TYPE_AUDIO) {
+ mAudioTimeUs = timeUs;
+ } else if (trackType == MEDIA_TRACK_TYPE_VIDEO) {
+ mVideoTimeUs = timeUs;
}
+
+ queueDiscontinuityIfNeeded(seeking, formatChange, trackType, track);
+
+ if (numBuffers == 0 && actualTimeUs != nullptr) {
+ *actualTimeUs = timeUs;
+ }
+ if (seeking) {
+ if (meta != nullptr && mode == MediaPlayer2SeekMode::SEEK_CLOSEST
+ && seekTimeUs > timeUs) {
+ sp<AMessage> extra = new AMessage;
+ extra->setInt64("resume-at-mediaTimeUs", seekTimeUs);
+ meta->setMessage("extra", extra);
+ }
+ }
+
+ track->mPackets->queueAccessUnit(abuf);
+ formatChange = false;
+ seeking = false;
+ ++numBuffers;
+ extractor->advance();
+
}
if (mIsStreaming
@@ -1453,7 +1384,7 @@
if (mPreparing || mSentPauseOnBuffering) {
Track *counterTrack =
(trackType == MEDIA_TRACK_TYPE_VIDEO ? &mAudioTrack : &mVideoTrack);
- if (counterTrack->mSource != NULL) {
+ if (counterTrack->mExtractor != NULL) {
durationUs = counterTrack->mPackets->getBufferedDurationUs(&finalResult);
}
if (finalResult == ERROR_END_OF_STREAM || durationUs >= markUs) {
@@ -1649,26 +1580,22 @@
// same source without being reset (called by prepareAsync/initFromDataSource)
mIsDrmReleased = false;
- if (mFileMeta == NULL) {
- ALOGI("checkDrmInfo: No metadata");
+ if (mExtractor == NULL) {
+ ALOGV("checkDrmInfo: No extractor");
return OK; // letting the caller responds accordingly
}
- uint32_t type;
- const void *pssh;
- size_t psshsize;
-
- if (!mFileMeta->findData(kKeyPssh, &type, &pssh, &psshsize)) {
+ PsshInfo *psshInfo = mExtractor->getPsshInfo();
+ if (psshInfo == NULL) {
ALOGV("checkDrmInfo: No PSSH");
return OK; // source without DRM info
}
- sp<ABuffer> drmInfoBuffer = NuPlayer2Drm::retrieveDrmInfo(pssh, psshsize);
- ALOGV("checkDrmInfo: MEDIA2_DRM_INFO PSSH size: %d drmInfoBuffer size: %d",
- (int)psshsize, (int)drmInfoBuffer->size());
+ sp<ABuffer> drmInfoBuffer = NuPlayer2Drm::retrieveDrmInfo(psshInfo);
+ ALOGV("checkDrmInfo: MEDIA_DRM_INFO PSSH drm info size: %d", (int)drmInfoBuffer->size());
if (drmInfoBuffer->size() == 0) {
- ALOGE("checkDrmInfo: Unexpected drmInfoBuffer size: 0");
+ ALOGE("checkDrmInfo: Unexpected parcel size: 0");
return UNKNOWN_ERROR;
}
diff --git a/media/libmediaplayer2/nuplayer2/GenericSource2.h b/media/libmediaplayer2/nuplayer2/GenericSource2.h
index 896c397..9bc5182 100644
--- a/media/libmediaplayer2/nuplayer2/GenericSource2.h
+++ b/media/libmediaplayer2/nuplayer2/GenericSource2.h
@@ -25,6 +25,9 @@
#include <media/stagefright/MediaBuffer.h>
#include <mediaplayer2/mediaplayer2.h>
+#include <media/NdkMediaDataSource.h>
+#include <media/NdkMediaExtractor.h>
+#include <media/NdkWrapper.h>
namespace android {
@@ -101,6 +104,7 @@
virtual void onMessageReceived(const sp<AMessage> &msg);
+ virtual sp<AMessage> getFormat(bool audio);
virtual sp<MetaData> getFormatMeta(bool audio);
private:
@@ -122,19 +126,14 @@
struct Track {
size_t mIndex;
- sp<IMediaSource> mSource;
+ sp<AMediaExtractorWrapper> mExtractor;
sp<AnotherPacketSource> mPackets;
};
- Vector<sp<IMediaSource> > mSources;
- Track mAudioTrack;
int64_t mAudioTimeUs;
int64_t mAudioLastDequeueTimeUs;
- Track mVideoTrack;
int64_t mVideoTimeUs;
int64_t mVideoLastDequeueTimeUs;
- Track mSubtitleTrack;
- Track mTimedTextTrack;
BufferingSettings mBufferingSettings;
int32_t mPrevBufferPercentage;
@@ -164,12 +163,20 @@
sp<NuCachedSource2> mCachedSource;
sp<DataSource> mHttpSource;
sp<MetaData> mFileMeta;
+ sp<AMediaDataSourceWrapper> mDataSourceWrapper;
+ sp<AMediaExtractorWrapper> mExtractor;
+ Vector<sp<AMediaExtractorWrapper> > mExtractors;
bool mStarted;
bool mPreparing;
int64_t mBitrate;
uint32_t mPendingReadBufferTypes;
sp<ABuffer> mGlobalTimedText;
+ Track mVideoTrack;
+ Track mAudioTrack;
+ Track mSubtitleTrack;
+ Track mTimedTextTrack;
+
mutable Mutex mLock;
sp<ALooper> mLooper;
@@ -227,6 +234,7 @@
void sendCacheStats();
+ sp<AMessage> getFormat_l(bool audio);
sp<MetaData> getFormatMeta_l(bool audio);
int32_t getDataGeneration(media_track_type type) const;
diff --git a/media/libstagefright/CCodecBufferChannel.cpp b/media/libstagefright/CCodecBufferChannel.cpp
index 449c6aa..5ce49d9 100644
--- a/media/libstagefright/CCodecBufferChannel.cpp
+++ b/media/libstagefright/CCodecBufferChannel.cpp
@@ -760,19 +760,18 @@
ALOGV("graphic = %s", graphic ? "true" : "false");
std::shared_ptr<C2BlockPool> pool;
- err = GetCodec2BlockPool(
- graphic ? C2BlockPool::BASIC_GRAPHIC : C2BlockPool::BASIC_LINEAR,
- component,
- &pool);
+ if (graphic) {
+ err = GetCodec2BlockPool(C2BlockPool::BASIC_GRAPHIC, component, &pool);
+ } else {
+ err = CreateCodec2BlockPool(C2PlatformAllocatorStore::ION,
+ component, &pool);
+ }
+
if (err == C2_OK) {
(*buffers)->setPool(pool);
} else {
// TODO: error
}
- // TODO: remove once we switch to proper buffer pool.
- if (!graphic) {
- *buffers = (*buffers)->toArrayMode();
- }
}
{
diff --git a/media/libstagefright/codec2/SimpleC2Component.cpp b/media/libstagefright/codec2/SimpleC2Component.cpp
index 333cfeb..0753b08 100644
--- a/media/libstagefright/codec2/SimpleC2Component.cpp
+++ b/media/libstagefright/codec2/SimpleC2Component.cpp
@@ -302,12 +302,15 @@
if (err != C2_OK) {
return err;
}
- err = GetCodec2BlockPool(
- (outputFormat.value == C2FormatVideo)
- ? C2BlockPool::BASIC_GRAPHIC
- : C2BlockPool::BASIC_LINEAR,
- shared_from_this(),
- &mOutputBlockPool);
+ if (outputFormat.value == C2FormatVideo) {
+ err = GetCodec2BlockPool(
+ C2BlockPool::BASIC_GRAPHIC,
+ shared_from_this(), &mOutputBlockPool);
+ } else {
+ err = CreateCodec2BlockPool(
+ C2PlatformAllocatorStore::ION,
+ shared_from_this(), &mOutputBlockPool);
+ }
if (err != C2_OK) {
return err;
}
diff --git a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
index 038be48..f389abc 100644
--- a/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
+++ b/media/libstagefright/codec2/tests/vndk/C2BufferTest.cpp
@@ -232,7 +232,8 @@
class C2BufferTest : public ::testing::Test {
public:
C2BufferTest()
- : mLinearAllocator(std::make_shared<C2AllocatorIon>('i')),
+ : mBlockPoolId(C2BlockPool::PLATFORM_START),
+ mLinearAllocator(std::make_shared<C2AllocatorIon>('i')),
mSize(0u),
mAddr(nullptr),
mGraphicAllocator(std::make_shared<C2AllocatorGralloc>('g')) {
@@ -281,7 +282,7 @@
}
std::shared_ptr<C2BlockPool> makeLinearBlockPool() {
- return std::make_shared<C2BasicLinearBlockPool>(mLinearAllocator);
+ return std::make_shared<C2PooledBlockPool>(mLinearAllocator, mBlockPoolId++);
}
void allocateGraphic(uint32_t width, uint32_t height) {
@@ -328,6 +329,7 @@
}
private:
+ C2BlockPool::local_id_t mBlockPoolId;
std::shared_ptr<C2Allocator> mLinearAllocator;
std::shared_ptr<C2LinearAllocation> mLinearAllocation;
size_t mSize;
@@ -745,4 +747,23 @@
EXPECT_FALSE(buffer->hasInfo(info2->type()));
}
+TEST_F(C2BufferTest, MultipleLinearMapTest) {
+ std::shared_ptr<C2BlockPool> pool(makeLinearBlockPool());
+ constexpr size_t kCapacity = 524288u;
+ for (int i = 0; i < 100; ++i) {
+ std::vector<C2WriteView> wViews;
+ std::vector<C2ReadView> rViews;
+ for (int j = 0; j < 16; ++j) {
+ std::shared_ptr<C2LinearBlock> block;
+ ASSERT_EQ(C2_OK, pool->fetchLinearBlock(
+ kCapacity,
+ { C2MemoryUsage::CPU_READ, C2MemoryUsage::CPU_WRITE },
+ &block));
+ wViews.push_back(block->map().get());
+ C2ConstLinearBlock cBlock = block->share(0, kCapacity / 2, C2Fence());
+ rViews.push_back(cBlock.map().get());
+ }
+ }
+}
+
} // namespace android
diff --git a/media/libstagefright/codec2/vndk/Android.bp b/media/libstagefright/codec2/vndk/Android.bp
index 47afd42..95e7c39 100644
--- a/media/libstagefright/codec2/vndk/Android.bp
+++ b/media/libstagefright/codec2/vndk/Android.bp
@@ -39,14 +39,17 @@
shared_libs: [
"android.hardware.graphics.allocator@2.0",
"android.hardware.graphics.mapper@2.0",
+ "android.hardware.media.bufferpool@1.0",
"libbinder",
"libcutils",
"libdl",
"libhardware",
"libhidlbase",
"libion",
+ "libfmq",
"liblog",
"libstagefright_foundation",
+ "libstagefright_bufferpool@1.0",
"libui",
"libutils",
],
diff --git a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
index cf7658a..664c09e 100644
--- a/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
+++ b/media/libstagefright/codec2/vndk/C2AllocatorIon.cpp
@@ -18,6 +18,8 @@
#define LOG_TAG "C2AllocatorIon"
#include <utils/Log.h>
+#include <list>
+
#include <ion/ion.h>
#include <sys/mman.h>
#include <unistd.h>
@@ -148,6 +150,7 @@
* so that we can capture the error.
*
* \param ionFd ion client (ownership transferred to created object)
+ * \param owned whehter native_handle_t is owned by an allocation or not.
* \param capacity size of allocation
* \param bufferFd buffer handle (ownership transferred to created object). Must be
* invalid if err is not 0.
@@ -155,14 +158,14 @@
* invalid if err is not 0.
* \param err errno during buffer allocation or import
*/
- Impl(int ionFd, size_t capacity, int bufferFd, ion_user_handle_t buffer, C2Allocator::id_t id, int err)
+ Impl(int ionFd, bool owned, size_t capacity, int bufferFd, ion_user_handle_t buffer, C2Allocator::id_t id, int err)
: mIonFd(ionFd),
+ mHandleOwned(owned),
mHandle(bufferFd, capacity),
mBuffer(buffer),
mId(id),
mInit(c2_map_errno<ENOMEM, EACCES, EINVAL>(err)),
- mMapFd(-1),
- mMapSize(0) {
+ mMapFd(-1) {
if (mInit != C2_OK) {
// close ionFd now on error
if (mIonFd >= 0) {
@@ -188,7 +191,7 @@
static Impl *Import(int ionFd, size_t capacity, int bufferFd, C2Allocator::id_t id) {
ion_user_handle_t buffer = -1;
int ret = ion_import(ionFd, bufferFd, &buffer);
- return new Impl(ionFd, capacity, bufferFd, buffer, id, ret);
+ return new Impl(ionFd, false, capacity, bufferFd, buffer, id, ret);
}
/**
@@ -215,13 +218,14 @@
buffer = -1;
}
}
- return new Impl(ionFd, size, bufferFd, buffer, id, ret);
+ return new Impl(ionFd, true, size, bufferFd, buffer, id, ret);
}
c2_status_t map(size_t offset, size_t size, C2MemoryUsage usage, C2Fence *fence, void **addr) {
(void)fence; // TODO: wait for fence
*addr = nullptr;
- if (mMapSize > 0) {
+ if (!mMappings.empty()) {
+ ALOGV("multiple map");
// TODO: technically we should return DUPLICATE here, but our block views don't
// actually unmap, so we end up remapping an ion buffer multiple times.
//
@@ -244,54 +248,63 @@
size_t alignmentBytes = offset % PAGE_SIZE;
size_t mapOffset = offset - alignmentBytes;
size_t mapSize = size + alignmentBytes;
+ Mapping map = { nullptr, alignmentBytes, mapSize };
c2_status_t err = C2_OK;
if (mMapFd == -1) {
int ret = ion_map(mIonFd, mBuffer, mapSize, prot,
- flags, mapOffset, (unsigned char**)&mMapAddr, &mMapFd);
+ flags, mapOffset, (unsigned char**)&map.addr, &mMapFd);
if (ret) {
mMapFd = -1;
- *addr = nullptr;
+ map.addr = *addr = nullptr;
err = c2_map_errno<EINVAL>(-ret);
} else {
- *addr = (uint8_t *)mMapAddr + alignmentBytes;
- mMapAlignmentBytes = alignmentBytes;
- mMapSize = mapSize;
+ *addr = (uint8_t *)map.addr + alignmentBytes;
}
} else {
- mMapAddr = mmap(nullptr, mapSize, prot, flags, mMapFd, mapOffset);
- if (mMapAddr == MAP_FAILED) {
- mMapAddr = *addr = nullptr;
+ map.addr = mmap(nullptr, mapSize, prot, flags, mMapFd, mapOffset);
+ if (map.addr == MAP_FAILED) {
+ map.addr = *addr = nullptr;
err = c2_map_errno<EINVAL>(errno);
} else {
- *addr = (uint8_t *)mMapAddr + alignmentBytes;
- mMapAlignmentBytes = alignmentBytes;
- mMapSize = mapSize;
+ *addr = (uint8_t *)map.addr + alignmentBytes;
}
}
+ if (map.addr) {
+ mMappings.push_back(map);
+ }
return err;
}
c2_status_t unmap(void *addr, size_t size, C2Fence *fence) {
- if (mMapFd < 0 || mMapSize == 0) {
+ if (mMapFd < 0 || mMappings.empty()) {
return C2_NOT_FOUND;
}
- if (addr != (uint8_t *)mMapAddr + mMapAlignmentBytes ||
- size + mMapAlignmentBytes != mMapSize) {
- return C2_BAD_VALUE;
+ for (auto it = mMappings.begin(); it != mMappings.end(); ++it) {
+ if (addr != (uint8_t *)it->addr + it->alignmentBytes ||
+ size + it->alignmentBytes != it->size) {
+ continue;
+ }
+ int err = munmap(it->addr, it->size);
+ if (err != 0) {
+ return c2_map_errno<EINVAL>(errno);
+ }
+ if (fence) {
+ *fence = C2Fence(); // not using fences
+ }
+ (void)mMappings.erase(it);
+ return C2_OK;
}
- int err = munmap(mMapAddr, mMapSize);
- if (err != 0) {
- return c2_map_errno<EINVAL>(errno);
- }
- if (fence) {
- *fence = C2Fence(); // not using fences
- }
- mMapSize = 0;
- return C2_OK;
+ return C2_BAD_VALUE;
}
~Impl() {
+ if (!mMappings.empty()) {
+ ALOGD("Dangling mappings!");
+ for (const Mapping &map : mMappings) {
+ (void)munmap(map.addr, map.size);
+ }
+ }
if (mMapFd >= 0) {
close(mMapFd);
mMapFd = -1;
@@ -302,7 +315,9 @@
if (mIonFd >= 0) {
close(mIonFd);
}
- native_handle_close(&mHandle);
+ if (mHandleOwned) {
+ native_handle_close(&mHandle);
+ }
}
c2_status_t status() const {
@@ -323,14 +338,18 @@
private:
int mIonFd;
+ bool mHandleOwned;
C2HandleIon mHandle;
ion_user_handle_t mBuffer;
C2Allocator::id_t mId;
c2_status_t mInit;
int mMapFd; // only one for now
- void *mMapAddr;
- size_t mMapAlignmentBytes;
- size_t mMapSize;
+ struct Mapping {
+ void *addr;
+ size_t alignmentBytes;
+ size_t size;
+ };
+ std::list<Mapping> mMappings;
};
c2_status_t C2AllocationIon::map(
diff --git a/media/libstagefright/codec2/vndk/C2Buffer.cpp b/media/libstagefright/codec2/vndk/C2Buffer.cpp
index dc765f5..91b21c2 100644
--- a/media/libstagefright/codec2/vndk/C2Buffer.cpp
+++ b/media/libstagefright/codec2/vndk/C2Buffer.cpp
@@ -25,8 +25,16 @@
#include <C2BufferPriv.h>
#include <C2BlockInternal.h>
+#include <ClientManager.h>
+
namespace {
+using android::hardware::media::bufferpool::V1_0::ResultStatus;
+using android::hardware::media::bufferpool::V1_0::implementation::BufferPoolAllocation;
+using android::hardware::media::bufferpool::V1_0::implementation::BufferPoolAllocator;
+using android::hardware::media::bufferpool::V1_0::implementation::ClientManager;
+using android::hardware::media::bufferpool::V1_0::implementation::ConnectionId;
+
// This anonymous namespace contains the helper classes that allow our implementation to create
// block/buffer objects.
//
@@ -341,6 +349,257 @@
return std::shared_ptr<C2LinearBlock>(new C2LinearBlock(impl, *impl));
}
+/**
+ * Wrapped C2Allocator which is injected to buffer pool on behalf of
+ * C2BlockPool.
+ */
+class _C2BufferPoolAllocator : public BufferPoolAllocator {
+public:
+ _C2BufferPoolAllocator(const std::shared_ptr<C2Allocator> &allocator)
+ : mAllocator(allocator) {}
+
+ ~_C2BufferPoolAllocator() override {}
+
+ ResultStatus allocate(const std::vector<uint8_t> ¶ms,
+ std::shared_ptr<BufferPoolAllocation> *alloc) override;
+
+ bool compatible(const std::vector<uint8_t> &newParams,
+ const std::vector<uint8_t> &oldParams) override;
+
+ // Methods for codec2 component (C2BlockPool).
+ /**
+ * Transforms linear allocation parameters for C2Allocator to parameters
+ * for buffer pool.
+ *
+ * @param capacity size of linear allocation
+ * @param usage memory usage pattern for linear allocation
+ * @param params allocation parameters for buffer pool
+ */
+ void getLinearParams(uint32_t capacity, C2MemoryUsage usage,
+ std::vector<uint8_t> *params);
+
+ /**
+ * Transforms graphic allocation parameters for C2Allocator to parameters
+ * for buffer pool.
+ *
+ * @param width width of graphic allocation
+ * @param height height of graphic allocation
+ * @param format color format of graphic allocation
+ * @param params allocation parameter for buffer pool
+ */
+ void getGraphicParams(uint32_t width, uint32_t height,
+ uint32_t format, C2MemoryUsage usage,
+ std::vector<uint8_t> *params);
+
+ /**
+ * Transforms an existing native handle to an C2LinearAllcation.
+ * Wrapper to C2Allocator#priorLinearAllocation
+ */
+ c2_status_t priorLinearAllocation(
+ const C2Handle *handle,
+ std::shared_ptr<C2LinearAllocation> *c2Allocation);
+
+ /**
+ * Transforms an existing native handle to an C2GraphicAllcation.
+ * Wrapper to C2Allocator#priorGraphicAllocation
+ */
+ c2_status_t priorGraphicAllocation(
+ const C2Handle *handle,
+ std::shared_ptr<C2GraphicAllocation> *c2Allocation);
+
+private:
+ static constexpr int kMaxIntParams = 5; // large enough number;
+
+ enum AllocType : uint8_t {
+ ALLOC_NONE = 0,
+
+ ALLOC_LINEAR,
+ ALLOC_GRAPHIC,
+ };
+
+ union AllocParams {
+ struct {
+ AllocType allocType;
+ C2MemoryUsage usage;
+ uint32_t params[kMaxIntParams];
+ } data;
+ uint8_t array[0];
+
+ AllocParams() : data{ALLOC_NONE, {0, 0}, {0}} {}
+ AllocParams(C2MemoryUsage usage, uint32_t capacity)
+ : data{ALLOC_LINEAR, usage, {[0] = capacity}} {}
+ AllocParams(
+ C2MemoryUsage usage,
+ uint32_t width, uint32_t height, uint32_t format)
+ : data{ALLOC_GRAPHIC, usage, {width, height, format}} {}
+ };
+
+ const std::shared_ptr<C2Allocator> mAllocator;
+};
+
+struct LinearAllocationDtor {
+ LinearAllocationDtor(const std::shared_ptr<C2LinearAllocation> &alloc)
+ : mAllocation(alloc) {}
+
+ void operator()(BufferPoolAllocation *poolAlloc) { delete poolAlloc; }
+
+ const std::shared_ptr<C2LinearAllocation> mAllocation;
+};
+
+ResultStatus _C2BufferPoolAllocator::allocate(
+ const std::vector<uint8_t> ¶ms,
+ std::shared_ptr<BufferPoolAllocation> *alloc) {
+ AllocParams c2Params;
+ memcpy(&c2Params, params.data(), std::min(sizeof(AllocParams), params.size()));
+ std::shared_ptr<C2LinearAllocation> c2Linear;
+ c2_status_t status = C2_BAD_VALUE;
+ switch(c2Params.data.allocType) {
+ case ALLOC_NONE:
+ break;
+ case ALLOC_LINEAR:
+ status = mAllocator->newLinearAllocation(
+ c2Params.data.params[0], c2Params.data.usage, &c2Linear);
+ if (status == C2_OK && c2Linear) {
+ BufferPoolAllocation *ptr = new BufferPoolAllocation(c2Linear->handle());
+ if (ptr) {
+ *alloc = std::shared_ptr<BufferPoolAllocation>(
+ ptr, LinearAllocationDtor(c2Linear));
+ if (*alloc) {
+ return ResultStatus::OK;
+ }
+ delete ptr;
+ }
+ return ResultStatus::NO_MEMORY;
+ }
+ break;
+ case ALLOC_GRAPHIC:
+ // TODO
+ break;
+ default:
+ break;
+ }
+ return ResultStatus::CRITICAL_ERROR;
+}
+
+bool _C2BufferPoolAllocator::compatible(
+ const std::vector<uint8_t> &newParams,
+ const std::vector<uint8_t> &oldParams) {
+ size_t newSize = newParams.size();
+ size_t oldSize = oldParams.size();
+
+ // TODO: support not exact matching. e.g) newCapacity < oldCapacity
+ if (newSize == oldSize) {
+ for (size_t i = 0; i < newSize; ++i) {
+ if (newParams[i] != oldParams[i]) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
+}
+
+void _C2BufferPoolAllocator::getLinearParams(
+ uint32_t capacity, C2MemoryUsage usage, std::vector<uint8_t> *params) {
+ AllocParams c2Params(usage, capacity);
+ params->assign(c2Params.array, c2Params.array + sizeof(AllocParams));
+}
+
+void _C2BufferPoolAllocator::getGraphicParams(
+ uint32_t width, uint32_t height, uint32_t format, C2MemoryUsage usage,
+ std::vector<uint8_t> *params) {
+ AllocParams c2Params(usage, width, height, format);
+ params->assign(c2Params.array, c2Params.array + sizeof(AllocParams));
+}
+
+c2_status_t _C2BufferPoolAllocator::priorLinearAllocation(
+ const C2Handle *handle,
+ std::shared_ptr<C2LinearAllocation> *c2Allocation) {
+ return mAllocator->priorLinearAllocation(handle, c2Allocation);
+}
+
+c2_status_t _C2BufferPoolAllocator::priorGraphicAllocation(
+ const C2Handle *handle,
+ std::shared_ptr<C2GraphicAllocation> *c2Allocation) {
+ return mAllocator->priorGraphicAllocation(handle, c2Allocation);
+}
+
+class C2PooledBlockPool::Impl {
+public:
+ Impl(const std::shared_ptr<C2Allocator> &allocator)
+ : mInit(C2_OK),
+ mBufferPoolManager(ClientManager::getInstance()),
+ mAllocator(std::make_shared<_C2BufferPoolAllocator>(allocator)) {
+ if (mAllocator && mBufferPoolManager) {
+ if (mBufferPoolManager->create(
+ mAllocator, &mConnectionId) == ResultStatus::OK) {
+ return;
+ }
+ }
+ mInit = C2_NO_INIT;
+ }
+
+ ~Impl() {
+ if (mInit == C2_OK) {
+ mBufferPoolManager->close(mConnectionId);
+ }
+ }
+
+ c2_status_t fetchLinearBlock(
+ uint32_t capacity, C2MemoryUsage usage,
+ std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
+ block->reset();
+ if (mInit != C2_OK) {
+ return mInit;
+ }
+ std::vector<uint8_t> params;
+ mAllocator->getLinearParams(capacity, usage, ¶ms);
+ std::shared_ptr<_C2BlockPoolData> poolData;
+ ResultStatus status = mBufferPoolManager->allocate(
+ mConnectionId, params, &poolData);
+ if (status == ResultStatus::OK) {
+ std::shared_ptr<C2LinearAllocation> alloc;
+ c2_status_t err = mAllocator->priorLinearAllocation(
+ poolData->mHandle, &alloc);
+ if (err == C2_OK && poolData && alloc) {
+ *block = _C2BlockFactory::CreateLinearBlock(
+ alloc, poolData, 0, capacity);
+ if (*block) {
+ return C2_OK;
+ }
+ }
+ return C2_NO_MEMORY;
+ }
+ if (status == ResultStatus::NO_MEMORY) {
+ return C2_NO_MEMORY;
+ }
+ return C2_CORRUPTED;
+ }
+
+private:
+ c2_status_t mInit;
+ const android::sp<ClientManager> mBufferPoolManager;
+ ConnectionId mConnectionId; // locally
+ const std::shared_ptr<_C2BufferPoolAllocator> mAllocator;
+};
+
+C2PooledBlockPool::C2PooledBlockPool(
+ const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId)
+ : mAllocator(allocator), mLocalId(localId), mImpl(new Impl(allocator)) {}
+
+C2PooledBlockPool::~C2PooledBlockPool() {
+}
+
+c2_status_t C2PooledBlockPool::fetchLinearBlock(
+ uint32_t capacity,
+ C2MemoryUsage usage,
+ std::shared_ptr<C2LinearBlock> *block /* nonnull */) {
+ if (mImpl) {
+ return mImpl->fetchLinearBlock(capacity, usage, block);
+ }
+ return C2_CORRUPTED;
+}
+
/* ========================================== 2D BLOCK ========================================= */
/**
diff --git a/media/libstagefright/codec2/vndk/C2Store.cpp b/media/libstagefright/codec2/vndk/C2Store.cpp
index 216a897..6f752ae 100644
--- a/media/libstagefright/codec2/vndk/C2Store.cpp
+++ b/media/libstagefright/codec2/vndk/C2Store.cpp
@@ -152,6 +152,39 @@
return res;
}
+c2_status_t CreateCodec2BlockPool(
+ C2PlatformAllocatorStore::id_t allocatorId,
+ std::shared_ptr<const C2Component> component,
+ std::shared_ptr<C2BlockPool> *pool) {
+ pool->reset();
+ if (!component) {
+ return C2_BAD_VALUE;
+ }
+ // TODO: support caching block pool along with GetCodec2BlockPool.
+ static std::atomic_int sBlockPoolId(C2BlockPool::PLATFORM_START);
+ std::shared_ptr<C2AllocatorStore> allocatorStore = GetCodec2PlatformAllocatorStore();
+ std::shared_ptr<C2Allocator> allocator;
+ c2_status_t res = C2_NOT_FOUND;
+
+ switch (allocatorId) {
+ case C2PlatformAllocatorStore::ION:
+ res = allocatorStore->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &allocator);
+ if (res == C2_OK) {
+ *pool = std::make_shared<C2PooledBlockPool>(allocator, sBlockPoolId++);
+ if (!*pool) {
+ res = C2_NO_MEMORY;
+ }
+ }
+ break;
+ case C2PlatformAllocatorStore::GRALLOC:
+ // TODO: support gralloc
+ break;
+ default:
+ break;
+ }
+ return res;
+}
+
class C2PlatformComponentStore : public C2ComponentStore {
public:
virtual std::vector<std::shared_ptr<const C2Component::Traits>> listComponents() override;
diff --git a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
index 977cf7b..211c13a 100644
--- a/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
+++ b/media/libstagefright/codec2/vndk/include/C2BufferPriv.h
@@ -71,4 +71,32 @@
const std::shared_ptr<C2Allocator> mAllocator;
};
+class C2PooledBlockPool : public C2BlockPool {
+public:
+ C2PooledBlockPool(const std::shared_ptr<C2Allocator> &allocator, const local_id_t localId);
+
+ virtual ~C2PooledBlockPool() override;
+
+ virtual C2Allocator::id_t getAllocatorId() const override {
+ return mAllocator->getId();
+ }
+
+ virtual local_id_t getLocalId() const override {
+ return mLocalId;
+ }
+
+ virtual c2_status_t fetchLinearBlock(
+ uint32_t capacity,
+ C2MemoryUsage usage,
+ std::shared_ptr<C2LinearBlock> *block /* nonnull */) override;
+
+ // TODO: fetchGraphicBlock, fetchCircularBlock
+private:
+ const std::shared_ptr<C2Allocator> mAllocator;
+ const local_id_t mLocalId;
+
+ class Impl;
+ std::unique_ptr<Impl> mImpl;
+};
+
#endif // STAGEFRIGHT_CODEC2_BUFFER_PRIV_H_
diff --git a/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h b/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
index afa51ee..211ee0c 100644
--- a/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
+++ b/media/libstagefright/codec2/vndk/include/C2PlatformSupport.h
@@ -82,6 +82,23 @@
std::shared_ptr<C2BlockPool> *pool);
/**
+ * Creates a block pool.
+ * \param allocatorId the allocator ID which is used to allocate blocks
+ * \param component the component using the block pool (must be non-null)
+ * \param pool pointer to where the created block pool shall be store on success.
+ * nullptr will be stored here on failure
+ *
+ * \retval C2_OK the operation was successful
+ * \retval C2_BAD_VALUE the component is null
+ * \retval C2_NOT_FOUND if the allocator does not exist
+ * \retval C2_NO_MEMORY not enough memory to create a block pool
+ */
+c2_status_t CreateCodec2BlockPool(
+ C2PlatformAllocatorStore::id_t allocatorId,
+ std::shared_ptr<const C2Component> component,
+ std::shared_ptr<C2BlockPool> *pool);
+
+/**
* Returns the platform component store.
* \retval nullptr if the platform component store could not be obtained
*/
diff --git a/media/libstagefright/codecs/cmds/codec2.cpp b/media/libstagefright/codecs/cmds/codec2.cpp
index 0ec1a77..5558bcf 100644
--- a/media/libstagefright/codecs/cmds/codec2.cpp
+++ b/media/libstagefright/codecs/cmds/codec2.cpp
@@ -93,6 +93,8 @@
sp<IProducerListener> mProducerListener;
+ std::atomic_int mLinearPoolId;
+
std::shared_ptr<C2Allocator> mAllocIon;
std::shared_ptr<C2BlockPool> mLinearPool;
@@ -137,12 +139,13 @@
SimplePlayer::SimplePlayer()
: mListener(new Listener(this)),
mProducerListener(new DummyProducerListener),
+ mLinearPoolId(C2BlockPool::PLATFORM_START),
mComposerClient(new SurfaceComposerClient) {
CHECK_EQ(mComposerClient->initCheck(), (status_t)OK);
std::shared_ptr<C2AllocatorStore> store = GetCodec2PlatformAllocatorStore();
CHECK_EQ(store->fetchAllocator(C2AllocatorStore::DEFAULT_LINEAR, &mAllocIon), C2_OK);
- mLinearPool = std::make_shared<C2BasicLinearBlockPool>(mAllocIon);
+ mLinearPool = std::make_shared<C2PooledBlockPool>(mAllocIon, mLinearPoolId++);
mControl = mComposerClient->createSurface(
String8("A Surface"),
@@ -284,7 +287,7 @@
});
long numFrames = 0;
- mLinearPool.reset(new C2BasicLinearBlockPool(mAllocIon));
+ mLinearPool.reset(new C2PooledBlockPool(mAllocIon, mLinearPoolId++));
for (;;) {
size_t size = 0u;
diff --git a/media/ndk/NdkMediaFormat.cpp b/media/ndk/NdkMediaFormat.cpp
index abcaa0a..9bf450c 100644
--- a/media/ndk/NdkMediaFormat.cpp
+++ b/media/ndk/NdkMediaFormat.cpp
@@ -286,7 +286,13 @@
EXPORT const char* AMEDIAFORMAT_KEY_COLOR_STANDARD = "color-standard";
EXPORT const char* AMEDIAFORMAT_KEY_COLOR_TRANSFER = "color-transfer";
EXPORT const char* AMEDIAFORMAT_KEY_COMPLEXITY = "complexity";
+EXPORT const char* AMEDIAFORMAT_KEY_CSD = "csd";
+EXPORT const char* AMEDIAFORMAT_KEY_CSD_0 = "csd-0";
+EXPORT const char* AMEDIAFORMAT_KEY_CSD_1 = "csd-1";
+EXPORT const char* AMEDIAFORMAT_KEY_CSD_2 = "csd-2";
EXPORT const char* AMEDIAFORMAT_KEY_DISPLAY_CROP = "crop";
+EXPORT const char* AMEDIAFORMAT_KEY_DISPLAY_HEIGHT = "display-height";
+EXPORT const char* AMEDIAFORMAT_KEY_DISPLAY_WIDTH = "display-width";
EXPORT const char* AMEDIAFORMAT_KEY_DURATION = "durationUs";
EXPORT const char* AMEDIAFORMAT_KEY_FLAC_COMPRESSION_LEVEL = "flac-compression-level";
EXPORT const char* AMEDIAFORMAT_KEY_FRAME_RATE = "frame-rate";
@@ -323,6 +329,7 @@
EXPORT const char* AMEDIAFORMAT_KEY_STRIDE = "stride";
EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID = "temporal-layer-id";
EXPORT const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYERING = "ts-schema";
+EXPORT const char* AMEDIAFORMAT_KEY_TIME_US = "timeUs";
EXPORT const char* AMEDIAFORMAT_KEY_TRACK_ID = "track-id";
EXPORT const char* AMEDIAFORMAT_KEY_TRACK_INDEX = "track-index";
EXPORT const char* AMEDIAFORMAT_KEY_WIDTH = "width";
diff --git a/media/ndk/include/media/NdkMediaFormat.h b/media/ndk/include/media/NdkMediaFormat.h
index 464c127..1da9197 100644
--- a/media/ndk/include/media/NdkMediaFormat.h
+++ b/media/ndk/include/media/NdkMediaFormat.h
@@ -100,7 +100,13 @@
extern const char* AMEDIAFORMAT_KEY_COLOR_STANDARD;
extern const char* AMEDIAFORMAT_KEY_COLOR_TRANSFER;
extern const char* AMEDIAFORMAT_KEY_COMPLEXITY;
+extern const char* AMEDIAFORMAT_KEY_CSD;
+extern const char* AMEDIAFORMAT_KEY_CSD_0;
+extern const char* AMEDIAFORMAT_KEY_CSD_1;
+extern const char* AMEDIAFORMAT_KEY_CSD_2;
extern const char* AMEDIAFORMAT_KEY_DISPLAY_CROP;
+extern const char* AMEDIAFORMAT_KEY_DISPLAY_HEIGHT;
+extern const char* AMEDIAFORMAT_KEY_DISPLAY_WIDTH;
extern const char* AMEDIAFORMAT_KEY_DURATION;
extern const char* AMEDIAFORMAT_KEY_FLAC_COMPRESSION_LEVEL;
extern const char* AMEDIAFORMAT_KEY_FRAME_RATE;
@@ -137,6 +143,7 @@
extern const char* AMEDIAFORMAT_KEY_STRIDE;
extern const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYER_ID;
extern const char* AMEDIAFORMAT_KEY_TEMPORAL_LAYERING;
+extern const char* AMEDIAFORMAT_KEY_TIME_US;
extern const char* AMEDIAFORMAT_KEY_TRACK_ID;
extern const char* AMEDIAFORMAT_KEY_TRACK_INDEX;
extern const char* AMEDIAFORMAT_KEY_WIDTH;
diff --git a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
index 1940953..69febc2 100644
--- a/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/MediaControlView2Impl.java
@@ -75,6 +75,13 @@
static final String KEY_STATE_IS_ADVERTISEMENT = "MediaTypeAdvertisement";
static final String EVENT_UPDATE_MEDIA_TYPE_STATUS = "UpdateMediaTypeStatus";
+ // String for receiving command to show subtitle from MediaSession.
+ static final String COMMAND_SHOW_SUBTITLE = "showSubtitle";
+ // String for receiving command to hide subtitle from MediaSession.
+ static final String COMMAND_HIDE_SUBTITLE = "hideSubtitle";
+ // TODO: remove once the implementation is revised
+ public static final String COMMAND_SET_FULLSCREEN = "setFullscreen";
+
private static final int MAX_PROGRESS = 1000;
private static final int DEFAULT_PROGRESS_UPDATE_TIME_MS = 1000;
private static final int REWIND_TIME_MS = 10000;
@@ -743,12 +750,12 @@
if (!mSubtitleIsEnabled) {
mSubtitleButton.setImageDrawable(
mResources.getDrawable(R.drawable.ic_media_subtitle_enabled, null));
- mController.sendCommand(MediaControlView2.COMMAND_SHOW_SUBTITLE, null, null);
+ mController.sendCommand(MediaControlView2Impl.COMMAND_SHOW_SUBTITLE, null, null);
mSubtitleIsEnabled = true;
} else {
mSubtitleButton.setImageDrawable(
mResources.getDrawable(R.drawable.ic_media_subtitle_disabled, null));
- mController.sendCommand(MediaControlView2.COMMAND_HIDE_SUBTITLE, null, null);
+ mController.sendCommand(MediaControlView2Impl.COMMAND_HIDE_SUBTITLE, null, null);
mSubtitleIsEnabled = false;
}
}
@@ -768,7 +775,7 @@
}
Bundle args = new Bundle();
args.putBoolean(ARGUMENT_KEY_FULLSCREEN, isEnteringFullScreen);
- mController.sendCommand(MediaControlView2.COMMAND_SET_FULLSCREEN, args, null);
+ mController.sendCommand(MediaControlView2Impl.COMMAND_SET_FULLSCREEN, args, null);
mIsFullScreen = isEnteringFullScreen;
}
diff --git a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
index d23395c..c3ca057 100644
--- a/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
+++ b/packages/MediaComponents/src/com/android/widget/VideoView2Impl.java
@@ -1001,13 +1001,13 @@
mRouteSessionCallback.onCommand(command, args, receiver);
} else {
switch (command) {
- case MediaControlView2.COMMAND_SHOW_SUBTITLE:
+ case MediaControlView2Impl.COMMAND_SHOW_SUBTITLE:
mInstance.setSubtitleEnabled(true);
break;
- case MediaControlView2.COMMAND_HIDE_SUBTITLE:
+ case MediaControlView2Impl.COMMAND_HIDE_SUBTITLE:
mInstance.setSubtitleEnabled(false);
break;
- case MediaControlView2.COMMAND_SET_FULLSCREEN:
+ case MediaControlView2Impl.COMMAND_SET_FULLSCREEN:
if (mFullScreenRequestListener != null) {
mFullScreenRequestListener.onFullScreenRequest(
mInstance,