summaryrefslogtreecommitdiffstats
path: root/media
diff options
context:
space:
mode:
authorAndreas Huber <andih@google.com>2010-12-23 10:27:40 -0800
committerAndreas Huber <andih@google.com>2010-12-23 10:27:40 -0800
commit5bc087c573c70c84c6a39946457590b42d392a33 (patch)
treea9326bfa5027a152a5a21dd9de86d228c7d92330 /media
parent53df1a460bcfdd129ca2bc416dee2009e35c042e (diff)
downloadframeworks_av-5bc087c573c70c84c6a39946457590b42d392a33.zip
frameworks_av-5bc087c573c70c84c6a39946457590b42d392a33.tar.gz
frameworks_av-5bc087c573c70c84c6a39946457590b42d392a33.tar.bz2
Squashed commit of the following:
commit eaeaa2672d4e0a82891493b2bde8bdd0c0e79a1b Author: Andreas Huber <andih@google.com> Date: Thu Dec 23 10:26:48 2010 -0800 Remove lowest bandwidth stream if using the legacy player. Change-Id: I2f885e26344996de9152f8fda9fd6bdef89bf953 commit 7d652972615b2750fd8f1c21b9fab0e136df2b82 Author: Andreas Huber <andih@google.com> Date: Thu Dec 23 10:14:36 2010 -0800 Don't clear the packet source's format for legacy discontinuities. Change-Id: I9bd5a21b9bd28043ad38bd0658ccc8eda3c1079a commit 2b18a45aac17cbfe1aa089d0f6510957d438dd64 Author: Andreas Huber <andih@google.com> Date: Thu Dec 23 10:13:55 2010 -0800 Use NuPlayer for HTTP live streaming based on runtime property. adb shell setprop media.httplive.enable-nuplayer true Change-Id: I22738df3403985dc8e6992b1ab5da5747309f773 commit 50d899fb7b9ea52c3994b0a58e993998d926aeed Author: Andreas Huber <andih@google.com> Date: Wed Dec 22 16:25:22 2010 -0800 Make ACodec a lot less verbose. Change-Id: I94c7e499b61032321ffaf999f5ad2c913cde6a48 commit b19e1740cb4d02990a56844654b5d019987c6405 Author: Andreas Huber <andih@google.com> Date: Wed Dec 22 16:22:22 2010 -0800 Wait until we have fresh codec-specific-data before instantiating the decoders after a discontinuity involving a format change. Change-Id: I7bcf9b5ae3319f08bf8978a117e8ee5220902e37 commit 06428c006906c9099e430aface3b439ff1d36ecc Author: Andreas Huber <andih@google.com> Date: Wed Dec 22 15:20:38 2010 -0800 Disable random seeks in the streaming tool for now. Change-Id: Ie86fde422dcfc4b2c7a01be51a193fda9c88cd71 commit e19db68f3bea8a61c191f60f6940f30e3a0d5f1b Author: Andreas Huber <andih@google.com> Date: Wed Dec 22 15:20:27 2010 -0800 Tweak HTTP live parameters. Change-Id: If4b71e12485facc523a8a43d8213d0feb190daab commit 1e9942791538c2256b579d96c6c04264b0d8b087 Author: Andreas Huber <andih@google.com> Date: Wed Dec 22 14:48:23 2010 -0800 Enable http live streaming through NuPlayer for http URLs containing the string m3u8 Change-Id: I1691fe12ae8f1507fe3673313959cd50bc324624 commit 4c33f96a6e499ee0efe0e70b687094430cb7c1c0 Author: Andreas Huber <andih@google.com> Date: Wed Dec 22 14:40:27 2010 -0800 Support for HTTP live streaming in NuPlayer. Change-Id: Iacba1c3ebaeb8d3b972185deaf4cff18c8009c54 commit ddf705ce553708bc5b13d89a878484cf839bd674 Author: Andreas Huber <andih@google.com> Date: Wed Dec 22 13:42:47 2010 -0800 StreamingSource now a subclass of abstract NuPlayer::Source Change-Id: Ia6c7c639628910b9d1f37decc55da48b07a70de3 commit 9e04a8406b1882a8e3fdeb7b4d52db5ae70b970a Author: Andreas Huber <andih@google.com> Date: Wed Dec 22 13:33:52 2010 -0800 Refactor media data sourcing to NuPlayer::Source. Change-Id: I1db9fb08c4e527bf7b19c29978cf342c2b0a0bc9 Change-Id: I9610a097481dda58f22142eacda3ac2dba0b63f9
Diffstat (limited to 'media')
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp15
-rw-r--r--media/libmediaplayerservice/nuplayer/Android.mk3
-rw-r--r--media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp132
-rw-r--r--media/libmediaplayerservice/nuplayer/HTTPLiveSource.h56
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp193
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.h28
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp22
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h4
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp22
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.h1
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp1
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h2
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerSource.h50
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp12
-rw-r--r--media/libmediaplayerservice/nuplayer/StreamingSource.cpp120
-rw-r--r--media/libmediaplayerservice/nuplayer/StreamingSource.h54
-rw-r--r--media/libstagefright/ACodec.cpp22
-rw-r--r--media/libstagefright/avc_utils.cpp4
-rw-r--r--media/libstagefright/httplive/LiveDataSource.cpp31
-rw-r--r--media/libstagefright/httplive/LiveDataSource.h3
-rw-r--r--media/libstagefright/httplive/LiveSession.cpp15
-rw-r--r--media/libstagefright/include/LiveSession.h2
-rw-r--r--media/libstagefright/mpeg2ts/ATSParser.cpp8
-rw-r--r--media/libstagefright/mpeg2ts/AnotherPacketSource.cpp29
-rw-r--r--media/libstagefright/mpeg2ts/AnotherPacketSource.h6
-rw-r--r--media/libstagefright/mpeg2ts/ESQueue.cpp8
26 files changed, 631 insertions, 212 deletions
diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp
index 6f011ce..97c541a 100644
--- a/media/libmediaplayerservice/MediaPlayerService.cpp
+++ b/media/libmediaplayerservice/MediaPlayerService.cpp
@@ -732,6 +732,21 @@ player_type getPlayerType(const char* url)
return TEST_PLAYER;
}
+ char value[PROPERTY_VALUE_MAX];
+ if (property_get("media.httplive.enable-nuplayer", value, NULL)
+ && (!strcasecmp(value, "true") || !strcmp(value, "1"))) {
+ if (!strncasecmp("http://", url, 7)) {
+ size_t len = strlen(url);
+ if (len >= 5 && !strcasecmp(".m3u8", &url[len - 5])) {
+ return NU_PLAYER;
+ }
+
+ if (strstr(url,"m3u8")) {
+ return NU_PLAYER;
+ }
+ }
+ }
+
// use MidiFile for MIDI extensions
int lenURL = strlen(url);
for (int i = 0; i < NELEM(FILE_EXTS); ++i) {
diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk
index c4f3764..c20e279 100644
--- a/media/libmediaplayerservice/nuplayer/Android.mk
+++ b/media/libmediaplayerservice/nuplayer/Android.mk
@@ -2,17 +2,20 @@ LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
+ HTTPLiveSource.cpp \
NuPlayer.cpp \
NuPlayerDecoder.cpp \
NuPlayerDriver.cpp \
NuPlayerRenderer.cpp \
NuPlayerStreamListener.cpp \
DecoderWrapper.cpp \
+ StreamingSource.cpp \
LOCAL_C_INCLUDES := \
$(TOP)/frameworks/base/include/media/stagefright/openmax \
$(TOP)/frameworks/base/media/libstagefright/include \
$(TOP)/frameworks/base/media/libstagefright/mpeg2ts \
+ $(TOP)/frameworks/base/media/libstagefright/httplive \
LOCAL_MODULE:= libstagefright_nuplayer
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
new file mode 100644
index 0000000..c656e69
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp
@@ -0,0 +1,132 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "HTTPLiveSource"
+#include <utils/Log.h>
+
+#include "HTTPLiveSource.h"
+
+#include "ATSParser.h"
+#include "AnotherPacketSource.h"
+#include "LiveDataSource.h"
+#include "LiveSession.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+NuPlayer::HTTPLiveSource::HTTPLiveSource(const char *url)
+ : mURL(url),
+ mEOS(false),
+ mOffset(0) {
+}
+
+NuPlayer::HTTPLiveSource::~HTTPLiveSource() {
+ mLiveSession->disconnect();
+ mLiveLooper->stop();
+}
+
+void NuPlayer::HTTPLiveSource::start() {
+ mLiveLooper = new ALooper;
+ mLiveLooper->setName("http live");
+ mLiveLooper->start();
+
+ mLiveSession = new LiveSession;
+ mLiveLooper->registerHandler(mLiveSession);
+
+ mLiveSession->connect(mURL.c_str());
+
+ mTSParser = new ATSParser;
+}
+
+sp<MetaData> NuPlayer::HTTPLiveSource::getFormat(bool audio) {
+ ATSParser::SourceType type =
+ audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO;
+
+ sp<AnotherPacketSource> source =
+ static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
+
+ if (source == NULL) {
+ return NULL;
+ }
+
+ return source->getFormat();
+}
+
+bool NuPlayer::HTTPLiveSource::feedMoreTSData() {
+ if (mEOS) {
+ return false;
+ }
+
+ sp<LiveDataSource> source =
+ static_cast<LiveDataSource *>(mLiveSession->getDataSource().get());
+
+ for (int32_t i = 0; i < 10; ++i) {
+ char buffer[188];
+ ssize_t n = source->readAtNonBlocking(mOffset, buffer, sizeof(buffer));
+
+ if (n == -EWOULDBLOCK) {
+ break;
+ } else if (n < 0) {
+ LOGI("input data EOS reached.");
+ mTSParser->signalEOS(ERROR_END_OF_STREAM);
+ mEOS = true;
+ break;
+ } else {
+ if (buffer[0] == 0x00) {
+ // XXX legacy
+ mTSParser->signalDiscontinuity(
+ buffer[1] == 0x00
+ ? ATSParser::DISCONTINUITY_SEEK
+ : ATSParser::DISCONTINUITY_FORMATCHANGE);
+ } else {
+ mTSParser->feedTSPacket(buffer, sizeof(buffer));
+ }
+
+ mOffset += n;
+ }
+ }
+
+ return true;
+}
+
+status_t NuPlayer::HTTPLiveSource::dequeueAccessUnit(
+ bool audio, sp<ABuffer> *accessUnit) {
+ ATSParser::SourceType type =
+ audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO;
+
+ sp<AnotherPacketSource> source =
+ static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
+
+ if (source == NULL) {
+ return -EWOULDBLOCK;
+ }
+
+ status_t finalResult;
+ if (!source->hasBufferAvailable(&finalResult)) {
+ return finalResult == OK ? -EWOULDBLOCK : finalResult;
+ }
+
+ return source->dequeueAccessUnit(accessUnit);
+}
+
+} // namespace android
+
diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
new file mode 100644
index 0000000..1b97699
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef HTTP_LIVE_SOURCE_H_
+
+#define HTTP_LIVE_SOURCE_H_
+
+#include "NuPlayer.h"
+#include "NuPlayerSource.h"
+
+namespace android {
+
+struct ATSParser;
+struct LiveSession;
+
+struct NuPlayer::HTTPLiveSource : public NuPlayer::Source {
+ HTTPLiveSource(const char *url);
+
+ void start();
+
+ // Returns true iff more data was available, false on EOS.
+ bool feedMoreTSData();
+
+ sp<MetaData> getFormat(bool audio);
+ status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
+
+protected:
+ virtual ~HTTPLiveSource();
+
+private:
+ AString mURL;
+ bool mEOS;
+ off64_t mOffset;
+ sp<ALooper> mLiveLooper;
+ sp<LiveSession> mLiveSession;
+ sp<ATSParser> mTSParser;
+
+ DISALLOW_EVIL_CONSTRUCTORS(HTTPLiveSource);
+};
+
+} // namespace android
+
+#endif // HTTP_LIVE_SOURCE_H_
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
index 967fa49..24efa35 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp
@@ -19,9 +19,14 @@
#include <utils/Log.h>
#include "NuPlayer.h"
+
+#include "HTTPLiveSource.h"
#include "NuPlayerDecoder.h"
#include "NuPlayerRenderer.h"
-#include "NuPlayerStreamListener.h"
+#include "NuPlayerSource.h"
+#include "StreamingSource.h"
+
+#include "ATSParser.h"
#include <media/stagefright/foundation/hexdump.h>
#include <media/stagefright/foundation/ABuffer.h>
@@ -37,9 +42,9 @@ namespace android {
////////////////////////////////////////////////////////////////////////////////
NuPlayer::NuPlayer()
- : mEOS(false),
- mAudioEOS(false),
+ : mAudioEOS(false),
mVideoEOS(false),
+ mScanSourcesPending(false),
mFlushingAudio(NONE),
mFlushingVideo(NONE) {
}
@@ -54,9 +59,15 @@ void NuPlayer::setListener(const wp<MediaPlayerBase> &listener) {
void NuPlayer::setDataSource(const sp<IStreamSource> &source) {
sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
- source->incStrong(this);
- msg->setPointer("source", source.get()); // XXX unsafe.
+ msg->setObject("source", new StreamingSource(source));
+ msg->post();
+}
+
+void NuPlayer::setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers) {
+ sp<AMessage> msg = new AMessage(kWhatSetDataSource, id());
+ msg->setObject("source", new HTTPLiveSource(url));
msg->post();
}
@@ -104,14 +115,10 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
CHECK(mSource == NULL);
- void *ptr;
- CHECK(msg->findPointer("source", &ptr));
-
- mSource = static_cast<IStreamSource *>(ptr);
- mSource->decStrong(this);
+ sp<RefBase> obj;
+ CHECK(msg->findObject("source", &obj));
- mStreamListener = new NuPlayerStreamListener(mSource, id());
- mTSParser = new ATSParser;
+ mSource = static_cast<Source *>(obj.get());
break;
}
@@ -139,7 +146,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
case kWhatStart:
{
- mStreamListener->start();
+ mSource->start();
mRenderer = new Renderer(
mAudioSink,
@@ -148,31 +155,27 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
looper()->registerHandler(mRenderer);
(new AMessage(kWhatScanSources, id()))->post();
+ mScanSourcesPending = true;
break;
}
case kWhatScanSources:
{
- instantiateDecoder(
- false,
- &mVideoDecoder,
- false /* ignoreCodecSpecificData */);
+ mScanSourcesPending = false;
+
+ instantiateDecoder(false, &mVideoDecoder);
if (mAudioSink != NULL) {
- instantiateDecoder(
- true,
- &mAudioDecoder,
- false /* ignoreCodecSpecificData */);
+ instantiateDecoder(true, &mAudioDecoder);
}
- if (mEOS) {
+ if (!mSource->feedMoreTSData()) {
break;
}
- feedMoreTSData();
-
if (mAudioDecoder == NULL || mVideoDecoder == NULL) {
msg->post(100000ll);
+ mScanSourcesPending = true;
}
break;
}
@@ -192,9 +195,10 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) {
status_t err = feedDecoderInputData(
audio, codecRequest);
- if (err == -EWOULDBLOCK && !mEOS) {
- feedMoreTSData();
- msg->post();
+ if (err == -EWOULDBLOCK) {
+ if (mSource->feedMoreTSData()) {
+ msg->post();
+ }
}
} else if (what == ACodec::kWhatEOS) {
mRenderer->queueEOS(audio, ERROR_END_OF_STREAM);
@@ -322,135 +326,37 @@ void NuPlayer::finishFlushIfPossible() {
mRenderer->signalTimeDiscontinuity();
+ bool scanSourcesAgain = false;
+
if (mFlushingAudio == SHUT_DOWN) {
- instantiateDecoder(
- true,
- &mAudioDecoder,
- true /* ignoreCodecSpecificData */);
- CHECK(mAudioDecoder != NULL);
+ scanSourcesAgain = true;
} else if (mAudioDecoder != NULL) {
mAudioDecoder->signalResume();
}
if (mFlushingVideo == SHUT_DOWN) {
- instantiateDecoder(
- false,
- &mVideoDecoder,
- true /* ignoreCodecSpecificData */);
- CHECK(mVideoDecoder != NULL);
+ scanSourcesAgain = true;
} else if (mVideoDecoder != NULL) {
mVideoDecoder->signalResume();
}
mFlushingAudio = NONE;
mFlushingVideo = NONE;
-}
-
-void NuPlayer::feedMoreTSData() {
- CHECK(!mEOS);
-
- for (int32_t i = 0; i < 10; ++i) {
- char buffer[188];
- ssize_t n = mStreamListener->read(buffer, sizeof(buffer));
-
- if (n == 0) {
- LOGI("input data EOS reached.");
- mTSParser->signalEOS(ERROR_END_OF_STREAM);
- mEOS = true;
- break;
- } else if (n == INFO_DISCONTINUITY) {
- mTSParser->signalDiscontinuity(ATSParser::DISCONTINUITY_SEEK);
- } else if (n < 0) {
- CHECK_EQ(n, -EWOULDBLOCK);
- break;
- } else {
- if (buffer[0] == 0x00) {
- // XXX legacy
- mTSParser->signalDiscontinuity(
- buffer[1] == 0x00
- ? ATSParser::DISCONTINUITY_SEEK
- : ATSParser::DISCONTINUITY_FORMATCHANGE);
- } else {
- mTSParser->feedTSPacket(buffer, sizeof(buffer));
- }
- }
- }
-}
-
-status_t NuPlayer::dequeueNextAccessUnit(
- ATSParser::SourceType *type, sp<ABuffer> *accessUnit) {
- accessUnit->clear();
- status_t audioErr = -EWOULDBLOCK;
- int64_t audioTimeUs;
-
- sp<AnotherPacketSource> audioSource =
- static_cast<AnotherPacketSource *>(
- mTSParser->getSource(ATSParser::MPEG2ADTS_AUDIO).get());
-
- if (audioSource != NULL) {
- audioErr = audioSource->nextBufferTime(&audioTimeUs);
- }
-
- status_t videoErr = -EWOULDBLOCK;
- int64_t videoTimeUs;
-
- sp<AnotherPacketSource> videoSource =
- static_cast<AnotherPacketSource *>(
- mTSParser->getSource(ATSParser::AVC_VIDEO).get());
-
- if (videoSource != NULL) {
- videoErr = videoSource->nextBufferTime(&videoTimeUs);
- }
-
- if (audioErr == -EWOULDBLOCK || videoErr == -EWOULDBLOCK) {
- return -EWOULDBLOCK;
- }
-
- if (audioErr != OK && videoErr != OK) {
- return audioErr;
- }
-
- if (videoErr != OK || (audioErr == OK && audioTimeUs < videoTimeUs)) {
- *type = ATSParser::MPEG2ADTS_AUDIO;
- return audioSource->dequeueAccessUnit(accessUnit);
- } else {
- *type = ATSParser::AVC_VIDEO;
- return videoSource->dequeueAccessUnit(accessUnit);
- }
-}
-
-status_t NuPlayer::dequeueAccessUnit(
- ATSParser::SourceType type, sp<ABuffer> *accessUnit) {
- sp<AnotherPacketSource> source =
- static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
-
- if (source == NULL) {
- return -EWOULDBLOCK;
+ if (scanSourcesAgain && !mScanSourcesPending) {
+ mScanSourcesPending = true;
+ (new AMessage(kWhatScanSources, id()))->post();
}
-
- status_t finalResult;
- if (!source->hasBufferAvailable(&finalResult)) {
- return finalResult == OK ? -EWOULDBLOCK : finalResult;
- }
-
- return source->dequeueAccessUnit(accessUnit);
}
-status_t NuPlayer::instantiateDecoder(
- bool audio, sp<Decoder> *decoder, bool ignoreCodecSpecificData) {
+status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) {
if (*decoder != NULL) {
return OK;
}
- ATSParser::SourceType type =
- audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO;
+ sp<MetaData> meta = mSource->getFormat(audio);
- sp<AnotherPacketSource> source =
- static_cast<AnotherPacketSource *>(
- mTSParser->getSource(type).get());
-
- if (source == NULL) {
+ if (meta == NULL) {
return -EWOULDBLOCK;
}
@@ -461,8 +367,7 @@ status_t NuPlayer::instantiateDecoder(
*decoder = new Decoder(notify, audio ? NULL : mSurface);
looper()->registerHandler(*decoder);
- const sp<MetaData> &meta = source->getFormat();
- (*decoder)->configure(meta, ignoreCodecSpecificData);
+ (*decoder)->configure(meta);
return OK;
}
@@ -479,19 +384,17 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp<AMessage> &msg) {
}
sp<ABuffer> accessUnit;
- status_t err = dequeueAccessUnit(
- audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO,
- &accessUnit);
+ status_t err = mSource->dequeueAccessUnit(audio, &accessUnit);
if (err == -EWOULDBLOCK) {
return err;
} else if (err != OK) {
if (err == INFO_DISCONTINUITY) {
- int32_t formatChange;
- if (!accessUnit->meta()->findInt32(
- "format-change", &formatChange)) {
- formatChange = 0;
- }
+ int32_t type;
+ CHECK(accessUnit->meta()->findInt32("discontinuity", &type));
+
+ bool formatChange =
+ type == ATSParser::DISCONTINUITY_FORMATCHANGE;
LOGI("%s discontinuity (formatChange=%d)",
audio ? "audio" : "video", formatChange);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h
index d4e7428..172a962 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h
@@ -21,9 +21,6 @@
#include <media/MediaPlayerInterface.h>
#include <media/stagefright/foundation/AHandler.h>
-#include "ATSParser.h"
-#include "AnotherPacketSource.h"
-
namespace android {
struct ACodec;
@@ -35,6 +32,10 @@ struct NuPlayer : public AHandler {
void setListener(const wp<MediaPlayerBase> &listener);
void setDataSource(const sp<IStreamSource> &source);
+
+ void setDataSource(
+ const char *url, const KeyedVector<String8, String8> *headers);
+
void setVideoSurface(const sp<Surface> &surface);
void setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink);
void start();
@@ -45,9 +46,12 @@ protected:
virtual void onMessageReceived(const sp<AMessage> &msg);
private:
- struct Renderer;
struct Decoder;
+ struct HTTPLiveSource;
struct NuPlayerStreamListener;
+ struct Renderer;
+ struct Source;
+ struct StreamingSource;
enum {
kWhatSetDataSource,
@@ -62,11 +66,9 @@ private:
};
wp<MediaPlayerBase> mListener;
- sp<IStreamSource> mSource;
+ sp<Source> mSource;
sp<Surface> mSurface;
sp<MediaPlayerBase::AudioSink> mAudioSink;
- sp<NuPlayerStreamListener> mStreamListener;
- sp<ATSParser> mTSParser;
sp<Decoder> mVideoDecoder;
sp<Decoder> mAudioDecoder;
sp<Renderer> mRenderer;
@@ -75,6 +77,8 @@ private:
bool mAudioEOS;
bool mVideoEOS;
+ bool mScanSourcesPending;
+
enum FlushStatus {
NONE,
AWAITING_DISCONTINUITY,
@@ -88,19 +92,11 @@ private:
FlushStatus mFlushingAudio;
FlushStatus mFlushingVideo;
- status_t instantiateDecoder(
- bool audio, sp<Decoder> *decoder, bool ignoreCodecSpecificData);
+ status_t instantiateDecoder(bool audio, sp<Decoder> *decoder);
status_t feedDecoderInputData(bool audio, const sp<AMessage> &msg);
void renderBuffer(bool audio, const sp<AMessage> &msg);
- status_t dequeueNextAccessUnit(
- ATSParser::SourceType *type, sp<ABuffer> *accessUnit);
-
- status_t dequeueAccessUnit(
- ATSParser::SourceType type, sp<ABuffer> *accessUnit);
-
- void feedMoreTSData();
void notifyListener(int msg, int ext1, int ext2);
void finishFlushIfPossible();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
index 1d78808..761dfa4 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp
@@ -25,6 +25,7 @@
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
#include <media/stagefright/ACodec.h>
#include <media/stagefright/MediaDefs.h>
#include <media/stagefright/MetaData.h>
@@ -42,8 +43,7 @@ NuPlayer::Decoder::Decoder(
NuPlayer::Decoder::~Decoder() {
}
-void NuPlayer::Decoder::configure(
- const sp<MetaData> &meta, bool ignoreCodecSpecificData) {
+void NuPlayer::Decoder::configure(const sp<MetaData> &meta) {
CHECK(mCodec == NULL);
CHECK(mWrapper == NULL);
@@ -55,10 +55,6 @@ void NuPlayer::Decoder::configure(
sp<AMessage> format = makeFormat(meta);
- if (ignoreCodecSpecificData) {
- mCSD.clear();
- }
-
if (mSurface != NULL) {
format->setObject("surface", mSurface);
}
@@ -128,6 +124,13 @@ sp<AMessage> NuPlayer::Decoder::makeFormat(const sp<MetaData> &meta) {
msg->setInt32("sample-rate", sampleRate);
}
+ int32_t maxInputSize;
+ if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
+ msg->setInt32("max-input-size", maxInputSize);
+ }
+
+ mCSDIndex = 0;
+
uint32_t type;
const void *data;
size_t size;
@@ -233,13 +236,6 @@ sp<AMessage> NuPlayer::Decoder::makeFormat(const sp<MetaData> &meta) {
#endif
}
- int32_t maxInputSize;
- if (meta->findInt32(kKeyMaxInputSize, &maxInputSize)) {
- msg->setInt32("max-input-size", maxInputSize);
- }
-
- mCSDIndex = 0;
-
return msg;
}
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
index 07fe47e..3874cfe 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h
@@ -24,13 +24,13 @@
namespace android {
+struct ABuffer;
struct DecoderWrapper;
struct NuPlayer::Decoder : public AHandler {
Decoder(const sp<AMessage> &notify, const sp<Surface> &surface = NULL);
- void configure(
- const sp<MetaData> &meta, bool ignoreCodecSpecificData);
+ void configure(const sp<MetaData> &meta);
void signalFlush();
void signalResume();
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
index b79251a..d21d4ff 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp
@@ -27,7 +27,8 @@
namespace android {
NuPlayerDriver::NuPlayerDriver()
- : mLooper(new ALooper) {
+ : mLooper(new ALooper),
+ mPlayer(false) {
mLooper->setName("NuPlayerDriver Looper");
mLooper->start(
@@ -51,7 +52,9 @@ status_t NuPlayerDriver::initCheck() {
status_t NuPlayerDriver::setDataSource(
const char *url, const KeyedVector<String8, String8> *headers) {
- return INVALID_OPERATION;
+ mPlayer->setDataSource(url, headers);
+
+ return OK;
}
status_t NuPlayerDriver::setDataSource(int fd, int64_t offset, int64_t length) {
@@ -75,25 +78,30 @@ status_t NuPlayerDriver::prepare() {
}
status_t NuPlayerDriver::prepareAsync() {
+ sendEvent(MEDIA_PREPARED);
+
return OK;
}
status_t NuPlayerDriver::start() {
mPlayer->start();
+ mPlaying = true;
return OK;
}
status_t NuPlayerDriver::stop() {
+ mPlaying = false;
return OK;
}
status_t NuPlayerDriver::pause() {
+ mPlaying = false;
return OK;
}
bool NuPlayerDriver::isPlaying() {
- return false;
+ return mPlaying;
}
status_t NuPlayerDriver::seekTo(int msec) {
@@ -101,11 +109,15 @@ status_t NuPlayerDriver::seekTo(int msec) {
}
status_t NuPlayerDriver::getCurrentPosition(int *msec) {
- return INVALID_OPERATION;
+ *msec = 0;
+
+ return OK;
}
status_t NuPlayerDriver::getDuration(int *msec) {
- return INVALID_OPERATION;
+ *msec = 0;
+
+ return OK;
}
status_t NuPlayerDriver::reset() {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
index 245f1dd..44ae3bf 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h
@@ -60,6 +60,7 @@ protected:
private:
sp<ALooper> mLooper;
sp<NuPlayer> mPlayer;
+ bool mPlaying;
DISALLOW_EVIL_CONSTRUCTORS(NuPlayerDriver);
};
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
index 57a652c..00cbec2 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp
@@ -22,6 +22,7 @@
#include <media/stagefright/foundation/ABuffer.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
namespace android {
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
index eaa004a..fb3903c 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h
@@ -22,6 +22,8 @@
namespace android {
+struct ABuffer;
+
struct NuPlayer::Renderer : public AHandler {
Renderer(const sp<MediaPlayerBase::AudioSink> &sink,
const sp<AMessage> &notify);
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
new file mode 100644
index 0000000..044e202
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h
@@ -0,0 +1,50 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef NUPLAYER_SOURCE_H_
+
+#define NUPLAYER_SOURCE_H_
+
+#include "NuPlayer.h"
+
+namespace android {
+
+struct ABuffer;
+
+struct NuPlayer::Source : public RefBase {
+ Source() {}
+
+ virtual void start() = 0;
+
+ // Returns true iff more data was available, false on EOS.
+ virtual bool feedMoreTSData() = 0;
+
+ virtual sp<MetaData> getFormat(bool audio) = 0;
+
+ virtual status_t dequeueAccessUnit(
+ bool audio, sp<ABuffer> *accessUnit) = 0;
+
+protected:
+ virtual ~Source() {}
+
+private:
+ DISALLOW_EVIL_CONSTRUCTORS(Source);
+};
+
+} // namespace android
+
+#endif // NUPLAYER_SOURCE_H_
+
diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
index 92642a8..a23beb7 100644
--- a/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
+++ b/media/libmediaplayerservice/nuplayer/NuPlayerStreamListener.cpp
@@ -22,6 +22,8 @@
#include <binder/MemoryDealer.h>
#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaErrors.h>
namespace android {
@@ -62,7 +64,10 @@ void NuPlayer::NuPlayerStreamListener::queueBuffer(size_t index, size_t size) {
if (mSendDataNotification) {
mSendDataNotification = false;
- (new AMessage(kWhatMoreDataQueued, mTargetID))->post();
+
+ if (mTargetID != 0) {
+ (new AMessage(kWhatMoreDataQueued, mTargetID))->post();
+ }
}
}
@@ -80,7 +85,10 @@ void NuPlayer::NuPlayerStreamListener::issueCommand(
if (mSendDataNotification) {
mSendDataNotification = false;
- (new AMessage(kWhatMoreDataQueued, mTargetID))->post();
+
+ if (mTargetID != 0) {
+ (new AMessage(kWhatMoreDataQueued, mTargetID))->post();
+ }
}
}
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.cpp b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
new file mode 100644
index 0000000..b85ac9f
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.cpp
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+//#define LOG_NDEBUG 0
+#define LOG_TAG "StreamingSource"
+#include <utils/Log.h>
+
+#include "StreamingSource.h"
+
+#include "ATSParser.h"
+#include "AnotherPacketSource.h"
+#include "NuPlayerStreamListener.h"
+
+#include <media/stagefright/foundation/ABuffer.h>
+#include <media/stagefright/foundation/ADebug.h>
+#include <media/stagefright/foundation/AMessage.h>
+#include <media/stagefright/MediaSource.h>
+#include <media/stagefright/MetaData.h>
+
+namespace android {
+
+NuPlayer::StreamingSource::StreamingSource(const sp<IStreamSource> &source)
+ : mSource(source),
+ mEOS(false) {
+}
+
+NuPlayer::StreamingSource::~StreamingSource() {
+}
+
+void NuPlayer::StreamingSource::start() {
+ mStreamListener = new NuPlayerStreamListener(mSource, 0);
+ mTSParser = new ATSParser;
+
+ mStreamListener->start();
+}
+
+bool NuPlayer::StreamingSource::feedMoreTSData() {
+ if (mEOS) {
+ return false;
+ }
+
+ for (int32_t i = 0; i < 10; ++i) {
+ char buffer[188];
+ ssize_t n = mStreamListener->read(buffer, sizeof(buffer));
+
+ if (n == 0) {
+ LOGI("input data EOS reached.");
+ mTSParser->signalEOS(ERROR_END_OF_STREAM);
+ mEOS = true;
+ break;
+ } else if (n == INFO_DISCONTINUITY) {
+ mTSParser->signalDiscontinuity(ATSParser::DISCONTINUITY_SEEK);
+ } else if (n < 0) {
+ CHECK_EQ(n, -EWOULDBLOCK);
+ break;
+ } else {
+ if (buffer[0] == 0x00) {
+ // XXX legacy
+ mTSParser->signalDiscontinuity(
+ buffer[1] == 0x00
+ ? ATSParser::DISCONTINUITY_SEEK
+ : ATSParser::DISCONTINUITY_FORMATCHANGE);
+ } else {
+ mTSParser->feedTSPacket(buffer, sizeof(buffer));
+ }
+ }
+ }
+
+ return true;
+}
+
+sp<MetaData> NuPlayer::StreamingSource::getFormat(bool audio) {
+ ATSParser::SourceType type =
+ audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO;
+
+ sp<AnotherPacketSource> source =
+ static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
+
+ if (source == NULL) {
+ return NULL;
+ }
+
+ return source->getFormat();
+}
+
+status_t NuPlayer::StreamingSource::dequeueAccessUnit(
+ bool audio, sp<ABuffer> *accessUnit) {
+ ATSParser::SourceType type =
+ audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO;
+
+ sp<AnotherPacketSource> source =
+ static_cast<AnotherPacketSource *>(mTSParser->getSource(type).get());
+
+ if (source == NULL) {
+ return -EWOULDBLOCK;
+ }
+
+ status_t finalResult;
+ if (!source->hasBufferAvailable(&finalResult)) {
+ return finalResult == OK ? -EWOULDBLOCK : finalResult;
+ }
+
+ return source->dequeueAccessUnit(accessUnit);
+}
+
+} // namespace android
+
diff --git a/media/libmediaplayerservice/nuplayer/StreamingSource.h b/media/libmediaplayerservice/nuplayer/StreamingSource.h
new file mode 100644
index 0000000..5f0a9dd
--- /dev/null
+++ b/media/libmediaplayerservice/nuplayer/StreamingSource.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef STREAMING_SOURCE_H_
+
+#define STREAMING_SOURCE_H_
+
+#include "NuPlayer.h"
+#include "NuPlayerSource.h"
+
+namespace android {
+
+struct ABuffer;
+struct ATSParser;
+
+struct NuPlayer::StreamingSource : public NuPlayer::Source {
+ StreamingSource(const sp<IStreamSource> &source);
+
+ void start();
+
+ // Returns true iff more data was available, false on EOS.
+ bool feedMoreTSData();
+
+ sp<MetaData> getFormat(bool audio);
+ status_t dequeueAccessUnit(bool audio, sp<ABuffer> *accessUnit);
+
+protected:
+ virtual ~StreamingSource();
+
+private:
+ sp<IStreamSource> mSource;
+ bool mEOS;
+ sp<NuPlayerStreamListener> mStreamListener;
+ sp<ATSParser> mTSParser;
+
+ DISALLOW_EVIL_CONSTRUCTORS(StreamingSource);
+};
+
+} // namespace android
+
+#endif // STREAMING_SOURCE_H_
diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp
index 3bb61f2..39e0c51 100644
--- a/media/libstagefright/ACodec.cpp
+++ b/media/libstagefright/ACodec.cpp
@@ -1082,7 +1082,7 @@ bool ACodec::BaseState::onOMXMessage(const sp<AMessage> &msg) {
bool ACodec::BaseState::onOMXEvent(
OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
if (event != OMX_EventError) {
- LOGI("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
+ LOGV("[%s] EVENT(%d, 0x%08lx, 0x%08lx)",
mCodec->mComponentName.c_str(), event, data1, data2);
return false;
@@ -1520,7 +1520,7 @@ ACodec::LoadedToIdleState::LoadedToIdleState(ACodec *codec)
}
void ACodec::LoadedToIdleState::stateEntered() {
- LOGI("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
+ LOGV("[%s] Now Loaded->Idle", mCodec->mComponentName.c_str());
CHECK_EQ(allocateBuffers(), (status_t)OK);
}
@@ -1577,7 +1577,7 @@ ACodec::IdleToExecutingState::IdleToExecutingState(ACodec *codec)
}
void ACodec::IdleToExecutingState::stateEntered() {
- LOGI("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
+ LOGV("[%s] Now Idle->Executing", mCodec->mComponentName.c_str());
}
bool ACodec::IdleToExecutingState::onMessageReceived(const sp<AMessage> &msg) {
@@ -1661,7 +1661,7 @@ void ACodec::ExecutingState::resume() {
}
void ACodec::ExecutingState::stateEntered() {
- LOGI("[%s] Now Executing", mCodec->mComponentName.c_str());
+ LOGV("[%s] Now Executing", mCodec->mComponentName.c_str());
mCodec->processDeferredMessages();
}
@@ -1787,7 +1787,7 @@ bool ACodec::OutputPortSettingsChangedState::onMessageReceived(
}
void ACodec::OutputPortSettingsChangedState::stateEntered() {
- LOGI("[%s] Now handling output port settings change",
+ LOGV("[%s] Now handling output port settings change",
mCodec->mComponentName.c_str());
}
@@ -1868,7 +1868,7 @@ bool ACodec::ExecutingToIdleState::onMessageReceived(const sp<AMessage> &msg) {
}
void ACodec::ExecutingToIdleState::stateEntered() {
- LOGI("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
+ LOGV("[%s] Now Executing->Idle", mCodec->mComponentName.c_str());
}
bool ACodec::ExecutingToIdleState::onOMXEvent(
@@ -1950,7 +1950,7 @@ bool ACodec::IdleToLoadedState::onMessageReceived(const sp<AMessage> &msg) {
}
void ACodec::IdleToLoadedState::stateEntered() {
- LOGI("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
+ LOGV("[%s] Now Idle->Loaded", mCodec->mComponentName.c_str());
}
bool ACodec::IdleToLoadedState::onOMXEvent(
@@ -1961,7 +1961,7 @@ bool ACodec::IdleToLoadedState::onOMXEvent(
CHECK_EQ(data1, (OMX_U32)OMX_CommandStateSet);
CHECK_EQ(data2, (OMX_U32)OMX_StateLoaded);
- LOGI("[%s] Now Loaded", mCodec->mComponentName.c_str());
+ LOGV("[%s] Now Loaded", mCodec->mComponentName.c_str());
CHECK_EQ(mCodec->mOMX->freeNode(mCodec->mNode), (status_t)OK);
@@ -1995,12 +1995,12 @@ bool ACodec::ErrorState::onMessageReceived(const sp<AMessage> &msg) {
}
void ACodec::ErrorState::stateEntered() {
- LOGI("[%s] Now in ErrorState", mCodec->mComponentName.c_str());
+ LOGV("[%s] Now in ErrorState", mCodec->mComponentName.c_str());
}
bool ACodec::ErrorState::onOMXEvent(
OMX_EVENTTYPE event, OMX_U32 data1, OMX_U32 data2) {
- LOGI("EVENT(%d, 0x%08lx, 0x%08lx)", event, data1, data2);
+ LOGV("EVENT(%d, 0x%08lx, 0x%08lx)", event, data1, data2);
return true;
}
@@ -2011,7 +2011,7 @@ ACodec::FlushingState::FlushingState(ACodec *codec)
}
void ACodec::FlushingState::stateEntered() {
- LOGI("[%s] Now Flushing", mCodec->mComponentName.c_str());
+ LOGV("[%s] Now Flushing", mCodec->mComponentName.c_str());
mFlushComplete[kPortIndexInput] = mFlushComplete[kPortIndexOutput] = false;
}
diff --git a/media/libstagefright/avc_utils.cpp b/media/libstagefright/avc_utils.cpp
index 2fe5e18..fa12cf0 100644
--- a/media/libstagefright/avc_utils.cpp
+++ b/media/libstagefright/avc_utils.cpp
@@ -14,6 +14,10 @@
* limitations under the License.
*/
+//#define LOG_NDEBUG 0
+#define LOG_TAG "avc_utils"
+#include <utils/Log.h>
+
#include "include/avc_utils.h"
#include <media/stagefright/foundation/ABitReader.h>
diff --git a/media/libstagefright/httplive/LiveDataSource.cpp b/media/libstagefright/httplive/LiveDataSource.cpp
index 25e2902..5f5c6d4 100644
--- a/media/libstagefright/httplive/LiveDataSource.cpp
+++ b/media/libstagefright/httplive/LiveDataSource.cpp
@@ -54,9 +54,40 @@ size_t LiveDataSource::countQueuedBuffers() {
return mBufferQueue.size();
}
+ssize_t LiveDataSource::readAtNonBlocking(
+ off64_t offset, void *data, size_t size) {
+ Mutex::Autolock autoLock(mLock);
+
+ if (offset != mOffset) {
+ LOGE("Attempt at reading non-sequentially from LiveDataSource.");
+ return -EPIPE;
+ }
+
+ size_t totalAvailable = 0;
+ for (List<sp<ABuffer> >::iterator it = mBufferQueue.begin();
+ it != mBufferQueue.end(); ++it) {
+ sp<ABuffer> buffer = *it;
+
+ totalAvailable += buffer->size();
+
+ if (totalAvailable >= size) {
+ break;
+ }
+ }
+
+ if (totalAvailable < size) {
+ return mFinalResult == OK ? -EWOULDBLOCK : mFinalResult;
+ }
+
+ return readAt_l(offset, data, size);
+}
+
ssize_t LiveDataSource::readAt(off64_t offset, void *data, size_t size) {
Mutex::Autolock autoLock(mLock);
+ return readAt_l(offset, data, size);
+}
+ssize_t LiveDataSource::readAt_l(off64_t offset, void *data, size_t size) {
if (offset != mOffset) {
LOGE("Attempt at reading non-sequentially from LiveDataSource.");
return -EPIPE;
diff --git a/media/libstagefright/httplive/LiveDataSource.h b/media/libstagefright/httplive/LiveDataSource.h
index a489ec6..b7be637 100644
--- a/media/libstagefright/httplive/LiveDataSource.h
+++ b/media/libstagefright/httplive/LiveDataSource.h
@@ -33,6 +33,7 @@ struct LiveDataSource : public DataSource {
virtual status_t initCheck() const;
virtual ssize_t readAt(off64_t offset, void *data, size_t size);
+ ssize_t readAtNonBlocking(off64_t offset, void *data, size_t size);
void queueBuffer(const sp<ABuffer> &buffer);
void queueEOS(status_t finalResult);
@@ -53,6 +54,8 @@ private:
FILE *mBackupFile;
+ ssize_t readAt_l(off64_t offset, void *data, size_t size);
+
DISALLOW_EVIL_CONSTRUCTORS(LiveDataSource);
};
diff --git a/media/libstagefright/httplive/LiveSession.cpp b/media/libstagefright/httplive/LiveSession.cpp
index 5c4c5df..5b1f14d 100644
--- a/media/libstagefright/httplive/LiveSession.cpp
+++ b/media/libstagefright/httplive/LiveSession.cpp
@@ -157,9 +157,16 @@ void LiveSession::onConnect(const sp<AMessage> &msg) {
mBandwidthItems.sort(SortByBandwidth);
- if (mBandwidthItems.size() > 1) {
- // XXX Remove the lowest bitrate stream for now...
- mBandwidthItems.removeAt(0);
+ char value[PROPERTY_VALUE_MAX];
+ if (!property_get("media.httplive.enable-nuplayer", value, NULL)
+ || (strcasecmp(value, "true") && strcmp(value, "1"))) {
+ // The "legacy" player cannot deal with audio format changes,
+ // some streams use different audio encoding parameters for
+ // their lowest bandwidth stream.
+ if (mBandwidthItems.size() > 1) {
+ // XXX Remove the lowest bitrate stream for now...
+ mBandwidthItems.removeAt(0);
+ }
}
}
@@ -421,7 +428,7 @@ void LiveSession::onDownloadNext() {
++mNumRetries;
mLastPlaylistFetchTimeUs = -1;
- postMonitorQueue(1000000ll);
+ postMonitorQueue(3000000ll);
return;
}
diff --git a/media/libstagefright/include/LiveSession.h b/media/libstagefright/include/LiveSession.h
index 50c0a99..3873d5d 100644
--- a/media/libstagefright/include/LiveSession.h
+++ b/media/libstagefright/include/LiveSession.h
@@ -50,7 +50,7 @@ protected:
private:
enum {
kMaxNumQueuedFragments = 2,
- kMaxNumRetries = 3,
+ kMaxNumRetries = 5,
};
static const int64_t kMaxPlaylistAgeUs;
diff --git a/media/libstagefright/mpeg2ts/ATSParser.cpp b/media/libstagefright/mpeg2ts/ATSParser.cpp
index ee9b573..7c81ffd 100644
--- a/media/libstagefright/mpeg2ts/ATSParser.cpp
+++ b/media/libstagefright/mpeg2ts/ATSParser.cpp
@@ -334,7 +334,7 @@ void ATSParser::Stream::signalDiscontinuity(DiscontinuityType type) {
if (mStreamType == 0x1b && mSource != NULL) {
// Don't signal discontinuities on audio streams.
- mSource->queueDiscontinuity(true /* formatChange */);
+ mSource->queueDiscontinuity(type);
}
break;
}
@@ -348,7 +348,7 @@ void ATSParser::Stream::signalDiscontinuity(DiscontinuityType type) {
if (mSource != NULL) {
mSource->clear();
- mSource->queueDiscontinuity(!isASeek);
+ mSource->queueDiscontinuity(type);
}
break;
}
@@ -561,6 +561,10 @@ void ATSParser::Stream::onPayloadData(
// After a discontinuity we invalidate the queue's format
// and won't enqueue any access units to the source until
// the queue has reestablished the new format.
+
+ if (mSource->getFormat() == NULL) {
+ mSource->setFormat(mQueue.getFormat());
+ }
mSource->queueAccessUnit(accessUnit);
}
}
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
index a8fe2c1..c6edf0a 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.cpp
@@ -33,6 +33,11 @@ AnotherPacketSource::AnotherPacketSource(const sp<MetaData> &meta)
mEOSResult(OK) {
}
+void AnotherPacketSource::setFormat(const sp<MetaData> &meta) {
+ CHECK(mFormat == NULL);
+ mFormat = meta;
+}
+
AnotherPacketSource::~AnotherPacketSource() {
}
@@ -61,8 +66,12 @@ status_t AnotherPacketSource::dequeueAccessUnit(sp<ABuffer> *buffer) {
mBuffers.erase(mBuffers.begin());
int32_t discontinuity;
- if ((*buffer)->meta()->findInt32("discontinuity", &discontinuity)
- && discontinuity) {
+ if ((*buffer)->meta()->findInt32("discontinuity", &discontinuity)) {
+
+ if (discontinuity == ATSParser::DISCONTINUITY_FORMATCHANGE) {
+ mFormat.clear();
+ }
+
return INFO_DISCONTINUITY;
}
@@ -86,8 +95,11 @@ status_t AnotherPacketSource::read(
mBuffers.erase(mBuffers.begin());
int32_t discontinuity;
- if (buffer->meta()->findInt32("discontinuity", &discontinuity)
- && discontinuity) {
+ if (buffer->meta()->findInt32("discontinuity", &discontinuity)) {
+ if (discontinuity == ATSParser::DISCONTINUITY_FORMATCHANGE) {
+ mFormat.clear();
+ }
+
return INFO_DISCONTINUITY;
} else {
int64_t timeUs;
@@ -123,13 +135,10 @@ void AnotherPacketSource::queueAccessUnit(const sp<ABuffer> &buffer) {
mCondition.signal();
}
-void AnotherPacketSource::queueDiscontinuity(bool formatChange) {
+void AnotherPacketSource::queueDiscontinuity(
+ ATSParser::DiscontinuityType type) {
sp<ABuffer> buffer = new ABuffer(0);
- buffer->meta()->setInt32("discontinuity", true);
-
- if (formatChange) {
- buffer->meta()->setInt32("format-change", true);
- }
+ buffer->meta()->setInt32("discontinuity", static_cast<int32_t>(type));
Mutex::Autolock autoLock(mLock);
diff --git a/media/libstagefright/mpeg2ts/AnotherPacketSource.h b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
index f25a067..c20fca3 100644
--- a/media/libstagefright/mpeg2ts/AnotherPacketSource.h
+++ b/media/libstagefright/mpeg2ts/AnotherPacketSource.h
@@ -23,6 +23,8 @@
#include <utils/threads.h>
#include <utils/List.h>
+#include "ATSParser.h"
+
namespace android {
struct ABuffer;
@@ -30,6 +32,8 @@ struct ABuffer;
struct AnotherPacketSource : public MediaSource {
AnotherPacketSource(const sp<MetaData> &meta);
+ void setFormat(const sp<MetaData> &meta);
+
virtual status_t start(MetaData *params = NULL);
virtual status_t stop();
virtual sp<MetaData> getFormat();
@@ -42,7 +46,7 @@ struct AnotherPacketSource : public MediaSource {
status_t nextBufferTime(int64_t *timeUs);
void queueAccessUnit(const sp<ABuffer> &buffer);
- void queueDiscontinuity(bool formatChange);
+ void queueDiscontinuity(ATSParser::DiscontinuityType type);
void signalEOS(status_t result);
void clear();
diff --git a/media/libstagefright/mpeg2ts/ESQueue.cpp b/media/libstagefright/mpeg2ts/ESQueue.cpp
index 4e7759d..73efdfe 100644
--- a/media/libstagefright/mpeg2ts/ESQueue.cpp
+++ b/media/libstagefright/mpeg2ts/ESQueue.cpp
@@ -225,6 +225,14 @@ sp<ABuffer> ElementaryStreamQueue::dequeueAccessUnitAAC() {
mFormat = MakeAACCodecSpecificData(
profile, sampling_freq_index, channel_configuration);
+
+ int32_t sampleRate;
+ int32_t numChannels;
+ CHECK(mFormat->findInt32(kKeySampleRate, &sampleRate));
+ CHECK(mFormat->findInt32(kKeyChannelCount, &numChannels));
+
+ LOGI("found AAC codec config (%d Hz, %d channels)",
+ sampleRate, numChannels);
} else {
// profile_ObjectType, sampling_frequency_index, private_bits,
// channel_configuration, original_copy, home