From 5bc087c573c70c84c6a39946457590b42d392a33 Mon Sep 17 00:00:00 2001 From: Andreas Huber Date: Thu, 23 Dec 2010 10:27:40 -0800 Subject: Squashed commit of the following: commit eaeaa2672d4e0a82891493b2bde8bdd0c0e79a1b Author: Andreas Huber 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 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 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 Date: Wed Dec 22 16:25:22 2010 -0800 Make ACodec a lot less verbose. Change-Id: I94c7e499b61032321ffaf999f5ad2c913cde6a48 commit b19e1740cb4d02990a56844654b5d019987c6405 Author: Andreas Huber 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 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 Date: Wed Dec 22 15:20:27 2010 -0800 Tweak HTTP live parameters. Change-Id: If4b71e12485facc523a8a43d8213d0feb190daab commit 1e9942791538c2256b579d96c6c04264b0d8b087 Author: Andreas Huber 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 Date: Wed Dec 22 14:40:27 2010 -0800 Support for HTTP live streaming in NuPlayer. Change-Id: Iacba1c3ebaeb8d3b972185deaf4cff18c8009c54 commit ddf705ce553708bc5b13d89a878484cf839bd674 Author: Andreas Huber 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 Date: Wed Dec 22 13:33:52 2010 -0800 Refactor media data sourcing to NuPlayer::Source. Change-Id: I1db9fb08c4e527bf7b19c29978cf342c2b0a0bc9 Change-Id: I9610a097481dda58f22142eacda3ac2dba0b63f9 --- media/libmediaplayerservice/MediaPlayerService.cpp | 15 ++ media/libmediaplayerservice/nuplayer/Android.mk | 3 + .../nuplayer/HTTPLiveSource.cpp | 132 ++++++++++++++ .../nuplayer/HTTPLiveSource.h | 56 ++++++ media/libmediaplayerservice/nuplayer/NuPlayer.cpp | 193 +++++---------------- media/libmediaplayerservice/nuplayer/NuPlayer.h | 28 ++- .../nuplayer/NuPlayerDecoder.cpp | 22 +-- .../nuplayer/NuPlayerDecoder.h | 4 +- .../nuplayer/NuPlayerDriver.cpp | 22 ++- .../nuplayer/NuPlayerDriver.h | 1 + .../nuplayer/NuPlayerRenderer.cpp | 1 + .../nuplayer/NuPlayerRenderer.h | 2 + .../nuplayer/NuPlayerSource.h | 50 ++++++ .../nuplayer/NuPlayerStreamListener.cpp | 12 +- .../nuplayer/StreamingSource.cpp | 120 +++++++++++++ .../nuplayer/StreamingSource.h | 54 ++++++ media/libstagefright/ACodec.cpp | 22 +-- media/libstagefright/avc_utils.cpp | 4 + media/libstagefright/httplive/LiveDataSource.cpp | 31 ++++ media/libstagefright/httplive/LiveDataSource.h | 3 + media/libstagefright/httplive/LiveSession.cpp | 15 +- media/libstagefright/include/LiveSession.h | 2 +- media/libstagefright/mpeg2ts/ATSParser.cpp | 8 +- .../libstagefright/mpeg2ts/AnotherPacketSource.cpp | 29 ++-- media/libstagefright/mpeg2ts/AnotherPacketSource.h | 6 +- media/libstagefright/mpeg2ts/ESQueue.cpp | 8 + 26 files changed, 631 insertions(+), 212 deletions(-) create mode 100644 media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp create mode 100644 media/libmediaplayerservice/nuplayer/HTTPLiveSource.h create mode 100644 media/libmediaplayerservice/nuplayer/NuPlayerSource.h create mode 100644 media/libmediaplayerservice/nuplayer/StreamingSource.cpp create mode 100644 media/libmediaplayerservice/nuplayer/StreamingSource.h (limited to 'media') 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 + +#include "HTTPLiveSource.h" + +#include "ATSParser.h" +#include "AnotherPacketSource.h" +#include "LiveDataSource.h" +#include "LiveSession.h" + +#include +#include +#include +#include +#include + +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 NuPlayer::HTTPLiveSource::getFormat(bool audio) { + ATSParser::SourceType type = + audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO; + + sp source = + static_cast(mTSParser->getSource(type).get()); + + if (source == NULL) { + return NULL; + } + + return source->getFormat(); +} + +bool NuPlayer::HTTPLiveSource::feedMoreTSData() { + if (mEOS) { + return false; + } + + sp source = + static_cast(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 *accessUnit) { + ATSParser::SourceType type = + audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO; + + sp source = + static_cast(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 getFormat(bool audio); + status_t dequeueAccessUnit(bool audio, sp *accessUnit); + +protected: + virtual ~HTTPLiveSource(); + +private: + AString mURL; + bool mEOS; + off64_t mOffset; + sp mLiveLooper; + sp mLiveSession; + sp 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 #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 #include @@ -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 &listener) { void NuPlayer::setDataSource(const sp &source) { sp 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 *headers) { + sp msg = new AMessage(kWhatSetDataSource, id()); + msg->setObject("source", new HTTPLiveSource(url)); msg->post(); } @@ -104,14 +115,10 @@ void NuPlayer::onMessageReceived(const sp &msg) { CHECK(mSource == NULL); - void *ptr; - CHECK(msg->findPointer("source", &ptr)); - - mSource = static_cast(ptr); - mSource->decStrong(this); + sp obj; + CHECK(msg->findObject("source", &obj)); - mStreamListener = new NuPlayerStreamListener(mSource, id()); - mTSParser = new ATSParser; + mSource = static_cast(obj.get()); break; } @@ -139,7 +146,7 @@ void NuPlayer::onMessageReceived(const sp &msg) { case kWhatStart: { - mStreamListener->start(); + mSource->start(); mRenderer = new Renderer( mAudioSink, @@ -148,31 +155,27 @@ void NuPlayer::onMessageReceived(const sp &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 &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 *accessUnit) { - accessUnit->clear(); - status_t audioErr = -EWOULDBLOCK; - int64_t audioTimeUs; - - sp audioSource = - static_cast( - mTSParser->getSource(ATSParser::MPEG2ADTS_AUDIO).get()); - - if (audioSource != NULL) { - audioErr = audioSource->nextBufferTime(&audioTimeUs); - } - - status_t videoErr = -EWOULDBLOCK; - int64_t videoTimeUs; - - sp videoSource = - static_cast( - 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 *accessUnit) { - sp source = - static_cast(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, bool ignoreCodecSpecificData) { +status_t NuPlayer::instantiateDecoder(bool audio, sp *decoder) { if (*decoder != NULL) { return OK; } - ATSParser::SourceType type = - audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO; + sp meta = mSource->getFormat(audio); - sp source = - static_cast( - 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 &meta = source->getFormat(); - (*decoder)->configure(meta, ignoreCodecSpecificData); + (*decoder)->configure(meta); return OK; } @@ -479,19 +384,17 @@ status_t NuPlayer::feedDecoderInputData(bool audio, const sp &msg) { } sp 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 #include -#include "ATSParser.h" -#include "AnotherPacketSource.h" - namespace android { struct ACodec; @@ -35,6 +32,10 @@ struct NuPlayer : public AHandler { void setListener(const wp &listener); void setDataSource(const sp &source); + + void setDataSource( + const char *url, const KeyedVector *headers); + void setVideoSurface(const sp &surface); void setAudioSink(const sp &sink); void start(); @@ -45,9 +46,12 @@ protected: virtual void onMessageReceived(const sp &msg); private: - struct Renderer; struct Decoder; + struct HTTPLiveSource; struct NuPlayerStreamListener; + struct Renderer; + struct Source; + struct StreamingSource; enum { kWhatSetDataSource, @@ -62,11 +66,9 @@ private: }; wp mListener; - sp mSource; + sp mSource; sp mSurface; sp mAudioSink; - sp mStreamListener; - sp mTSParser; sp mVideoDecoder; sp mAudioDecoder; sp 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, bool ignoreCodecSpecificData); + status_t instantiateDecoder(bool audio, sp *decoder); status_t feedDecoderInputData(bool audio, const sp &msg); void renderBuffer(bool audio, const sp &msg); - status_t dequeueNextAccessUnit( - ATSParser::SourceType *type, sp *accessUnit); - - status_t dequeueAccessUnit( - ATSParser::SourceType type, sp *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 #include +#include #include #include #include @@ -42,8 +43,7 @@ NuPlayer::Decoder::Decoder( NuPlayer::Decoder::~Decoder() { } -void NuPlayer::Decoder::configure( - const sp &meta, bool ignoreCodecSpecificData) { +void NuPlayer::Decoder::configure(const sp &meta) { CHECK(mCodec == NULL); CHECK(mWrapper == NULL); @@ -55,10 +55,6 @@ void NuPlayer::Decoder::configure( sp format = makeFormat(meta); - if (ignoreCodecSpecificData) { - mCSD.clear(); - } - if (mSurface != NULL) { format->setObject("surface", mSurface); } @@ -128,6 +124,13 @@ sp NuPlayer::Decoder::makeFormat(const sp &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 NuPlayer::Decoder::makeFormat(const sp &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 ¬ify, const sp &surface = NULL); - void configure( - const sp &meta, bool ignoreCodecSpecificData); + void configure(const sp &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 *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 mLooper; sp 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 #include +#include 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 &sink, const sp ¬ify); 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 getFormat(bool audio) = 0; + + virtual status_t dequeueAccessUnit( + bool audio, sp *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 #include +#include +#include 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 + +#include "StreamingSource.h" + +#include "ATSParser.h" +#include "AnotherPacketSource.h" +#include "NuPlayerStreamListener.h" + +#include +#include +#include +#include +#include + +namespace android { + +NuPlayer::StreamingSource::StreamingSource(const sp &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 NuPlayer::StreamingSource::getFormat(bool audio) { + ATSParser::SourceType type = + audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO; + + sp source = + static_cast(mTSParser->getSource(type).get()); + + if (source == NULL) { + return NULL; + } + + return source->getFormat(); +} + +status_t NuPlayer::StreamingSource::dequeueAccessUnit( + bool audio, sp *accessUnit) { + ATSParser::SourceType type = + audio ? ATSParser::MPEG2ADTS_AUDIO : ATSParser::AVC_VIDEO; + + sp source = + static_cast(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 &source); + + void start(); + + // Returns true iff more data was available, false on EOS. + bool feedMoreTSData(); + + sp getFormat(bool audio); + status_t dequeueAccessUnit(bool audio, sp *accessUnit); + +protected: + virtual ~StreamingSource(); + +private: + sp mSource; + bool mEOS; + sp mStreamListener; + sp 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 &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 &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 &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 &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 &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 + #include "include/avc_utils.h" #include 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 >::iterator it = mBufferQueue.begin(); + it != mBufferQueue.end(); ++it) { + sp 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 &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 &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 &meta) mEOSResult(OK) { } +void AnotherPacketSource::setFormat(const sp &meta) { + CHECK(mFormat == NULL); + mFormat = meta; +} + AnotherPacketSource::~AnotherPacketSource() { } @@ -61,8 +66,12 @@ status_t AnotherPacketSource::dequeueAccessUnit(sp *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 &buffer) { mCondition.signal(); } -void AnotherPacketSource::queueDiscontinuity(bool formatChange) { +void AnotherPacketSource::queueDiscontinuity( + ATSParser::DiscontinuityType type) { sp buffer = new ABuffer(0); - buffer->meta()->setInt32("discontinuity", true); - - if (formatChange) { - buffer->meta()->setInt32("format-change", true); - } + buffer->meta()->setInt32("discontinuity", static_cast(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 #include +#include "ATSParser.h" + namespace android { struct ABuffer; @@ -30,6 +32,8 @@ struct ABuffer; struct AnotherPacketSource : public MediaSource { AnotherPacketSource(const sp &meta); + void setFormat(const sp &meta); + virtual status_t start(MetaData *params = NULL); virtual status_t stop(); virtual sp getFormat(); @@ -42,7 +46,7 @@ struct AnotherPacketSource : public MediaSource { status_t nextBufferTime(int64_t *timeUs); void queueAccessUnit(const sp &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 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 -- cgit v1.1