summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
Diffstat (limited to 'media')
-rw-r--r--media/libmedia/AudioRecord.cpp10
-rw-r--r--media/libmedia/AudioSystem.cpp3
-rw-r--r--media/libmedia/AudioTrack.cpp33
-rw-r--r--media/libmedia/IAudioPolicyService.cpp5
-rw-r--r--media/libmedia/ICrypto.cpp24
-rw-r--r--media/libmediaplayerservice/Crypto.cpp5
-rw-r--r--media/libmediaplayerservice/Crypto.h2
-rw-r--r--media/libmediaplayerservice/Drm.cpp66
-rw-r--r--media/libmediaplayerservice/Drm.h9
-rw-r--r--media/libstagefright/MPEG4Extractor.cpp10
-rw-r--r--media/libstagefright/MediaClock.cpp5
-rw-r--r--media/libstagefright/MediaCodec.cpp20
-rw-r--r--media/libstagefright/httplive/LiveSession.cpp147
-rw-r--r--media/libstagefright/httplive/LiveSession.h3
-rw-r--r--media/libstagefright/httplive/PlaylistFetcher.cpp98
-rw-r--r--media/libstagefright/httplive/PlaylistFetcher.h5
-rw-r--r--media/libstagefright/mpeg2ts/AnotherPacketSource.cpp4
-rw-r--r--media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp17
-rw-r--r--media/libstagefright/omx/SoftOMXPlugin.cpp2
19 files changed, 344 insertions, 124 deletions
diff --git a/media/libmedia/AudioRecord.cpp b/media/libmedia/AudioRecord.cpp
index 100a914..f4cdde2 100644
--- a/media/libmedia/AudioRecord.cpp
+++ b/media/libmedia/AudioRecord.cpp
@@ -189,13 +189,9 @@ status_t AudioRecord::set(
}
// validate parameters
- if (!audio_is_valid_format(format)) {
- ALOGE("Invalid format %#x", format);
- return BAD_VALUE;
- }
- // Temporary restriction: AudioFlinger currently supports 16-bit PCM only
- if (format != AUDIO_FORMAT_PCM_16_BIT) {
- ALOGE("Format %#x is not supported", format);
+ // AudioFlinger capture only supports linear PCM
+ if (!audio_is_valid_format(format) || !audio_is_linear_pcm(format)) {
+ ALOGE("Format %#x is not linear pcm", format);
return BAD_VALUE;
}
mFormat = format;
diff --git a/media/libmedia/AudioSystem.cpp b/media/libmedia/AudioSystem.cpp
index 9150a94..8db72ee 100644
--- a/media/libmedia/AudioSystem.cpp
+++ b/media/libmedia/AudioSystem.cpp
@@ -658,13 +658,14 @@ status_t AudioSystem::getOutputForAttr(const audio_attributes_t *attr,
audio_format_t format,
audio_channel_mask_t channelMask,
audio_output_flags_t flags,
+ audio_port_handle_t selectedDeviceId,
const audio_offload_info_t *offloadInfo)
{
const sp<IAudioPolicyService>& aps = AudioSystem::get_audio_policy_service();
if (aps == 0) return NO_INIT;
return aps->getOutputForAttr(attr, output, session, stream,
samplingRate, format, channelMask,
- flags, offloadInfo);
+ flags, selectedDeviceId, offloadInfo);
}
status_t AudioSystem::startOutput(audio_io_handle_t output,
diff --git a/media/libmedia/AudioTrack.cpp b/media/libmedia/AudioTrack.cpp
index ce30c62..9e9ec5b 100644
--- a/media/libmedia/AudioTrack.cpp
+++ b/media/libmedia/AudioTrack.cpp
@@ -121,7 +121,8 @@ AudioTrack::AudioTrack()
mIsTimed(false),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT),
- mPausedPosition(0)
+ mPausedPosition(0),
+ mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
{
mAttributes.content_type = AUDIO_CONTENT_TYPE_UNKNOWN;
mAttributes.usage = AUDIO_USAGE_UNKNOWN;
@@ -149,7 +150,8 @@ AudioTrack::AudioTrack(
mIsTimed(false),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT),
- mPausedPosition(0)
+ mPausedPosition(0),
+ mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
{
mStatus = set(streamType, sampleRate, format, channelMask,
frameCount, flags, cbf, user, notificationFrames,
@@ -177,7 +179,8 @@ AudioTrack::AudioTrack(
mIsTimed(false),
mPreviousPriority(ANDROID_PRIORITY_NORMAL),
mPreviousSchedulingGroup(SP_DEFAULT),
- mPausedPosition(0)
+ mPausedPosition(0),
+ mSelectedDeviceId(AUDIO_PORT_HANDLE_NONE)
{
mStatus = set(streamType, sampleRate, format, channelMask,
0 /*frameCount*/, flags, cbf, user, notificationFrames,
@@ -928,6 +931,21 @@ audio_io_handle_t AudioTrack::getOutput() const
return mOutput;
}
+status_t AudioTrack::setOutputDevice(audio_port_handle_t deviceId) {
+ AutoMutex lock(mLock);
+ if (mSelectedDeviceId != deviceId) {
+ mSelectedDeviceId = deviceId;
+ return restoreTrack_l("setOutputDevice() restart");
+ } else {
+ return NO_ERROR;
+ }
+}
+
+audio_port_handle_t AudioTrack::getOutputDevice() {
+ AutoMutex lock(mLock);
+ return mSelectedDeviceId;
+}
+
status_t AudioTrack::attachAuxEffect(int effectId)
{
AutoMutex lock(mLock);
@@ -960,11 +978,12 @@ status_t AudioTrack::createTrack_l()
audio_io_handle_t output;
audio_stream_type_t streamType = mStreamType;
audio_attributes_t *attr = (mStreamType == AUDIO_STREAM_DEFAULT) ? &mAttributes : NULL;
- status_t status = AudioSystem::getOutputForAttr(attr, &output,
- (audio_session_t)mSessionId, &streamType,
- mSampleRate, mFormat, mChannelMask,
- mFlags, mOffloadInfo);
+ status_t status;
+ status = AudioSystem::getOutputForAttr(attr, &output,
+ (audio_session_t)mSessionId, &streamType,
+ mSampleRate, mFormat, mChannelMask,
+ mFlags, mSelectedDeviceId, mOffloadInfo);
if (status != NO_ERROR || output == AUDIO_IO_HANDLE_NONE) {
ALOGE("Could not get audio output for session %d, stream type %d, usage %d, sample rate %u, format %#x,"
diff --git a/media/libmedia/IAudioPolicyService.cpp b/media/libmedia/IAudioPolicyService.cpp
index 39374d8..4b86532 100644
--- a/media/libmedia/IAudioPolicyService.cpp
+++ b/media/libmedia/IAudioPolicyService.cpp
@@ -173,6 +173,7 @@ public:
audio_format_t format,
audio_channel_mask_t channelMask,
audio_output_flags_t flags,
+ audio_port_handle_t selectedDeviceId,
const audio_offload_info_t *offloadInfo)
{
Parcel data, reply;
@@ -208,6 +209,7 @@ public:
data.writeInt32(static_cast <uint32_t>(format));
data.writeInt32(channelMask);
data.writeInt32(static_cast <uint32_t>(flags));
+ data.writeInt32(selectedDeviceId);
// hasOffloadInfo
if (offloadInfo == NULL) {
data.writeInt32(0);
@@ -815,6 +817,7 @@ status_t BnAudioPolicyService::onTransact(
audio_channel_mask_t channelMask = data.readInt32();
audio_output_flags_t flags =
static_cast <audio_output_flags_t>(data.readInt32());
+ audio_port_handle_t selectedDeviceId = data.readInt32();
bool hasOffloadInfo = data.readInt32() != 0;
audio_offload_info_t offloadInfo;
if (hasOffloadInfo) {
@@ -824,7 +827,7 @@ status_t BnAudioPolicyService::onTransact(
status_t status = getOutputForAttr(hasAttributes ? &attr : NULL,
&output, session, &stream,
samplingRate, format, channelMask,
- flags, hasOffloadInfo ? &offloadInfo : NULL);
+ flags, selectedDeviceId, hasOffloadInfo ? &offloadInfo : NULL);
reply->writeInt32(status);
reply->writeInt32(output);
reply->writeInt32(stream);
diff --git a/media/libmedia/ICrypto.cpp b/media/libmedia/ICrypto.cpp
index c26c5bf..23308c1 100644
--- a/media/libmedia/ICrypto.cpp
+++ b/media/libmedia/ICrypto.cpp
@@ -19,6 +19,7 @@
#include <utils/Log.h>
#include <binder/Parcel.h>
+#include <binder/IMemory.h>
#include <media/ICrypto.h>
#include <media/stagefright/MediaErrors.h>
#include <media/stagefright/foundation/ADebug.h>
@@ -97,7 +98,7 @@ struct BpCrypto : public BpInterface<ICrypto> {
const uint8_t key[16],
const uint8_t iv[16],
CryptoPlugin::Mode mode,
- const void *srcPtr,
+ const sp<IMemory> &sharedBuffer, size_t offset,
const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
void *dstPtr,
AString *errorDetailMsg) {
@@ -126,7 +127,8 @@ struct BpCrypto : public BpInterface<ICrypto> {
}
data.writeInt32(totalSize);
- data.write(srcPtr, totalSize);
+ data.writeStrongBinder(IInterface::asBinder(sharedBuffer));
+ data.writeInt32(offset);
data.writeInt32(numSubSamples);
data.write(subSamples, sizeof(CryptoPlugin::SubSample) * numSubSamples);
@@ -245,8 +247,9 @@ status_t BnCrypto::onTransact(
data.read(iv, sizeof(iv));
size_t totalSize = data.readInt32();
- void *srcData = malloc(totalSize);
- data.read(srcData, totalSize);
+ sp<IMemory> sharedBuffer =
+ interface_cast<IMemory>(data.readStrongBinder());
+ int32_t offset = data.readInt32();
int32_t numSubSamples = data.readInt32();
@@ -265,15 +268,21 @@ status_t BnCrypto::onTransact(
}
AString errorDetailMsg;
- ssize_t result = decrypt(
+ ssize_t result;
+
+ if (offset + totalSize > sharedBuffer->size()) {
+ result = -EINVAL;
+ } else {
+ result = decrypt(
secure,
key,
iv,
mode,
- srcData,
+ sharedBuffer, offset,
subSamples, numSubSamples,
dstPtr,
&errorDetailMsg);
+ }
reply->writeInt32(result);
@@ -294,9 +303,6 @@ status_t BnCrypto::onTransact(
delete[] subSamples;
subSamples = NULL;
- free(srcData);
- srcData = NULL;
-
return OK;
}
diff --git a/media/libmediaplayerservice/Crypto.cpp b/media/libmediaplayerservice/Crypto.cpp
index 8ee7c0b..e768772 100644
--- a/media/libmediaplayerservice/Crypto.cpp
+++ b/media/libmediaplayerservice/Crypto.cpp
@@ -22,6 +22,7 @@
#include "Crypto.h"
+#include <binder/IMemory.h>
#include <media/hardware/CryptoAPI.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/foundation/AString.h>
@@ -238,7 +239,7 @@ ssize_t Crypto::decrypt(
const uint8_t key[16],
const uint8_t iv[16],
CryptoPlugin::Mode mode,
- const void *srcPtr,
+ const sp<IMemory> &sharedBuffer, size_t offset,
const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
void *dstPtr,
AString *errorDetailMsg) {
@@ -252,6 +253,8 @@ ssize_t Crypto::decrypt(
return -EINVAL;
}
+ const void *srcPtr = static_cast<uint8_t *>(sharedBuffer->pointer()) + offset;
+
return mPlugin->decrypt(
secure, key, iv, mode, srcPtr, subSamples, numSubSamples, dstPtr,
errorDetailMsg);
diff --git a/media/libmediaplayerservice/Crypto.h b/media/libmediaplayerservice/Crypto.h
index 0037c2e..d5f3c50 100644
--- a/media/libmediaplayerservice/Crypto.h
+++ b/media/libmediaplayerservice/Crypto.h
@@ -52,7 +52,7 @@ struct Crypto : public BnCrypto {
const uint8_t key[16],
const uint8_t iv[16],
CryptoPlugin::Mode mode,
- const void *srcPtr,
+ const sp<IMemory> &sharedBuffer, size_t offset,
const CryptoPlugin::SubSample *subSamples, size_t numSubSamples,
void *dstPtr,
AString *errorDetailMsg);
diff --git a/media/libmediaplayerservice/Drm.cpp b/media/libmediaplayerservice/Drm.cpp
index 49e01d1..62cf3e5 100644
--- a/media/libmediaplayerservice/Drm.cpp
+++ b/media/libmediaplayerservice/Drm.cpp
@@ -136,22 +136,54 @@ void Drm::sendEvent(DrmPlugin::EventType eventType, int extra,
if (listener != NULL) {
Parcel obj;
- if (sessionId && sessionId->size()) {
- obj.writeInt32(sessionId->size());
- obj.write(sessionId->array(), sessionId->size());
- } else {
- obj.writeInt32(0);
- }
+ writeByteArray(obj, sessionId);
+ writeByteArray(obj, data);
- if (data && data->size()) {
- obj.writeInt32(data->size());
- obj.write(data->array(), data->size());
- } else {
- obj.writeInt32(0);
+ Mutex::Autolock lock(mNotifyLock);
+ listener->notify(eventType, extra, &obj);
+ }
+}
+
+void Drm::sendExpirationUpdate(Vector<uint8_t> const *sessionId,
+ int64_t expiryTimeInMS)
+{
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Parcel obj;
+ writeByteArray(obj, sessionId);
+ obj.writeInt64(expiryTimeInMS);
+
+ Mutex::Autolock lock(mNotifyLock);
+ listener->notify(DrmPlugin::kDrmPluginEventExpirationUpdate, 0, &obj);
+ }
+}
+
+void Drm::sendKeysChange(Vector<uint8_t> const *sessionId,
+ Vector<DrmPlugin::KeyStatus> const *keyStatusList,
+ bool hasNewUsableKey)
+{
+ mEventLock.lock();
+ sp<IDrmClient> listener = mListener;
+ mEventLock.unlock();
+
+ if (listener != NULL) {
+ Parcel obj;
+ writeByteArray(obj, sessionId);
+
+ size_t nkeys = keyStatusList->size();
+ obj.writeInt32(keyStatusList->size());
+ for (size_t i = 0; i < nkeys; ++i) {
+ const DrmPlugin::KeyStatus *keyStatus = &keyStatusList->itemAt(i);
+ writeByteArray(obj, &keyStatus->mKeyId);
+ obj.writeInt32(keyStatus->mType);
}
+ obj.writeInt32(hasNewUsableKey);
Mutex::Autolock lock(mNotifyLock);
- listener->notify(eventType, extra, &obj);
+ listener->notify(DrmPlugin::kDrmPluginEventKeysChange, 0, &obj);
}
}
@@ -756,4 +788,14 @@ void Drm::binderDied(const wp<IBinder> &the_late_who)
closeFactory();
}
+void Drm::writeByteArray(Parcel &obj, Vector<uint8_t> const *array)
+{
+ if (array && array->size()) {
+ obj.writeInt32(array->size());
+ obj.write(array->array(), array->size());
+ } else {
+ obj.writeInt32(0);
+ }
+}
+
} // namespace android
diff --git a/media/libmediaplayerservice/Drm.h b/media/libmediaplayerservice/Drm.h
index 7e8f246..1591738 100644
--- a/media/libmediaplayerservice/Drm.h
+++ b/media/libmediaplayerservice/Drm.h
@@ -133,6 +133,13 @@ struct Drm : public BnDrm,
Vector<uint8_t> const *sessionId,
Vector<uint8_t> const *data);
+ virtual void sendExpirationUpdate(Vector<uint8_t> const *sessionId,
+ int64_t expiryTimeInMS);
+
+ virtual void sendKeysChange(Vector<uint8_t> const *sessionId,
+ Vector<DrmPlugin::KeyStatus> const *keyStatusList,
+ bool hasNewUsableKey);
+
virtual void binderDied(const wp<IBinder> &the_late_who);
private:
@@ -157,7 +164,7 @@ private:
void findFactoryForScheme(const uint8_t uuid[16]);
bool loadLibraryForScheme(const String8 &path, const uint8_t uuid[16]);
void closeFactory();
-
+ void writeByteArray(Parcel &obj, Vector<uint8_t> const *array);
DISALLOW_EVIL_CONSTRUCTORS(Drm);
};
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 87d14b7..f7fa2b6 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -1178,6 +1178,11 @@ status_t MPEG4Extractor::parseChunk(off64_t *offset, int depth) {
return ERROR_IO;
}
+ if (!timescale) {
+ ALOGE("timescale should not be ZERO.");
+ return ERROR_MALFORMED;
+ }
+
mLastTrack->timescale = ntohl(timescale);
// 14496-12 says all ones means indeterminate, but some files seem to use
@@ -2702,6 +2707,11 @@ status_t MPEG4Extractor::verifyTrack(Track *track) {
return ERROR_MALFORMED;
}
+ if (track->timescale == 0) {
+ ALOGE("timescale invalid.");
+ return ERROR_MALFORMED;
+ }
+
return OK;
}
diff --git a/media/libstagefright/MediaClock.cpp b/media/libstagefright/MediaClock.cpp
index 433f555..2641e4e 100644
--- a/media/libstagefright/MediaClock.cpp
+++ b/media/libstagefright/MediaClock.cpp
@@ -92,6 +92,11 @@ void MediaClock::setPlaybackRate(float rate) {
mPlaybackRate = rate;
}
+float MediaClock::getPlaybackRate() const {
+ Mutex::Autolock autoLock(mLock);
+ return mPlaybackRate;
+}
+
status_t MediaClock::getMediaTime(
int64_t realUs, int64_t *outMediaUs, bool allowPastMaxTime) const {
if (outMediaUs == NULL) {
diff --git a/media/libstagefright/MediaCodec.cpp b/media/libstagefright/MediaCodec.cpp
index 0597f1d..8186f63 100644
--- a/media/libstagefright/MediaCodec.cpp
+++ b/media/libstagefright/MediaCodec.cpp
@@ -22,7 +22,9 @@
#include "include/SoftwareRenderer.h"
#include <binder/IBatteryStats.h>
+#include <binder/IMemory.h>
#include <binder/IServiceManager.h>
+#include <binder/MemoryDealer.h>
#include <gui/Surface.h>
#include <media/ICrypto.h>
#include <media/stagefright/foundation/ABuffer.h>
@@ -969,6 +971,17 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
size_t numBuffers = portDesc->countBuffers();
+ size_t totalSize = 0;
+ for (size_t i = 0; i < numBuffers; ++i) {
+ if (portIndex == kPortIndexInput && mCrypto != NULL) {
+ totalSize += portDesc->bufferAt(i)->capacity();
+ }
+ }
+
+ if (totalSize) {
+ mDealer = new MemoryDealer(totalSize, "MediaCodec");
+ }
+
for (size_t i = 0; i < numBuffers; ++i) {
BufferInfo info;
info.mBufferID = portDesc->bufferIDAt(i);
@@ -976,8 +989,10 @@ void MediaCodec::onMessageReceived(const sp<AMessage> &msg) {
info.mData = portDesc->bufferAt(i);
if (portIndex == kPortIndexInput && mCrypto != NULL) {
+ sp<IMemory> mem = mDealer->allocate(info.mData->capacity());
info.mEncryptedData =
- new ABuffer(info.mData->capacity());
+ new ABuffer(mem->pointer(), info.mData->capacity());
+ info.mSharedEncryptedBuffer = mem;
}
buffers->push_back(info);
@@ -1953,7 +1968,8 @@ status_t MediaCodec::onQueueInputBuffer(const sp<AMessage> &msg) {
key,
iv,
mode,
- info->mEncryptedData->base() + offset,
+ info->mSharedEncryptedBuffer,
+ offset,
subSamples,
numSubSamples,
info->mData->base(),
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 2d93152..26f8da1 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -141,6 +141,21 @@ const char *LiveSession::getKeyForStream(StreamType type) {
return NULL;
}
+//static
+const char *LiveSession::getNameForStream(StreamType type) {
+ switch (type) {
+ case STREAMTYPE_VIDEO:
+ return "video";
+ case STREAMTYPE_AUDIO:
+ return "audio";
+ case STREAMTYPE_SUBTITLES:
+ return "subs";
+ default:
+ break;
+ }
+ return "unknown";
+}
+
LiveSession::LiveSession(
const sp<AMessage> &notify, uint32_t flags,
const sp<IMediaHTTPService> &httpService)
@@ -192,7 +207,11 @@ status_t LiveSession::dequeueAccessUnit(
status_t finalResult = OK;
sp<AnotherPacketSource> packetSource = mPacketSources.valueFor(stream);
- ssize_t idx = typeToIndex(stream);
+ ssize_t streamIdx = typeToIndex(stream);
+ if (streamIdx < 0) {
+ return INVALID_VALUE;
+ }
+ const char *streamStr = getNameForStream(stream);
// Do not let client pull data if we don't have data packets yet.
// We might only have a format discontinuity queued without data.
// When NuPlayerDecoder dequeues the format discontinuity, it will
@@ -200,6 +219,9 @@ status_t LiveSession::dequeueAccessUnit(
// thinks it can do seamless change, so will not shutdown decoder.
// When the actual format arrives, it can't handle it and get stuck.
if (!packetSource->hasDataBufferAvailable(&finalResult)) {
+ ALOGV("[%s] dequeueAccessUnit: no buffer available (finalResult=%d)",
+ streamStr, finalResult);
+
if (finalResult == OK) {
return -EAGAIN;
} else {
@@ -212,25 +234,6 @@ status_t LiveSession::dequeueAccessUnit(
status_t err = packetSource->dequeueAccessUnit(accessUnit);
- size_t streamIdx;
- const char *streamStr;
- switch (stream) {
- case STREAMTYPE_AUDIO:
- streamIdx = kAudioIndex;
- streamStr = "audio";
- break;
- case STREAMTYPE_VIDEO:
- streamIdx = kVideoIndex;
- streamStr = "video";
- break;
- case STREAMTYPE_SUBTITLES:
- streamIdx = kSubtitleIndex;
- streamStr = "subs";
- break;
- default:
- TRESPASS();
- }
-
StreamItem& strm = mStreams[streamIdx];
if (err == INFO_DISCONTINUITY) {
// adaptive streaming, discontinuities in the playlist
@@ -249,9 +252,10 @@ status_t LiveSession::dequeueAccessUnit(
} else if (err == OK) {
if (stream == STREAMTYPE_AUDIO || stream == STREAMTYPE_VIDEO) {
- int64_t timeUs;
+ int64_t timeUs, originalTimeUs;
int32_t discontinuitySeq = 0;
CHECK((*accessUnit)->meta()->findInt64("timeUs", &timeUs));
+ originalTimeUs = timeUs;
(*accessUnit)->meta()->findInt32("discontinuitySeq", &discontinuitySeq);
if (discontinuitySeq > (int32_t) strm.mCurDiscontinuitySeq) {
int64_t offsetTimeUs;
@@ -303,7 +307,8 @@ status_t LiveSession::dequeueAccessUnit(
timeUs += mDiscontinuityOffsetTimesUs.valueFor(discontinuitySeq);
}
- ALOGV("[%s] read buffer at time %" PRId64 " us", streamStr, timeUs);
+ ALOGV("[%s] dequeueAccessUnit: time %lld us, original %lld us",
+ streamStr, (long long)timeUs, (long long)originalTimeUs);
(*accessUnit)->meta()->setInt64("timeUs", timeUs);
mLastDequeuedTimeUs = timeUs;
mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
@@ -409,7 +414,7 @@ bool LiveSession::checkSwitchProgress(
if (lastDequeueMeta == NULL) {
// this means we don't have enough cushion, try again later
ALOGV("[%s] up switching failed due to insufficient buffer",
- stream == STREAMTYPE_AUDIO ? "audio" : "video");
+ getNameForStream(stream));
return false;
}
} else {
@@ -428,7 +433,7 @@ bool LiveSession::checkSwitchProgress(
if (firstNewMeta[i] == NULL) {
HLSTime dequeueTime(lastDequeueMeta);
ALOGV("[%s] dequeue time (%d, %lld) past start time",
- stream == STREAMTYPE_AUDIO ? "audio" : "video",
+ getNameForStream(stream),
dequeueTime.mSeq, (long long) dequeueTime.mTimeUs);
return false;
}
@@ -493,16 +498,15 @@ void LiveSession::onMessageReceived(const sp<AMessage> &msg) {
case kWhatSeek:
{
- sp<AReplyToken> seekReplyID;
- CHECK(msg->senderAwaitsResponse(&seekReplyID));
- mSeekReplyID = seekReplyID;
- mSeekReply = new AMessage;
-
- status_t err = onSeek(msg);
-
- if (err != OK) {
+ if (mReconfigurationInProgress) {
msg->post(50000);
+ break;
}
+
+ CHECK(msg->senderAwaitsResponse(&mSeekReplyID));
+ mSeekReply = new AMessage;
+
+ onSeek(msg);
break;
}
@@ -525,6 +529,11 @@ void LiveSession::onMessageReceived(const sp<AMessage> &msg) {
break;
}
+ ALOGV("fetcher-%d %s",
+ mFetcherInfos[index].mFetcher->getFetcherID(),
+ what == PlaylistFetcher::kWhatPaused ?
+ "paused" : "stopped");
+
if (what == PlaylistFetcher::kWhatStopped) {
mFetcherLooper->unregisterHandler(
mFetcherInfos[index].mFetcher->id());
@@ -544,6 +553,7 @@ void LiveSession::onMessageReceived(const sp<AMessage> &msg) {
if (--mContinuationCounter == 0) {
mContinuation->post();
}
+ ALOGV("%zu fetcher(s) left", mContinuationCounter);
}
break;
}
@@ -636,6 +646,9 @@ void LiveSession::onMessageReceived(const sp<AMessage> &msg) {
int32_t switchGeneration;
CHECK(msg->findInt32("switchGeneration", &switchGeneration));
+ ALOGV("kWhatStartedAt: switchGen=%d, mSwitchGen=%d",
+ switchGeneration, mSwitchGeneration);
+
if (switchGeneration != mSwitchGeneration) {
break;
}
@@ -667,6 +680,7 @@ void LiveSession::onMessageReceived(const sp<AMessage> &msg) {
if (checkSwitchProgress(stopParams, delayUs, &needResumeUntil)) {
// playback time hasn't passed startAt time
if (!needResumeUntil) {
+ ALOGV("finish switch");
for (size_t i = 0; i < kMaxStreams; ++i) {
if ((mSwapMask & indexToType(i))
&& uri == mStreams[i].mNewUri) {
@@ -682,6 +696,7 @@ void LiveSession::onMessageReceived(const sp<AMessage> &msg) {
// Resume fetcher for the original variant; the resumed fetcher should
// continue until the timestamps found in msg, which is stored by the
// new fetcher to indicate where the new variant has started buffering.
+ ALOGV("finish switch with resumeUntilAsync");
for (size_t i = 0; i < mFetcherInfos.size(); i++) {
const FetcherInfo &info = mFetcherInfos.valueAt(i);
if (info.mToBeRemoved) {
@@ -693,8 +708,10 @@ void LiveSession::onMessageReceived(const sp<AMessage> &msg) {
// playback time passed startAt time
if (switchUp) {
// if switching up, cancel and retry if condition satisfies again
+ ALOGV("cancel up switch because we're too late");
cancelBandwidthSwitch(true /* resume */);
} else {
+ ALOGV("retry down switch at next sample");
resumeFetcher(uri, mSwapMask, -1, true /* newUri */);
}
}
@@ -933,7 +950,8 @@ sp<PlaylistFetcher> LiveSession::addFetcher(const char *uri) {
notify->setInt32("switchGeneration", mSwitchGeneration);
FetcherInfo info;
- info.mFetcher = new PlaylistFetcher(notify, this, uri, mSubtitleGeneration);
+ info.mFetcher = new PlaylistFetcher(
+ notify, this, uri, mCurBandwidthIndex, mSubtitleGeneration);
info.mDurationUs = -1ll;
info.mToBeRemoved = false;
info.mToBeResumed = false;
@@ -1167,9 +1185,13 @@ bool LiveSession::resumeFetcher(
}
if (resume) {
- ALOGV("resuming fetcher %s, timeUs %lld", uri.c_str(), (long long)timeUs);
+ sp<PlaylistFetcher> &fetcher = mFetcherInfos.editValueAt(index).mFetcher;
SeekMode seekMode = newUri ? kSeekModeNextSample : kSeekModeExactPosition;
- mFetcherInfos.editValueAt(index).mFetcher->startAsync(
+
+ ALOGV("resuming fetcher-%d, timeUs=%lld, seekMode=%d",
+ fetcher->getFetcherID(), (long long)timeUs, seekMode);
+
+ fetcher->startAsync(
sources[kAudioIndex],
sources[kVideoIndex],
sources[kSubtitleIndex],
@@ -1349,16 +1371,10 @@ HLSTime LiveSession::latestMediaSegmentStartTime() const {
return audioTime < videoTime ? videoTime : audioTime;
}
-status_t LiveSession::onSeek(const sp<AMessage> &msg) {
+void LiveSession::onSeek(const sp<AMessage> &msg) {
int64_t timeUs;
CHECK(msg->findInt64("timeUs", &timeUs));
-
- if (!mReconfigurationInProgress) {
- changeConfiguration(timeUs);
- return OK;
- } else {
- return -EWOULDBLOCK;
- }
+ changeConfiguration(timeUs);
}
status_t LiveSession::getDuration(int64_t *durationUs) const {
@@ -1406,6 +1422,9 @@ status_t LiveSession::selectTrack(size_t index, bool select) {
return INVALID_OPERATION;
}
+ ALOGV("selectTrack: index=%zu, select=%d, mSubtitleGen=%d++",
+ index, select, mSubtitleGeneration);
+
++mSubtitleGeneration;
status_t err = mPlaylist->selectTrack(index, select);
if (err == OK) {
@@ -1426,6 +1445,9 @@ ssize_t LiveSession::getSelectedTrack(media_track_type type) const {
void LiveSession::changeConfiguration(
int64_t timeUs, ssize_t bandwidthIndex, bool pickTrack) {
+ ALOGV("changeConfiguration: timeUs=%lld us, bwIndex=%zd, pickTrack=%d",
+ (long long)timeUs, bandwidthIndex, pickTrack);
+
cancelBandwidthSwitch();
CHECK(!mReconfigurationInProgress);
@@ -1478,6 +1500,7 @@ void LiveSession::changeConfiguration(
}
if (discardFetcher) {
+ ALOGV("discarding fetcher-%d", fetcher->getFetcherID());
fetcher->stopAsync();
} else {
float threshold = -1.0f; // always finish fetching by default
@@ -1490,8 +1513,8 @@ void LiveSession::changeConfiguration(
mOrigBandwidthIndex, mCurBandwidthIndex);
}
- ALOGV("Pausing with threshold %.3f", threshold);
-
+ ALOGV("pausing fetcher-%d, threshold=%.2f",
+ fetcher->getFetcherID(), threshold);
fetcher->pauseAsync(threshold);
}
}
@@ -1526,6 +1549,8 @@ void LiveSession::changeConfiguration(
}
void LiveSession::onChangeConfiguration(const sp<AMessage> &msg) {
+ ALOGV("onChangeConfiguration");
+
if (!mReconfigurationInProgress) {
int32_t pickTrack = 0;
msg->findInt32("pickTrack", &pickTrack);
@@ -1536,6 +1561,8 @@ void LiveSession::onChangeConfiguration(const sp<AMessage> &msg) {
}
void LiveSession::onChangeConfiguration2(const sp<AMessage> &msg) {
+ ALOGV("onChangeConfiguration2");
+
mContinuation.clear();
// All fetchers are either suspended or have been removed now.
@@ -1670,6 +1697,11 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
mRealTimeBaseUs = ALooper::GetNowUs() - timeUs;
}
+ ALOGV("onChangeConfiguration3: timeUs=%lld, switching=%d, pickTrack=%d, "
+ "mStreamMask=0x%x, mNewStreamMask=0x%x, mSwapMask=0x%x",
+ (long long)timeUs, switching, pickTrack,
+ mStreamMask, mNewStreamMask, mSwapMask);
+
for (size_t i = 0; i < kMaxStreams; ++i) {
if (streamMask & indexToType(i)) {
if (switching) {
@@ -1687,6 +1719,9 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
for (size_t i = 0; i < mFetcherInfos.size(); ++i) {
const AString &uri = mFetcherInfos.keyAt(i);
if (!resumeFetcher(uri, resumeMask, timeUs)) {
+ ALOGV("marking fetcher-%d to be removed",
+ mFetcherInfos[i].mFetcher->getFetcherID());
+
mFetcherInfos.editValueAt(i).mToBeRemoved = true;
}
}
@@ -1776,6 +1811,14 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
}
}
+ ALOGV("[fetcher-%d] startAsync: startTimeUs %lld mLastSeekTimeUs %lld "
+ "segmentStartTimeUs %lld seekMode %d",
+ fetcher->getFetcherID(),
+ (long long)startTime.mTimeUs,
+ (long long)mLastSeekTimeUs,
+ (long long)startTime.getSegmentTimeUs(true /* midpoint */),
+ seekMode);
+
// Set the target segment start time to the middle point of the
// segment where the last sample was.
// This gives a better guess if segments of the two variants are not
@@ -1795,7 +1838,6 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
// All fetchers have now been started, the configuration change
// has completed.
- ALOGV("XXX configuration change completed.");
mReconfigurationInProgress = false;
if (switching) {
mSwitchInProgress = true;
@@ -1804,13 +1846,16 @@ void LiveSession::onChangeConfiguration3(const sp<AMessage> &msg) {
mOrigBandwidthIndex = mCurBandwidthIndex;
}
+ ALOGV("onChangeConfiguration3: mSwitchInProgress %d, mStreamMask 0x%x",
+ mSwitchInProgress, mStreamMask);
+
if (mDisconnectReplyID != NULL) {
finishDisconnect();
}
}
void LiveSession::swapPacketSource(StreamType stream) {
- ALOGV("swapPacketSource: stream = %d", stream);
+ ALOGV("[%s] swapPacketSource", getNameForStream(stream));
// transfer packets from source2 to source
sp<AnotherPacketSource> &aps = mPacketSources.editValueFor(stream);
@@ -1858,7 +1903,7 @@ void LiveSession::tryToFinishBandwidthSwitch(const AString &oldUri) {
mFetcherInfos.editValueAt(index).mFetcher->stopAsync(false /* clear */);
- ALOGV("tryToFinishBandwidthSwitch: mSwapMask=%x", mSwapMask);
+ ALOGV("tryToFinishBandwidthSwitch: mSwapMask=0x%x", mSwapMask);
if (mSwapMask != 0) {
return;
}
@@ -1983,7 +2028,7 @@ void LiveSession::cancelBandwidthSwitch(bool resume) {
}
ALOGI("#### Canceled Bandwidth Switch: %zd => %zd",
- mCurBandwidthIndex, mOrigBandwidthIndex);
+ mOrigBandwidthIndex, mCurBandwidthIndex);
mSwitchGeneration++;
mSwitchInProgress = false;
@@ -2022,7 +2067,9 @@ bool LiveSession::checkBuffering(
int64_t bufferedDurationUs =
mPacketSources[i]->getEstimatedDurationUs();
- ALOGV("source[%zu]: buffered %lld us", i, (long long)bufferedDurationUs);
+ ALOGV("[%s] buffered %lld us",
+ getNameForStream(mPacketSources.keyAt(i)),
+ (long long)bufferedDurationUs);
if (durationUs >= 0) {
int32_t percent;
if (mPacketSources[i]->isFinished(0 /* duration */)) {
diff --git a/media/libstagefright/httplive/LiveSession.h b/media/libstagefright/httplive/LiveSession.h
index b5e31c9..c587f40 100644
--- a/media/libstagefright/httplive/LiveSession.h
+++ b/media/libstagefright/httplive/LiveSession.h
@@ -91,6 +91,7 @@ struct LiveSession : public AHandler {
bool hasDynamicDuration() const;
static const char *getKeyForStream(StreamType type);
+ static const char *getNameForStream(StreamType type);
enum {
kWhatStreamsChanged,
@@ -236,7 +237,7 @@ private:
sp<PlaylistFetcher> addFetcher(const char *uri);
void onConnect(const sp<AMessage> &msg);
- status_t onSeek(const sp<AMessage> &msg);
+ void onSeek(const sp<AMessage> &msg);
void onFinishDisconnect2();
// If given a non-zero block_size (default 0), it is used to cap the number of
diff --git a/media/libstagefright/httplive/PlaylistFetcher.cpp b/media/libstagefright/httplive/PlaylistFetcher.cpp
index 368612d..ce79cc2 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.cpp
+++ b/media/libstagefright/httplive/PlaylistFetcher.cpp
@@ -45,6 +45,10 @@
#include <openssl/aes.h>
#include <openssl/md5.h>
+#define FLOGV(fmt, ...) ALOGV("[fetcher-%d] " fmt, mFetcherID, ##__VA_ARGS__)
+#define FSLOGV(stream, fmt, ...) ALOGV("[fetcher-%d] [%s] " fmt, mFetcherID, \
+ LiveSession::getNameForStream(stream), ##__VA_ARGS__)
+
namespace android {
// static
@@ -143,10 +147,12 @@ PlaylistFetcher::PlaylistFetcher(
const sp<AMessage> &notify,
const sp<LiveSession> &session,
const char *uri,
+ int32_t id,
int32_t subtitleGeneration)
: mNotify(notify),
mSession(session),
mURI(uri),
+ mFetcherID(id),
mStreamTypeMask(0),
mStartTimeUs(-1ll),
mSegmentStartTimeUs(-1ll),
@@ -176,6 +182,10 @@ PlaylistFetcher::PlaylistFetcher(
PlaylistFetcher::~PlaylistFetcher() {
}
+int32_t PlaylistFetcher::getFetcherID() const {
+ return mFetcherID;
+}
+
int64_t PlaylistFetcher::getSegmentStartTimeUs(int32_t seqNumber) const {
CHECK(mPlaylist != NULL);
@@ -436,7 +446,7 @@ void PlaylistFetcher::postMonitorQueue(int64_t delayUs, int64_t minDelayUs) {
maxDelayUs = minDelayUs;
}
if (delayUs > maxDelayUs) {
- ALOGV("Need to refresh playlist in %" PRId64 , maxDelayUs);
+ FLOGV("Need to refresh playlist in %lld", (long long)maxDelayUs);
delayUs = maxDelayUs;
}
sp<AMessage> msg = new AMessage(kWhatMonitorQueue, this);
@@ -507,6 +517,8 @@ void PlaylistFetcher::stopAsync(bool clear) {
}
void PlaylistFetcher::resumeUntilAsync(const sp<AMessage> &params) {
+ FLOGV("resumeUntilAsync: params=%s", params->debugString().c_str());
+
AMessage* msg = new AMessage(kWhatResumeUntil, this);
msg->setMessage("params", params);
msg->post();
@@ -763,8 +775,9 @@ void PlaylistFetcher::onMonitorQueue() {
int64_t bufferedStreamDurationUs =
mPacketSources.valueAt(i)->getBufferedDurationUs(&finalResult);
- ALOGV("buffered %" PRId64 " for stream %d",
- bufferedStreamDurationUs, mPacketSources.keyAt(i));
+
+ FSLOGV(mPacketSources.keyAt(i), "buffered %lld", (long long)bufferedStreamDurationUs);
+
if (bufferedDurationUs == -1ll
|| bufferedStreamDurationUs < bufferedDurationUs) {
bufferedDurationUs = bufferedStreamDurationUs;
@@ -776,8 +789,9 @@ void PlaylistFetcher::onMonitorQueue() {
}
if (finalResult == OK && bufferedDurationUs < kMinBufferedDurationUs) {
- ALOGV("monitoring, buffered=%" PRId64 " < %" PRId64 "",
- bufferedDurationUs, kMinBufferedDurationUs);
+ FLOGV("monitoring, buffered=%lld < %lld",
+ (long long)bufferedDurationUs, (long long)kMinBufferedDurationUs);
+
// delay the next download slightly; hopefully this gives other concurrent fetchers
// a better chance to run.
// onDownloadNext();
@@ -792,8 +806,12 @@ void PlaylistFetcher::onMonitorQueue() {
if (delayUs > targetDurationUs / 2) {
delayUs = targetDurationUs / 2;
}
- ALOGV("pausing for %" PRId64 ", buffered=%" PRId64 " > %" PRId64 "",
- delayUs, bufferedDurationUs, kMinBufferedDurationUs);
+
+ FLOGV("pausing for %lld, buffered=%lld > %lld",
+ (long long)delayUs,
+ (long long)bufferedDurationUs,
+ (long long)kMinBufferedDurationUs);
+
postMonitorQueue(delayUs);
}
}
@@ -891,6 +909,12 @@ bool PlaylistFetcher::shouldPauseDownload() {
}
}
lastEnqueueUs -= mSegmentFirstPTS;
+
+ FLOGV("%spausing now, thresholdUs %lld, remaining %lld",
+ targetDurationUs - lastEnqueueUs > thresholdUs ? "" : "not ",
+ (long long)thresholdUs,
+ (long long)(targetDurationUs - lastEnqueueUs));
+
if (targetDurationUs - lastEnqueueUs > thresholdUs) {
return true;
}
@@ -940,8 +964,8 @@ bool PlaylistFetcher::initDownloadState(
mStartTimeUs -= getSegmentStartTimeUs(mSeqNumber);
}
mStartTimeUsRelative = true;
- ALOGV("Initial sequence number for time %" PRId64 " is %d from (%d .. %d)",
- mStartTimeUs, mSeqNumber, firstSeqNumberInPlaylist,
+ FLOGV("Initial sequence number for time %lld is %d from (%d .. %d)",
+ (long long)mStartTimeUs, mSeqNumber, firstSeqNumberInPlaylist,
lastSeqNumberInPlaylist);
} else {
// When adapting or track switching, mSegmentStartTimeUs (relative
@@ -966,7 +990,7 @@ bool PlaylistFetcher::initDownloadState(
if (mSeqNumber > lastSeqNumberInPlaylist) {
mSeqNumber = lastSeqNumberInPlaylist;
}
- ALOGV("Initial sequence number for live event %d from (%d .. %d)",
+ FLOGV("Initial sequence number is %d from (%d .. %d)",
mSeqNumber, firstSeqNumberInPlaylist,
lastSeqNumberInPlaylist);
}
@@ -995,10 +1019,10 @@ bool PlaylistFetcher::initDownloadState(
if (delayUs > kMaxMonitorDelayUs) {
delayUs = kMaxMonitorDelayUs;
}
- ALOGV("sequence number high: %d from (%d .. %d), "
- "monitor in %" PRId64 " (retry=%d)",
+ FLOGV("sequence number high: %d from (%d .. %d), "
+ "monitor in %lld (retry=%d)",
mSeqNumber, firstSeqNumberInPlaylist,
- lastSeqNumberInPlaylist, delayUs, mNumRetries);
+ lastSeqNumberInPlaylist, (long long)delayUs, mNumRetries);
postMonitorQueue(delayUs);
return false;
}
@@ -1067,9 +1091,9 @@ bool PlaylistFetcher::initDownloadState(
// Seek jumped to a new discontinuity sequence. We need to signal
// a format change to decoder. Decoder needs to shutdown and be
// created again if seamless format change is unsupported.
- ALOGV("saw discontinuity: mStartup %d, mLastDiscontinuitySeq %d, "
+ FLOGV("saw discontinuity: mStartup %d, mLastDiscontinuitySeq %d, "
"mDiscontinuitySeq %d, mStartTimeUs %lld",
- mStartup, mLastDiscontinuitySeq, mDiscontinuitySeq, (long long)mStartTimeUs);
+ mStartup, mLastDiscontinuitySeq, mDiscontinuitySeq, (long long)mStartTimeUs);
discontinuity = true;
}
mLastDiscontinuitySeq = -1;
@@ -1134,7 +1158,7 @@ bool PlaylistFetcher::initDownloadState(
}
}
- ALOGV("fetching segment %d from (%d .. %d)",
+ FLOGV("fetching segment %d from (%d .. %d)",
mSeqNumber, firstSeqNumberInPlaylist, lastSeqNumberInPlaylist);
return true;
}
@@ -1157,7 +1181,7 @@ void PlaylistFetcher::onDownloadNext() {
firstSeqNumberInPlaylist,
lastSeqNumberInPlaylist);
connectHTTP = false;
- ALOGV("resuming: '%s'", uri.c_str());
+ FLOGV("resuming: '%s'", uri.c_str());
} else {
if (!initDownloadState(
uri,
@@ -1166,7 +1190,7 @@ void PlaylistFetcher::onDownloadNext() {
lastSeqNumberInPlaylist)) {
return;
}
- ALOGV("fetching: '%s'", uri.c_str());
+ FLOGV("fetching: '%s'", uri.c_str());
}
int64_t range_offset, range_length;
@@ -1196,6 +1220,11 @@ void PlaylistFetcher::onDownloadNext() {
| LiveSession::STREAMTYPE_VIDEO))) {
int64_t delayUs = ALooper::GetNowUs() - startUs;
mSession->addBandwidthMeasurement(bytesRead, delayUs);
+
+ if (delayUs > 2000000ll) {
+ FLOGV("bytesRead %zd took %.2f seconds - abnormal bandwidth dip",
+ bytesRead, (double)delayUs / 1.0e6);
+ }
}
connectHTTP = false;
@@ -1584,6 +1613,16 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
// (newSeqNumber), start at least 1 segment prior.
int32_t newSeqNumber = getSeqNumberWithAnchorTime(
timeUs, targetDiffUs);
+
+ FLOGV("guessed wrong seq number: timeUs=%lld, mStartTimeUs=%lld, "
+ "targetDurationUs=%lld, mSeqNumber=%d, newSeq=%d, firstSeq=%d",
+ (long long)timeUs,
+ (long long)mStartTimeUs,
+ (long long)targetDurationUs,
+ mSeqNumber,
+ newSeqNumber,
+ firstSeqNumberInPlaylist);
+
if (newSeqNumber >= mSeqNumber) {
--mSeqNumber;
} else {
@@ -1604,8 +1643,13 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
}
bool startTimeReached = true;
if (mStartTimeUsRelative) {
+ FLOGV("startTimeUsRelative, timeUs (%lld) - %lld = %lld",
+ (long long)timeUs,
+ (long long)mFirstTimeUs,
+ (long long)(timeUs - mFirstTimeUs));
timeUs -= mFirstTimeUs;
if (timeUs < 0) {
+ FLOGV("clamp negative timeUs to 0");
timeUs = 0;
}
startTimeReached = (timeUs >= mStartTimeUs);
@@ -1614,13 +1658,17 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
if (!startTimeReached || (isAvc && !mIDRFound)) {
// buffer up to the closest preceding IDR frame in the next segement,
// or the closest succeeding IDR frame after the exact position
+ FSLOGV(stream, "timeUs=%lld, mStartTimeUs=%lld, mIDRFound=%d",
+ (long long)timeUs, (long long)mStartTimeUs, mIDRFound);
if (isAvc) {
if (IsIDR(accessUnit)) {
mVideoBuffer->clear();
+ FSLOGV(stream, "found IDR, clear mVideoBuffer");
mIDRFound = true;
}
if (mIDRFound && mStartTimeUsRelative && !startTimeReached) {
mVideoBuffer->queueAccessUnit(accessUnit);
+ FSLOGV(stream, "saving AVC video AccessUnit");
}
}
if (!startTimeReached || (isAvc && !mIDRFound)) {
@@ -1635,15 +1683,17 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
if (!(streamMask & mPacketSources.keyAt(i))) {
streamMask |= mPacketSources.keyAt(i);
mStartTimeUsNotify->setInt32("streamMask", streamMask);
+ FSLOGV(stream, "found start point, timeUs=%lld, streamMask becomes %x",
+ (long long)timeUs, streamMask);
if (streamMask == mStreamTypeMask) {
+ FLOGV("found start point for all streams");
mStartup = false;
}
}
}
if (mStopParams != NULL) {
- // Queue discontinuity in original stream.
int32_t discontinuitySeq;
int64_t stopTimeUs;
if (!mStopParams->findInt32("discontinuitySeq", &discontinuitySeq)
@@ -1651,13 +1701,13 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
|| !mStopParams->findInt64(key, &stopTimeUs)
|| (discontinuitySeq == mDiscontinuitySeq
&& timeUs >= stopTimeUs)) {
+ FSLOGV(stream, "reached stop point, timeUs=%lld", (long long)timeUs);
mStreamTypeMask &= ~stream;
mPacketSources.removeItemsAt(i);
break;
}
}
- // Note that we do NOT dequeue any discontinuities except for format change.
if (stream == LiveSession::STREAMTYPE_VIDEO) {
const bool discard = true;
status_t status;
@@ -1666,11 +1716,16 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
mVideoBuffer->dequeueAccessUnit(&videoBuffer);
setAccessUnitProperties(videoBuffer, source, discard);
packetSource->queueAccessUnit(videoBuffer);
+ int64_t bufferTimeUs;
+ CHECK(videoBuffer->meta()->findInt64("timeUs", &bufferTimeUs));
+ FSLOGV(stream, "queueAccessUnit (saved), timeUs=%lld",
+ (long long)bufferTimeUs);
}
}
setAccessUnitProperties(accessUnit, source);
packetSource->queueAccessUnit(accessUnit);
+ FSLOGV(stream, "queueAccessUnit, timeUs=%lld", (long long)timeUs);
}
if (err != OK) {
@@ -1688,7 +1743,7 @@ status_t PlaylistFetcher::extractAndQueueAccessUnitsFromTs(const sp<ABuffer> &bu
if (!mStreamTypeMask) {
// Signal gap is filled between original and new stream.
- ALOGV("ERROR OUT OF RANGE");
+ FLOGV("reached stop point for all streams");
return ERROR_OUT_OF_RANGE;
}
@@ -1918,7 +1973,6 @@ status_t PlaylistFetcher::extractAndQueueAccessUnits(
}
if (mStopParams != NULL) {
- // Queue discontinuity in original stream.
int32_t discontinuitySeq;
int64_t stopTimeUs;
if (!mStopParams->findInt32("discontinuitySeq", &discontinuitySeq)
diff --git a/media/libstagefright/httplive/PlaylistFetcher.h b/media/libstagefright/httplive/PlaylistFetcher.h
index dab56df..f64d160 100644
--- a/media/libstagefright/httplive/PlaylistFetcher.h
+++ b/media/libstagefright/httplive/PlaylistFetcher.h
@@ -55,8 +55,11 @@ struct PlaylistFetcher : public AHandler {
const sp<AMessage> &notify,
const sp<LiveSession> &session,
const char *uri,
+ int32_t id,
int32_t subtitleGeneration);
+ int32_t getFetcherID() const;
+
sp<DataSource> getDataSource();
void startAsync(
@@ -113,6 +116,8 @@ private:
sp<LiveSession> mSession;
AString mURI;
+ int32_t mFetcherID;
+
uint32_t mStreamTypeMask;
int64_t mStartTimeUs;
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index c5bb41b..0676a33 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -514,7 +514,7 @@ void AnotherPacketSource::trimBuffersAfterMeta(
}
HLSTime stopTime(meta);
- ALOGV("trimBuffersAfterMeta: discontinuitySeq %zu, timeUs %lld",
+ ALOGV("trimBuffersAfterMeta: discontinuitySeq %d, timeUs %lld",
stopTime.mSeq, (long long)stopTime.mTimeUs);
List<sp<ABuffer> >::iterator it;
@@ -554,7 +554,7 @@ void AnotherPacketSource::trimBuffersAfterMeta(
sp<AMessage> AnotherPacketSource::trimBuffersBeforeMeta(
const sp<AMessage> &meta) {
HLSTime startTime(meta);
- ALOGV("trimBuffersBeforeMeta: discontinuitySeq %zu, timeUs %lld",
+ ALOGV("trimBuffersBeforeMeta: discontinuitySeq %d, timeUs %lld",
startTime.mSeq, (long long)startTime.mTimeUs);
sp<AMessage> firstMeta;
diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
index 1f43d6d..33cfd1d 100644
--- a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
@@ -85,12 +85,6 @@ status_t MPEG2TSSource::read(
MediaBuffer **out, const ReadOptions *options) {
*out = NULL;
- int64_t seekTimeUs;
- ReadOptions::SeekMode seekMode;
- if (mSeekable && options && options->getSeekTo(&seekTimeUs, &seekMode)) {
- return ERROR_UNSUPPORTED;
- }
-
status_t finalResult;
while (!mImpl->hasBufferAvailable(&finalResult)) {
if (finalResult != OK) {
@@ -103,6 +97,17 @@ status_t MPEG2TSSource::read(
}
}
+ int64_t seekTimeUs;
+ ReadOptions::SeekMode seekMode;
+ if (mSeekable && options && options->getSeekTo(&seekTimeUs, &seekMode)) {
+ // A seek was requested, but we don't actually support seeking and so can only "seek" to
+ // the current position
+ int64_t nextBufTimeUs;
+ if (mImpl->nextBufferTime(&nextBufTimeUs) != OK || seekTimeUs != nextBufTimeUs) {
+ return ERROR_UNSUPPORTED;
+ }
+ }
+
return mImpl->read(out, options);
}
diff --git a/media/libstagefright/omx/SoftOMXPlugin.cpp b/media/libstagefright/omx/SoftOMXPlugin.cpp
index 9b6958a..3ab241a 100644
--- a/media/libstagefright/omx/SoftOMXPlugin.cpp
+++ b/media/libstagefright/omx/SoftOMXPlugin.cpp
@@ -85,7 +85,7 @@ OMX_ERRORTYPE SoftOMXPlugin::makeComponentInstance(
void *libHandle = dlopen(libName.c_str(), RTLD_NOW);
if (libHandle == NULL) {
- ALOGE("unable to dlopen %s", libName.c_str());
+ ALOGE("unable to dlopen %s: %s", libName.c_str(), dlerror());
return OMX_ErrorComponentNotFound;
}