diff options
Diffstat (limited to 'media/libmediaplayerservice')
35 files changed, 800 insertions, 648 deletions
diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk index 85c9464..caf2dfc 100644 --- a/media/libmediaplayerservice/Android.mk +++ b/media/libmediaplayerservice/Android.mk @@ -45,7 +45,6 @@ LOCAL_STATIC_LIBRARIES := \ libstagefright_rtsp \ LOCAL_C_INCLUDES := \ - $(call include-path-for, graphics corecg) \ $(TOP)/frameworks/av/media/libstagefright/include \ $(TOP)/frameworks/av/media/libstagefright/rtsp \ $(TOP)/frameworks/av/media/libstagefright/wifi-display \ diff --git a/media/libmediaplayerservice/HDCP.cpp b/media/libmediaplayerservice/HDCP.cpp index c2ac1a3..afe3936 100644 --- a/media/libmediaplayerservice/HDCP.cpp +++ b/media/libmediaplayerservice/HDCP.cpp @@ -107,11 +107,7 @@ uint32_t HDCP::getCaps() { return NO_INIT; } - // TO-DO: - // Only support HDCP_CAPS_ENCRYPT (byte-array to byte-array) for now. - // use mHDCPModule->getCaps() when the HDCP libraries get updated. - //return mHDCPModule->getCaps(); - return HDCPModule::HDCP_CAPS_ENCRYPT; + return mHDCPModule->getCaps(); } status_t HDCP::encrypt( diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp index 90aed39..74e5013 100644 --- a/media/libmediaplayerservice/MediaPlayerFactory.cpp +++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp @@ -67,6 +67,12 @@ player_type MediaPlayerFactory::getDefaultPlayerType() { return NU_PLAYER; } + // TODO: remove this EXPERIMENTAL developer settings property + if (property_get("persist.sys.media.use-nuplayer", value, NULL) + && !strcasecmp("true", value)) { + return NU_PLAYER; + } + return STAGEFRIGHT_PLAYER; } diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index a392b76..778eb9a 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -44,6 +44,7 @@ #include <utils/SystemClock.h> #include <utils/Vector.h> +#include <media/IMediaHTTPService.h> #include <media/IRemoteDisplay.h> #include <media/IRemoteDisplayClient.h> #include <media/MediaPlayerInterface.h> @@ -306,11 +307,6 @@ sp<IRemoteDisplay> MediaPlayerService::listenForRemoteDisplay( return new RemoteDisplay(client, iface.string()); } -status_t MediaPlayerService::updateProxyConfig( - const char *host, int32_t port, const char *exclusionList) { - return HTTPBase::UpdateProxyConfig(host, port, exclusionList); -} - status_t MediaPlayerService::AudioCache::dump(int fd, const Vector<String16>& args) const { const size_t SIZE = 256; @@ -590,7 +586,8 @@ sp<MediaPlayerBase> MediaPlayerService::Client::setDataSource_pre( } if (!p->hardwareOutput()) { - mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid()); + mAudioOutput = new AudioOutput(mAudioSessionId, IPCThreadState::self()->getCallingUid(), + mPid); static_cast<MediaPlayerInterface*>(p.get())->setAudioSink(mAudioOutput); } @@ -622,7 +619,9 @@ void MediaPlayerService::Client::setDataSource_post( } status_t MediaPlayerService::Client::setDataSource( - const char *url, const KeyedVector<String8, String8> *headers) + const sp<IMediaHTTPService> &httpService, + const char *url, + const KeyedVector<String8, String8> *headers) { ALOGV("setDataSource(%s)", url); if (url == NULL) @@ -657,7 +656,7 @@ status_t MediaPlayerService::Client::setDataSource( return NO_INIT; } - setDataSource_post(p, p->setDataSource(url, headers)); + setDataSource_post(p, p->setDataSource(httpService, url, headers)); return mStatus; } } @@ -1176,9 +1175,14 @@ int Antagonizer::callbackThread(void* user) } #endif -status_t MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, - audio_format_t* pFormat, - const sp<IMemoryHeap>& heap, size_t *pSize) +status_t MediaPlayerService::decode( + const sp<IMediaHTTPService> &httpService, + const char* url, + uint32_t *pSampleRate, + int* pNumChannels, + audio_format_t* pFormat, + const sp<IMemoryHeap>& heap, + size_t *pSize) { ALOGV("decode(%s)", url); sp<MediaPlayerBase> player; @@ -1206,7 +1210,7 @@ status_t MediaPlayerService::decode(const char* url, uint32_t *pSampleRate, int* static_cast<MediaPlayerInterface*>(player.get())->setAudioSink(cache); // set data source - if (player->setDataSource(url) != NO_ERROR) goto Exit; + if (player->setDataSource(httpService, url) != NO_ERROR) goto Exit; ALOGV("prepare"); player->prepareAsync(); @@ -1296,13 +1300,14 @@ Exit: #undef LOG_TAG #define LOG_TAG "AudioSink" -MediaPlayerService::AudioOutput::AudioOutput(int sessionId, int uid) +MediaPlayerService::AudioOutput::AudioOutput(int sessionId, int uid, int pid) : mCallback(NULL), mCallbackCookie(NULL), mCallbackData(NULL), mBytesWritten(0), mSessionId(sessionId), mUid(uid), + mPid(pid), mFlags(AUDIO_OUTPUT_FLAG_NONE) { ALOGV("AudioOutput(%d)", sessionId); mStreamType = AUDIO_STREAM_MUSIC; @@ -1450,7 +1455,7 @@ status_t MediaPlayerService::AudioOutput::open( format, bufferCount, mSessionId, flags); uint32_t afSampleRate; size_t afFrameCount; - uint32_t frameCount; + size_t frameCount; // offloading is only supported in callback mode for now. // offloadInfo must be present if offload flag is set @@ -1551,7 +1556,8 @@ status_t MediaPlayerService::AudioOutput::open( mSessionId, AudioTrack::TRANSFER_CALLBACK, offloadInfo, - mUid); + mUid, + mPid); } else { t = new AudioTrack( mStreamType, @@ -1566,7 +1572,8 @@ status_t MediaPlayerService::AudioOutput::open( mSessionId, AudioTrack::TRANSFER_DEFAULT, NULL, // offload info - mUid); + mUid, + mPid); } if ((t == 0) || (t->initCheck() != NO_ERROR)) { @@ -1672,7 +1679,7 @@ void MediaPlayerService::AudioOutput::switchToNextOutput() { ssize_t MediaPlayerService::AudioOutput::write(const void* buffer, size_t size) { - LOG_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback."); + LOG_ALWAYS_FATAL_IF(mCallback != NULL, "Don't call write if supplying a callback."); //ALOGV("write(%p, %u)", buffer, size); if (mTrack != 0) { diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 9c084e1..448f27a 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -72,7 +72,7 @@ class MediaPlayerService : public BnMediaPlayerService class CallbackData; public: - AudioOutput(int sessionId, int uid); + AudioOutput(int sessionId, int uid, int pid); virtual ~AudioOutput(); virtual bool ready() const { return mTrack != 0; } @@ -140,6 +140,7 @@ class MediaPlayerService : public BnMediaPlayerService float mMsecsPerFrame; int mSessionId; int mUid; + int mPid; float mSendLevel; int mAuxEffectId; static bool mIsOnEmulator; @@ -211,12 +212,12 @@ class MediaPlayerService : public BnMediaPlayerService virtual void flush() {} virtual void pause() {} virtual void close() {} - void setAudioStreamType(audio_stream_type_t streamType) {} + void setAudioStreamType(audio_stream_type_t streamType __unused) {} // stream type is not used for AudioCache virtual audio_stream_type_t getAudioStreamType() const { return AUDIO_STREAM_DEFAULT; } - void setVolume(float left, float right) {} - virtual status_t setPlaybackRatePermille(int32_t ratePermille) { return INVALID_OPERATION; } + void setVolume(float left __unused, float right __unused) {} + virtual status_t setPlaybackRatePermille(int32_t ratePermille __unused) { return INVALID_OPERATION; } uint32_t sampleRate() const { return mSampleRate; } audio_format_t format() const { return mFormat; } size_t size() const { return mSize; } @@ -256,9 +257,15 @@ public: virtual sp<IMediaPlayer> create(const sp<IMediaPlayerClient>& client, int audioSessionId); - virtual status_t decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, - audio_format_t* pFormat, - const sp<IMemoryHeap>& heap, size_t *pSize); + virtual status_t decode( + const sp<IMediaHTTPService> &httpService, + const char* url, + uint32_t *pSampleRate, + int* pNumChannels, + audio_format_t* pFormat, + const sp<IMemoryHeap>& heap, + size_t *pSize); + virtual status_t decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, audio_format_t* pFormat, @@ -272,9 +279,6 @@ public: const String8& iface); virtual status_t dump(int fd, const Vector<String16>& args); - virtual status_t updateProxyConfig( - const char *host, int32_t port, const char *exclusionList); - void removeClient(wp<Client> client); // For battery usage tracking purpose @@ -356,6 +360,7 @@ private: sp<MediaPlayerBase> createPlayer(player_type playerType); virtual status_t setDataSource( + const sp<IMediaHTTPService> &httpService, const char *url, const KeyedVector<String8, String8> *headers); diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp index 348957f..c61cf89 100644 --- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp +++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp @@ -31,6 +31,7 @@ #include <binder/MemoryHeapBase.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> +#include <media/IMediaHTTPService.h> #include <media/MediaMetadataRetrieverInterface.h> #include <media/MediaPlayerInterface.h> #include <private/media/VideoFrame.h> @@ -106,7 +107,9 @@ static sp<MediaMetadataRetrieverBase> createRetriever(player_type playerType) } status_t MetadataRetrieverClient::setDataSource( - const char *url, const KeyedVector<String8, String8> *headers) + const sp<IMediaHTTPService> &httpService, + const char *url, + const KeyedVector<String8, String8> *headers) { ALOGV("setDataSource(%s)", url); Mutex::Autolock lock(mLock); @@ -127,7 +130,7 @@ status_t MetadataRetrieverClient::setDataSource( ALOGV("player type = %d", playerType); sp<MediaMetadataRetrieverBase> p = createRetriever(playerType); if (p == NULL) return NO_INIT; - status_t ret = p->setDataSource(url, headers); + status_t ret = p->setDataSource(httpService, url, headers); if (ret == NO_ERROR) mRetriever = p; return ret; } diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h index f08f933..9d3fbe9 100644 --- a/media/libmediaplayerservice/MetadataRetrieverClient.h +++ b/media/libmediaplayerservice/MetadataRetrieverClient.h @@ -30,6 +30,7 @@ namespace android { +struct IMediaHTTPService; class IMediaPlayerService; class MemoryDealer; @@ -43,7 +44,9 @@ public: virtual void disconnect(); virtual status_t setDataSource( - const char *url, const KeyedVector<String8, String8> *headers); + const sp<IMediaHTTPService> &httpService, + const char *url, + const KeyedVector<String8, String8> *headers); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); virtual sp<IMemory> getFrameAtTime(int64_t timeUs, int option); diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp index 0a6aa90..deeddd1 100644 --- a/media/libmediaplayerservice/MidiFile.cpp +++ b/media/libmediaplayerservice/MidiFile.cpp @@ -114,7 +114,9 @@ MidiFile::~MidiFile() { } status_t MidiFile::setDataSource( - const char* path, const KeyedVector<String8, String8> *) { + const sp<IMediaHTTPService> &httpService, + const char* path, + const KeyedVector<String8, String8> *) { ALOGV("MidiFile::setDataSource url=%s", path); Mutex::Autolock lock(mMutex); diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h index 24d59b4..12802ba 100644 --- a/media/libmediaplayerservice/MidiFile.h +++ b/media/libmediaplayerservice/MidiFile.h @@ -32,7 +32,9 @@ public: virtual status_t initCheck(); virtual status_t setDataSource( - const char* path, const KeyedVector<String8, String8> *headers); + const sp<IMediaHTTPService> &httpService, + const char* path, + const KeyedVector<String8, String8> *headers); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); virtual status_t setVideoSurfaceTexture( diff --git a/media/libmediaplayerservice/MidiMetadataRetriever.cpp b/media/libmediaplayerservice/MidiMetadataRetriever.cpp index 465209f..f3cf6ef 100644 --- a/media/libmediaplayerservice/MidiMetadataRetriever.cpp +++ b/media/libmediaplayerservice/MidiMetadataRetriever.cpp @@ -22,6 +22,8 @@ #include "MidiMetadataRetriever.h" #include <media/mediametadataretriever.h> +#include <media/IMediaHTTPService.h> + namespace android { static status_t ERROR_NOT_OPEN = -1; @@ -36,7 +38,9 @@ void MidiMetadataRetriever::clearMetadataValues() } status_t MidiMetadataRetriever::setDataSource( - const char *url, const KeyedVector<String8, String8> *headers) + const sp<IMediaHTTPService> &httpService, + const char *url, + const KeyedVector<String8, String8> *headers) { ALOGV("setDataSource: %s", url? url: "NULL pointer"); Mutex::Autolock lock(mLock); @@ -44,7 +48,7 @@ status_t MidiMetadataRetriever::setDataSource( if (mMidiPlayer == 0) { mMidiPlayer = new MidiFile(); } - return mMidiPlayer->setDataSource(url, headers); + return mMidiPlayer->setDataSource(httpService, url, headers); } status_t MidiMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length) diff --git a/media/libmediaplayerservice/MidiMetadataRetriever.h b/media/libmediaplayerservice/MidiMetadataRetriever.h index 4cee42d..b8214ee 100644 --- a/media/libmediaplayerservice/MidiMetadataRetriever.h +++ b/media/libmediaplayerservice/MidiMetadataRetriever.h @@ -32,7 +32,9 @@ public: ~MidiMetadataRetriever() {} virtual status_t setDataSource( - const char *url, const KeyedVector<String8, String8> *headers); + const sp<IMediaHTTPService> &httpService, + const char *url, + const KeyedVector<String8, String8> *headers); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); virtual const char* extractMetadata(int keyCode); diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp index de61d9b..b37aee3 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.cpp +++ b/media/libmediaplayerservice/StagefrightPlayer.cpp @@ -54,8 +54,10 @@ status_t StagefrightPlayer::setUID(uid_t uid) { } status_t StagefrightPlayer::setDataSource( - const char *url, const KeyedVector<String8, String8> *headers) { - return mPlayer->setDataSource(url, headers); + const sp<IMediaHTTPService> &httpService, + const char *url, + const KeyedVector<String8, String8> *headers) { + return mPlayer->setDataSource(httpService, url, headers); } // Warning: The filedescriptor passed into this method will only be valid until @@ -187,7 +189,7 @@ status_t StagefrightPlayer::getParameter(int key, Parcel *reply) { } status_t StagefrightPlayer::getMetadata( - const media::Metadata::Filter& ids, Parcel *records) { + const media::Metadata::Filter& /* ids */, Parcel *records) { using media::Metadata; uint32_t flags = mPlayer->flags(); diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h index 600945e..e6c30ff 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.h +++ b/media/libmediaplayerservice/StagefrightPlayer.h @@ -34,7 +34,9 @@ public: virtual status_t setUID(uid_t uid); virtual status_t setDataSource( - const char *url, const KeyedVector<String8, String8> *headers); + const sp<IMediaHTTPService> &httpService, + const char *url, + const KeyedVector<String8, String8> *headers); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); diff --git a/media/libmediaplayerservice/StagefrightRecorder.cpp b/media/libmediaplayerservice/StagefrightRecorder.cpp index 4da74e1..5b7a236 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.cpp +++ b/media/libmediaplayerservice/StagefrightRecorder.cpp @@ -25,8 +25,10 @@ #include <binder/IServiceManager.h> #include <media/IMediaPlayerService.h> -#include <media/openmax/OMX_Audio.h> +#include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> +#include <media/stagefright/foundation/AMessage.h> +#include <media/stagefright/foundation/ALooper.h> #include <media/stagefright/AudioSource.h> #include <media/stagefright/AMRWriter.h> #include <media/stagefright/AACWriter.h> @@ -36,13 +38,12 @@ #include <media/stagefright/MPEG4Writer.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MetaData.h> +#include <media/stagefright/MediaCodecSource.h> #include <media/stagefright/OMXClient.h> #include <media/stagefright/OMXCodec.h> -#include <media/stagefright/SurfaceMediaSource.h> #include <media/MediaProfiles.h> #include <camera/ICamera.h> #include <camera/CameraParameters.h> -#include <gui/Surface.h> #include <utils/Errors.h> #include <sys/types.h> @@ -72,8 +73,7 @@ StagefrightRecorder::StagefrightRecorder() mAudioSource(AUDIO_SOURCE_CNT), mVideoSource(VIDEO_SOURCE_LIST_END), mCaptureTimeLapse(false), - mStarted(false), - mSurfaceMediaSource(NULL) { + mStarted(false) { ALOGV("Constructor"); reset(); @@ -82,10 +82,19 @@ StagefrightRecorder::StagefrightRecorder() StagefrightRecorder::~StagefrightRecorder() { ALOGV("Destructor"); stop(); + + if (mLooper != NULL) { + mLooper->stop(); + } } status_t StagefrightRecorder::init() { ALOGV("init"); + + mLooper = new ALooper; + mLooper->setName("recorder_looper"); + mLooper->start(); + return OK; } @@ -94,7 +103,7 @@ status_t StagefrightRecorder::init() { // while encoding GL Frames sp<IGraphicBufferProducer> StagefrightRecorder::querySurfaceMediaSource() const { ALOGV("Get SurfaceMediaSource"); - return mSurfaceMediaSource->getBufferQueue(); + return mGraphicBufferProducer; } status_t StagefrightRecorder::setAudioSource(audio_source_t as) { @@ -234,7 +243,7 @@ status_t StagefrightRecorder::setPreviewSurface(const sp<IGraphicBufferProducer> return OK; } -status_t StagefrightRecorder::setOutputFile(const char *path) { +status_t StagefrightRecorder::setOutputFile(const char * /* path */) { ALOGE("setOutputFile(const char*) must not be called"); // We don't actually support this at all, as the media_server process // no longer has permissions to create files. @@ -681,10 +690,10 @@ status_t StagefrightRecorder::setParameter( return setParamTimeLapseEnable(timeLapseEnable); } } else if (key == "time-between-time-lapse-frame-capture") { - int64_t timeBetweenTimeLapseFrameCaptureMs; - if (safe_strtoi64(value.string(), &timeBetweenTimeLapseFrameCaptureMs)) { + int64_t timeBetweenTimeLapseFrameCaptureUs; + if (safe_strtoi64(value.string(), &timeBetweenTimeLapseFrameCaptureUs)) { return setParamTimeBetweenTimeLapseFrameCapture( - 1000LL * timeBetweenTimeLapseFrameCaptureMs); + timeBetweenTimeLapseFrameCaptureUs); } } else { ALOGE("setParameter: failed to find key %s", key.string()); @@ -739,19 +748,15 @@ status_t StagefrightRecorder::setClientName(const String16& clientName) { return OK; } -status_t StagefrightRecorder::prepare() { - return OK; -} - -status_t StagefrightRecorder::start() { - CHECK_GE(mOutputFd, 0); +status_t StagefrightRecorder::prepareInternal() { + ALOGV("prepare"); + if (mOutputFd < 0) { + ALOGE("Output file descriptor is invalid"); + return INVALID_OPERATION; + } // Get UID here for permission checking mClientUid = IPCThreadState::self()->getCallingUid(); - if (mWriter != NULL) { - ALOGE("File writer is not avaialble"); - return UNKNOWN_ERROR; - } status_t status = OK; @@ -759,31 +764,97 @@ status_t StagefrightRecorder::start() { case OUTPUT_FORMAT_DEFAULT: case OUTPUT_FORMAT_THREE_GPP: case OUTPUT_FORMAT_MPEG_4: - status = startMPEG4Recording(); + status = setupMPEG4Recording(); break; case OUTPUT_FORMAT_AMR_NB: case OUTPUT_FORMAT_AMR_WB: - status = startAMRRecording(); + status = setupAMRRecording(); break; case OUTPUT_FORMAT_AAC_ADIF: case OUTPUT_FORMAT_AAC_ADTS: - status = startAACRecording(); + status = setupAACRecording(); break; case OUTPUT_FORMAT_RTP_AVP: - status = startRTPRecording(); + status = setupRTPRecording(); + break; + + case OUTPUT_FORMAT_MPEG2TS: + status = setupMPEG2TSRecording(); + break; + + default: + ALOGE("Unsupported output file format: %d", mOutputFormat); + status = UNKNOWN_ERROR; + break; + } + + return status; +} + +status_t StagefrightRecorder::prepare() { + if (mVideoSource == VIDEO_SOURCE_SURFACE) { + return prepareInternal(); + } + return OK; +} + +status_t StagefrightRecorder::start() { + ALOGV("start"); + if (mOutputFd < 0) { + ALOGE("Output file descriptor is invalid"); + return INVALID_OPERATION; + } + + status_t status = OK; + + if (mVideoSource != VIDEO_SOURCE_SURFACE) { + status = prepareInternal(); + if (status != OK) { + return status; + } + } + + if (mWriter == NULL) { + ALOGE("File writer is not avaialble"); + return UNKNOWN_ERROR; + } + + switch (mOutputFormat) { + case OUTPUT_FORMAT_DEFAULT: + case OUTPUT_FORMAT_THREE_GPP: + case OUTPUT_FORMAT_MPEG_4: + { + sp<MetaData> meta = new MetaData; + setupMPEG4MetaData(&meta); + status = mWriter->start(meta.get()); break; + } + case OUTPUT_FORMAT_AMR_NB: + case OUTPUT_FORMAT_AMR_WB: + case OUTPUT_FORMAT_AAC_ADIF: + case OUTPUT_FORMAT_AAC_ADTS: + case OUTPUT_FORMAT_RTP_AVP: case OUTPUT_FORMAT_MPEG2TS: - status = startMPEG2TSRecording(); + { + status = mWriter->start(); break; + } default: + { ALOGE("Unsupported output file format: %d", mOutputFormat); status = UNKNOWN_ERROR; break; + } + } + + if (status != OK) { + mWriter.clear(); + mWriter = NULL; } if ((status == OK) && (!mStarted)) { @@ -817,58 +888,54 @@ sp<MediaSource> StagefrightRecorder::createAudioSource() { return NULL; } - sp<MetaData> encMeta = new MetaData; + sp<AMessage> format = new AMessage; const char *mime; switch (mAudioEncoder) { case AUDIO_ENCODER_AMR_NB: case AUDIO_ENCODER_DEFAULT: - mime = MEDIA_MIMETYPE_AUDIO_AMR_NB; + format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_NB); break; case AUDIO_ENCODER_AMR_WB: - mime = MEDIA_MIMETYPE_AUDIO_AMR_WB; + format->setString("mime", MEDIA_MIMETYPE_AUDIO_AMR_WB); break; case AUDIO_ENCODER_AAC: - mime = MEDIA_MIMETYPE_AUDIO_AAC; - encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectLC); + format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); + format->setInt32("aac-profile", OMX_AUDIO_AACObjectLC); break; case AUDIO_ENCODER_HE_AAC: - mime = MEDIA_MIMETYPE_AUDIO_AAC; - encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectHE); + format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); + format->setInt32("aac-profile", OMX_AUDIO_AACObjectHE); break; case AUDIO_ENCODER_AAC_ELD: - mime = MEDIA_MIMETYPE_AUDIO_AAC; - encMeta->setInt32(kKeyAACProfile, OMX_AUDIO_AACObjectELD); + format->setString("mime", MEDIA_MIMETYPE_AUDIO_AAC); + format->setInt32("aac-profile", OMX_AUDIO_AACObjectELD); break; default: ALOGE("Unknown audio encoder: %d", mAudioEncoder); return NULL; } - encMeta->setCString(kKeyMIMEType, mime); int32_t maxInputSize; CHECK(audioSource->getFormat()->findInt32( kKeyMaxInputSize, &maxInputSize)); - encMeta->setInt32(kKeyMaxInputSize, maxInputSize); - encMeta->setInt32(kKeyChannelCount, mAudioChannels); - encMeta->setInt32(kKeySampleRate, mSampleRate); - encMeta->setInt32(kKeyBitRate, mAudioBitRate); + format->setInt32("max-input-size", maxInputSize); + format->setInt32("channel-count", mAudioChannels); + format->setInt32("sample-rate", mSampleRate); + format->setInt32("bitrate", mAudioBitRate); if (mAudioTimeScale > 0) { - encMeta->setInt32(kKeyTimeScale, mAudioTimeScale); + format->setInt32("time-scale", mAudioTimeScale); } - OMXClient client; - CHECK_EQ(client.connect(), (status_t)OK); sp<MediaSource> audioEncoder = - OMXCodec::Create(client.interface(), encMeta, - true /* createEncoder */, audioSource); + MediaCodecSource::Create(mLooper, format, audioSource); mAudioSourceNode = audioSource; return audioEncoder; } -status_t StagefrightRecorder::startAACRecording() { +status_t StagefrightRecorder::setupAACRecording() { // FIXME: // Add support for OUTPUT_FORMAT_AAC_ADIF CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_AAC_ADTS); @@ -879,16 +946,10 @@ status_t StagefrightRecorder::startAACRecording() { CHECK(mAudioSource != AUDIO_SOURCE_CNT); mWriter = new AACWriter(mOutputFd); - status_t status = startRawAudioRecording(); - if (status != OK) { - mWriter.clear(); - mWriter = NULL; - } - - return status; + return setupRawAudioRecording(); } -status_t StagefrightRecorder::startAMRRecording() { +status_t StagefrightRecorder::setupAMRRecording() { CHECK(mOutputFormat == OUTPUT_FORMAT_AMR_NB || mOutputFormat == OUTPUT_FORMAT_AMR_WB); @@ -908,15 +969,10 @@ status_t StagefrightRecorder::startAMRRecording() { } mWriter = new AMRWriter(mOutputFd); - status_t status = startRawAudioRecording(); - if (status != OK) { - mWriter.clear(); - mWriter = NULL; - } - return status; + return setupRawAudioRecording(); } -status_t StagefrightRecorder::startRawAudioRecording() { +status_t StagefrightRecorder::setupRawAudioRecording() { if (mAudioSource >= AUDIO_SOURCE_CNT) { ALOGE("Invalid audio source: %d", mAudioSource); return BAD_VALUE; @@ -942,12 +998,11 @@ status_t StagefrightRecorder::startRawAudioRecording() { mWriter->setMaxFileSize(mMaxFileSizeBytes); } mWriter->setListener(mListener); - mWriter->start(); return OK; } -status_t StagefrightRecorder::startRTPRecording() { +status_t StagefrightRecorder::setupRTPRecording() { CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_RTP_AVP); if ((mAudioSource != AUDIO_SOURCE_CNT @@ -974,7 +1029,7 @@ status_t StagefrightRecorder::startRTPRecording() { return err; } - err = setupVideoEncoder(mediaSource, mVideoBitRate, &source); + err = setupVideoEncoder(mediaSource, &source); if (err != OK) { return err; } @@ -984,10 +1039,10 @@ status_t StagefrightRecorder::startRTPRecording() { mWriter->addSource(source); mWriter->setListener(mListener); - return mWriter->start(); + return OK; } -status_t StagefrightRecorder::startMPEG2TSRecording() { +status_t StagefrightRecorder::setupMPEG2TSRecording() { CHECK_EQ(mOutputFormat, OUTPUT_FORMAT_MPEG2TS); sp<MediaWriter> writer = new MPEG2TSWriter(mOutputFd); @@ -1018,7 +1073,7 @@ status_t StagefrightRecorder::startMPEG2TSRecording() { } sp<MediaSource> encoder; - err = setupVideoEncoder(mediaSource, mVideoBitRate, &encoder); + err = setupVideoEncoder(mediaSource, &encoder); if (err != OK) { return err; @@ -1037,7 +1092,7 @@ status_t StagefrightRecorder::startMPEG2TSRecording() { mWriter = writer; - return mWriter->start(); + return OK; } void StagefrightRecorder::clipVideoFrameRate() { @@ -1278,49 +1333,14 @@ status_t StagefrightRecorder::setupMediaSource( return err; } *mediaSource = cameraSource; - } else if (mVideoSource == VIDEO_SOURCE_GRALLOC_BUFFER) { - // If using GRAlloc buffers, setup surfacemediasource. - // Later a handle to that will be passed - // to the client side when queried - status_t err = setupSurfaceMediaSource(); - if (err != OK) { - return err; - } - *mediaSource = mSurfaceMediaSource; + } else if (mVideoSource == VIDEO_SOURCE_SURFACE) { + *mediaSource = NULL; } else { return INVALID_OPERATION; } return OK; } -// setupSurfaceMediaSource creates a source with the given -// width and height and framerate. -// TODO: This could go in a static function inside SurfaceMediaSource -// similar to that in CameraSource -status_t StagefrightRecorder::setupSurfaceMediaSource() { - status_t err = OK; - mSurfaceMediaSource = new SurfaceMediaSource(mVideoWidth, mVideoHeight); - if (mSurfaceMediaSource == NULL) { - return NO_INIT; - } - - if (mFrameRate == -1) { - int32_t frameRate = 0; - CHECK (mSurfaceMediaSource->getFormat()->findInt32( - kKeyFrameRate, &frameRate)); - ALOGI("Frame rate is not explicitly set. Use the current frame " - "rate (%d fps)", frameRate); - mFrameRate = frameRate; - } else { - err = mSurfaceMediaSource->setFrameRate(mFrameRate); - } - CHECK(mFrameRate != -1); - - mIsMetaDataStoredInVideoBuffers = - mSurfaceMediaSource->isMetaDataStoredInVideoBuffers(); - return err; -} - status_t StagefrightRecorder::setupCameraSource( sp<CameraSource> *cameraSource) { status_t err = OK; @@ -1384,25 +1404,22 @@ status_t StagefrightRecorder::setupCameraSource( status_t StagefrightRecorder::setupVideoEncoder( sp<MediaSource> cameraSource, - int32_t videoBitRate, sp<MediaSource> *source) { source->clear(); - sp<MetaData> enc_meta = new MetaData; - enc_meta->setInt32(kKeyBitRate, videoBitRate); - enc_meta->setInt32(kKeyFrameRate, mFrameRate); + sp<AMessage> format = new AMessage(); switch (mVideoEncoder) { case VIDEO_ENCODER_H263: - enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_H263); + format->setString("mime", MEDIA_MIMETYPE_VIDEO_H263); break; case VIDEO_ENCODER_MPEG_4_SP: - enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_MPEG4); + format->setString("mime", MEDIA_MIMETYPE_VIDEO_MPEG4); break; case VIDEO_ENCODER_H264: - enc_meta->setCString(kKeyMIMEType, MEDIA_MIMETYPE_VIDEO_AVC); + format->setString("mime", MEDIA_MIMETYPE_VIDEO_AVC); break; default: @@ -1410,59 +1427,80 @@ status_t StagefrightRecorder::setupVideoEncoder( break; } - sp<MetaData> meta = cameraSource->getFormat(); + if (cameraSource != NULL) { + sp<MetaData> meta = cameraSource->getFormat(); - int32_t width, height, stride, sliceHeight, colorFormat; - CHECK(meta->findInt32(kKeyWidth, &width)); - CHECK(meta->findInt32(kKeyHeight, &height)); - CHECK(meta->findInt32(kKeyStride, &stride)); - CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight)); - CHECK(meta->findInt32(kKeyColorFormat, &colorFormat)); + int32_t width, height, stride, sliceHeight, colorFormat; + CHECK(meta->findInt32(kKeyWidth, &width)); + CHECK(meta->findInt32(kKeyHeight, &height)); + CHECK(meta->findInt32(kKeyStride, &stride)); + CHECK(meta->findInt32(kKeySliceHeight, &sliceHeight)); + CHECK(meta->findInt32(kKeyColorFormat, &colorFormat)); + + format->setInt32("width", width); + format->setInt32("height", height); + format->setInt32("stride", stride); + format->setInt32("slice-height", sliceHeight); + format->setInt32("color-format", colorFormat); + } else { + format->setInt32("width", mVideoWidth); + format->setInt32("height", mVideoHeight); + format->setInt32("stride", mVideoWidth); + format->setInt32("slice-height", mVideoWidth); + format->setInt32("color-format", OMX_COLOR_FormatAndroidOpaque); + + // set up time lapse/slow motion for surface source + if (mCaptureTimeLapse) { + if (mTimeBetweenTimeLapseFrameCaptureUs <= 0) { + ALOGE("Invalid mTimeBetweenTimeLapseFrameCaptureUs value: %lld", + mTimeBetweenTimeLapseFrameCaptureUs); + return BAD_VALUE; + } + format->setInt64("time-lapse", + mTimeBetweenTimeLapseFrameCaptureUs); + } + } + + format->setInt32("bitrate", mVideoBitRate); + format->setInt32("frame-rate", mFrameRate); + format->setInt32("i-frame-interval", mIFramesIntervalSec); - enc_meta->setInt32(kKeyWidth, width); - enc_meta->setInt32(kKeyHeight, height); - enc_meta->setInt32(kKeyIFramesInterval, mIFramesIntervalSec); - enc_meta->setInt32(kKeyStride, stride); - enc_meta->setInt32(kKeySliceHeight, sliceHeight); - enc_meta->setInt32(kKeyColorFormat, colorFormat); if (mVideoTimeScale > 0) { - enc_meta->setInt32(kKeyTimeScale, mVideoTimeScale); + format->setInt32("time-scale", mVideoTimeScale); } if (mVideoEncoderProfile != -1) { - enc_meta->setInt32(kKeyVideoProfile, mVideoEncoderProfile); + format->setInt32("profile", mVideoEncoderProfile); } if (mVideoEncoderLevel != -1) { - enc_meta->setInt32(kKeyVideoLevel, mVideoEncoderLevel); + format->setInt32("level", mVideoEncoderLevel); } - OMXClient client; - CHECK_EQ(client.connect(), (status_t)OK); - - uint32_t encoder_flags = 0; + uint32_t flags = 0; if (mIsMetaDataStoredInVideoBuffers) { - encoder_flags |= OMXCodec::kStoreMetaDataInVideoBuffers; + flags |= MediaCodecSource::FLAG_USE_METADATA_INPUT; } - // Do not wait for all the input buffers to become available. - // This give timelapse video recording faster response in - // receiving output from video encoder component. - if (mCaptureTimeLapse) { - encoder_flags |= OMXCodec::kOnlySubmitOneInputBufferAtOneTime; + if (cameraSource == NULL) { + flags |= MediaCodecSource::FLAG_USE_SURFACE_INPUT; } - sp<MediaSource> encoder = OMXCodec::Create( - client.interface(), enc_meta, - true /* createEncoder */, cameraSource, - NULL, encoder_flags); + sp<MediaCodecSource> encoder = + MediaCodecSource::Create(mLooper, format, cameraSource, flags); if (encoder == NULL) { ALOGW("Failed to create the encoder"); // When the encoder fails to be created, we need // release the camera source due to the camera's lock // and unlock mechanism. - cameraSource->stop(); + if (cameraSource != NULL) { + cameraSource->stop(); + } return UNKNOWN_ERROR; } + if (cameraSource == NULL) { + mGraphicBufferProducer = encoder->getGraphicBufferProducer(); + } + *source = encoder; return OK; @@ -1496,16 +1534,12 @@ status_t StagefrightRecorder::setupAudioEncoder(const sp<MediaWriter>& writer) { return OK; } -status_t StagefrightRecorder::setupMPEG4Recording( - int outputFd, - int32_t videoWidth, int32_t videoHeight, - int32_t videoBitRate, - int32_t *totalBitRate, - sp<MediaWriter> *mediaWriter) { - mediaWriter->clear(); - *totalBitRate = 0; +status_t StagefrightRecorder::setupMPEG4Recording() { + mWriter.clear(); + mTotalBitRate = 0; + status_t err = OK; - sp<MediaWriter> writer = new MPEG4Writer(outputFd); + sp<MediaWriter> writer = new MPEG4Writer(mOutputFd); if (mVideoSource < VIDEO_SOURCE_LIST_END) { @@ -1516,13 +1550,13 @@ status_t StagefrightRecorder::setupMPEG4Recording( } sp<MediaSource> encoder; - err = setupVideoEncoder(mediaSource, videoBitRate, &encoder); + err = setupVideoEncoder(mediaSource, &encoder); if (err != OK) { return err; } writer->addSource(encoder); - *totalBitRate += videoBitRate; + mTotalBitRate += mVideoBitRate; } // Audio source is added at the end if it exists. @@ -1531,7 +1565,7 @@ status_t StagefrightRecorder::setupMPEG4Recording( if (!mCaptureTimeLapse && (mAudioSource != AUDIO_SOURCE_CNT)) { err = setupAudioEncoder(writer); if (err != OK) return err; - *totalBitRate += mAudioBitRate; + mTotalBitRate += mAudioBitRate; } if (mInterleaveDurationUs > 0) { @@ -1549,22 +1583,28 @@ status_t StagefrightRecorder::setupMPEG4Recording( writer->setMaxFileSize(mMaxFileSizeBytes); } - mStartTimeOffsetMs = mEncoderProfiles->getStartTimeOffsetMs(mCameraId); + if (mVideoSource == VIDEO_SOURCE_DEFAULT + || mVideoSource == VIDEO_SOURCE_CAMERA) { + mStartTimeOffsetMs = mEncoderProfiles->getStartTimeOffsetMs(mCameraId); + } else if (mVideoSource == VIDEO_SOURCE_SURFACE) { + // surface source doesn't need large initial delay + mStartTimeOffsetMs = 200; + } if (mStartTimeOffsetMs > 0) { reinterpret_cast<MPEG4Writer *>(writer.get())-> setStartTimeOffsetMs(mStartTimeOffsetMs); } writer->setListener(mListener); - *mediaWriter = writer; + mWriter = writer; return OK; } -void StagefrightRecorder::setupMPEG4MetaData(int64_t startTimeUs, int32_t totalBitRate, - sp<MetaData> *meta) { +void StagefrightRecorder::setupMPEG4MetaData(sp<MetaData> *meta) { + int64_t startTimeUs = systemTime() / 1000; (*meta)->setInt64(kKeyTime, startTimeUs); (*meta)->setInt32(kKeyFileType, mOutputFormat); - (*meta)->setInt32(kKeyBitRate, totalBitRate); + (*meta)->setInt32(kKeyBitRate, mTotalBitRate); (*meta)->setInt32(kKey64BitFileOffset, mUse64BitFileOffset); if (mMovieTimeScale > 0) { (*meta)->setInt32(kKeyTimeScale, mMovieTimeScale); @@ -1577,27 +1617,6 @@ void StagefrightRecorder::setupMPEG4MetaData(int64_t startTimeUs, int32_t totalB } } -status_t StagefrightRecorder::startMPEG4Recording() { - int32_t totalBitRate; - status_t err = setupMPEG4Recording( - mOutputFd, mVideoWidth, mVideoHeight, - mVideoBitRate, &totalBitRate, &mWriter); - if (err != OK) { - return err; - } - - int64_t startTimeUs = systemTime() / 1000; - sp<MetaData> meta = new MetaData; - setupMPEG4MetaData(startTimeUs, totalBitRate, &meta); - - err = mWriter->start(meta.get()); - if (err != OK) { - return err; - } - - return OK; -} - status_t StagefrightRecorder::pause() { ALOGV("pause"); if (mWriter == NULL) { @@ -1637,6 +1656,8 @@ status_t StagefrightRecorder::stop() { mWriter.clear(); } + mGraphicBufferProducer.clear(); + if (mOutputFd >= 0) { ::close(mOutputFd); mOutputFd = -1; @@ -1656,7 +1677,6 @@ status_t StagefrightRecorder::stop() { addBatteryData(params); } - return err; } @@ -1708,6 +1728,7 @@ status_t StagefrightRecorder::reset() { mRotationDegrees = 0; mLatitudex10000 = -3600000; mLongitudex10000 = -3600000; + mTotalBitRate = 0; mOutputFd = -1; diff --git a/media/libmediaplayerservice/StagefrightRecorder.h b/media/libmediaplayerservice/StagefrightRecorder.h index 31f09e0..377d168 100644 --- a/media/libmediaplayerservice/StagefrightRecorder.h +++ b/media/libmediaplayerservice/StagefrightRecorder.h @@ -37,6 +37,7 @@ struct AudioSource; class MediaProfiles; class IGraphicBufferProducer; class SurfaceMediaSource; +class ALooper; struct StagefrightRecorder : public MediaRecorderBase { StagefrightRecorder(); @@ -106,6 +107,7 @@ private: int32_t mLatitudex10000; int32_t mLongitudex10000; int32_t mStartTimeOffsetMs; + int32_t mTotalBitRate; bool mCaptureTimeLapse; int64_t mTimeBetweenTimeLapseFrameCaptureUs; @@ -122,22 +124,17 @@ private: // An <IGraphicBufferProducer> pointer // will be sent to the client side using which the // frame buffers will be queued and dequeued - sp<SurfaceMediaSource> mSurfaceMediaSource; - - status_t setupMPEG4Recording( - int outputFd, - int32_t videoWidth, int32_t videoHeight, - int32_t videoBitRate, - int32_t *totalBitRate, - sp<MediaWriter> *mediaWriter); - void setupMPEG4MetaData(int64_t startTimeUs, int32_t totalBitRate, - sp<MetaData> *meta); - status_t startMPEG4Recording(); - status_t startAMRRecording(); - status_t startAACRecording(); - status_t startRawAudioRecording(); - status_t startRTPRecording(); - status_t startMPEG2TSRecording(); + sp<IGraphicBufferProducer> mGraphicBufferProducer; + sp<ALooper> mLooper; + + status_t prepareInternal(); + status_t setupMPEG4Recording(); + void setupMPEG4MetaData(sp<MetaData> *meta); + status_t setupAMRRecording(); + status_t setupAACRecording(); + status_t setupRawAudioRecording(); + status_t setupRTPRecording(); + status_t setupMPEG2TSRecording(); sp<MediaSource> createAudioSource(); status_t checkVideoEncoderCapabilities( bool *supportsCameraSourceMetaDataMode); @@ -147,14 +144,8 @@ private: // depending on the videosource type status_t setupMediaSource(sp<MediaSource> *mediaSource); status_t setupCameraSource(sp<CameraSource> *cameraSource); - // setup the surfacemediasource for the encoder - status_t setupSurfaceMediaSource(); - status_t setupAudioEncoder(const sp<MediaWriter>& writer); - status_t setupVideoEncoder( - sp<MediaSource> cameraSource, - int32_t videoBitRate, - sp<MediaSource> *source); + status_t setupVideoEncoder(sp<MediaSource> cameraSource, sp<MediaSource> *source); // Encoding parameter handling utilities status_t setParameter(const String8 &key, const String8 &value); diff --git a/media/libmediaplayerservice/TestPlayerStub.cpp b/media/libmediaplayerservice/TestPlayerStub.cpp index 5d9728a..5795773 100644 --- a/media/libmediaplayerservice/TestPlayerStub.cpp +++ b/media/libmediaplayerservice/TestPlayerStub.cpp @@ -113,7 +113,9 @@ status_t TestPlayerStub::parseUrl() // Create the test player. // Call setDataSource on the test player with the url in param. status_t TestPlayerStub::setDataSource( - const char *url, const KeyedVector<String8, String8> *headers) { + const sp<IMediaHTTPService> &httpService, + const char *url, + const KeyedVector<String8, String8> *headers) { if (!isTestUrl(url) || NULL != mHandle) { return INVALID_OPERATION; } @@ -162,7 +164,7 @@ status_t TestPlayerStub::setDataSource( } mPlayer = (*mNewPlayer)(); - return mPlayer->setDataSource(mContentUrl, headers); + return mPlayer->setDataSource(httpService, mContentUrl, headers); } // Internal cleanup. diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h index a3802eb..55bf2c8 100644 --- a/media/libmediaplayerservice/TestPlayerStub.h +++ b/media/libmediaplayerservice/TestPlayerStub.h @@ -66,7 +66,9 @@ class TestPlayerStub : public MediaPlayerInterface { // @param url Should be a test url. See class comment. virtual status_t setDataSource( - const char* url, const KeyedVector<String8, String8> *headers); + const sp<IMediaHTTPService> &httpService, + const char* url, + const KeyedVector<String8, String8> *headers); // Test player for a file descriptor source is not supported. virtual status_t setDataSource(int, int64_t, int64_t) { diff --git a/media/libmediaplayerservice/nuplayer/Android.mk b/media/libmediaplayerservice/nuplayer/Android.mk index f946c1c..f97ba57 100644 --- a/media/libmediaplayerservice/nuplayer/Android.mk +++ b/media/libmediaplayerservice/nuplayer/Android.mk @@ -11,7 +11,6 @@ LOCAL_SRC_FILES:= \ NuPlayerStreamListener.cpp \ RTSPSource.cpp \ StreamingSource.cpp \ - mp4/MP4Source.cpp \ LOCAL_C_INCLUDES := \ $(TOP)/frameworks/av/media/libstagefright/httplive \ diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp index b04e7a6..06aac33 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp +++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp @@ -33,17 +33,16 @@ namespace android { NuPlayer::GenericSource::GenericSource( const sp<AMessage> ¬ify, + const sp<IMediaHTTPService> &httpService, const char *url, - const KeyedVector<String8, String8> *headers, - bool uidValid, - uid_t uid) + const KeyedVector<String8, String8> *headers) : Source(notify), mDurationUs(0ll), mAudioIsVorbis(false) { DataSource::RegisterDefaultSniffers(); sp<DataSource> dataSource = - DataSource::CreateFromURI(url, headers); + DataSource::CreateFromURI(httpService, url, headers); CHECK(dataSource != NULL); initFromDataSource(dataSource); diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h index 2da680c..20d597e 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.h +++ b/media/libmediaplayerservice/nuplayer/GenericSource.h @@ -33,10 +33,9 @@ struct MediaSource; struct NuPlayer::GenericSource : public NuPlayer::Source { GenericSource( const sp<AMessage> ¬ify, + const sp<IMediaHTTPService> &httpService, const char *url, - const KeyedVector<String8, String8> *headers, - bool uidValid = false, - uid_t uid = 0); + const KeyedVector<String8, String8> *headers); GenericSource( const sp<AMessage> ¬ify, diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp index f1782cc..cbedf5c 100644 --- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp +++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.cpp @@ -24,6 +24,7 @@ #include "LiveDataSource.h" #include "LiveSession.h" +#include <media/IMediaHTTPService.h> #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> @@ -34,13 +35,12 @@ namespace android { NuPlayer::HTTPLiveSource::HTTPLiveSource( const sp<AMessage> ¬ify, + const sp<IMediaHTTPService> &httpService, const char *url, - const KeyedVector<String8, String8> *headers, - bool uidValid, uid_t uid) + const KeyedVector<String8, String8> *headers) : Source(notify), + mHTTPService(httpService), mURL(url), - mUIDValid(uidValid), - mUID(uid), mFlags(0), mFinalResult(OK), mOffset(0), @@ -79,8 +79,7 @@ void NuPlayer::HTTPLiveSource::prepareAsync() { mLiveSession = new LiveSession( notify, (mFlags & kFlagIncognito) ? LiveSession::kFlagIncognito : 0, - mUIDValid, - mUID); + mHTTPService); mLiveLooper->registerHandler(mLiveSession); @@ -140,7 +139,7 @@ status_t NuPlayer::HTTPLiveSource::selectTrack(size_t trackIndex, bool select) { // LiveSession::selectTrack returns BAD_VALUE when selecting the currently // selected track, or unselecting a non-selected track. In this case it's an // no-op so we return OK. - return (err == OK || err == BAD_VALUE) ? OK : err; + return (err == OK || err == BAD_VALUE) ? (status_t)OK : err; } status_t NuPlayer::HTTPLiveSource::seekTo(int64_t seekTimeUs) { diff --git a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h index bcc3f8b..4d7251f 100644 --- a/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h +++ b/media/libmediaplayerservice/nuplayer/HTTPLiveSource.h @@ -28,10 +28,9 @@ struct LiveSession; struct NuPlayer::HTTPLiveSource : public NuPlayer::Source { HTTPLiveSource( const sp<AMessage> ¬ify, + const sp<IMediaHTTPService> &httpService, const char *url, - const KeyedVector<String8, String8> *headers, - bool uidValid = false, - uid_t uid = 0); + const KeyedVector<String8, String8> *headers); virtual void prepareAsync(); virtual void start(); @@ -61,10 +60,9 @@ private: kWhatFetchSubtitleData, }; + sp<IMediaHTTPService> mHTTPService; AString mURL; KeyedVector<String8, String8> mExtraHeaders; - bool mUIDValid; - uid_t mUID; uint32_t mFlags; status_t mFinalResult; off64_t mOffset; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 25d55a3..d8d939a 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -28,18 +28,13 @@ #include "RTSPSource.h" #include "StreamingSource.h" #include "GenericSource.h" -#include "mp4/MP4Source.h" #include "ATSParser.h" -#include "SoftwareRenderer.h" - -#include <cutils/properties.h> // for property_get #include <media/stagefright/foundation/hexdump.h> #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/MediaErrors.h> #include <media/stagefright/MetaData.h> @@ -148,7 +143,6 @@ NuPlayer::NuPlayer() : mUIDValid(false), mSourceFlags(0), mVideoIsAVC(false), - mNeedsSwRenderer(false), mAudioEOS(false), mVideoEOS(false), mScanSourcesPending(false), @@ -183,14 +177,7 @@ void NuPlayer::setDataSourceAsync(const sp<IStreamSource> &source) { sp<AMessage> notify = new AMessage(kWhatSourceNotify, id()); - char prop[PROPERTY_VALUE_MAX]; - if (property_get("media.stagefright.use-mp4source", prop, NULL) - && (!strcmp(prop, "1") || !strcasecmp(prop, "true"))) { - msg->setObject("source", new MP4Source(notify, source)); - } else { - msg->setObject("source", new StreamingSource(notify, source)); - } - + msg->setObject("source", new StreamingSource(notify, source)); msg->post(); } @@ -212,7 +199,9 @@ static bool IsHTTPLiveURL(const char *url) { } void NuPlayer::setDataSourceAsync( - const char *url, const KeyedVector<String8, String8> *headers) { + const sp<IMediaHTTPService> &httpService, + const char *url, + const KeyedVector<String8, String8> *headers) { sp<AMessage> msg = new AMessage(kWhatSetDataSource, id()); size_t len = strlen(url); @@ -220,16 +209,18 @@ void NuPlayer::setDataSourceAsync( sp<Source> source; if (IsHTTPLiveURL(url)) { - source = new HTTPLiveSource(notify, url, headers, mUIDValid, mUID); + source = new HTTPLiveSource(notify, httpService, url, headers); } else if (!strncasecmp(url, "rtsp://", 7)) { - source = new RTSPSource(notify, url, headers, mUIDValid, mUID); + source = new RTSPSource( + notify, httpService, url, headers, mUIDValid, mUID); } else if ((!strncasecmp(url, "http://", 7) || !strncasecmp(url, "https://", 8)) && ((len >= 4 && !strcasecmp(".sdp", &url[len - 4])) || strstr(url, ".sdp?"))) { - source = new RTSPSource(notify, url, headers, mUIDValid, mUID, true); + source = new RTSPSource( + notify, httpService, url, headers, mUIDValid, mUID, true); } else { - source = new GenericSource(notify, url, headers, mUIDValid, mUID); + source = new GenericSource(notify, httpService, url, headers); } msg->setObject("source", source); @@ -447,7 +438,6 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { ALOGV("kWhatStart"); mVideoIsAVC = false; - mNeedsSwRenderer = false; mAudioEOS = false; mVideoEOS = false; mSkipRenderingAudioUntilMediaTimeUs = -1; @@ -538,24 +528,21 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { { bool audio = msg->what() == kWhatAudioNotify; - sp<AMessage> codecRequest; - CHECK(msg->findMessage("codec-request", &codecRequest)); - int32_t what; - CHECK(codecRequest->findInt32("what", &what)); + CHECK(msg->findInt32("what", &what)); - if (what == ACodec::kWhatFillThisBuffer) { + if (what == Decoder::kWhatFillThisBuffer) { status_t err = feedDecoderInputData( - audio, codecRequest); + audio, msg); if (err == -EWOULDBLOCK) { if (mSource->feedMoreTSData() == OK) { msg->post(10000ll); } } - } else if (what == ACodec::kWhatEOS) { + } else if (what == Decoder::kWhatEOS) { int32_t err; - CHECK(codecRequest->findInt32("err", &err)); + CHECK(msg->findInt32("err", &err)); if (err == ERROR_END_OF_STREAM) { ALOGV("got %s decoder EOS", audio ? "audio" : "video"); @@ -566,7 +553,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { } mRenderer->queueEOS(audio, err); - } else if (what == ACodec::kWhatFlushCompleted) { + } else if (what == Decoder::kWhatFlushCompleted) { bool needShutdown; if (audio) { @@ -595,14 +582,17 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { } finishFlushIfPossible(); - } else if (what == ACodec::kWhatOutputFormatChanged) { + } else if (what == Decoder::kWhatOutputFormatChanged) { + sp<AMessage> format; + CHECK(msg->findMessage("format", &format)); + if (audio) { int32_t numChannels; - CHECK(codecRequest->findInt32( + CHECK(format->findInt32( "channel-count", &numChannels)); int32_t sampleRate; - CHECK(codecRequest->findInt32("sample-rate", &sampleRate)); + CHECK(format->findInt32("sample-rate", &sampleRate)); ALOGV("Audio output format changed to %d Hz, %d channels", sampleRate, numChannels); @@ -626,7 +616,7 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { } int32_t channelMask; - if (!codecRequest->findInt32("channel-mask", &channelMask)) { + if (!format->findInt32("channel-mask", &channelMask)) { channelMask = CHANNEL_MASK_USE_CHANNEL_ORDER; } @@ -647,11 +637,11 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { // video int32_t width, height; - CHECK(codecRequest->findInt32("width", &width)); - CHECK(codecRequest->findInt32("height", &height)); + CHECK(format->findInt32("width", &width)); + CHECK(format->findInt32("height", &height)); int32_t cropLeft, cropTop, cropRight, cropBottom; - CHECK(codecRequest->findRect( + CHECK(format->findRect( "crop", &cropLeft, &cropTop, &cropRight, &cropBottom)); @@ -684,22 +674,8 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { notifyListener( MEDIA_SET_VIDEO_SIZE, displayWidth, displayHeight); - - if (mNeedsSwRenderer && mNativeWindow != NULL) { - int32_t colorFormat; - CHECK(codecRequest->findInt32("color-format", &colorFormat)); - - sp<MetaData> meta = new MetaData; - meta->setInt32(kKeyWidth, width); - meta->setInt32(kKeyHeight, height); - meta->setRect(kKeyCropRect, cropLeft, cropTop, cropRight, cropBottom); - meta->setInt32(kKeyColorFormat, colorFormat); - - mRenderer->setSoftRenderer( - new SoftwareRenderer(mNativeWindow->getNativeWindow(), meta)); - } } - } else if (what == ACodec::kWhatShutdownCompleted) { + } else if (what == Decoder::kWhatShutdownCompleted) { ALOGV("%s shutdown completed", audio ? "audio" : "video"); if (audio) { mAudioDecoder.clear(); @@ -714,22 +690,15 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { } finishFlushIfPossible(); - } else if (what == ACodec::kWhatError) { + } else if (what == Decoder::kWhatError) { ALOGE("Received error from %s decoder, aborting playback.", audio ? "audio" : "video"); mRenderer->queueEOS(audio, UNKNOWN_ERROR); - } else if (what == ACodec::kWhatDrainThisBuffer) { - renderBuffer(audio, codecRequest); - } else if (what == ACodec::kWhatComponentAllocated) { - if (!audio) { - AString name; - CHECK(codecRequest->findString("componentName", &name)); - mNeedsSwRenderer = name.startsWith("OMX.google."); - } - } else if (what != ACodec::kWhatComponentConfigured - && what != ACodec::kWhatBuffersAllocated) { - ALOGV("Unhandled codec notification %d '%c%c%c%c'.", + } else if (what == Decoder::kWhatDrainThisBuffer) { + renderBuffer(audio, msg); + } else { + ALOGV("Unhandled decoder notification %d '%c%c%c%c'.", what, what >> 24, (what >> 16) & 0xff, @@ -930,8 +899,7 @@ status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) { *decoder = audio ? new Decoder(notify) : new Decoder(notify, mNativeWindow); - looper()->registerHandler(*decoder); - + (*decoder)->init(); (*decoder)->configure(format); return OK; @@ -1531,7 +1499,7 @@ void NuPlayer::Source::notifyPrepared(status_t err) { notify->post(); } -void NuPlayer::Source::onMessageReceived(const sp<AMessage> &msg) { +void NuPlayer::Source::onMessageReceived(const sp<AMessage> & /* msg */) { TRESPASS(); } diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h index 590e1f2..f1d3d55 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h @@ -24,7 +24,6 @@ namespace android { -struct ACodec; struct MetaData; struct NuPlayerDriver; @@ -38,7 +37,9 @@ struct NuPlayer : public AHandler { void setDataSourceAsync(const sp<IStreamSource> &source); void setDataSourceAsync( - const char *url, const KeyedVector<String8, String8> *headers); + const sp<IMediaHTTPService> &httpService, + const char *url, + const KeyedVector<String8, String8> *headers); void setDataSourceAsync(int fd, int64_t offset, int64_t length); @@ -116,7 +117,6 @@ private: sp<MediaPlayerBase::AudioSink> mAudioSink; sp<Decoder> mVideoDecoder; bool mVideoIsAVC; - bool mNeedsSwRenderer; sp<Decoder> mAudioDecoder; sp<Renderer> mRenderer; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp index 2423fd5..469c9ca 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp @@ -17,14 +17,17 @@ //#define LOG_NDEBUG 0 #define LOG_TAG "NuPlayerDecoder" #include <utils/Log.h> +#include <inttypes.h> #include "NuPlayerDecoder.h" +#include <media/ICrypto.h> #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/MediaCodec.h> #include <media/stagefright/MediaDefs.h> +#include <media/stagefright/MediaErrors.h> namespace android { @@ -32,122 +35,425 @@ NuPlayer::Decoder::Decoder( const sp<AMessage> ¬ify, const sp<NativeWindowWrapper> &nativeWindow) : mNotify(notify), - mNativeWindow(nativeWindow) { + mNativeWindow(nativeWindow), + mBufferGeneration(0), + mComponentName("decoder") { + // Every decoder has its own looper because MediaCodec operations + // are blocking, but NuPlayer needs asynchronous operations. + mDecoderLooper = new ALooper; + mDecoderLooper->setName("NuPlayerDecoder"); + mDecoderLooper->start(false, false, ANDROID_PRIORITY_AUDIO); + + mCodecLooper = new ALooper; + mCodecLooper->setName("NuPlayerDecoder-MC"); + mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO); } NuPlayer::Decoder::~Decoder() { } -void NuPlayer::Decoder::configure(const sp<AMessage> &format) { +void NuPlayer::Decoder::onConfigure(const sp<AMessage> &format) { CHECK(mCodec == NULL); + ++mBufferGeneration; + AString mime; CHECK(format->findString("mime", &mime)); - sp<AMessage> notifyMsg = - new AMessage(kWhatCodecNotify, id()); + sp<Surface> surface = NULL; + if (mNativeWindow != NULL) { + surface = mNativeWindow->getSurfaceTextureClient(); + } - mCSDIndex = 0; - for (size_t i = 0;; ++i) { - sp<ABuffer> csd; - if (!format->findBuffer(StringPrintf("csd-%d", i).c_str(), &csd)) { - break; - } + mComponentName = mime; + mComponentName.append(" decoder"); + ALOGV("[%s] onConfigure (surface=%p)", mComponentName.c_str(), surface.get()); - mCSD.push(csd); + mCodec = MediaCodec::CreateByType(mCodecLooper, mime.c_str(), false /* encoder */); + if (mCodec == NULL) { + ALOGE("Failed to create %s decoder", mime.c_str()); + handleError(UNKNOWN_ERROR); + return; } + mCodec->getName(&mComponentName); + if (mNativeWindow != NULL) { - format->setObject("native-window", mNativeWindow); + // disconnect from surface as MediaCodec will reconnect + CHECK_EQ((int)NO_ERROR, + native_window_api_disconnect( + surface.get(), + NATIVE_WINDOW_API_MEDIA)); + } + status_t err = mCodec->configure( + format, surface, NULL /* crypto */, 0 /* flags */); + if (err != OK) { + ALOGE("Failed to configure %s decoder (err=%d)", mComponentName.c_str(), err); + handleError(err); + return; + } + // the following should work in configured state + CHECK_EQ((status_t)OK, mCodec->getOutputFormat(&mOutputFormat)); + CHECK_EQ((status_t)OK, mCodec->getInputFormat(&mInputFormat)); + + err = mCodec->start(); + if (err != OK) { + ALOGE("Failed to start %s decoder (err=%d)", mComponentName.c_str(), err); + handleError(err); + return; } - // Current video decoders do not return from OMX_FillThisBuffer - // quickly, violating the OpenMAX specs, until that is remedied - // we need to invest in an extra looper to free the main event - // queue. - bool needDedicatedLooper = !strncasecmp(mime.c_str(), "video/", 6); + // the following should work after start + CHECK_EQ((status_t)OK, mCodec->getInputBuffers(&mInputBuffers)); + CHECK_EQ((status_t)OK, mCodec->getOutputBuffers(&mOutputBuffers)); + ALOGV("[%s] got %zu input and %zu output buffers", + mComponentName.c_str(), + mInputBuffers.size(), + mOutputBuffers.size()); - mFormat = format; - mCodec = new ACodec; + requestCodecNotification(); +} - if (needDedicatedLooper && mCodecLooper == NULL) { - mCodecLooper = new ALooper; - mCodecLooper->setName("NuPlayerDecoder"); - mCodecLooper->start(false, false, ANDROID_PRIORITY_AUDIO); +void NuPlayer::Decoder::requestCodecNotification() { + if (mCodec != NULL) { + sp<AMessage> reply = new AMessage(kWhatCodecNotify, id()); + reply->setInt32("generation", mBufferGeneration); + mCodec->requestActivityNotification(reply); } +} - (needDedicatedLooper ? mCodecLooper : looper())->registerHandler(mCodec); +bool NuPlayer::Decoder::isStaleReply(const sp<AMessage> &msg) { + int32_t generation; + CHECK(msg->findInt32("generation", &generation)); + return generation != mBufferGeneration; +} - mCodec->setNotificationMessage(notifyMsg); - mCodec->initiateSetup(format); +void NuPlayer::Decoder::init() { + mDecoderLooper->registerHandler(this); } -void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) { - switch (msg->what()) { - case kWhatCodecNotify: - { - int32_t what; - CHECK(msg->findInt32("what", &what)); - - if (what == ACodec::kWhatFillThisBuffer) { - onFillThisBuffer(msg); - } else { - sp<AMessage> notify = mNotify->dup(); - notify->setMessage("codec-request", msg); - notify->post(); - } - break; +void NuPlayer::Decoder::configure(const sp<AMessage> &format) { + sp<AMessage> msg = new AMessage(kWhatConfigure, id()); + msg->setMessage("format", format); + msg->post(); +} + +void NuPlayer::Decoder::handleError(int32_t err) +{ + sp<AMessage> notify = mNotify->dup(); + notify->setInt32("what", kWhatError); + notify->setInt32("err", err); + notify->post(); +} + +bool NuPlayer::Decoder::handleAnInputBuffer() { + size_t bufferIx = -1; + status_t res = mCodec->dequeueInputBuffer(&bufferIx); + ALOGV("[%s] dequeued input: %d", + mComponentName.c_str(), res == OK ? (int)bufferIx : res); + if (res != OK) { + if (res != -EAGAIN) { + handleError(res); } + return false; + } - default: - TRESPASS(); - break; + CHECK_LT(bufferIx, mInputBuffers.size()); + + sp<AMessage> reply = new AMessage(kWhatInputBufferFilled, id()); + reply->setSize("buffer-ix", bufferIx); + reply->setInt32("generation", mBufferGeneration); + + sp<AMessage> notify = mNotify->dup(); + notify->setInt32("what", kWhatFillThisBuffer); + notify->setBuffer("buffer", mInputBuffers[bufferIx]); + notify->setMessage("reply", reply); + notify->post(); + return true; +} + +void android::NuPlayer::Decoder::onInputBufferFilled(const sp<AMessage> &msg) { + size_t bufferIx; + CHECK(msg->findSize("buffer-ix", &bufferIx)); + CHECK_LT(bufferIx, mInputBuffers.size()); + sp<ABuffer> codecBuffer = mInputBuffers[bufferIx]; + + sp<ABuffer> buffer; + bool hasBuffer = msg->findBuffer("buffer", &buffer); + if (buffer == NULL /* includes !hasBuffer */) { + int32_t streamErr = ERROR_END_OF_STREAM; + CHECK(msg->findInt32("err", &streamErr) || !hasBuffer); + + if (streamErr == OK) { + /* buffers are returned to hold on to */ + return; + } + + // attempt to queue EOS + status_t err = mCodec->queueInputBuffer( + bufferIx, + 0, + 0, + 0, + MediaCodec::BUFFER_FLAG_EOS); + if (streamErr == ERROR_END_OF_STREAM && err != OK) { + streamErr = err; + // err will not be ERROR_END_OF_STREAM + } + + if (streamErr != ERROR_END_OF_STREAM) { + handleError(streamErr); + } + } else { + int64_t timeUs = 0; + uint32_t flags = 0; + CHECK(buffer->meta()->findInt64("timeUs", &timeUs)); + + int32_t eos; + // we do not expect CODECCONFIG or SYNCFRAME for decoder + if (buffer->meta()->findInt32("eos", &eos) && eos) { + flags |= MediaCodec::BUFFER_FLAG_EOS; + } + + // copy into codec buffer + if (buffer != codecBuffer) { + CHECK_LE(buffer->size(), codecBuffer->capacity()); + codecBuffer->setRange(0, buffer->size()); + memcpy(codecBuffer->data(), buffer->data(), buffer->size()); + } + + status_t err = mCodec->queueInputBuffer( + bufferIx, + codecBuffer->offset(), + codecBuffer->size(), + timeUs, + flags); + if (err != OK) { + ALOGE("Failed to queue input buffer for %s (err=%d)", + mComponentName.c_str(), err); + handleError(err); + } } } -void NuPlayer::Decoder::onFillThisBuffer(const sp<AMessage> &msg) { - sp<AMessage> reply; - CHECK(msg->findMessage("reply", &reply)); +bool NuPlayer::Decoder::handleAnOutputBuffer() { + size_t bufferIx = -1; + size_t offset; + size_t size; + int64_t timeUs; + uint32_t flags; + status_t res = mCodec->dequeueOutputBuffer( + &bufferIx, &offset, &size, &timeUs, &flags); + + if (res != OK) { + ALOGV("[%s] dequeued output: %d", mComponentName.c_str(), res); + } else { + ALOGV("[%s] dequeued output: %d (time=%lld flags=%" PRIu32 ")", + mComponentName.c_str(), (int)bufferIx, timeUs, flags); + } -#if 0 - sp<ABuffer> outBuffer; - CHECK(msg->findBuffer("buffer", &outBuffer)); -#else - sp<ABuffer> outBuffer; -#endif + if (res == INFO_OUTPUT_BUFFERS_CHANGED) { + res = mCodec->getOutputBuffers(&mOutputBuffers); + if (res != OK) { + ALOGE("Failed to get output buffers for %s after INFO event (err=%d)", + mComponentName.c_str(), res); + handleError(res); + return false; + } + // NuPlayer ignores this + return true; + } else if (res == INFO_FORMAT_CHANGED) { + sp<AMessage> format = new AMessage(); + res = mCodec->getOutputFormat(&format); + if (res != OK) { + ALOGE("Failed to get output format for %s after INFO event (err=%d)", + mComponentName.c_str(), res); + handleError(res); + return false; + } - if (mCSDIndex < mCSD.size()) { - outBuffer = mCSD.editItemAt(mCSDIndex++); - outBuffer->meta()->setInt64("timeUs", 0); + sp<AMessage> notify = mNotify->dup(); + notify->setInt32("what", kWhatOutputFormatChanged); + notify->setMessage("format", format); + notify->post(); + return true; + } else if (res == INFO_DISCONTINUITY) { + // nothing to do + return true; + } else if (res != OK) { + if (res != -EAGAIN) { + handleError(res); + } + return false; + } - reply->setBuffer("buffer", outBuffer); - reply->post(); - return; + CHECK_LT(bufferIx, mOutputBuffers.size()); + sp<ABuffer> buffer = mOutputBuffers[bufferIx]; + buffer->setRange(offset, size); + buffer->meta()->clear(); + buffer->meta()->setInt64("timeUs", timeUs); + if (flags & MediaCodec::BUFFER_FLAG_EOS) { + buffer->meta()->setInt32("eos", true); } + // we do not expect CODECCONFIG or SYNCFRAME for decoder + + sp<AMessage> reply = new AMessage(kWhatRenderBuffer, id()); + reply->setSize("buffer-ix", bufferIx); + reply->setInt32("generation", mBufferGeneration); sp<AMessage> notify = mNotify->dup(); - notify->setMessage("codec-request", msg); + notify->setInt32("what", kWhatDrainThisBuffer); + notify->setBuffer("buffer", buffer); + notify->setMessage("reply", reply); notify->post(); + + // FIXME: This should be handled after rendering is complete, + // but Renderer needs it now + if (flags & MediaCodec::BUFFER_FLAG_EOS) { + ALOGV("queueing eos [%s]", mComponentName.c_str()); + sp<AMessage> notify = mNotify->dup(); + notify->setInt32("what", kWhatEOS); + notify->setInt32("err", ERROR_END_OF_STREAM); + notify->post(); + } + return true; } -void NuPlayer::Decoder::signalFlush() { - if (mCodec != NULL) { - mCodec->signalFlush(); +void NuPlayer::Decoder::onRenderBuffer(const sp<AMessage> &msg) { + status_t err; + int32_t render; + size_t bufferIx; + CHECK(msg->findSize("buffer-ix", &bufferIx)); + if (msg->findInt32("render", &render) && render) { + err = mCodec->renderOutputBufferAndRelease(bufferIx); + } else { + err = mCodec->releaseOutputBuffer(bufferIx); + } + if (err != OK) { + ALOGE("failed to release output buffer for %s (err=%d)", + mComponentName.c_str(), err); + handleError(err); } } -void NuPlayer::Decoder::signalResume() { +void NuPlayer::Decoder::onFlush() { + status_t err = OK; if (mCodec != NULL) { - mCodec->signalResume(); + err = mCodec->flush(); + ++mBufferGeneration; } + + if (err != OK) { + ALOGE("failed to flush %s (err=%d)", mComponentName.c_str(), err); + handleError(err); + return; + } + + sp<AMessage> notify = mNotify->dup(); + notify->setInt32("what", kWhatFlushCompleted); + notify->post(); } -void NuPlayer::Decoder::initiateShutdown() { +void NuPlayer::Decoder::onShutdown() { + status_t err = OK; if (mCodec != NULL) { - mCodec->initiateShutdown(); + err = mCodec->release(); + mCodec = NULL; + ++mBufferGeneration; + + if (mNativeWindow != NULL) { + // reconnect to surface as MediaCodec disconnected from it + CHECK_EQ((int)NO_ERROR, + native_window_api_connect( + mNativeWindow->getNativeWindow().get(), + NATIVE_WINDOW_API_MEDIA)); + } + mComponentName = "decoder"; + } + + if (err != OK) { + ALOGE("failed to release %s (err=%d)", mComponentName.c_str(), err); + handleError(err); + return; + } + + sp<AMessage> notify = mNotify->dup(); + notify->setInt32("what", kWhatShutdownCompleted); + notify->post(); +} + +void NuPlayer::Decoder::onMessageReceived(const sp<AMessage> &msg) { + ALOGV("[%s] onMessage: %s", mComponentName.c_str(), msg->debugString().c_str()); + + switch (msg->what()) { + case kWhatConfigure: + { + sp<AMessage> format; + CHECK(msg->findMessage("format", &format)); + onConfigure(format); + break; + } + + case kWhatCodecNotify: + { + if (!isStaleReply(msg)) { + while (handleAnInputBuffer()) { + } + + while (handleAnOutputBuffer()) { + } + } + + requestCodecNotification(); + break; + } + + case kWhatInputBufferFilled: + { + if (!isStaleReply(msg)) { + onInputBufferFilled(msg); + } + break; + } + + case kWhatRenderBuffer: + { + if (!isStaleReply(msg)) { + onRenderBuffer(msg); + } + break; + } + + case kWhatFlush: + { + onFlush(); + break; + } + + case kWhatShutdown: + { + onShutdown(); + break; + } + + default: + TRESPASS(); + break; } } +void NuPlayer::Decoder::signalFlush() { + (new AMessage(kWhatFlush, id()))->post(); +} + +void NuPlayer::Decoder::signalResume() { + // nothing to do +} + +void NuPlayer::Decoder::initiateShutdown() { + (new AMessage(kWhatShutdown, id()))->post(); +} + bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(const sp<AMessage> &targetFormat) const { if (targetFormat == NULL) { return true; @@ -163,14 +469,16 @@ bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(const sp<AMessage> &ta const char * keys[] = { "channel-count", "sample-rate", "is-adts" }; for (unsigned int i = 0; i < sizeof(keys) / sizeof(keys[0]); i++) { int32_t oldVal, newVal; - if (!mFormat->findInt32(keys[i], &oldVal) || !targetFormat->findInt32(keys[i], &newVal) - || oldVal != newVal) { + if (!mOutputFormat->findInt32(keys[i], &oldVal) || + !targetFormat->findInt32(keys[i], &newVal) || + oldVal != newVal) { return false; } } sp<ABuffer> oldBuf, newBuf; - if (mFormat->findBuffer("csd-0", &oldBuf) && targetFormat->findBuffer("csd-0", &newBuf)) { + if (mOutputFormat->findBuffer("csd-0", &oldBuf) && + targetFormat->findBuffer("csd-0", &newBuf)) { if (oldBuf->size() != newBuf->size()) { return false; } @@ -181,7 +489,7 @@ bool NuPlayer::Decoder::supportsSeamlessAudioFormatChange(const sp<AMessage> &ta } bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetFormat) const { - if (mFormat == NULL) { + if (mOutputFormat == NULL) { return false; } @@ -190,7 +498,7 @@ bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetF } AString oldMime, newMime; - if (!mFormat->findString("mime", &oldMime) + if (!mOutputFormat->findString("mime", &oldMime) || !targetFormat->findString("mime", &newMime) || !(oldMime == newMime)) { return false; @@ -201,7 +509,10 @@ bool NuPlayer::Decoder::supportsSeamlessFormatChange(const sp<AMessage> &targetF if (audio) { seamless = supportsSeamlessAudioFormatChange(targetFormat); } else { - seamless = mCodec != NULL && mCodec->isConfiguredForAdaptivePlayback(); + int32_t isAdaptive; + seamless = (mCodec != NULL && + mInputFormat->findInt32("adaptive-playback", &isAdaptive) && + isAdaptive); } ALOGV("%s seamless support for %s", seamless ? "yes" : "no", oldMime.c_str()); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h index 78ea74a..94243fc 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h @@ -25,12 +25,14 @@ namespace android { struct ABuffer; +struct MediaCodec; struct NuPlayer::Decoder : public AHandler { Decoder(const sp<AMessage> ¬ify, const sp<NativeWindowWrapper> &nativeWindow = NULL); void configure(const sp<AMessage> &format); + void init(); void signalFlush(); void signalResume(); @@ -38,7 +40,18 @@ struct NuPlayer::Decoder : public AHandler { bool supportsSeamlessFormatChange(const sp<AMessage> &to) const; + enum { + kWhatFillThisBuffer = 'flTB', + kWhatDrainThisBuffer = 'drTB', + kWhatOutputFormatChanged = 'fmtC', + kWhatFlushCompleted = 'flsC', + kWhatShutdownCompleted = 'shDC', + kWhatEOS = 'eos ', + kWhatError = 'err ', + }; + protected: + virtual ~Decoder(); virtual void onMessageReceived(const sp<AMessage> &msg); @@ -46,21 +59,40 @@ protected: private: enum { kWhatCodecNotify = 'cdcN', + kWhatConfigure = 'conf', + kWhatInputBufferFilled = 'inpF', + kWhatRenderBuffer = 'rndr', + kWhatFlush = 'flus', + kWhatShutdown = 'shuD', }; sp<AMessage> mNotify; sp<NativeWindowWrapper> mNativeWindow; - sp<AMessage> mFormat; - sp<ACodec> mCodec; + sp<AMessage> mInputFormat; + sp<AMessage> mOutputFormat; + sp<MediaCodec> mCodec; sp<ALooper> mCodecLooper; + sp<ALooper> mDecoderLooper; + + Vector<sp<ABuffer> > mInputBuffers; + Vector<sp<ABuffer> > mOutputBuffers; + + void handleError(int32_t err); + bool handleAnInputBuffer(); + bool handleAnOutputBuffer(); - Vector<sp<ABuffer> > mCSD; - size_t mCSDIndex; + void requestCodecNotification(); + bool isStaleReply(const sp<AMessage> &msg); - sp<AMessage> makeFormat(const sp<MetaData> &meta); + void onConfigure(const sp<AMessage> &format); + void onFlush(); + void onInputBufferFilled(const sp<AMessage> &msg); + void onRenderBuffer(const sp<AMessage> &msg); + void onShutdown(); - void onFillThisBuffer(const sp<AMessage> &msg); + int32_t mBufferGeneration; + AString mComponentName; bool supportsSeamlessAudioFormatChange(const sp<AMessage> &targetFormat) const; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp index 239296e..e4850f0 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp @@ -71,7 +71,9 @@ status_t NuPlayerDriver::setUID(uid_t uid) { } status_t NuPlayerDriver::setDataSource( - const char *url, const KeyedVector<String8, String8> *headers) { + const sp<IMediaHTTPService> &httpService, + const char *url, + const KeyedVector<String8, String8> *headers) { Mutex::Autolock autoLock(mLock); if (mState != STATE_IDLE) { @@ -80,7 +82,7 @@ status_t NuPlayerDriver::setDataSource( mState = STATE_SET_DATASOURCE_PENDING; - mPlayer->setDataSourceAsync(url, headers); + mPlayer->setDataSourceAsync(httpService, url, headers); while (mState == STATE_SET_DATASOURCE_PENDING) { mCondition.wait(mLock); @@ -365,7 +367,7 @@ status_t NuPlayerDriver::reset() { return OK; } -status_t NuPlayerDriver::setLooping(int loop) { +status_t NuPlayerDriver::setLooping(int /* loop */) { return INVALID_OPERATION; } @@ -421,16 +423,17 @@ void NuPlayerDriver::setAudioSink(const sp<AudioSink> &audioSink) { mPlayer->setAudioSink(audioSink); } -status_t NuPlayerDriver::setParameter(int key, const Parcel &request) { +status_t NuPlayerDriver::setParameter( + int /* key */, const Parcel & /* request */) { return INVALID_OPERATION; } -status_t NuPlayerDriver::getParameter(int key, Parcel *reply) { +status_t NuPlayerDriver::getParameter(int /* key */, Parcel * /* reply */) { return INVALID_OPERATION; } status_t NuPlayerDriver::getMetadata( - const media::Metadata::Filter& ids, Parcel *records) { + const media::Metadata::Filter& /* ids */, Parcel *records) { Mutex::Autolock autoLock(mLock); using media::Metadata; @@ -494,7 +497,8 @@ void NuPlayerDriver::notifyFrameStats( mNumFramesDropped = numFramesDropped; } -status_t NuPlayerDriver::dump(int fd, const Vector<String16> &args) const { +status_t NuPlayerDriver::dump( + int fd, const Vector<String16> & /* args */) const { Mutex::Autolock autoLock(mLock); FILE *out = fdopen(dup(fd), "w"); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h index 99f72a6..0148fb1 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h @@ -31,7 +31,9 @@ struct NuPlayerDriver : public MediaPlayerInterface { virtual status_t setUID(uid_t uid); virtual status_t setDataSource( - const char *url, const KeyedVector<String8, String8> *headers); + const sp<IMediaHTTPService> &httpService, + const char *url, + const KeyedVector<String8, String8> *headers); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp index bf5271e..a070c1a 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.cpp @@ -20,8 +20,6 @@ #include "NuPlayerRenderer.h" -#include "SoftwareRenderer.h" - #include <media/stagefright/foundation/ABuffer.h> #include <media/stagefright/foundation/ADebug.h> #include <media/stagefright/foundation/AMessage.h> @@ -36,7 +34,6 @@ NuPlayer::Renderer::Renderer( const sp<AMessage> ¬ify, uint32_t flags) : mAudioSink(sink), - mSoftRenderer(NULL), mNotify(notify), mFlags(flags), mNumFramesWritten(0), @@ -60,12 +57,6 @@ NuPlayer::Renderer::Renderer( } NuPlayer::Renderer::~Renderer() { - delete mSoftRenderer; -} - -void NuPlayer::Renderer::setSoftRenderer(SoftwareRenderer *softRenderer) { - delete mSoftRenderer; - mSoftRenderer = softRenderer; } void NuPlayer::Renderer::queueBuffer( @@ -425,9 +416,6 @@ void NuPlayer::Renderer::onDrainVideoQueue() { ALOGV("rendering video at media time %.2f secs", (mFlags & FLAG_REAL_TIME ? realTimeUs : (realTimeUs + mAnchorTimeMediaUs - mAnchorTimeRealUs)) / 1E6); - if (mSoftRenderer != NULL) { - mSoftRenderer->render(entry->mBuffer->data(), entry->mBuffer->size(), NULL); - } } entry->mNotifyConsumed->setInt32("render", !tooLate); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h index 9124e03..94a05ea 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerRenderer.h @@ -23,7 +23,6 @@ namespace android { struct ABuffer; -class SoftwareRenderer; struct NuPlayer::Renderer : public AHandler { enum Flags { @@ -57,8 +56,6 @@ struct NuPlayer::Renderer : public AHandler { kWhatMediaRenderingStart = 'mdrd', }; - void setSoftRenderer(SoftwareRenderer *softRenderer); - protected: virtual ~Renderer(); @@ -86,7 +83,6 @@ private: static const int64_t kMinPositionUpdateDelayUs; sp<MediaPlayerBase::AudioSink> mAudioSink; - SoftwareRenderer *mSoftRenderer; sp<AMessage> mNotify; uint32_t mFlags; List<QueueEntry> mAudioQueue; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h index e50533a..11279fc 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerSource.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerSource.h @@ -68,19 +68,19 @@ struct NuPlayer::Source : public AHandler { virtual status_t dequeueAccessUnit( bool audio, sp<ABuffer> *accessUnit) = 0; - virtual status_t getDuration(int64_t *durationUs) { + virtual status_t getDuration(int64_t * /* durationUs */) { return INVALID_OPERATION; } - virtual status_t getTrackInfo(Parcel* reply) const { + virtual status_t getTrackInfo(Parcel* /* reply */) const { return INVALID_OPERATION; } - virtual status_t selectTrack(size_t trackIndex, bool select) { + virtual status_t selectTrack(size_t /* trackIndex */, bool /* select */) { return INVALID_OPERATION; } - virtual status_t seekTo(int64_t seekTimeUs) { + virtual status_t seekTo(int64_t /* seekTimeUs */) { return INVALID_OPERATION; } @@ -93,7 +93,7 @@ protected: virtual void onMessageReceived(const sp<AMessage> &msg); - virtual sp<MetaData> getFormatMeta(bool audio) { return NULL; } + virtual sp<MetaData> getFormatMeta(bool /* audio */) { return NULL; } sp<AMessage> dupNotify() const { return mNotify->dup(); } diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp index 18cf6d1..94800ba 100644 --- a/media/libmediaplayerservice/nuplayer/RTSPSource.cpp +++ b/media/libmediaplayerservice/nuplayer/RTSPSource.cpp @@ -24,6 +24,7 @@ #include "MyHandler.h" #include "SDPLoader.h" +#include <media/IMediaHTTPService.h> #include <media/stagefright/MediaDefs.h> #include <media/stagefright/MetaData.h> @@ -33,12 +34,14 @@ const int64_t kNearEOSTimeoutUs = 2000000ll; // 2 secs NuPlayer::RTSPSource::RTSPSource( const sp<AMessage> ¬ify, + const sp<IMediaHTTPService> &httpService, const char *url, const KeyedVector<String8, String8> *headers, bool uidValid, uid_t uid, bool isSDP) : Source(notify), + mHTTPService(httpService), mURL(url), mUIDValid(uidValid), mUID(uid), @@ -92,7 +95,7 @@ void NuPlayer::RTSPSource::prepareAsync() { if (mIsSDP) { mSDPLoader = new SDPLoader(notify, (mFlags & kFlagIncognito) ? SDPLoader::kFlagIncognito : 0, - mUIDValid, mUID); + mHTTPService); mSDPLoader->load( mURL.c_str(), mExtraHeaders.isEmpty() ? NULL : &mExtraHeaders); diff --git a/media/libmediaplayerservice/nuplayer/RTSPSource.h b/media/libmediaplayerservice/nuplayer/RTSPSource.h index 8cf34a0..3718bf9 100644 --- a/media/libmediaplayerservice/nuplayer/RTSPSource.h +++ b/media/libmediaplayerservice/nuplayer/RTSPSource.h @@ -34,6 +34,7 @@ struct SDPLoader; struct NuPlayer::RTSPSource : public NuPlayer::Source { RTSPSource( const sp<AMessage> ¬ify, + const sp<IMediaHTTPService> &httpService, const char *url, const KeyedVector<String8, String8> *headers, bool uidValid = false, @@ -88,6 +89,7 @@ private: bool mNPTMappingValid; }; + sp<IMediaHTTPService> mHTTPService; AString mURL; KeyedVector<String8, String8> mExtraHeaders; bool mUIDValid; diff --git a/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp b/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp deleted file mode 100644 index 2aae4dd..0000000 --- a/media/libmediaplayerservice/nuplayer/mp4/MP4Source.cpp +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (C) 2012 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. - */ - -#include "MP4Source.h" - -#include "FragmentedMP4Parser.h" -#include "../NuPlayerStreamListener.h" - -#include <media/IStreamSource.h> -#include <media/stagefright/foundation/AMessage.h> -#include <media/stagefright/MediaErrors.h> -#include <media/stagefright/MetaData.h> - -namespace android { - -struct StreamSource : public FragmentedMP4Parser::Source { - StreamSource(const sp<IStreamSource> &source) - : mListener(new NuPlayer::NuPlayerStreamListener(source, 0)), - mPosition(0) { - mListener->start(); - } - - virtual ssize_t readAt(off64_t offset, void *data, size_t size) { - if (offset < mPosition) { - return -EPIPE; - } - - while (offset > mPosition) { - char buffer[1024]; - off64_t skipBytes = offset - mPosition; - if (skipBytes > sizeof(buffer)) { - skipBytes = sizeof(buffer); - } - - sp<AMessage> extra; - ssize_t n; - for (;;) { - n = mListener->read(buffer, skipBytes, &extra); - - if (n == -EWOULDBLOCK) { - usleep(10000); - continue; - } - - break; - } - - ALOGV("skipped %ld bytes at offset %lld", n, mPosition); - - if (n < 0) { - return n; - } - - mPosition += n; - } - - sp<AMessage> extra; - size_t total = 0; - while (total < size) { - ssize_t n = mListener->read( - (uint8_t *)data + total, size - total, &extra); - - if (n == -EWOULDBLOCK) { - usleep(10000); - continue; - } else if (n == 0) { - break; - } else if (n < 0) { - mPosition += total; - return n; - } - - total += n; - } - - ALOGV("read %ld bytes at offset %lld", total, mPosition); - - mPosition += total; - - return total; - } - - bool isSeekable() { - return false; - } - -private: - sp<NuPlayer::NuPlayerStreamListener> mListener; - off64_t mPosition; - - DISALLOW_EVIL_CONSTRUCTORS(StreamSource); -}; - -MP4Source::MP4Source( - const sp<AMessage> ¬ify, const sp<IStreamSource> &source) - : Source(notify), - mSource(source), - mLooper(new ALooper), - mParser(new FragmentedMP4Parser), - mEOS(false) { - mLooper->registerHandler(mParser); -} - -MP4Source::~MP4Source() { -} - -void MP4Source::prepareAsync() { - notifyVideoSizeChanged(0, 0); - notifyFlagsChanged(0); - notifyPrepared(); -} - -void MP4Source::start() { - mLooper->start(false /* runOnCallingThread */); - mParser->start(new StreamSource(mSource)); -} - -status_t MP4Source::feedMoreTSData() { - return mEOS ? ERROR_END_OF_STREAM : (status_t)OK; -} - -sp<AMessage> MP4Source::getFormat(bool audio) { - return mParser->getFormat(audio); -} - -status_t MP4Source::dequeueAccessUnit( - bool audio, sp<ABuffer> *accessUnit) { - return mParser->dequeueAccessUnit(audio, accessUnit); -} - -} // namespace android diff --git a/media/libmediaplayerservice/nuplayer/mp4/MP4Source.h b/media/libmediaplayerservice/nuplayer/mp4/MP4Source.h deleted file mode 100644 index a6ef622..0000000 --- a/media/libmediaplayerservice/nuplayer/mp4/MP4Source.h +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright (C) 2012 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 MP4_SOURCE_H -#define MP4_SOURCE_H - -#include "NuPlayerSource.h" - -namespace android { - -struct FragmentedMP4Parser; - -struct MP4Source : public NuPlayer::Source { - MP4Source(const sp<AMessage> ¬ify, const sp<IStreamSource> &source); - - virtual void prepareAsync(); - virtual void start(); - - virtual status_t feedMoreTSData(); - - virtual sp<AMessage> getFormat(bool audio); - - virtual status_t dequeueAccessUnit( - bool audio, sp<ABuffer> *accessUnit); - -protected: - virtual ~MP4Source(); - -private: - sp<IStreamSource> mSource; - sp<ALooper> mLooper; - sp<FragmentedMP4Parser> mParser; - bool mEOS; - - DISALLOW_EVIL_CONSTRUCTORS(MP4Source); -}; - -} // namespace android - -#endif // MP4_SOURCE_H |