am 100ef9be
: Merge "Disable vorbis seek when streaming from localhost." into froyo
Merge commit '100ef9bee48c9beb83d885d233de6a42c64f55af' into froyo-plus-aosp * commit '100ef9bee48c9beb83d885d233de6a42c64f55af': Disable vorbis seek when streaming from localhost.
This commit is contained in:
@ -33,7 +33,8 @@ class String8;
|
|||||||
class DataSource : public RefBase {
|
class DataSource : public RefBase {
|
||||||
public:
|
public:
|
||||||
enum Flags {
|
enum Flags {
|
||||||
kWantsPrefetching = 1,
|
kWantsPrefetching = 1,
|
||||||
|
kStreamedFromLocalHost = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
static sp<DataSource> CreateFromURI(
|
static sp<DataSource> CreateFromURI(
|
||||||
|
@ -45,9 +45,7 @@ public:
|
|||||||
|
|
||||||
virtual status_t getSize(off_t *size);
|
virtual status_t getSize(off_t *size);
|
||||||
|
|
||||||
virtual uint32_t flags() {
|
virtual uint32_t flags();
|
||||||
return kWantsPrefetching;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~HTTPDataSource();
|
virtual ~HTTPDataSource();
|
||||||
|
@ -44,6 +44,16 @@ public:
|
|||||||
// returns an empty metadata object.
|
// returns an empty metadata object.
|
||||||
virtual sp<MetaData> getMetaData();
|
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:
|
protected:
|
||||||
MediaExtractor() {}
|
MediaExtractor() {}
|
||||||
virtual ~MediaExtractor() {}
|
virtual ~MediaExtractor() {}
|
||||||
|
@ -6,6 +6,9 @@
|
|||||||
|
|
||||||
#include "AwesomePlayer.h"
|
#include "AwesomePlayer.h"
|
||||||
|
|
||||||
|
#include <media/Metadata.h>
|
||||||
|
#include <media/stagefright/MediaExtractor.h>
|
||||||
|
|
||||||
namespace android {
|
namespace android {
|
||||||
|
|
||||||
StagefrightPlayer::StagefrightPlayer()
|
StagefrightPlayer::StagefrightPlayer()
|
||||||
@ -109,7 +112,8 @@ status_t StagefrightPlayer::getDuration(int *msec) {
|
|||||||
status_t err = mPlayer->getDuration(&durationUs);
|
status_t err = mPlayer->getDuration(&durationUs);
|
||||||
|
|
||||||
if (err != OK) {
|
if (err != OK) {
|
||||||
return err;
|
*msec = 0;
|
||||||
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
*msec = (durationUs + 500) / 1000;
|
*msec = (durationUs + 500) / 1000;
|
||||||
@ -156,4 +160,27 @@ void StagefrightPlayer::setAudioSink(const sp<AudioSink> &audioSink) {
|
|||||||
mPlayer->setAudioSink(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
|
} // namespace android
|
||||||
|
@ -53,6 +53,9 @@ public:
|
|||||||
virtual status_t suspend();
|
virtual status_t suspend();
|
||||||
virtual status_t resume();
|
virtual status_t resume();
|
||||||
|
|
||||||
|
virtual status_t getMetadata(
|
||||||
|
const media::Metadata::Filter& ids, Parcel *records);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
AwesomePlayer *mPlayer;
|
AwesomePlayer *mPlayer;
|
||||||
|
|
||||||
|
@ -184,6 +184,7 @@ AwesomePlayer::AwesomePlayer()
|
|||||||
mVideoRendererIsPreview(false),
|
mVideoRendererIsPreview(false),
|
||||||
mAudioPlayer(NULL),
|
mAudioPlayer(NULL),
|
||||||
mFlags(0),
|
mFlags(0),
|
||||||
|
mExtractorFlags(0),
|
||||||
mLastVideoBuffer(NULL),
|
mLastVideoBuffer(NULL),
|
||||||
mVideoBuffer(NULL),
|
mVideoBuffer(NULL),
|
||||||
mSuspensionState(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() {
|
void AwesomePlayer::reset() {
|
||||||
@ -390,6 +397,7 @@ void AwesomePlayer::reset_l() {
|
|||||||
|
|
||||||
mDurationUs = -1;
|
mDurationUs = -1;
|
||||||
mFlags = 0;
|
mFlags = 0;
|
||||||
|
mExtractorFlags = 0;
|
||||||
mVideoWidth = mVideoHeight = -1;
|
mVideoWidth = mVideoHeight = -1;
|
||||||
mTimeSourceDeltaUs = 0;
|
mTimeSourceDeltaUs = 0;
|
||||||
mVideoTimeUs = 0;
|
mVideoTimeUs = 0;
|
||||||
@ -683,8 +691,14 @@ status_t AwesomePlayer::getPosition(int64_t *positionUs) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
status_t AwesomePlayer::seekTo(int64_t timeUs) {
|
status_t AwesomePlayer::seekTo(int64_t timeUs) {
|
||||||
Mutex::Autolock autoLock(mLock);
|
if (mExtractorFlags
|
||||||
return seekTo_l(timeUs);
|
& (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) {
|
status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
|
||||||
@ -1362,5 +1376,9 @@ status_t AwesomePlayer::resume() {
|
|||||||
return OK;
|
return OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t AwesomePlayer::flags() const {
|
||||||
|
return mExtractorFlags;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace android
|
} // namespace android
|
||||||
|
|
||||||
|
@ -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
|
} // namespace android
|
||||||
|
|
||||||
|
@ -36,6 +36,10 @@ sp<MetaData> MediaExtractor::getMetaData() {
|
|||||||
return new MetaData;
|
return new MetaData;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
uint32_t MediaExtractor::flags() const {
|
||||||
|
return CAN_SEEK_BACKWARD | CAN_SEEK_FORWARD | CAN_PAUSE;
|
||||||
|
}
|
||||||
|
|
||||||
// static
|
// static
|
||||||
sp<MediaExtractor> MediaExtractor::Create(
|
sp<MediaExtractor> MediaExtractor::Create(
|
||||||
const sp<DataSource> &source, const char *mime) {
|
const sp<DataSource> &source, const char *mime) {
|
||||||
|
@ -20,6 +20,7 @@
|
|||||||
|
|
||||||
#include "include/VorbisExtractor.h"
|
#include "include/VorbisExtractor.h"
|
||||||
|
|
||||||
|
#include <cutils/properties.h>
|
||||||
#include <media/stagefright/DataSource.h>
|
#include <media/stagefright/DataSource.h>
|
||||||
#include <media/stagefright/MediaBuffer.h>
|
#include <media/stagefright/MediaBuffer.h>
|
||||||
#include <media/stagefright/MediaBufferGroup.h>
|
#include <media/stagefright/MediaBufferGroup.h>
|
||||||
@ -37,8 +38,23 @@ namespace android {
|
|||||||
struct VorbisDataSource {
|
struct VorbisDataSource {
|
||||||
sp<DataSource> mDataSource;
|
sp<DataSource> mDataSource;
|
||||||
off_t mOffset;
|
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(
|
static size_t VorbisRead(
|
||||||
void *ptr, size_t size, size_t nmemb, void *datasource) {
|
void *ptr, size_t size, size_t nmemb, void *datasource) {
|
||||||
VorbisDataSource *vds = (VorbisDataSource *)datasource;
|
VorbisDataSource *vds = (VorbisDataSource *)datasource;
|
||||||
@ -58,6 +74,11 @@ static int VorbisSeek(
|
|||||||
void *datasource, ogg_int64_t offset, int whence) {
|
void *datasource, ogg_int64_t offset, int whence) {
|
||||||
VorbisDataSource *vds = (VorbisDataSource *)datasource;
|
VorbisDataSource *vds = (VorbisDataSource *)datasource;
|
||||||
|
|
||||||
|
if (vds->mSeekDisabled) {
|
||||||
|
errno = ESPIPE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
switch (whence) {
|
switch (whence) {
|
||||||
case SEEK_SET:
|
case SEEK_SET:
|
||||||
vds->mOffset = offset;
|
vds->mOffset = offset;
|
||||||
@ -218,6 +239,7 @@ VorbisExtractor::VorbisExtractor(const sp<DataSource> &source)
|
|||||||
mInitCheck(NO_INIT) {
|
mInitCheck(NO_INIT) {
|
||||||
mVorbisDataSource->mDataSource = mDataSource;
|
mVorbisDataSource->mDataSource = mDataSource;
|
||||||
mVorbisDataSource->mOffset = 0;
|
mVorbisDataSource->mOffset = 0;
|
||||||
|
mVorbisDataSource->mSeekDisabled = ShouldDisableSeek(mDataSource);
|
||||||
|
|
||||||
int res = ov_open_callbacks(
|
int res = ov_open_callbacks(
|
||||||
mVorbisDataSource, mFile, NULL, 0, gVorbisCallbacks);
|
mVorbisDataSource, mFile, NULL, 0, gVorbisCallbacks);
|
||||||
@ -291,6 +313,7 @@ bool SniffVorbis(
|
|||||||
VorbisDataSource vds;
|
VorbisDataSource vds;
|
||||||
vds.mDataSource = source;
|
vds.mDataSource = source;
|
||||||
vds.mOffset = 0;
|
vds.mOffset = 0;
|
||||||
|
vds.mSeekDisabled = ShouldDisableSeek(source);
|
||||||
|
|
||||||
int res = ov_test_callbacks(&vds, &file, NULL, 0, gVorbisCallbacks);
|
int res = ov_test_callbacks(&vds, &file, NULL, 0, gVorbisCallbacks);
|
||||||
|
|
||||||
@ -308,4 +331,13 @@ bool SniffVorbis(
|
|||||||
return true;
|
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
|
} // namespace android
|
||||||
|
@ -84,10 +84,13 @@ struct AwesomePlayer {
|
|||||||
status_t suspend();
|
status_t suspend();
|
||||||
status_t resume();
|
status_t resume();
|
||||||
|
|
||||||
|
// This is a mask of MediaExtractor::Flags.
|
||||||
|
uint32_t flags() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
friend struct AwesomeEvent;
|
friend struct AwesomeEvent;
|
||||||
|
|
||||||
enum Flags {
|
enum {
|
||||||
PLAYING = 1,
|
PLAYING = 1,
|
||||||
LOOPING = 2,
|
LOOPING = 2,
|
||||||
FIRST_FRAME = 4,
|
FIRST_FRAME = 4,
|
||||||
@ -126,6 +129,7 @@ private:
|
|||||||
int64_t mDurationUs;
|
int64_t mDurationUs;
|
||||||
|
|
||||||
uint32_t mFlags;
|
uint32_t mFlags;
|
||||||
|
uint32_t mExtractorFlags;
|
||||||
|
|
||||||
int32_t mVideoWidth, mVideoHeight;
|
int32_t mVideoWidth, mVideoHeight;
|
||||||
int64_t mTimeSourceDeltaUs;
|
int64_t mTimeSourceDeltaUs;
|
||||||
|
@ -38,6 +38,8 @@ struct VorbisExtractor : public MediaExtractor {
|
|||||||
|
|
||||||
virtual sp<MetaData> getMetaData();
|
virtual sp<MetaData> getMetaData();
|
||||||
|
|
||||||
|
uint32_t flags() const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
virtual ~VorbisExtractor();
|
virtual ~VorbisExtractor();
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user