Merge "Added preset reverb." into gingerbread
diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h
index 6f7dc38..9d2cff6 100644
--- a/include/media/stagefright/DataSource.h
+++ b/include/media/stagefright/DataSource.h
@@ -28,6 +28,7 @@
namespace android {
+struct AMessage;
class String8;
class DataSource : public RefBase {
@@ -59,10 +60,14 @@
////////////////////////////////////////////////////////////////////////////
- bool sniff(String8 *mimeType, float *confidence);
+ bool sniff(String8 *mimeType, float *confidence, sp<AMessage> *meta);
+ // The sniffer can optionally fill in "meta" with an AMessage containing
+ // a dictionary of values that helps the corresponding extractor initialize
+ // its state without duplicating effort already exerted by the sniffer.
typedef bool (*SnifferFunc)(
- const sp<DataSource> &source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType,
+ float *confidence, sp<AMessage> *meta);
static void RegisterSniffer(SnifferFunc func);
static void RegisterDefaultSniffers();
diff --git a/include/private/surfaceflinger/SharedBufferStack.h b/include/private/surfaceflinger/SharedBufferStack.h
index 1eb178e..d016dfa 100644
--- a/include/private/surfaceflinger/SharedBufferStack.h
+++ b/include/private/surfaceflinger/SharedBufferStack.h
@@ -54,11 +54,6 @@
// ----------------------------------------------------------------------------
-// 4 * (11 + 7 + (1 + 2*NUM_RECT_MAX) * NUM_BUFFER_MAX) * NUM_LAYERS_MAX
-// 4 * (11 + 7 + (1 + 2*7)*16) * 31
-// 1032 * 31
-// = ~27 KiB (31992)
-
class SharedBufferStack
{
friend class SharedClient;
@@ -85,7 +80,7 @@
};
struct FlatRegion { // 52 bytes = 4 * (1 + 2*N)
- static const unsigned int NUM_RECT_MAX = 6;
+ static const unsigned int NUM_RECT_MAX = 5;
uint32_t count;
SmallRect rects[NUM_RECT_MAX];
};
@@ -93,13 +88,18 @@
struct BufferData {
FlatRegion dirtyRegion;
SmallRect crop;
+ uint8_t transform;
+ uint8_t reserved[3];
};
SharedBufferStack();
void init(int32_t identity);
status_t setDirtyRegion(int buffer, const Region& reg);
status_t setCrop(int buffer, const Rect& reg);
+ status_t setTransform(int buffer, uint8_t transform);
Region getDirtyRegion(int buffer) const;
+ Rect getCrop(int buffer) const;
+ uint32_t getTransform(int buffer) const;
// these attributes are part of the conditions/updates
volatile int32_t head; // server's current front buffer
@@ -117,7 +117,7 @@
int32_t reserved32[1];
Statistics stats;
int32_t reserved;
- BufferData buffers[NUM_BUFFER_MAX]; // 960 bytes
+ BufferData buffers[NUM_BUFFER_MAX]; // 1024 bytes
};
// ----------------------------------------------------------------------------
@@ -206,7 +206,7 @@
bool needNewBuffer(int buffer) const;
status_t setDirtyRegion(int buffer, const Region& reg);
status_t setCrop(int buffer, const Rect& reg);
-
+ status_t setTransform(int buffer, uint32_t transform);
class SetBufferCountCallback {
friend class SharedBufferClient;
@@ -275,6 +275,8 @@
status_t reallocateAllExcept(int buffer);
int32_t getQueuedCount() const;
Region getDirtyRegion(int buffer) const;
+ Rect getCrop(int buffer) const;
+ uint32_t getTransform(int buffer) const;
status_t resize(int newNumBuffers);
diff --git a/media/libmedia/fixedfft.cpp b/media/libmedia/fixedfft.cpp
index 28eb05a..9cf05ba 100644
--- a/media/libmedia/fixedfft.cpp
+++ b/media/libmedia/fixedfft.cpp
@@ -26,7 +26,9 @@
#include <stdio.h>
#include <stdint.h>
+#ifdef __ARM_ARCH__
#include <machine/cpu-features.h>
+#endif
#define LOG_FFT_SIZE 10
#define MAX_FFT_SIZE (1 << LOG_FFT_SIZE)
diff --git a/media/libstagefright/AMRExtractor.cpp b/media/libstagefright/AMRExtractor.cpp
index 70af2da..1b05528 100644
--- a/media/libstagefright/AMRExtractor.cpp
+++ b/media/libstagefright/AMRExtractor.cpp
@@ -87,7 +87,7 @@
mInitCheck(NO_INIT) {
String8 mimeType;
float confidence;
- if (!SniffAMR(mDataSource, &mimeType, &confidence)) {
+ if (!SniffAMR(mDataSource, &mimeType, &confidence, NULL)) {
return;
}
@@ -276,7 +276,8 @@
////////////////////////////////////////////////////////////////////////////////
bool SniffAMR(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
char header[9];
if (source->readAt(0, header, sizeof(header)) != sizeof(header)) {
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index f2653cf..a0cd5c3 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -196,6 +196,7 @@
mExtractorFlags(0),
mLastVideoBuffer(NULL),
mVideoBuffer(NULL),
+ mRTSPTimeOffset(0),
mSuspensionState(NULL) {
CHECK_EQ(mClient.connect(), OK);
@@ -393,7 +394,11 @@
mVideoBuffer = NULL;
}
- mRTSPController.clear();
+ if (mRTSPController != NULL) {
+ mRTSPController->disconnect();
+ mRTSPController.clear();
+ }
+
mRTPPusher.clear();
mRTCPPusher.clear();
mRTPSession.clear();
@@ -453,27 +458,34 @@
return;
}
+ bool eos;
+ size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos);
+
size_t lowWatermark = 400000;
size_t highWatermark = 1000000;
- off_t size;
- if (mDurationUs >= 0 && mCachedSource->getSize(&size) == OK) {
- int64_t bitrate = size * 8000000ll / mDurationUs; // in bits/sec
+ if (eos) {
+ notifyListener_l(MEDIA_BUFFERING_UPDATE, 100);
+ } else {
+ off_t size;
+ if (mDurationUs >= 0 && mCachedSource->getSize(&size) == OK) {
+ int64_t bitrate = size * 8000000ll / mDurationUs; // in bits/sec
- size_t cachedSize = mCachedSource->cachedSize();
- int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
+ size_t cachedSize = mCachedSource->cachedSize();
+ int64_t cachedDurationUs = cachedSize * 8000000ll / bitrate;
- double percentage = (double)cachedDurationUs / mDurationUs;
+ int percentage = 100.0 * (double)cachedDurationUs / mDurationUs;
+ if (percentage > 100) {
+ percentage = 100;
+ }
- notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage * 100.0);
+ notifyListener_l(MEDIA_BUFFERING_UPDATE, percentage);
- lowWatermark = 2 * bitrate / 8; // 2 secs
- highWatermark = 10 * bitrate / 8; // 10 secs
+ lowWatermark = 2 * bitrate / 8; // 2 secs
+ highWatermark = 10 * bitrate / 8; // 10 secs
+ }
}
- bool eos;
- size_t cachedDataRemaining = mCachedSource->approxDataRemaining(&eos);
-
if ((mFlags & PLAYING) && !eos && (cachedDataRemaining < lowWatermark)) {
LOGI("cache is running low (< %d) , pausing.", lowWatermark);
mFlags |= CACHE_UNDERRUN;
@@ -738,6 +750,10 @@
*positionUs = 0;
}
+ if (mRTSPController != NULL) {
+ *positionUs += mRTSPTimeOffset;
+ }
+
return OK;
}
@@ -753,6 +769,17 @@
}
status_t AwesomePlayer::seekTo_l(int64_t timeUs) {
+ if (mRTSPController != NULL) {
+ pause_l();
+ mRTSPController->seek(timeUs);
+ play_l();
+
+ notifyListener_l(MEDIA_SEEK_COMPLETE);
+ mSeekNotificationSent = true;
+ mRTSPTimeOffset = timeUs;
+ return OK;
+ }
+
if (mFlags & CACHE_UNDERRUN) {
mFlags &= ~CACHE_UNDERRUN;
play_l();
diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp
index 90a596c..49eac62 100644
--- a/media/libstagefright/DataSource.cpp
+++ b/media/libstagefright/DataSource.cpp
@@ -25,6 +25,7 @@
#include "matroska/MatroskaExtractor.h"
+#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/FileSource.h>
#include <media/stagefright/MediaErrors.h>
@@ -56,19 +57,23 @@
Mutex DataSource::gSnifferMutex;
List<DataSource::SnifferFunc> DataSource::gSniffers;
-bool DataSource::sniff(String8 *mimeType, float *confidence) {
+bool DataSource::sniff(
+ String8 *mimeType, float *confidence, sp<AMessage> *meta) {
*mimeType = "";
*confidence = 0.0f;
+ meta->clear();
Mutex::Autolock autoLock(gSnifferMutex);
for (List<SnifferFunc>::iterator it = gSniffers.begin();
it != gSniffers.end(); ++it) {
String8 newMimeType;
float newConfidence;
- if ((*it)(this, &newMimeType, &newConfidence)) {
+ sp<AMessage> newMeta;
+ if ((*it)(this, &newMimeType, &newConfidence, &newMeta)) {
if (newConfidence > *confidence) {
*mimeType = newMimeType;
*confidence = newConfidence;
+ *meta = newMeta;
}
}
}
@@ -92,13 +97,13 @@
// static
void DataSource::RegisterDefaultSniffers() {
- RegisterSniffer(SniffMP3);
RegisterSniffer(SniffMPEG4);
- RegisterSniffer(SniffAMR);
- RegisterSniffer(SniffWAV);
- RegisterSniffer(SniffOgg);
RegisterSniffer(SniffMatroska);
+ RegisterSniffer(SniffOgg);
+ RegisterSniffer(SniffWAV);
+ RegisterSniffer(SniffAMR);
RegisterSniffer(SniffMPEG2TS);
+ RegisterSniffer(SniffMP3);
}
// static
diff --git a/media/libstagefright/MP3Extractor.cpp b/media/libstagefright/MP3Extractor.cpp
index 4058fbc..2e36968 100644
--- a/media/libstagefright/MP3Extractor.cpp
+++ b/media/libstagefright/MP3Extractor.cpp
@@ -22,6 +22,7 @@
#include "include/ID3.h"
+#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaBuffer.h>
#include <media/stagefright/MediaBufferGroup.h>
@@ -456,15 +457,31 @@
MP3Source &operator=(const MP3Source &);
};
-MP3Extractor::MP3Extractor(const sp<DataSource> &source)
+MP3Extractor::MP3Extractor(
+ const sp<DataSource> &source, const sp<AMessage> &meta)
: mDataSource(source),
mFirstFramePos(-1),
mFixedHeader(0),
mByteNumber(0) {
off_t pos = 0;
uint32_t header;
- bool success = Resync(mDataSource, 0, &pos, &header);
- CHECK(success);
+ bool success;
+
+ int64_t meta_offset;
+ uint32_t meta_header;
+ if (meta != NULL
+ && meta->findInt64("offset", &meta_offset)
+ && meta->findInt32("header", (int32_t *)&meta_header)) {
+ // The sniffer has already done all the hard work for us, simply
+ // accept its judgement.
+ pos = (off_t)meta_offset;
+ header = meta_header;
+
+ success = true;
+ } else {
+ success = Resync(mDataSource, 0, &pos, &header);
+ CHECK(success);
+ }
if (success) {
mFirstFramePos = pos;
@@ -759,15 +776,20 @@
}
bool SniffMP3(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ const sp<DataSource> &source, String8 *mimeType,
+ float *confidence, sp<AMessage> *meta) {
off_t pos = 0;
uint32_t header;
if (!Resync(source, 0, &pos, &header)) {
return false;
}
+ *meta = new AMessage;
+ (*meta)->setInt64("offset", pos);
+ (*meta)->setInt32("header", header);
+
*mimeType = MEDIA_MIMETYPE_AUDIO_MPEG;
- *confidence = 0.3f;
+ *confidence = 0.2f;
return true;
}
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index 12a1e6e..ba90407 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -1738,7 +1738,7 @@
|| !memcmp(header, "ftypM4A ", 8) || !memcmp(header, "ftypf4v ", 8)
|| !memcmp(header, "ftypkddi", 8) || !memcmp(header, "ftypM4VP", 8)) {
*mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
- *confidence = 0.1;
+ *confidence = 0.4;
return true;
}
@@ -1805,13 +1805,14 @@
}
*mimeType = MEDIA_MIMETYPE_CONTAINER_MPEG4;
- *confidence = 0.3f;
+ *confidence = 0.4f;
return true;
}
bool SniffMPEG4(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
if (BetterSniffMPEG4(source, mimeType, confidence)) {
return true;
}
diff --git a/media/libstagefright/MediaExtractor.cpp b/media/libstagefright/MediaExtractor.cpp
index 56e6136..9bc94de 100644
--- a/media/libstagefright/MediaExtractor.cpp
+++ b/media/libstagefright/MediaExtractor.cpp
@@ -27,6 +27,7 @@
#include "matroska/MatroskaExtractor.h"
+#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/DataSource.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MediaExtractor.h>
@@ -46,10 +47,12 @@
// static
sp<MediaExtractor> MediaExtractor::Create(
const sp<DataSource> &source, const char *mime) {
+ sp<AMessage> meta;
+
String8 tmp;
if (mime == NULL) {
float confidence;
- if (!source->sniff(&tmp, &confidence)) {
+ if (!source->sniff(&tmp, &confidence, &meta)) {
LOGV("FAILED to autodetect media content.");
return NULL;
@@ -64,7 +67,7 @@
|| !strcasecmp(mime, "audio/mp4")) {
return new MPEG4Extractor(source);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_MPEG)) {
- return new MP3Extractor(source);
+ return new MP3Extractor(source, meta);
} else if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_NB)
|| !strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AMR_WB)) {
return new AMRExtractor(source);
diff --git a/media/libstagefright/OggExtractor.cpp b/media/libstagefright/OggExtractor.cpp
index 9630092..2c1311a 100644
--- a/media/libstagefright/OggExtractor.cpp
+++ b/media/libstagefright/OggExtractor.cpp
@@ -804,7 +804,8 @@
}
bool SniffOgg(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
char tmp[4];
if (source->readAt(0, tmp, 4) < 4 || memcmp(tmp, "OggS", 4)) {
return false;
diff --git a/media/libstagefright/WAVExtractor.cpp b/media/libstagefright/WAVExtractor.cpp
index 8d820c0..57c1075 100644
--- a/media/libstagefright/WAVExtractor.cpp
+++ b/media/libstagefright/WAVExtractor.cpp
@@ -404,7 +404,8 @@
////////////////////////////////////////////////////////////////////////////////
bool SniffWAV(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
char header[12];
if (source->readAt(0, header, sizeof(header)) < (ssize_t)sizeof(header)) {
return false;
diff --git a/media/libstagefright/include/AMRExtractor.h b/media/libstagefright/include/AMRExtractor.h
index db49fe4..1cdf36d 100644
--- a/media/libstagefright/include/AMRExtractor.h
+++ b/media/libstagefright/include/AMRExtractor.h
@@ -22,6 +22,7 @@
namespace android {
+struct AMessage;
class String8;
class AMRExtractor : public MediaExtractor {
@@ -49,7 +50,8 @@
};
bool SniffAMR(
- const sp<DataSource> &source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
} // namespace android
diff --git a/media/libstagefright/include/ARTSPController.h b/media/libstagefright/include/ARTSPController.h
index 2542e4e..7020564 100644
--- a/media/libstagefright/include/ARTSPController.h
+++ b/media/libstagefright/include/ARTSPController.h
@@ -33,6 +33,8 @@
status_t connect(const char *url);
void disconnect();
+ void seek(int64_t timeUs);
+
virtual size_t countTracks();
virtual sp<MediaSource> getTrack(size_t index);
diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h
index 55e2c36..49b5c78 100644
--- a/media/libstagefright/include/AwesomePlayer.h
+++ b/media/libstagefright/include/AwesomePlayer.h
@@ -180,6 +180,7 @@
sp<ALooper> mLooper;
sp<ARTSPController> mRTSPController;
+ int64_t mRTSPTimeOffset;
sp<ARTPSession> mRTPSession;
sp<UDPPusher> mRTPPusher, mRTCPPusher;
diff --git a/media/libstagefright/include/MP3Extractor.h b/media/libstagefright/include/MP3Extractor.h
index 3ce6df3..0e6ccde 100644
--- a/media/libstagefright/include/MP3Extractor.h
+++ b/media/libstagefright/include/MP3Extractor.h
@@ -22,13 +22,14 @@
namespace android {
+struct AMessage;
class DataSource;
class String8;
class MP3Extractor : public MediaExtractor {
public:
// Extractor assumes ownership of "source".
- MP3Extractor(const sp<DataSource> &source);
+ MP3Extractor(const sp<DataSource> &source, const sp<AMessage> &meta);
virtual size_t countTracks();
virtual sp<MediaSource> getTrack(size_t index);
@@ -52,7 +53,8 @@
};
bool SniffMP3(
- const sp<DataSource> &source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *meta);
} // namespace android
diff --git a/media/libstagefright/include/MPEG2TSExtractor.h b/media/libstagefright/include/MPEG2TSExtractor.h
index c96973b..1bf4cd1 100644
--- a/media/libstagefright/include/MPEG2TSExtractor.h
+++ b/media/libstagefright/include/MPEG2TSExtractor.h
@@ -9,6 +9,7 @@
namespace android {
+struct AMessage;
struct AnotherPacketSource;
struct ATSParser;
struct DataSource;
@@ -47,7 +48,8 @@
};
bool SniffMPEG2TS(
- const sp<DataSource> &source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
} // namespace android
diff --git a/media/libstagefright/include/MPEG4Extractor.h b/media/libstagefright/include/MPEG4Extractor.h
index c8663d5..1c9cc7e 100644
--- a/media/libstagefright/include/MPEG4Extractor.h
+++ b/media/libstagefright/include/MPEG4Extractor.h
@@ -23,6 +23,7 @@
namespace android {
+struct AMessage;
class DataSource;
class SampleTable;
class String8;
@@ -75,7 +76,8 @@
};
bool SniffMPEG4(
- const sp<DataSource> &source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
} // namespace android
diff --git a/media/libstagefright/include/OggExtractor.h b/media/libstagefright/include/OggExtractor.h
index 7066669..1eda025 100644
--- a/media/libstagefright/include/OggExtractor.h
+++ b/media/libstagefright/include/OggExtractor.h
@@ -22,6 +22,7 @@
namespace android {
+struct AMessage;
class DataSource;
class String8;
@@ -53,7 +54,8 @@
};
bool SniffOgg(
- const sp<DataSource> &source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
} // namespace android
diff --git a/media/libstagefright/include/WAVExtractor.h b/media/libstagefright/include/WAVExtractor.h
index 3e847b9..df6d3e7 100644
--- a/media/libstagefright/include/WAVExtractor.h
+++ b/media/libstagefright/include/WAVExtractor.h
@@ -22,6 +22,7 @@
namespace android {
+struct AMessage;
class DataSource;
class String8;
@@ -58,7 +59,8 @@
};
bool SniffWAV(
- const sp<DataSource> &source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
} // namespace android
diff --git a/media/libstagefright/matroska/MatroskaExtractor.cpp b/media/libstagefright/matroska/MatroskaExtractor.cpp
index 71f6587..7c7d69e 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.cpp
+++ b/media/libstagefright/matroska/MatroskaExtractor.cpp
@@ -579,7 +579,8 @@
}
bool SniffMatroska(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
DataSourceReader reader(source);
mkvparser::EBMLHeader ebmlHeader;
long long pos;
diff --git a/media/libstagefright/matroska/MatroskaExtractor.h b/media/libstagefright/matroska/MatroskaExtractor.h
index 7471848..fa20b84 100644
--- a/media/libstagefright/matroska/MatroskaExtractor.h
+++ b/media/libstagefright/matroska/MatroskaExtractor.h
@@ -27,6 +27,7 @@
namespace android {
+struct AMessage;
class String8;
struct DataSourceReader;
@@ -69,7 +70,8 @@
};
bool SniffMatroska(
- const sp<DataSource> &source, String8 *mimeType, float *confidence);
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *);
} // namespace android
diff --git a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
index b287c95..56ca375 100644
--- a/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
+++ b/media/libstagefright/mpeg2ts/MPEG2TSExtractor.cpp
@@ -174,7 +174,8 @@
////////////////////////////////////////////////////////////////////////////////
bool SniffMPEG2TS(
- const sp<DataSource> &source, String8 *mimeType, float *confidence) {
+ const sp<DataSource> &source, String8 *mimeType, float *confidence,
+ sp<AMessage> *) {
#if 0
char header;
if (source->readAt(0, &header, 1) != 1 || header != 0x47) {
diff --git a/media/libstagefright/rtsp/APacketSource.cpp b/media/libstagefright/rtsp/APacketSource.cpp
index 8c56cb7..b930184 100644
--- a/media/libstagefright/rtsp/APacketSource.cpp
+++ b/media/libstagefright/rtsp/APacketSource.cpp
@@ -406,9 +406,7 @@
const sp<ASessionDescription> &sessionDesc, size_t index)
: mInitCheck(NO_INIT),
mFormat(new MetaData),
- mEOSResult(OK),
- mFirstAccessUnit(true),
- mFirstAccessUnitNTP(0) {
+ mEOSResult(OK) {
unsigned long PT;
AString desc;
AString params;
@@ -550,9 +548,6 @@
}
status_t APacketSource::start(MetaData *params) {
- mFirstAccessUnit = true;
- mFirstAccessUnitNTP = 0;
-
return OK;
}
@@ -600,25 +595,6 @@
return;
}
- uint64_t ntpTime;
- CHECK(buffer->meta()->findInt64(
- "ntp-time", (int64_t *)&ntpTime));
-
- if (mFirstAccessUnit) {
- mFirstAccessUnit = false;
- mFirstAccessUnitNTP = ntpTime;
- }
-
- if (ntpTime > mFirstAccessUnitNTP) {
- ntpTime -= mFirstAccessUnitNTP;
- } else {
- ntpTime = 0;
- }
-
- int64_t timeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32));
-
- buffer->meta()->setInt64("timeUs", timeUs);
-
Mutex::Autolock autoLock(mLock);
mBuffers.push_back(buffer);
mCondition.signal();
@@ -632,31 +608,9 @@
mCondition.signal();
}
-int64_t APacketSource::getQueuedDuration(bool *eos) {
+void APacketSource::flushQueue() {
Mutex::Autolock autoLock(mLock);
-
- *eos = (mEOSResult != OK);
-
- if (mBuffers.empty()) {
- return 0;
- }
-
- sp<ABuffer> buffer = *mBuffers.begin();
-
- uint64_t ntpTime;
- CHECK(buffer->meta()->findInt64(
- "ntp-time", (int64_t *)&ntpTime));
-
- int64_t firstTimeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32));
-
- buffer = *--mBuffers.end();
-
- CHECK(buffer->meta()->findInt64(
- "ntp-time", (int64_t *)&ntpTime));
-
- int64_t lastTimeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32));
-
- return lastTimeUs - firstTimeUs;
+ mBuffers.clear();
}
} // namespace android
diff --git a/media/libstagefright/rtsp/APacketSource.h b/media/libstagefright/rtsp/APacketSource.h
index 647da6e..197af3e 100644
--- a/media/libstagefright/rtsp/APacketSource.h
+++ b/media/libstagefright/rtsp/APacketSource.h
@@ -43,7 +43,7 @@
void queueAccessUnit(const sp<ABuffer> &buffer);
void signalEOS(status_t result);
- int64_t getQueuedDuration(bool *eos);
+ void flushQueue();
protected:
virtual ~APacketSource();
@@ -58,9 +58,6 @@
List<sp<ABuffer> > mBuffers;
status_t mEOSResult;
- bool mFirstAccessUnit;
- uint64_t mFirstAccessUnitNTP;
-
DISALLOW_EVIL_CONSTRUCTORS(APacketSource);
};
diff --git a/media/libstagefright/rtsp/ARTSPController.cpp b/media/libstagefright/rtsp/ARTSPController.cpp
index ceae3a6..9df17cb 100644
--- a/media/libstagefright/rtsp/ARTSPController.cpp
+++ b/media/libstagefright/rtsp/ARTSPController.cpp
@@ -33,7 +33,7 @@
}
ARTSPController::~ARTSPController() {
- disconnect();
+ CHECK_EQ((int)mState, (int)DISCONNECTED);
mLooper->unregisterHandler(mReflector->id());
}
@@ -80,6 +80,16 @@
mHandler.clear();
}
+void ARTSPController::seek(int64_t timeUs) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (mState != CONNECTED) {
+ return;
+ }
+
+ mHandler->seek(timeUs);
+}
+
size_t ARTSPController::countTracks() {
if (mHandler == NULL) {
return 0;
diff --git a/media/libstagefright/rtsp/MyHandler.h b/media/libstagefright/rtsp/MyHandler.h
index 90070c9..e248463 100644
--- a/media/libstagefright/rtsp/MyHandler.h
+++ b/media/libstagefright/rtsp/MyHandler.h
@@ -38,7 +38,10 @@
mConn(new ARTSPConnection),
mRTPConn(new ARTPConnection),
mSessionURL(url),
- mSetupTracksSuccessful(false) {
+ mSetupTracksSuccessful(false),
+ mSeekPending(false),
+ mFirstAccessUnit(true),
+ mFirstAccessUnitNTP(0) {
mNetLooper->start(false /* runOnCallingThread */,
false /* canCallJava */,
@@ -62,6 +65,12 @@
(new AMessage('abor', id()))->post();
}
+ void seek(int64_t timeUs) {
+ sp<AMessage> msg = new AMessage('seek', id());
+ msg->setInt64("time", timeUs);
+ msg->post();
+ }
+
virtual void onMessageReceived(const sp<AMessage> &msg) {
switch (msg->what()) {
case 'conn':
@@ -88,8 +97,6 @@
case 'disc':
{
- LOG(INFO) << "disconnect completed";
-
(new AMessage('quit', id()))->post();
break;
}
@@ -337,7 +344,20 @@
CHECK(accessUnit->meta()->findInt64(
"ntp-time", (int64_t *)&ntpTime));
- accessUnit->meta()->setInt64("ntp-time", ntpTime);
+ if (mFirstAccessUnit) {
+ mFirstAccessUnit = false;
+ mFirstAccessUnitNTP = ntpTime;
+ }
+
+ if (ntpTime >= mFirstAccessUnitNTP) {
+ ntpTime -= mFirstAccessUnitNTP;
+ } else {
+ ntpTime = 0;
+ }
+
+ int64_t timeUs = (int64_t)(ntpTime * 1E6 / (1ll << 32));
+
+ accessUnit->meta()->setInt64("timeUs", timeUs);
#if 0
int32_t damaged;
@@ -353,6 +373,84 @@
break;
}
+ case 'seek':
+ {
+ if (mSeekPending) {
+ break;
+ }
+
+ int64_t timeUs;
+ CHECK(msg->findInt64("time", &timeUs));
+
+ mSeekPending = true;
+
+ AString request = "PAUSE ";
+ request.append(mSessionURL);
+ request.append(" RTSP/1.0\r\n");
+
+ request.append("Session: ");
+ request.append(mSessionID);
+ request.append("\r\n");
+
+ request.append("\r\n");
+
+ sp<AMessage> reply = new AMessage('see1', id());
+ reply->setInt64("time", timeUs);
+ mConn->sendRequest(request.c_str(), reply);
+ break;
+ }
+
+ case 'see1':
+ {
+ int64_t timeUs;
+ CHECK(msg->findInt64("time", &timeUs));
+
+ AString request = "PLAY ";
+ request.append(mSessionURL);
+ request.append(" RTSP/1.0\r\n");
+
+ request.append("Session: ");
+ request.append(mSessionID);
+ request.append("\r\n");
+
+ request.append(
+ StringPrintf(
+ "Range: npt=%lld-\r\n", timeUs / 1000000ll));
+
+ request.append("\r\n");
+
+ sp<AMessage> reply = new AMessage('see2', id());
+ mConn->sendRequest(request.c_str(), reply);
+ break;
+ }
+
+ case 'see2':
+ {
+ CHECK(mSeekPending);
+
+ LOG(INFO) << "seek completed.";
+ mSeekPending = false;
+
+ int32_t result;
+ CHECK(msg->findInt32("result", &result));
+ if (result != OK) {
+ LOG(ERROR) << "seek FAILED";
+ break;
+ }
+
+ sp<RefBase> obj;
+ CHECK(msg->findObject("response", &obj));
+ sp<ARTSPResponse> response =
+ static_cast<ARTSPResponse *>(obj.get());
+
+ CHECK_EQ(response->mStatusCode, 200u);
+
+ for (size_t i = 0; i < mTracks.size(); ++i) {
+ mTracks.editItemAt(i).mPacketSource->flushQueue();
+ }
+ break;
+ }
+
default:
TRESPASS();
break;
@@ -380,6 +478,9 @@
AString mBaseURL;
AString mSessionID;
bool mSetupTracksSuccessful;
+ bool mSeekPending;
+ bool mFirstAccessUnit;
+ uint64_t mFirstAccessUnitNTP;
struct TrackInfo {
int mRTPSocket;