diff options
author | Chris Watkins <watk@google.com> | 2015-04-16 17:06:37 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2015-04-16 17:06:42 +0000 |
commit | c224ec53a17994fa97ab2f29304647c9f195c51c (patch) | |
tree | 6086a1cf5720b82e7dc25b7ecd60af39d66c738d | |
parent | f2326ac96366ec4d05f470cc4a0b407e7805bab7 (diff) | |
parent | 99f31604136d66ae10e20669fb6b5716f342bde0 (diff) | |
download | frameworks_av-c224ec53a17994fa97ab2f29304647c9f195c51c.zip frameworks_av-c224ec53a17994fa97ab2f29304647c9f195c51c.tar.gz frameworks_av-c224ec53a17994fa97ab2f29304647c9f195c51c.tar.bz2 |
Merge "Unhide the android.media.[Media]DataSource interface."
33 files changed, 552 insertions, 29 deletions
diff --git a/include/media/IDataSource.h b/include/media/IDataSource.h new file mode 100644 index 0000000..07e46f7 --- /dev/null +++ b/include/media/IDataSource.h @@ -0,0 +1,61 @@ +/* + * Copyright 2015 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 ANDROID_IDATASOURCE_H +#define ANDROID_IDATASOURCE_H + +#include <binder/IInterface.h> +#include <media/stagefright/foundation/ABase.h> +#include <utils/Errors.h> + +namespace android { + +class IMemory; + +// A binder interface for implementing a stagefright DataSource remotely. +class IDataSource : public IInterface { +public: + DECLARE_META_INTERFACE(DataSource); + + // Get the memory that readAt writes into. + virtual sp<IMemory> getIMemory() = 0; + // Read up to |size| bytes into the memory returned by getIMemory(). Returns + // the number of bytes read, or -1 on error. |size| must not be larger than + // the buffer. + virtual ssize_t readAt(off64_t offset, size_t size) = 0; + // Get the size, or -1 if the size is unknown. + virtual status_t getSize(off64_t* size) = 0; + // This should be called before deleting |this|. The other methods may + // return errors if they're called after calling close(). + virtual void close() = 0; + +private: + DISALLOW_EVIL_CONSTRUCTORS(IDataSource); +}; + +// ---------------------------------------------------------------------------- + +class BnDataSource : public BnInterface<IDataSource> { +public: + virtual status_t onTransact(uint32_t code, + const Parcel& data, + Parcel* reply, + uint32_t flags = 0); +}; + +}; // namespace android + +#endif // ANDROID_IDATASOURCE_H diff --git a/include/media/IMediaMetadataRetriever.h b/include/media/IMediaMetadataRetriever.h index 2529800..95851fd 100644 --- a/include/media/IMediaMetadataRetriever.h +++ b/include/media/IMediaMetadataRetriever.h @@ -26,7 +26,8 @@ namespace android { -struct IMediaHTTPService; +class IDataSource; +class IMediaHTTPService; class IMediaMetadataRetriever: public IInterface { @@ -40,6 +41,7 @@ public: const KeyedVector<String8, String8> *headers = NULL) = 0; virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; + virtual status_t setDataSource(const sp<IDataSource>& dataSource) = 0; virtual sp<IMemory> getFrameAtTime(int64_t timeUs, int option) = 0; virtual sp<IMemory> extractAlbumArt() = 0; virtual const char* extractMetadata(int keyCode) = 0; diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h index 4153c25..17ef489 100644 --- a/include/media/IMediaPlayer.h +++ b/include/media/IMediaPlayer.h @@ -31,6 +31,7 @@ namespace android { class Parcel; class Surface; +class IDataSource; class IStreamSource; class IGraphicBufferProducer; struct IMediaHTTPService; @@ -49,6 +50,7 @@ public: virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; virtual status_t setDataSource(const sp<IStreamSource>& source) = 0; + virtual status_t setDataSource(const sp<IDataSource>& source) = 0; virtual status_t setVideoSurfaceTexture( const sp<IGraphicBufferProducer>& bufferProducer) = 0; virtual status_t prepareAsync() = 0; diff --git a/include/media/MediaMetadataRetrieverInterface.h b/include/media/MediaMetadataRetrieverInterface.h index 38dbb20..df6c7d6 100644 --- a/include/media/MediaMetadataRetrieverInterface.h +++ b/include/media/MediaMetadataRetrieverInterface.h @@ -25,7 +25,8 @@ namespace android { -struct IMediaHTTPService; +class DataSource; +class IMediaHTTPService; // Abstract base class class MediaMetadataRetrieverBase : public RefBase @@ -40,6 +41,7 @@ public: const KeyedVector<String8, String8> *headers = NULL) = 0; virtual status_t setDataSource(int fd, int64_t offset, int64_t length) = 0; + virtual status_t setDataSource(const sp<DataSource>& source) = 0; virtual VideoFrame* getFrameAtTime(int64_t timeUs, int option) = 0; virtual MediaAlbumArt* extractAlbumArt() = 0; virtual const char* extractMetadata(int keyCode) = 0; diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index d6fe390..90211b1 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -36,6 +36,7 @@ struct sockaddr_in; namespace android { +class DataSource; class Parcel; class Surface; class IGraphicBufferProducer; @@ -158,6 +159,10 @@ public: return INVALID_OPERATION; } + virtual status_t setDataSource(const sp<DataSource> &source) { + return INVALID_OPERATION; + } + // pass the buffered IGraphicBufferProducer to the media player service virtual status_t setVideoSurfaceTexture( const sp<IGraphicBufferProducer>& bufferProducer) = 0; diff --git a/include/media/mediametadataretriever.h b/include/media/mediametadataretriever.h index 7191965..08049c4 100644 --- a/include/media/mediametadataretriever.h +++ b/include/media/mediametadataretriever.h @@ -25,7 +25,8 @@ namespace android { -struct IMediaHTTPService; +class IDataSource; +class IMediaHTTPService; class IMediaPlayerService; class IMediaMetadataRetriever; @@ -75,6 +76,7 @@ public: const KeyedVector<String8, String8> *headers = NULL); status_t setDataSource(int fd, int64_t offset, int64_t length); + status_t setDataSource(const sp<IDataSource>& dataSource); sp<IMemory> getFrameAtTime(int64_t timeUs, int option); sp<IMemory> extractAlbumArt(); const char* extractMetadata(int keyCode); diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h index 808e893..269a2d7 100644 --- a/include/media/mediaplayer.h +++ b/include/media/mediaplayer.h @@ -211,6 +211,7 @@ public: status_t setDataSource(int fd, int64_t offset, int64_t length); status_t setDataSource(const sp<IStreamSource> &source); + status_t setDataSource(const sp<IDataSource> &source); status_t setVideoSurfaceTexture( const sp<IGraphicBufferProducer>& bufferProducer); status_t setListener(const sp<MediaPlayerListener>& listener); diff --git a/include/media/stagefright/DataSource.h b/include/media/stagefright/DataSource.h index 3630263..997fe95 100644 --- a/include/media/stagefright/DataSource.h +++ b/include/media/stagefright/DataSource.h @@ -32,6 +32,7 @@ namespace android { struct AMessage; struct AString; +struct IDataSource; struct IMediaHTTPService; class String8; struct HTTPBase; @@ -53,11 +54,15 @@ public: HTTPBase *httpSource = NULL); static sp<DataSource> CreateMediaHTTP(const sp<IMediaHTTPService> &httpService); + static sp<DataSource> CreateFromIDataSource(const sp<IDataSource> &source); DataSource() {} virtual status_t initCheck() const = 0; + // Returns the number of bytes read, or -1 on failure. It's not an error if + // this returns zero; it just means the given offset is equal to, or + // beyond, the end of the source. virtual ssize_t readAt(off64_t offset, void *data, size_t size) = 0; // Convenience methods: diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 3b260d6..78baa43 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -19,6 +19,7 @@ LOCAL_SRC_FILES:= \ IAudioTrack.cpp \ IAudioRecord.cpp \ ICrypto.cpp \ + IDataSource.cpp \ IDrm.cpp \ IDrmClient.cpp \ IHDCP.cpp \ diff --git a/media/libmedia/IDataSource.cpp b/media/libmedia/IDataSource.cpp new file mode 100644 index 0000000..76d1d68 --- /dev/null +++ b/media/libmedia/IDataSource.cpp @@ -0,0 +1,108 @@ +/* + * Copyright 2015 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 "IDataSource" +#include <utils/Log.h> +#include <utils/Timers.h> + +#include <media/IDataSource.h> + +#include <binder/IMemory.h> +#include <binder/Parcel.h> +#include <media/stagefright/foundation/ADebug.h> + +namespace android { + +enum { + GET_IMEMORY = IBinder::FIRST_CALL_TRANSACTION, + READ_AT, + GET_SIZE, + CLOSE, +}; + +struct BpDataSource : public BpInterface<IDataSource> { + BpDataSource(const sp<IBinder>& impl) : BpInterface<IDataSource>(impl) {} + + virtual sp<IMemory> getIMemory() { + Parcel data, reply; + data.writeInterfaceToken(IDataSource::getInterfaceDescriptor()); + remote()->transact(GET_IMEMORY, data, &reply); + sp<IBinder> binder = reply.readStrongBinder(); + return interface_cast<IMemory>(binder); + } + + virtual ssize_t readAt(off64_t offset, size_t size) { + Parcel data, reply; + data.writeInterfaceToken(IDataSource::getInterfaceDescriptor()); + data.writeInt64(offset); + data.writeInt64(size); + remote()->transact(READ_AT, data, &reply); + return reply.readInt64(); + } + + virtual status_t getSize(off64_t* size) { + Parcel data, reply; + data.writeInterfaceToken(IDataSource::getInterfaceDescriptor()); + remote()->transact(GET_SIZE, data, &reply); + status_t err = reply.readInt32(); + *size = reply.readInt64(); + return err; + } + + virtual void close() { + Parcel data, reply; + data.writeInterfaceToken(IDataSource::getInterfaceDescriptor()); + remote()->transact(CLOSE, data, &reply); + } +}; + +IMPLEMENT_META_INTERFACE(DataSource, "android.media.IDataSource"); + +status_t BnDataSource::onTransact( + uint32_t code, const Parcel& data, Parcel* reply, uint32_t flags) { + switch (code) { + case GET_IMEMORY: { + CHECK_INTERFACE(IDataSource, data, reply); + reply->writeStrongBinder(IInterface::asBinder(getIMemory())); + return NO_ERROR; + } break; + case READ_AT: { + CHECK_INTERFACE(IDataSource, data, reply); + off64_t offset = (off64_t) data.readInt64(); + size_t size = (size_t) data.readInt64(); + reply->writeInt64(readAt(offset, size)); + return NO_ERROR; + } break; + case GET_SIZE: { + CHECK_INTERFACE(IDataSource, data, reply); + off64_t size; + status_t err = getSize(&size); + reply->writeInt32(err); + reply->writeInt64(size); + return NO_ERROR; + } break; + case CLOSE: { + CHECK_INTERFACE(IDataSource, data, reply); + close(); + return NO_ERROR; + } break; + default: + return BBinder::onTransact(code, data, reply, flags); + } +} + +} // namespace android diff --git a/media/libmedia/IMediaMetadataRetriever.cpp b/media/libmedia/IMediaMetadataRetriever.cpp index 551cffe..9765f0d 100644 --- a/media/libmedia/IMediaMetadataRetriever.cpp +++ b/media/libmedia/IMediaMetadataRetriever.cpp @@ -20,6 +20,7 @@ #include <sys/types.h> #include <binder/Parcel.h> +#include <media/IDataSource.h> #include <media/IMediaHTTPService.h> #include <media/IMediaMetadataRetriever.h> #include <utils/String8.h> @@ -65,6 +66,7 @@ enum { DISCONNECT = IBinder::FIRST_CALL_TRANSACTION, SET_DATA_SOURCE_URL, SET_DATA_SOURCE_FD, + SET_DATA_SOURCE_CALLBACK, GET_FRAME_AT_TIME, EXTRACT_ALBUM_ART, EXTRACT_METADATA, @@ -125,6 +127,15 @@ public: return reply.readInt32(); } + status_t setDataSource(const sp<IDataSource>& source) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaMetadataRetriever::getInterfaceDescriptor()); + data.writeStrongBinder(IInterface::asBinder(source)); + remote()->transact(SET_DATA_SOURCE_CALLBACK, data, &reply); + return reply.readInt32(); + } + sp<IMemory> getFrameAtTime(int64_t timeUs, int option) { ALOGV("getTimeAtTime: time(%" PRId64 " us) and option(%d)", timeUs, option); @@ -235,6 +246,13 @@ status_t BnMediaMetadataRetriever::onTransact( reply->writeInt32(setDataSource(fd, offset, length)); return NO_ERROR; } break; + case SET_DATA_SOURCE_CALLBACK: { + CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); + sp<IDataSource> source = + interface_cast<IDataSource>(data.readStrongBinder()); + reply->writeInt32(setDataSource(source)); + return NO_ERROR; + } break; case GET_FRAME_AT_TIME: { CHECK_INTERFACE(IMediaMetadataRetriever, data, reply); int64_t timeUs = data.readInt64(); diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp index ce3009a..0091078 100644 --- a/media/libmedia/IMediaPlayer.cpp +++ b/media/libmedia/IMediaPlayer.cpp @@ -21,6 +21,7 @@ #include <binder/Parcel.h> +#include <media/IDataSource.h> #include <media/IMediaHTTPService.h> #include <media/IMediaPlayer.h> #include <media/IStreamSource.h> @@ -35,6 +36,7 @@ enum { SET_DATA_SOURCE_URL, SET_DATA_SOURCE_FD, SET_DATA_SOURCE_STREAM, + SET_DATA_SOURCE_CALLBACK, PREPARE_ASYNC, START, STOP, @@ -121,6 +123,14 @@ public: return reply.readInt32(); } + status_t setDataSource(const sp<IDataSource> &source) { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + data.writeStrongBinder(IInterface::asBinder(source)); + remote()->transact(SET_DATA_SOURCE_CALLBACK, data, &reply); + return reply.readInt32(); + } + // pass the buffered IGraphicBufferProducer to the media player service status_t setVideoSurfaceTexture(const sp<IGraphicBufferProducer>& bufferProducer) { @@ -406,6 +416,13 @@ status_t BnMediaPlayer::onTransact( reply->writeInt32(setDataSource(source)); return NO_ERROR; } + case SET_DATA_SOURCE_CALLBACK: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + sp<IDataSource> source = + interface_cast<IDataSource>(data.readStrongBinder()); + reply->writeInt32(setDataSource(source)); + return NO_ERROR; + } case SET_VIDEO_SURFACETEXTURE: { CHECK_INTERFACE(IMediaPlayer, data, reply); sp<IGraphicBufferProducer> bufferProducer = diff --git a/media/libmedia/mediametadataretriever.cpp b/media/libmedia/mediametadataretriever.cpp index 873808a..9a76f58 100644 --- a/media/libmedia/mediametadataretriever.cpp +++ b/media/libmedia/mediametadataretriever.cpp @@ -129,6 +129,18 @@ status_t MediaMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t l return mRetriever->setDataSource(fd, offset, length); } +status_t MediaMetadataRetriever::setDataSource( + const sp<IDataSource>& dataSource) +{ + ALOGV("setDataSource(IDataSource)"); + Mutex::Autolock _l(mLock); + if (mRetriever == 0) { + ALOGE("retriever is not initialized"); + return INVALID_OPERATION; + } + return mRetriever->setDataSource(dataSource); +} + sp<IMemory> MediaMetadataRetriever::getFrameAtTime(int64_t timeUs, int option) { ALOGV("getFrameAtTime: time(%" PRId64 " us) option(%d)", timeUs, option); diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 5dd8c02..6eddcb6 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -33,6 +33,7 @@ #include <media/mediaplayer.h> #include <media/AudioSystem.h> +#include <media/IDataSource.h> #include <binder/MemoryBase.h> @@ -195,6 +196,22 @@ status_t MediaPlayer::setDataSource(const sp<IStreamSource> &source) return err; } +status_t MediaPlayer::setDataSource(const sp<IDataSource> &source) +{ + ALOGV("setDataSource(IDataSource)"); + status_t err = UNKNOWN_ERROR; + const sp<IMediaPlayerService>& service(getMediaPlayerService()); + if (service != 0) { + sp<IMediaPlayer> player(service->create(this, mAudioSessionId)); + if ((NO_ERROR != doSetRetransmitEndpoint(player)) || + (NO_ERROR != player->setDataSource(source))) { + player.clear(); + } + err = attachNewPlayer(player); + } + return err; +} + status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply) { Mutex::Autolock _l(mLock); diff --git a/media/libmediaplayerservice/MediaPlayerFactory.cpp b/media/libmediaplayerservice/MediaPlayerFactory.cpp index 48884b9..ca33aed 100644 --- a/media/libmediaplayerservice/MediaPlayerFactory.cpp +++ b/media/libmediaplayerservice/MediaPlayerFactory.cpp @@ -131,6 +131,11 @@ player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client, GET_PLAYER_TYPE_IMPL(client, source); } +player_type MediaPlayerFactory::getPlayerType(const sp<IMediaPlayer>& client, + const sp<DataSource> &source) { + GET_PLAYER_TYPE_IMPL(client, source); +} + #undef GET_PLAYER_TYPE_IMPL sp<MediaPlayerBase> MediaPlayerFactory::createPlayer( @@ -273,6 +278,13 @@ class NuPlayerFactory : public MediaPlayerFactory::IFactory { return 1.0; } + virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, + const sp<DataSource>& /*source*/, + float /*curScore*/) { + // Only NuPlayer supports setting a DataSource source directly. + return 1.0; + } + virtual sp<MediaPlayerBase> createPlayer() { ALOGV(" create NuPlayer"); return new NuPlayerDriver; diff --git a/media/libmediaplayerservice/MediaPlayerFactory.h b/media/libmediaplayerservice/MediaPlayerFactory.h index 55ff918..7f9b3b5 100644 --- a/media/libmediaplayerservice/MediaPlayerFactory.h +++ b/media/libmediaplayerservice/MediaPlayerFactory.h @@ -43,6 +43,10 @@ class MediaPlayerFactory { const sp<IStreamSource> &/*source*/, float /*curScore*/) { return 0.0; } + virtual float scoreFactory(const sp<IMediaPlayer>& /*client*/, + const sp<DataSource> &/*source*/, + float /*curScore*/) { return 0.0; } + virtual sp<MediaPlayerBase> createPlayer() = 0; }; @@ -57,6 +61,8 @@ class MediaPlayerFactory { int64_t length); static player_type getPlayerType(const sp<IMediaPlayer>& client, const sp<IStreamSource> &source); + static player_type getPlayerType(const sp<IMediaPlayer>& client, + const sp<DataSource> &source); static sp<MediaPlayerBase> createPlayer(player_type playerType, void* cookie, diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index f113e21..8e2e214 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -790,6 +790,19 @@ status_t MediaPlayerService::Client::setDataSource( return mStatus; } +status_t MediaPlayerService::Client::setDataSource( + const sp<IDataSource> &source) { + sp<DataSource> dataSource = DataSource::CreateFromIDataSource(source); + player_type playerType = MediaPlayerFactory::getPlayerType(this, dataSource); + sp<MediaPlayerBase> p = setDataSource_pre(playerType); + if (p == NULL) { + return NO_INIT; + } + // now set data source + setDataSource_post(p, p->setDataSource(dataSource)); + return mStatus; +} + void MediaPlayerService::Client::disconnectNativeWindow() { if (mConnectedWindow != NULL) { status_t err = native_window_api_disconnect(mConnectedWindow.get(), diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 4ce4b81..2a95ce1 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -35,6 +35,7 @@ namespace android { class AudioTrack; +class IDataSource; class IMediaRecorder; class IMediaMetadataRetriever; class IOMX; @@ -292,6 +293,8 @@ private: virtual status_t setDataSource(int fd, int64_t offset, int64_t length); virtual status_t setDataSource(const sp<IStreamSource> &source); + virtual status_t setDataSource(const sp<IDataSource> &source); + sp<MediaPlayerBase> setDataSource_pre(player_type playerType); void setDataSource_post(const sp<MediaPlayerBase>& p, diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.cpp b/media/libmediaplayerservice/MetadataRetrieverClient.cpp index 715cc0c..80804a7 100644 --- a/media/libmediaplayerservice/MetadataRetrieverClient.cpp +++ b/media/libmediaplayerservice/MetadataRetrieverClient.cpp @@ -34,6 +34,7 @@ #include <media/IMediaHTTPService.h> #include <media/MediaMetadataRetrieverInterface.h> #include <media/MediaPlayerInterface.h> +#include <media/stagefright/DataSource.h> #include <private/media/VideoFrame.h> #include "MetadataRetrieverClient.h" #include "StagefrightMetadataRetriever.h" @@ -173,6 +174,23 @@ status_t MetadataRetrieverClient::setDataSource(int fd, int64_t offset, int64_t return status; } +status_t MetadataRetrieverClient::setDataSource( + const sp<IDataSource>& source) +{ + ALOGV("setDataSource(IDataSource)"); + Mutex::Autolock lock(mLock); + + sp<DataSource> dataSource = DataSource::CreateFromIDataSource(source); + player_type playerType = + MediaPlayerFactory::getPlayerType(NULL /* client */, dataSource); + ALOGV("player type = %d", playerType); + sp<MediaMetadataRetrieverBase> p = createRetriever(playerType); + if (p == NULL) return NO_INIT; + status_t ret = p->setDataSource(dataSource); + if (ret == NO_ERROR) mRetriever = p; + return ret; +} + sp<IMemory> MetadataRetrieverClient::getFrameAtTime(int64_t timeUs, int option) { ALOGV("getFrameAtTime: time(%lld us) option(%d)", timeUs, option); diff --git a/media/libmediaplayerservice/MetadataRetrieverClient.h b/media/libmediaplayerservice/MetadataRetrieverClient.h index 9d3fbe9..ce52b91 100644 --- a/media/libmediaplayerservice/MetadataRetrieverClient.h +++ b/media/libmediaplayerservice/MetadataRetrieverClient.h @@ -49,6 +49,7 @@ public: const KeyedVector<String8, String8> *headers); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); + virtual status_t setDataSource(const sp<IDataSource>& source); virtual sp<IMemory> getFrameAtTime(int64_t timeUs, int option); virtual sp<IMemory> extractAlbumArt(); virtual const char* extractMetadata(int keyCode); diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.cpp b/media/libmediaplayerservice/nuplayer/GenericSource.cpp index 5a31b74..8f1cd57 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.cpp +++ b/media/libmediaplayerservice/nuplayer/GenericSource.cpp @@ -124,6 +124,12 @@ status_t NuPlayer::GenericSource::setDataSource( return OK; } +status_t NuPlayer::GenericSource::setDataSource(const sp<DataSource>& source) { + resetDataSource(); + mDataSource = source; + return OK; +} + sp<MetaData> NuPlayer::GenericSource::getFileFormatMeta() const { return mFileMeta; } @@ -377,20 +383,20 @@ void NuPlayer::GenericSource::onPrepareAsync() { notifyPreparedAndCleanup(UNKNOWN_ERROR); return; } + } - if (mDataSource->flags() & DataSource::kIsCachingDataSource) { - mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get()); - } - - // For widevine or other cached streaming cases, we need to wait for - // enough buffering before reporting prepared. - // Note that even when URL doesn't start with widevine://, mIsWidevine - // could still be set to true later, if the streaming or file source - // is sniffed to be widevine. We don't want to buffer for file source - // in that case, so must check the flag now. - mIsStreaming = (mIsWidevine || mCachedSource != NULL); + if (mDataSource->flags() & DataSource::kIsCachingDataSource) { + mCachedSource = static_cast<NuCachedSource2 *>(mDataSource.get()); } + // For widevine or other cached streaming cases, we need to wait for + // enough buffering before reporting prepared. + // Note that even when URL doesn't start with widevine://, mIsWidevine + // could still be set to true later, if the streaming or file source + // is sniffed to be widevine. We don't want to buffer for file source + // in that case, so must check the flag now. + mIsStreaming = (mIsWidevine || mCachedSource != NULL); + // init extractor from data source status_t err = initFromDataSource(); diff --git a/media/libmediaplayerservice/nuplayer/GenericSource.h b/media/libmediaplayerservice/nuplayer/GenericSource.h index 862ee5f..2f6e78e 100644 --- a/media/libmediaplayerservice/nuplayer/GenericSource.h +++ b/media/libmediaplayerservice/nuplayer/GenericSource.h @@ -32,6 +32,7 @@ class DrmManagerClient; struct AnotherPacketSource; struct ARTSPController; struct DataSource; +struct IDataSource; struct IMediaHTTPService; struct MediaSource; class MediaBuffer; @@ -48,6 +49,8 @@ struct NuPlayer::GenericSource : public NuPlayer::Source { status_t setDataSource(int fd, int64_t offset, int64_t length); + status_t setDataSource(const sp<DataSource>& dataSource); + virtual void prepareAsync(); virtual void start(); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 02d9f32..db73784 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -285,6 +285,22 @@ void NuPlayer::setDataSourceAsync(int fd, int64_t offset, int64_t length) { msg->post(); } +void NuPlayer::setDataSourceAsync(const sp<DataSource> &dataSource) { + sp<AMessage> msg = new AMessage(kWhatSetDataSource, this); + sp<AMessage> notify = new AMessage(kWhatSourceNotify, this); + + sp<GenericSource> source = new GenericSource(notify, mUIDValid, mUID); + status_t err = source->setDataSource(dataSource); + + if (err != OK) { + ALOGE("Failed to set data source!"); + source = NULL; + } + + msg->setObject("source", source); + msg->post(); +} + void NuPlayer::prepareAsync() { (new AMessage(kWhatPrepare, this))->post(); } diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h index 2bc20d7..623b0ce 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h @@ -26,6 +26,7 @@ namespace android { struct ABuffer; struct AMessage; +struct IDataSource; class MetaData; struct NuPlayerDriver; @@ -45,6 +46,8 @@ struct NuPlayer : public AHandler { void setDataSourceAsync(int fd, int64_t offset, int64_t length); + void setDataSourceAsync(const sp<DataSource> &source); + void prepareAsync(); void setVideoSurfaceTextureAsync( diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp index 1fa9cef..bb1255f 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp @@ -135,6 +135,25 @@ status_t NuPlayerDriver::setDataSource(const sp<IStreamSource> &source) { return mAsyncResult; } +status_t NuPlayerDriver::setDataSource(const sp<DataSource> &source) { + ALOGV("setDataSource(%p) callback source", this); + Mutex::Autolock autoLock(mLock); + + if (mState != STATE_IDLE) { + return INVALID_OPERATION; + } + + mState = STATE_SET_DATASOURCE_PENDING; + + mPlayer->setDataSourceAsync(source); + + while (mState == STATE_SET_DATASOURCE_PENDING) { + mCondition.wait(mLock); + } + + return mAsyncResult; +} + status_t NuPlayerDriver::setVideoSurfaceTexture( const sp<IGraphicBufferProducer> &bufferProducer) { ALOGV("setVideoSurfaceTexture(%p)", this); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h index e53abcd..65f170e 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h @@ -39,6 +39,8 @@ struct NuPlayerDriver : public MediaPlayerInterface { virtual status_t setDataSource(const sp<IStreamSource> &source); + virtual status_t setDataSource(const sp<DataSource>& dataSource); + virtual status_t setVideoSurfaceTexture( const sp<IGraphicBufferProducer> &bufferProducer); virtual status_t prepare(); diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index b0eeb7f..0ba6743 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -12,6 +12,7 @@ LOCAL_SRC_FILES:= \ AudioPlayer.cpp \ AudioSource.cpp \ AwesomePlayer.cpp \ + CallbackDataSource.cpp \ CameraSource.cpp \ CameraSourceTimeLapse.cpp \ ClockEstimator.cpp \ diff --git a/media/libstagefright/CallbackDataSource.cpp b/media/libstagefright/CallbackDataSource.cpp new file mode 100644 index 0000000..e16cef7 --- /dev/null +++ b/media/libstagefright/CallbackDataSource.cpp @@ -0,0 +1,97 @@ +/* + * Copyright 2015 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 "CallbackDataSource" +#include <utils/Log.h> + +#include "include/CallbackDataSource.h" + +#include <binder/IMemory.h> +#include <media/IDataSource.h> +#include <media/stagefright/foundation/ADebug.h> + +#include <algorithm> + +namespace android { + +CallbackDataSource::CallbackDataSource( + const sp<IDataSource>& binderDataSource) + : mIDataSource(binderDataSource) { + // Set up the buffer to read into. + mMemory = mIDataSource->getIMemory(); +} + +CallbackDataSource::~CallbackDataSource() { + ALOGV("~CallbackDataSource"); + mIDataSource->close(); +} + +status_t CallbackDataSource::initCheck() const { + if (mMemory == NULL) { + return UNKNOWN_ERROR; + } + return OK; +} + +ssize_t CallbackDataSource::readAt(off64_t offset, void* data, size_t size) { + if (mMemory == NULL) { + return -1; + } + + // IDataSource can only read up to mMemory->size() bytes at a time, but this + // method should be able to read any number of bytes, so read in a loop. + size_t totalNumRead = 0; + size_t numLeft = size; + const size_t bufferSize = mMemory->size(); + + while (numLeft > 0) { + size_t numToRead = std::min(numLeft, bufferSize); + ssize_t numRead = + mIDataSource->readAt(offset + totalNumRead, numToRead); + // A negative return value represents an error. Pass it on. + if (numRead < 0) { + return numRead; + } + // A zero return value signals EOS. Return the bytes read so far. + if (numRead == 0) { + return totalNumRead; + } + // Sanity check. + CHECK((size_t)numRead <= numToRead && numRead >= 0 && + numRead <= bufferSize); + memcpy(((uint8_t*)data) + totalNumRead, mMemory->pointer(), numRead); + numLeft -= numRead; + totalNumRead += numRead; + } + + return totalNumRead; +} + +status_t CallbackDataSource::getSize(off64_t *size) { + status_t err = mIDataSource->getSize(size); + if (err != OK) { + return err; + } + if (*size < 0) { + // IDataSource will set size to -1 to indicate unknown size, but + // DataSource returns ERROR_UNSUPPORTED for that. + return ERROR_UNSUPPORTED; + } + return OK; +} + +} // namespace android diff --git a/media/libstagefright/DataSource.cpp b/media/libstagefright/DataSource.cpp index f7dcf35..6a89154 100644 --- a/media/libstagefright/DataSource.cpp +++ b/media/libstagefright/DataSource.cpp @@ -19,6 +19,7 @@ #include "include/AMRExtractor.h" #include "include/AACExtractor.h" +#include "include/CallbackDataSource.h" #include "include/DRMExtractor.h" #include "include/FLACExtractor.h" #include "include/HTTPBase.h" @@ -281,6 +282,10 @@ sp<DataSource> DataSource::CreateMediaHTTP(const sp<IMediaHTTPService> &httpServ } } +sp<DataSource> DataSource::CreateFromIDataSource(const sp<IDataSource> &source) { + return new CallbackDataSource(source); +} + String8 DataSource::getMIMEType() const { return String8("application/octet-stream"); } diff --git a/media/libstagefright/StagefrightMetadataRetriever.cpp b/media/libstagefright/StagefrightMetadataRetriever.cpp index 820b2fc..e9566f2 100644 --- a/media/libstagefright/StagefrightMetadataRetriever.cpp +++ b/media/libstagefright/StagefrightMetadataRetriever.cpp @@ -47,10 +47,7 @@ StagefrightMetadataRetriever::StagefrightMetadataRetriever() StagefrightMetadataRetriever::~StagefrightMetadataRetriever() { ALOGV("~StagefrightMetadataRetriever()"); - - delete mAlbumArt; - mAlbumArt = NULL; - + clearMetadata(); mClient.disconnect(); } @@ -60,11 +57,7 @@ status_t StagefrightMetadataRetriever::setDataSource( const KeyedVector<String8, String8> *headers) { ALOGV("setDataSource(%s)", uri); - mParsedMetaData = false; - mMetaData.clear(); - delete mAlbumArt; - mAlbumArt = NULL; - + clearMetadata(); mSource = DataSource::CreateFromURI(httpService, uri, headers); if (mSource == NULL) { @@ -92,11 +85,7 @@ status_t StagefrightMetadataRetriever::setDataSource( ALOGV("setDataSource(%d, %" PRId64 ", %" PRId64 ")", fd, offset, length); - mParsedMetaData = false; - mMetaData.clear(); - delete mAlbumArt; - mAlbumArt = NULL; - + clearMetadata(); mSource = new FileSource(fd, offset, length); status_t err; @@ -117,6 +106,23 @@ status_t StagefrightMetadataRetriever::setDataSource( return OK; } +status_t StagefrightMetadataRetriever::setDataSource( + const sp<DataSource>& source) { + ALOGV("setDataSource(DataSource)"); + + clearMetadata(); + mSource = source; + mExtractor = MediaExtractor::Create(mSource); + + if (mExtractor == NULL) { + ALOGE("Failed to instantiate a MediaExtractor."); + mSource.clear(); + return UNKNOWN_ERROR; + } + + return OK; +} + static bool isYUV420PlanarSupported( OMXClient *client, const sp<MetaData> &trackMeta) { @@ -635,4 +641,11 @@ void StagefrightMetadataRetriever::parseMetaData() { } } +void StagefrightMetadataRetriever::clearMetadata() { + mParsedMetaData = false; + mMetaData.clear(); + delete mAlbumArt; + mAlbumArt = NULL; +} + } // namespace android diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h index 77d65e0..4704ad3 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -33,7 +33,7 @@ namespace android { struct AudioPlayer; struct ClockEstimator; -struct DataSource; +struct IDataSource; struct MediaBuffer; struct MediaExtractor; struct MediaSource; diff --git a/media/libstagefright/include/CallbackDataSource.h b/media/libstagefright/include/CallbackDataSource.h new file mode 100644 index 0000000..678eb2e --- /dev/null +++ b/media/libstagefright/include/CallbackDataSource.h @@ -0,0 +1,49 @@ +/* + * Copyright 2015 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 ANDROID_CALLBACKDATASOURCE_H +#define ANDROID_CALLBACKDATASOURCE_H + +#include <media/stagefright/DataSource.h> +#include <media/stagefright/foundation/ADebug.h> + +namespace android { + +class IDataSource; +class IMemory; + +// A stagefright DataSource that wraps a binder IDataSource. It's a "Callback" +// DataSource because it calls back to the IDataSource for data. +class CallbackDataSource : public DataSource { +public: + CallbackDataSource(const sp<IDataSource>& iDataSource); + virtual ~CallbackDataSource(); + + // DataSource implementation. + virtual status_t initCheck() const; + virtual ssize_t readAt(off64_t offset, void *data, size_t size); + virtual status_t getSize(off64_t *size); + +private: + sp<IDataSource> mIDataSource; + sp<IMemory> mMemory; + + DISALLOW_EVIL_CONSTRUCTORS(CallbackDataSource); +}; + +}; // namespace android + +#endif // ANDROID_CALLBACKDATASOURCE_H diff --git a/media/libstagefright/include/StagefrightMetadataRetriever.h b/media/libstagefright/include/StagefrightMetadataRetriever.h index 6632c27..96a35f3 100644 --- a/media/libstagefright/include/StagefrightMetadataRetriever.h +++ b/media/libstagefright/include/StagefrightMetadataRetriever.h @@ -38,6 +38,7 @@ struct StagefrightMetadataRetriever : public MediaMetadataRetrieverInterface { const KeyedVector<String8, String8> *headers); virtual status_t setDataSource(int fd, int64_t offset, int64_t length); + virtual status_t setDataSource(const sp<DataSource>& source); virtual VideoFrame *getFrameAtTime(int64_t timeUs, int option); virtual MediaAlbumArt *extractAlbumArt(); @@ -53,6 +54,8 @@ private: MediaAlbumArt *mAlbumArt; void parseMetaData(); + // Delete album art and clear metadata. + void clearMetadata(); StagefrightMetadataRetriever(const StagefrightMetadataRetriever &); |