media_status_t MPEG2TSExtractor::setMediaCas(const uint8_t* casToken, size_t size) {
HalToken halToken;
halToken.setToExternal((uint8_t*)casToken, size);
sp<ICas> cas = ICas::castFrom(retrieveHalInterface(halToken));
ALOGD("setMediaCas: %p", cas.get());
status_t err = mParser->setMediaCas(cas);
if (err == OK) {
ALOGI("All tracks now have descramblers");
init();
return AMEDIA_OK;
}
return AMEDIA_ERROR_UNKNOWN;
}
status_t MPEG2TSExtractor::findIndexOfSource(const sp<AnotherPacketSource> &impl, size_t *index) {
for (size_t i = 0; i < mSourceImpls.size(); i++) {
if (mSourceImpls[i] == impl) {
*index = i;
return OK;
}
}
return NAME_NOT_FOUND;
}
void MPEG2TSExtractor::addSource(const sp<AnotherPacketSource> &impl) {
size_t index;
if (findIndexOfSource(impl, &index) != OK) {
mSourceImpls.push(impl);
mSyncPoints.push();
}
}
void MPEG2TSExtractor::init() {
bool haveAudio = false;
bool haveVideo = false;
int64_t startTime = ALooper::GetNowUs();
size_t index;
status_t err;
while ((err = feedMore(true )) == OK
|| err == ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED) {
if (haveAudio && haveVideo) {
addSyncPoint_l(mLastSyncEvent);
mLastSyncEvent.reset();
break;
}
if (!haveVideo) {
sp<AnotherPacketSource> impl = mParser->getSource(ATSParser::VIDEO);
if (impl != NULL) {
sp<MetaData> format = impl->getFormat();
if (format != NULL) {
haveVideo = true;
addSource(impl);
if (!isScrambledFormat(*(format.get()))) {
if (findIndexOfSource(impl, &index) == OK) {
mSeekSyncPoints = &mSyncPoints.editItemAt(index);
}
}
}
}
}
if (!haveAudio) {
sp<AnotherPacketSource> impl = mParser->getSource(ATSParser::AUDIO);
if (impl != NULL) {
sp<MetaData> format = impl->getFormat();
if (format != NULL) {
haveAudio = true;
addSource(impl);
if (!isScrambledFormat(*(format.get())) && !haveVideo) {
if (findIndexOfSource(impl, &index) == OK) {
mSeekSyncPoints = &mSyncPoints.editItemAt(index);
}
}
}
}
}
addSyncPoint_l(mLastSyncEvent);
mLastSyncEvent.reset();
if (err == ERROR_DRM_DECRYPT_UNIT_NOT_INITIALIZED) {
ALOGI("stopped parsing scrambled content, "
"haveAudio=%d, haveVideo=%d, elaspedTime=%" PRId64,
haveAudio, haveVideo, ALooper::GetNowUs() - startTime);
return;
}
if (ALooper::GetNowUs() - startTime > 2000000LL) {
break;
}
}
off64_t size;
if (mDataSource->getSize(&size) == OK && (haveAudio || haveVideo)) {
size_t prevSyncSize = 1;
int64_t durationUs = -1;
List<int64_t> durations;
while (feedMore() == OK
&& ALooper::GetNowUs() - startTime <= 2000000LL) {
if (mSeekSyncPoints->size() > prevSyncSize) {
prevSyncSize = mSeekSyncPoints->size();
int64_t diffUs = mSeekSyncPoints->keyAt(prevSyncSize - 1)
- mSeekSyncPoints->keyAt(0);
off64_t diffOffset = mSeekSyncPoints->valueAt(prevSyncSize - 1)
- mSeekSyncPoints->valueAt(0);
int64_t currentDurationUs = size * diffUs / diffOffset;
durations.push_back(currentDurationUs);
if (durations.size() > 5) {
durations.erase(durations.begin());
int64_t min = *durations.begin();
int64_t max = *durations.begin();
for (auto duration : durations) {
if (min > duration) {
min = duration;
}
if (max < duration) {
max = duration;
}
}
if (max - min < 500 * 1000) {
durationUs = currentDurationUs;
break;
}
}
}
}
bool found = false;
for (int i = 0; i < ATSParser::NUM_SOURCE_TYPES; ++i) {
ATSParser::SourceType type = static_cast<ATSParser::SourceType>(i);
sp<AnotherPacketSource> impl = mParser->getSource(type);
if (impl == NULL) {
continue;
}
int64_t trackDurationUs = durationUs;
status_t err;
int64_t bufferedDurationUs = impl->getBufferedDurationUs(&err);
if (err == ERROR_END_OF_STREAM) {
trackDurationUs = bufferedDurationUs;
}
if (trackDurationUs > 0) {
ALOGV("[SourceType%d] durationUs=%" PRId64 "", type, trackDurationUs);
const sp<MetaData> meta = impl->getFormat();
meta->setInt64(kKeyDuration, trackDurationUs);
impl->setFormat(meta);
found = true;
}
}
if (!found) {
estimateDurationsFromTimesUsAtEnd();
}
}
ALOGI("haveAudio=%d, haveVideo=%d, elaspedTime=%" PRId64,
haveAudio, haveVideo, ALooper::GetNowUs() - startTime);
}