summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/media/stagefright/DataSource.h3
-rw-r--r--include/media/stagefright/HTTPDataSource.h4
-rw-r--r--include/media/stagefright/MediaExtractor.h10
-rw-r--r--media/libmediaplayerservice/StagefrightPlayer.cpp29
-rw-r--r--media/libmediaplayerservice/StagefrightPlayer.h3
-rw-r--r--media/libstagefright/AwesomePlayer.cpp24
-rw-r--r--media/libstagefright/HTTPDataSource.cpp11
-rw-r--r--media/libstagefright/MediaExtractor.cpp4
-rw-r--r--media/libstagefright/VorbisExtractor.cpp32
-rw-r--r--media/libstagefright/include/AwesomePlayer.h6
-rw-r--r--media/libstagefright/include/VorbisExtractor.h2
11 files changed, 119 insertions, 9 deletions
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index 913da47..6f7dc38 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -33,7 +33,8 @@ class String8;
class DataSource : public RefBase {
public:
enum Flags {
- kWantsPrefetching = 1,
+ kWantsPrefetching = 1,
+ kStreamedFromLocalHost = 2,
};
static sp<DataSource> CreateFromURI(
diff --git a/include/media/stagefright/HTTPDataSource.h b/include/media/stagefright/HTTPDataSource.h
index ea31942..f3b44fd 100644
--- a/include/media/stagefright/HTTPDataSource.h
+++ b/include/media/stagefright/HTTPDataSource.h
@@ -45,9 +45,7 @@ public:
virtual status_t getSize(off_t *size);
- virtual uint32_t flags() {
- return kWantsPrefetching;
- }
+ virtual uint32_t flags();
protected:
virtual ~HTTPDataSource();
diff --git a/include/media/stagefright/MediaExtractor.h b/include/media/stagefright/MediaExtractor.h
index 0ed7b40..21338ca 100644
--- a/include/media/stagefright/MediaExtractor.h
+++ b/include/media/stagefright/MediaExtractor.h
@@ -44,6 +44,16 @@ public:
// returns an empty metadata object.
virtual sp<MetaData> getMetaData();
+ enum Flags {
+ CAN_SEEK_BACKWARD = 1,
+ CAN_SEEK_FORWARD = 2,
+ CAN_PAUSE = 4,
+ };
+
+ // If subclasses do _not_ override this, the default is
+ // CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_PAUSE
+ virtual uint32_t flags() const;
+
protected:
MediaExtractor() {}
virtual ~MediaExtractor() {}
diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp
index 7776b4e..2c96d6d 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.cpp
+++ b/media/libmediaplayerservice/StagefrightPlayer.cpp
@@ -6,6 +6,9 @@
#include "AwesomePlayer.h"
+#include <media/Metadata.h>
+#include <media/stagefright/MediaExtractor.h>
+
namespace android {
StagefrightPlayer::StagefrightPlayer()
@@ -109,7 +112,8 @@ status_t StagefrightPlayer::getDuration(int *msec) {
status_t err = mPlayer->getDuration(&durationUs);
if (err != OK) {
- return err;
+ *msec = 0;
+ return OK;
}
*msec = (durationUs + 500) / 1000;
@@ -156,4 +160,27 @@ void StagefrightPlayer::setAudioSink(const sp<AudioSink> &audioSink) {
mPlayer->setAudioSink(audioSink);
}
+status_t StagefrightPlayer::getMetadata(
+ const media::Metadata::Filter& ids, Parcel *records) {
+ using media::Metadata;
+
+ uint32_t flags = mPlayer->flags();
+
+ Metadata metadata(records);
+
+ metadata.appendBool(
+ Metadata::kPauseAvailable,
+ flags & MediaExtractor::CAN_PAUSE);
+
+ metadata.appendBool(
+ Metadata::kSeekBackwardAvailable,
+ flags & MediaExtractor::CAN_SEEK_BACKWARD);
+
+ metadata.appendBool(
+ Metadata::kSeekForwardAvailable,
+ flags & MediaExtractor::CAN_SEEK_FORWARD);
+
+ return OK;
+}
+
} // namespace android
diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h
index 4446582..781eb44 100644
--- a/media/libmediaplayerservice/StagefrightPlayer.h
+++ b/media/libmediaplayerservice/StagefrightPlayer.h
@@ -53,6 +53,9 @@ public:
virtual status_t suspend();
virtual status_t resume();
+ virtual status_t getMetadata(
+ const media::Metadata::Filter& ids, Parcel *records);
+
private:
AwesomePlayer *mPlayer;
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index b14a03c..475160e 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -184,6 +184,7 @@ AwesomePlayer::AwesomePlayer()
mVideoRendererIsPreview(false),
mAudioPlayer(NULL),
mFlags(0),
+ mExtractorFlags(0),
mLastVideoBuffer(NULL),
mVideoBuffer(NULL),
mSuspensionState(NULL) {
@@ -310,7 +311,13 @@ status_t AwesomePlayer::setDataSource_l(const sp<MediaExtractor> &extractor) {
}
}
- return !haveAudio && !haveVideo ? UNKNOWN_ERROR : OK;
+ if (!haveAudio && !haveVideo) {
+ return UNKNOWN_ERROR;
+ }
+
+ mExtractorFlags = extractor->flags();
+
+ return OK;
}
void AwesomePlayer::reset() {
@@ -390,6 +397,7 @@ void AwesomePlayer::reset_l() {
mDurationUs = -1;
mFlags = 0;
+ mExtractorFlags = 0;
mVideoWidth = mVideoHeight = -1;
mTimeSourceDeltaUs = 0;
mVideoTimeUs = 0;
@@ -683,8 +691,14 @@ status_t AwesomePlayer::getPosition(int64_t *positionUs) {
}
status_t AwesomePlayer::seekTo(int64_t timeUs) {
- Mutex::Autolock autoLock(mLock);
- return seekTo_l(timeUs);
+ if (mExtractorFlags
+ & (MediaExtractor::CAN_SEEK_FORWARD
+ | MediaExtractor::CAN_SEEK_BACKWARD)) {
+ Mutex::Autolock autoLock(mLock);
+ return seekTo_l(timeUs);
+ }
+
+ return OK;
}
status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
@@ -1362,5 +1376,9 @@ status_t AwesomePlayer::resume() {
return OK;
}
+uint32_t AwesomePlayer::flags() const {
+ return mExtractorFlags;
+}
+
} // namespace android
diff --git a/media/libstagefright/HTTPDataSource.cpp b/media/libstagefright/HTTPDataSource.cpp
index cca6062..8e26c37 100644
--- a/media/libstagefright/HTTPDataSource.cpp
+++ b/media/libstagefright/HTTPDataSource.cpp
@@ -425,5 +425,16 @@ void HTTPDataSource::initHeaders(
}
}
+uint32_t HTTPDataSource::flags() {
+ uint32_t f = kWantsPrefetching;
+
+ if (!strcasecmp(mStartingHost.string(), "localhost")
+ || !strcmp(mStartingHost.string(), "127.0.0.1")) {
+ f |= kStreamedFromLocalHost;
+ }
+
+ return f;
+}
+
} // namespace android
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 832db04..dfddbe0 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -36,6 +36,10 @@ sp<MetaData> MediaExtractor::getMetaData() {
return new MetaData;
}
+uint32_t MediaExtractor::flags() const {
+ return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_PAUSE;
+}
+
// static
sp<MediaExtractor> MediaExtractor::Create(
const sp<DataSource> &source, const char *mime) {
diff --git a/media/libstagefright/VorbisExtractor.cpp b/media/libstagefright/VorbisExtractor.cpp
index 96b05c0..e7b62d6 100644
--- a/media/libstagefright/VorbisExtractor.cpp
+++ b/media/libstagefright/VorbisExtractor.cpp
@@ -20,6 +20,7 @@
#include "include/VorbisExtractor.h"
+#include <cutils/properties.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
@@ -37,8 +38,23 @@ namespace android {
struct VorbisDataSource {
sp<DataSource> mDataSource;
off_t mOffset;
+ bool mSeekDisabled;
};
+static bool ShouldDisableSeek(const sp<DataSource> &source) {
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.vorbis.always-allow-seek", value, NULL)
+ && (!strcmp(value, "1") || !strcasecmp(value, "true"))) {
+ return false;
+ }
+
+ // This is a workaround for an application streaming data through
+ // a local HTTP proxy that doesn't really conform to the HTTP/1.1
+ // specs. We have to disable seek functionality in this case.
+
+ return source->flags() & DataSource::kStreamedFromLocalHost;
+}
+
static size_t VorbisRead(
void *ptr, size_t size, size_t nmemb, void *datasource) {
VorbisDataSource *vds = (VorbisDataSource *)datasource;
@@ -58,6 +74,11 @@ static int VorbisSeek(
void *datasource, ogg_int64_t offset, int whence) {
VorbisDataSource *vds = (VorbisDataSource *)datasource;
+ if (vds->mSeekDisabled) {
+ errno = ESPIPE;
+ return -1;
+ }
+
switch (whence) {
case SEEK_SET:
vds->mOffset = offset;
@@ -218,6 +239,7 @@ VorbisExtractor::VorbisExtractor(const sp<DataSource> &source)
mInitCheck(NO_INIT) {
mVorbisDataSource->mDataSource = mDataSource;
mVorbisDataSource->mOffset = 0;
+ mVorbisDataSource->mSeekDisabled = ShouldDisableSeek(mDataSource);
int res = ov_open_callbacks(
mVorbisDataSource, mFile, NULL, 0, gVorbisCallbacks);
@@ -291,6 +313,7 @@ bool SniffVorbis(
VorbisDataSource vds;
vds.mDataSource = source;
vds.mOffset = 0;
+ vds.mSeekDisabled = ShouldDisableSeek(source);
int res = ov_test_callbacks(&vds, &file, NULL, 0, gVorbisCallbacks);
@@ -308,4 +331,13 @@ bool SniffVorbis(
return true;
}
+uint32_t VorbisExtractor::flags() const {
+ if (ShouldDisableSeek(mDataSource)) {
+ LOGI("This is streamed from local host, seek disabled");
+ return CAN_PAUSE;
+ } else {
+ return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_PAUSE;
+ }
+}
+
} // namespace android
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 9e8a674..9455743 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -84,10 +84,13 @@ struct AwesomePlayer {
status_t suspend();
status_t resume();
+ // This is a mask of MediaExtractor::Flags.
+ uint32_t flags() const;
+
private:
friend struct AwesomeEvent;
- enum Flags {
+ enum {
PLAYING = 1,
LOOPING = 2,
FIRST_FRAME = 4,
@@ -126,6 +129,7 @@ private:
int64_t mDurationUs;
uint32_t mFlags;
+ uint32_t mExtractorFlags;
int32_t mVideoWidth, mVideoHeight;
int64_t mTimeSourceDeltaUs;
diff --git a/media/libstagefright/include/VorbisExtractor.h b/media/libstagefright/include/VorbisExtractor.h
index 8e38a93..2bb7deb 100644
--- a/media/libstagefright/include/VorbisExtractor.h
+++ b/media/libstagefright/include/VorbisExtractor.h
@@ -38,6 +38,8 @@ struct VorbisExtractor : public MediaExtractor {
virtual sp<MetaData> getMetaData();
+ uint32_t flags() const;
+
protected:
virtual ~VorbisExtractor();