Merge "The HTTP/1.1 Host request header must include port if it's not the default (80)."
diff --git a/include/media/stagefright/ACodec.h b/include/media/stagefright/ACodec.h
index 940470d..b3815c4 100644
--- a/include/media/stagefright/ACodec.h
+++ b/include/media/stagefright/ACodec.h
@@ -14,11 +14,12 @@
struct ACodec : public AHierarchicalStateMachine {
enum {
- kWhatFillThisBuffer = 'fill',
- kWhatDrainThisBuffer = 'drai',
- kWhatEOS = 'eos ',
- kWhatShutdownCompleted = 'scom',
- kWhatFlushCompleted = 'fcom',
+ kWhatFillThisBuffer = 'fill',
+ kWhatDrainThisBuffer = 'drai',
+ kWhatEOS = 'eos ',
+ kWhatShutdownCompleted = 'scom',
+ kWhatFlushCompleted = 'fcom',
+ kWhatOutputFormatChanged = 'outC',
};
ACodec();
diff --git a/include/media/stagefright/foundation/AMessage.h b/include/media/stagefright/foundation/AMessage.h
index 941f6b9..91ec60c 100644
--- a/include/media/stagefright/foundation/AMessage.h
+++ b/include/media/stagefright/foundation/AMessage.h
@@ -64,6 +64,9 @@
void post(int64_t delayUs = 0);
+ // Performs a deep-copy of "this", contained messages are in turn "dup'ed".
+ // Warning: RefBase items, i.e. "objects" are _not_ copied but only have
+ // their refcount incremented.
sp<AMessage> dup() const;
AString debugString(int32_t indent = 0) const;
diff --git a/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp b/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp
index 89a5e69..9738e33 100644
--- a/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp
+++ b/media/libmediaplayerservice/nuplayer/DecoderWrapper.cpp
@@ -166,6 +166,9 @@
sp<MediaSource> mDecoder;
sp<AMessage> mNotify;
bool mEOS;
+ bool mSentFormat;
+
+ void sendFormatChange();
DISALLOW_EVIL_CONSTRUCTORS(WrapperReader);
};
@@ -174,7 +177,8 @@
const sp<MediaSource> &decoder, const sp<AMessage> ¬ify)
: mDecoder(decoder),
mNotify(notify),
- mEOS(false) {
+ mEOS(false),
+ mSentFormat(false) {
}
DecoderWrapper::WrapperReader::~WrapperReader() {
@@ -215,12 +219,17 @@
MediaBuffer *src;
status_t err = mDecoder->read(&src, &options);
- sp<AMessage> notify = mNotify->dup();
-
- sp<AMessage> realNotify;
- CHECK(notify->findMessage("real-notify", &realNotify));
-
if (err == OK) {
+ if (!mSentFormat) {
+ sendFormatChange();
+ mSentFormat = true;
+ }
+
+ sp<AMessage> notify = mNotify->dup();
+
+ sp<AMessage> realNotify;
+ CHECK(notify->findMessage("real-notify", &realNotify));
+
realNotify->setInt32("what", ACodec::kWhatDrainThisBuffer);
sp<ABuffer> dst = new ABuffer(src->range_length());
@@ -236,12 +245,23 @@
dst->meta()->setInt64("timeUs", timeUs);
realNotify->setObject("buffer", dst);
+
+ notify->post();
+ } else if (err == INFO_FORMAT_CHANGED) {
+ sendFormatChange();
+
+ readMore(false /* flush */);
} else {
+ sp<AMessage> notify = mNotify->dup();
+
+ sp<AMessage> realNotify;
+ CHECK(notify->findMessage("real-notify", &realNotify));
+
realNotify->setInt32("what", ACodec::kWhatEOS);
mEOS = true;
- }
- notify->post();
+ notify->post();
+ }
break;
}
@@ -251,6 +271,46 @@
}
}
+void DecoderWrapper::WrapperReader::sendFormatChange() {
+ sp<AMessage> notify = mNotify->dup();
+
+ sp<AMessage> realNotify;
+ CHECK(notify->findMessage("real-notify", &realNotify));
+
+ realNotify->setInt32("what", ACodec::kWhatOutputFormatChanged);
+
+ sp<MetaData> meta = mDecoder->getFormat();
+
+ const char *mime;
+ CHECK(meta->findCString(kKeyMIMEType, &mime));
+
+ realNotify->setString("mime", mime);
+
+ if (!strncasecmp("audio/", mime, 6)) {
+ int32_t numChannels;
+ CHECK(meta->findInt32(kKeyChannelCount, &numChannels));
+
+ int32_t sampleRate;
+ CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
+
+ realNotify->setInt32("channel-count", numChannels);
+ realNotify->setInt32("sample-rate", sampleRate);
+ } else {
+ CHECK(!strncasecmp("video/", mime, 6));
+
+ int32_t width, height;
+ CHECK(meta->findInt32(kKeyWidth, &width));
+ CHECK(meta->findInt32(kKeyHeight, &height));
+
+ realNotify->setInt32("width", width);
+ realNotify->setInt32("height", height);
+ }
+
+ notify->post();
+
+ mSentFormat = true;
+}
+
////////////////////////////////////////////////////////////////////////////////
DecoderWrapper::DecoderWrapper()
@@ -327,24 +387,33 @@
case kWhatFillBufferDone:
{
- CHECK_GT(mNumPendingDecodes, 0);
- --mNumPendingDecodes;
-
- if (mFlushing) {
- completeFlushIfPossible();
- break;
- }
-
sp<AMessage> notify;
CHECK(msg->findMessage("real-notify", ¬ify));
- sp<AMessage> reply =
- new AMessage(kWhatOutputBufferDrained, id());
+ int32_t what;
+ CHECK(notify->findInt32("what", &what));
- notify->setMessage("reply", reply);
+ if (what == ACodec::kWhatDrainThisBuffer) {
+ CHECK_GT(mNumPendingDecodes, 0);
+ --mNumPendingDecodes;
+
+ sp<AMessage> reply =
+ new AMessage(kWhatOutputBufferDrained, id());
+
+ notify->setMessage("reply", reply);
+
+ ++mNumOutstandingOutputBuffers;
+ } else if (what == ACodec::kWhatEOS) {
+ CHECK_GT(mNumPendingDecodes, 0);
+ --mNumPendingDecodes;
+
+ if (mFlushing) {
+ completeFlushIfPossible();
+ break;
+ }
+ }
+
notify->post();
-
- ++mNumOutstandingOutputBuffers;
break;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 403029a..e99c24a 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -198,6 +198,21 @@
mFlushingAudio = NONE;
mFlushingVideo = NONE;
}
+ } else if (what == ACodec::kWhatOutputFormatChanged) {
+ CHECK(audio);
+
+ int32_t numChannels;
+ CHECK(codecRequest->findInt32("channel-count", &numChannels));
+
+ int32_t sampleRate;
+ CHECK(codecRequest->findInt32("sample-rate", &sampleRate));
+
+ LOGI("Audio output format changed to %d Hz, %d channels",
+ sampleRate, numChannels);
+
+ mAudioSink->close();
+ CHECK_EQ(mAudioSink->open(sampleRate, numChannels), (status_t)OK);
+ mAudioSink->start();
} else {
CHECK_EQ((int)what, (int)ACodec::kWhatDrainThisBuffer);
@@ -365,18 +380,6 @@
const sp<MetaData> &meta = source->getFormat();
(*decoder)->configure(meta);
- if (audio) {
- int32_t sampleRate;
- int32_t channelCount;
- CHECK(meta->findInt32(kKeySampleRate, &sampleRate));
- CHECK(meta->findInt32(kKeyChannelCount, &channelCount));
-
- channelCount = 2; // XXX
-
- CHECK_EQ(mAudioSink->open(sampleRate, channelCount), (status_t)OK);
- mAudioSink->start();
- }
-
return OK;
}
diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp
index 7613d04..d1525cf 100644
--- a/media/libstagefright/AwesomePlayer.cpp
+++ b/media/libstagefright/AwesomePlayer.cpp
@@ -33,8 +33,6 @@
#include "UDPPusher.h"
#include <binder/IPCThreadState.h>
-#include <binder/MemoryDealer.h>
-#include <media/IStreamSource.h>
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/foundation/ADebug.h>
#include <media/stagefright/AudioPlayer.h>
@@ -161,245 +159,6 @@
////////////////////////////////////////////////////////////////////////////////
-struct QueueDataSource;
-
-struct QueueListener : public BnStreamListener {
- QueueListener(QueueDataSource *owner)
- : mOwner(owner) {
- }
-
- void clearOwner();
-
- virtual void queueBuffer(size_t index, size_t size);
-
- virtual void issueCommand(
- Command cmd, bool synchronous, const sp<AMessage> &msg);
-
-private:
- Mutex mLock;
-
- QueueDataSource *mOwner;
-
- DISALLOW_EVIL_CONSTRUCTORS(QueueListener);
-};
-
-struct QueueDataSource : public DataSource {
- QueueDataSource(const sp<IStreamSource> &source);
-
- virtual status_t initCheck() const;
-
- virtual ssize_t readAt(off64_t offset, void *data, size_t size);
-
- virtual void queueBuffer(size_t index, size_t size);
-
- virtual void issueCommand(
- IStreamListener::Command cmd,
- bool synchronous,
- const sp<AMessage> &msg);
-
-protected:
- virtual ~QueueDataSource();
-
-private:
- enum {
- kNumBuffers = 16
- };
-
- struct QueueEntry {
- bool mIsCommand;
-
- IStreamListener::Command mCommand;
- sp<AMessage> mCommandMessage;
-
- size_t mIndex;
- size_t mOffset;
- size_t mSize;
- };
-
- Mutex mLock;
- Condition mCondition;
-
- sp<IStreamSource> mSource;
- sp<QueueListener> mListener;
- sp<MemoryDealer> mDealer;
- Vector<sp<IMemory> > mBuffers;
-
- List<QueueEntry> mQueue;
-
- off64_t mPosition;
- bool mEOS;
-
- DISALLOW_EVIL_CONSTRUCTORS(QueueDataSource);
-};
-
-QueueDataSource::QueueDataSource(const sp<IStreamSource> &source)
- : mSource(source),
- mPosition(0),
- mEOS(false) {
- mListener = new QueueListener(this);
- mSource->setListener(mListener);
-
- static const size_t kBufferSize = (8192 / 188) * 188;
-
- mDealer = new MemoryDealer(kNumBuffers * kBufferSize);
- for (size_t i = 0; i < kNumBuffers; ++i) {
- sp<IMemory> mem = mDealer->allocate(kBufferSize);
- CHECK(mem != NULL);
-
- mBuffers.push(mem);
- }
- mSource->setBuffers(mBuffers);
-
- for (size_t i = 0; i < kNumBuffers; ++i) {
- mSource->onBufferAvailable(i);
- }
-}
-
-QueueDataSource::~QueueDataSource() {
- Mutex::Autolock autoLock(mLock);
-
- mListener->clearOwner();
-}
-
-status_t QueueDataSource::initCheck() const {
- return OK;
-}
-
-ssize_t QueueDataSource::readAt(off64_t offset, void *data, size_t size) {
- if (offset != mPosition) {
- return -EPIPE;
- }
-
- Mutex::Autolock autoLock(mLock);
-
- if (mEOS) {
- return ERROR_END_OF_STREAM;
- }
-
- size_t sizeDone = 0;
-
- while (sizeDone < size) {
- while (mQueue.empty()) {
- mCondition.wait(mLock);
- }
-
- QueueEntry &entry = *mQueue.begin();
-
- if (entry.mIsCommand) {
- switch (entry.mCommand) {
- case IStreamListener::EOS:
- {
- mEOS = true;
-
- if (sizeDone > 0) {
- offset += sizeDone;
- return sizeDone;
- } else {
- return ERROR_END_OF_STREAM;
- }
- break;
- }
-
- case IStreamListener::DISCONTINUITY:
- {
- CHECK_EQ(size, 188u);
- CHECK_EQ(sizeDone, 0u);
-
- memset(data, 0, size);
- sizeDone = size;
- break;
- }
-
- default:
- break;
- }
-
- mQueue.erase(mQueue.begin());
- continue;
- }
-
- size_t copy = size - sizeDone;
- if (copy > entry.mSize) {
- copy = entry.mSize;
- }
-
- memcpy((uint8_t *)data + sizeDone,
- (const uint8_t *)mBuffers.itemAt(entry.mIndex)->pointer()
- + entry.mOffset,
- copy);
-
- entry.mSize -= copy;
- entry.mOffset += copy;
- sizeDone += copy;
-
- if (entry.mSize == 0) {
- mSource->onBufferAvailable(entry.mIndex);
- mQueue.erase(mQueue.begin());
- }
- }
-
- mPosition += sizeDone;
-
- return sizeDone;
-}
-
-void QueueDataSource::queueBuffer(size_t index, size_t size) {
- Mutex::Autolock autoLock(mLock);
-
- CHECK_LT(index, mBuffers.size());
- CHECK_LE(size, mBuffers.itemAt(index)->size());
-
- QueueEntry entry;
- entry.mIsCommand = false;
- entry.mIndex = index;
- entry.mSize = size;
- entry.mOffset = 0;
-
- mQueue.push_back(entry);
- mCondition.signal();
-}
-
-void QueueDataSource::issueCommand(
- IStreamListener::Command cmd,
- bool synchronous,
- const sp<AMessage> &msg) {
- Mutex::Autolock autoLock(mLock);
-
- CHECK(!synchronous);
-
- QueueEntry entry;
- entry.mIsCommand = true;
- entry.mCommand = cmd;
- entry.mCommandMessage = msg;
- mQueue.push_back(entry);
-
- mCondition.signal();
-}
-
-void QueueListener::clearOwner() {
- Mutex::Autolock autoLock(mLock);
- mOwner = NULL;
-}
-
-void QueueListener::queueBuffer(size_t index, size_t size) {
- Mutex::Autolock autoLock(mLock);
- if (mOwner == NULL) {
- return;
- }
- mOwner->queueBuffer(index, size);
-}
-
-void QueueListener::issueCommand(
- Command cmd, bool synchronous, const sp<AMessage> &msg) {
- Mutex::Autolock autoLock(mLock);
- if (mOwner == NULL) {
- return;
- }
- mOwner->issueCommand(cmd, synchronous, msg);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-
AwesomePlayer::AwesomePlayer()
: mQueueStarted(false),
mTimeSource(NULL),
@@ -511,14 +270,7 @@
}
status_t AwesomePlayer::setDataSource(const sp<IStreamSource> &source) {
- Mutex::Autolock autoLock(mLock);
-
- reset_l();
-
- sp<DataSource> dataSource = new QueueDataSource(source);
- sp<MediaExtractor> extractor = new MPEG2TSExtractor(dataSource);
-
- return setDataSource_l(extractor);
+ return INVALID_OPERATION;
}
status_t AwesomePlayer::setDataSource_l(
diff --git a/media/libstagefright/MPEG4Extractor.cpp b/media/libstagefright/MPEG4Extractor.cpp
index d3c7445..dfc9b5a 100644
--- a/media/libstagefright/MPEG4Extractor.cpp
+++ b/media/libstagefright/MPEG4Extractor.cpp
@@ -959,6 +959,13 @@
uint16_t width = U16_AT(&buffer[6 + 18]);
uint16_t height = U16_AT(&buffer[6 + 20]);
+ // The video sample is not stand-compliant if it has invalid dimension.
+ // Use some default width and height value, and
+ // let the decoder figure out the actual width and height (and thus
+ // be prepared for INFO_FOMRAT_CHANGED event).
+ if (width == 0) width = 352;
+ if (height == 0) height = 288;
+
// printf("*** coding='%s' width=%d height=%d\n",
// chunk, width, height);
diff --git a/media/libstagefright/foundation/AMessage.cpp b/media/libstagefright/foundation/AMessage.cpp
index 7da9cb8..0e40acc 100644
--- a/media/libstagefright/foundation/AMessage.cpp
+++ b/media/libstagefright/foundation/AMessage.cpp
@@ -224,13 +224,22 @@
}
case kTypeObject:
- case kTypeMessage:
{
to->u.refValue = from->u.refValue;
to->u.refValue->incStrong(msg.get());
break;
}
+ case kTypeMessage:
+ {
+ sp<AMessage> copy =
+ static_cast<AMessage *>(from->u.refValue)->dup();
+
+ to->u.refValue = copy.get();
+ to->u.refValue->incStrong(msg.get());
+ break;
+ }
+
default:
{
to->u = from->u;
diff --git a/services/audioflinger/AudioPolicyManagerBase.cpp b/services/audioflinger/AudioPolicyManagerBase.cpp
index 5b9273d..855af9f 100644
--- a/services/audioflinger/AudioPolicyManagerBase.cpp
+++ b/services/audioflinger/AudioPolicyManagerBase.cpp
@@ -1605,10 +1605,8 @@
break;
case AudioSystem::FORCE_SPEAKER:
- if (!isInCall() || strategy != STRATEGY_DTMF) {
- device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_BLUETOOTH_SCO_CARKIT;
- if (device) break;
- }
+ device = mAvailableOutputDevices & AudioSystem::DEVICE_OUT_ANLG_DOCK_HEADSET;
+ if (device) break;
#ifdef WITH_A2DP
// when not in a phone call, phone strategy should route STREAM_VOICE_CALL to
// A2DP speaker when forcing to speaker output