diff options
Diffstat (limited to 'media/libmediaplayerservice')
16 files changed, 532 insertions, 183 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> ¬ify, 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> ¬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<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_  | 
