summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorChris Watkins <watk@google.com>2015-03-20 13:06:33 -0700
committerChris Watkins <watk@google.com>2015-04-15 17:12:22 -0700
commit99f31604136d66ae10e20669fb6b5716f342bde0 (patch)
tree20e64f4f26533b37b087ce8656b1040b8189e24f
parent2f33dbc6ca08d45efea2df775c158e2a11e07ab6 (diff)
downloadframeworks_av-99f31604136d66ae10e20669fb6b5716f342bde0.zip
frameworks_av-99f31604136d66ae10e20669fb6b5716f342bde0.tar.gz
frameworks_av-99f31604136d66ae10e20669fb6b5716f342bde0.tar.bz2
Unhide the android.media.[Media]DataSource interface.
This allows apps to implement MediaDataSource, which is modeled on stagefright's DataSource, to supply media data to the framework. This was already implemented for MediaExtractor, but it was renamed from DataSource. MediaExtractor, MediaPlayer and MediaMetadataRetriever each have a new overload: #setDataSource(android.media.MediaDataSource) Only NuPlayer supports this new data source. The change introduces: * IDataSource: The binder interface for DataSource. * JMediaDataSource: The native counterpart to the java interface. It implements IDataSource. * CallbackDataSource: A stagefright DataSource that wraps an IDataSource. Change-Id: Ib3c944b49cc8a792c8eb9c85e5015c07f298ebc1
-rw-r--r--include/media/IDataSource.h61
-rw-r--r--include/media/IMediaMetadataRetriever.h4
-rw-r--r--include/media/IMediaPlayer.h2
-rw-r--r--include/media/MediaMetadataRetrieverInterface.h4
-rw-r--r--include/media/MediaPlayerInterface.h5
-rw-r--r--include/media/mediametadataretriever.h4
-rw-r--r--include/media/mediaplayer.h1
-rw-r--r--include/media/stagefright/DataSource.h5
-rw-r--r--media/libmedia/Android.mk1
-rw-r--r--media/libmedia/IDataSource.cpp108
-rw-r--r--media/libmedia/IMediaMetadataRetriever.cpp18
-rw-r--r--media/libmedia/IMediaPlayer.cpp17
-rw-r--r--media/libmedia/mediametadataretriever.cpp12
-rw-r--r--media/libmedia/mediaplayer.cpp17
-rw-r--r--media/libmediaplayerservice/MediaPlayerFactory.cpp12
-rw-r--r--media/libmediaplayerservice/MediaPlayerFactory.h6
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.cpp13
-rw-r--r--media/libmediaplayerservice/MediaPlayerService.h3
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.cpp18
-rw-r--r--media/libmediaplayerservice/MetadataRetrieverClient.h1
-rw-r--r--media/libmediaplayerservice/nuplayer/GenericSource.cpp28
-rw-r--r--media/libmediaplayerservice/nuplayer/GenericSource.h3
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.cpp16
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayer.h3
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp19
-rw-r--r--media/libmediaplayerservice/nuplayer/NuPlayerDriver.h2
-rw-r--r--media/libstagefright/Android.mk1
-rw-r--r--media/libstagefright/CallbackDataSource.cpp97
-rw-r--r--media/libstagefright/DataSource.cpp5
-rw-r--r--media/libstagefright/StagefrightMetadataRetriever.cpp41
-rw-r--r--media/libstagefright/include/AwesomePlayer.h2
-rw-r--r--media/libstagefright/include/CallbackDataSource.h49
-rw-r--r--media/libstagefright/include/StagefrightMetadataRetriever.h3
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 b35cf32..2261a7f 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;
@@ -74,6 +75,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 101fc8a..5d2a32c 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) {
@@ -629,4 +635,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 &);