diff options
Diffstat (limited to 'media')
-rw-r--r-- | media/java/android/media/MediaPlayer.java | 28 | ||||
-rw-r--r-- | media/jni/android_media_MediaPlayer.cpp | 95 | ||||
-rw-r--r-- | media/libmedia/IMediaPlayerService.cpp | 33 | ||||
-rw-r--r-- | media/libmedia/mediaplayer.cpp | 9 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.cpp | 11 | ||||
-rw-r--r-- | media/libmediaplayerservice/MediaPlayerService.h | 12 | ||||
-rw-r--r-- | media/libmediaplayerservice/MidiFile.cpp | 4 | ||||
-rw-r--r-- | media/libmediaplayerservice/MidiFile.h | 5 | ||||
-rw-r--r-- | media/libmediaplayerservice/MidiMetadataRetriever.cpp | 3 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightPlayer.cpp | 5 | ||||
-rw-r--r-- | media/libmediaplayerservice/StagefrightPlayer.h | 5 | ||||
-rw-r--r-- | media/libmediaplayerservice/TestPlayerStub.cpp | 6 | ||||
-rw-r--r-- | media/libmediaplayerservice/TestPlayerStub.h | 3 | ||||
-rw-r--r-- | media/libmediaplayerservice/VorbisMetadataRetriever.cpp | 3 | ||||
-rw-r--r-- | media/libmediaplayerservice/VorbisPlayer.cpp | 6 | ||||
-rw-r--r-- | media/libmediaplayerservice/VorbisPlayer.h | 5 | ||||
-rw-r--r-- | media/tests/players/invoke_mock_media_player.cpp | 6 |
17 files changed, 205 insertions, 34 deletions
diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 07542ed..89ee7d3 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -34,6 +34,7 @@ import android.media.AudioManager; import java.io.FileDescriptor; import java.io.IOException; +import java.util.Map; import java.util.Set; import java.lang.ref.WeakReference; @@ -665,6 +666,20 @@ public class MediaPlayer */ public void setDataSource(Context context, Uri uri) throws IOException, IllegalArgumentException, SecurityException, IllegalStateException { + setDataSource(context, uri, null); + } + + /** + * Sets the data source as a content Uri. + * + * @param context the Context to use when resolving the Uri + * @param uri the Content URI of the data you want to play + * @param headers the headers to be sent together with the request for the data + * @throws IllegalStateException if it is called in an invalid state + * @hide pending API council + */ + public void setDataSource(Context context, Uri uri, Map<String, String> headers) + throws IOException, IllegalArgumentException, SecurityException, IllegalStateException { String scheme = uri.getScheme(); if(scheme == null || scheme.equals("file")) { @@ -696,7 +711,7 @@ public class MediaPlayer } } Log.d(TAG, "Couldn't open file on client side, trying server side"); - setDataSource(uri.toString()); + setDataSource(uri.toString(), headers); return; } @@ -709,6 +724,17 @@ public class MediaPlayer public native void setDataSource(String path) throws IOException, IllegalArgumentException, IllegalStateException; /** + * Sets the data source (file-path or http/rtsp URL) to use. + * + * @param path the path of the file, or the http/rtsp URL of the stream you want to play + * @param headers the headers associated with the http request for the stream you want to play + * @throws IllegalStateException if it is called in an invalid state + * @hide pending API council + */ + public native void setDataSource(String path, Map<String, String> headers) + throws IOException, IllegalArgumentException, IllegalStateException; + + /** * Sets the data source (FileDescriptor) to use. It is the caller's responsibility * to close the file descriptor. It is safe to do so as soon as this call returns. * diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp index 703afd2..27f5668 100644 --- a/media/jni/android_media_MediaPlayer.cpp +++ b/media/jni/android_media_MediaPlayer.cpp @@ -31,6 +31,8 @@ #include "JNIHelp.h" #include "android_runtime/AndroidRuntime.h" #include "utils/Errors.h" // for status_t +#include "utils/KeyedVector.h" +#include "utils/String8.h" #include "android_util_Binder.h" #include <binder/Parcel.h> @@ -156,8 +158,8 @@ static void process_media_player_call(JNIEnv *env, jobject thiz, status_t opStat } static void -android_media_MediaPlayer_setDataSource(JNIEnv *env, jobject thiz, jstring path) -{ +android_media_MediaPlayer_setDataSourceAndHeaders( + JNIEnv *env, jobject thiz, jstring path, jobject headers) { sp<MediaPlayer> mp = getMediaPlayer(env, thiz); if (mp == NULL ) { jniThrowException(env, "java/lang/IllegalStateException", NULL); @@ -174,12 +176,96 @@ android_media_MediaPlayer_setDataSource(JNIEnv *env, jobject thiz, jstring path) jniThrowException(env, "java/lang/RuntimeException", "Out of memory"); return; } + + // headers is a Map<String, String>. + // We build a similar KeyedVector out of it. + KeyedVector<String8, String8> headersVector; + if (headers) { + // Get the Map's entry Set. + jclass mapClass = env->FindClass("java/util/Map"); + + jmethodID entrySet = + env->GetMethodID(mapClass, "entrySet", "()Ljava/util/Set;"); + + jobject set = env->CallObjectMethod(headers, entrySet); + // Obtain an iterator over the Set + jclass setClass = env->FindClass("java/util/Set"); + + jmethodID iterator = + env->GetMethodID(setClass, "iterator", "()Ljava/util/Iterator;"); + + jobject iter = env->CallObjectMethod(set, iterator); + // Get the Iterator method IDs + jclass iteratorClass = env->FindClass("java/util/Iterator"); + jmethodID hasNext = env->GetMethodID(iteratorClass, "hasNext", "()Z"); + + jmethodID next = + env->GetMethodID(iteratorClass, "next", "()Ljava/lang/Object;"); + + // Get the Entry class method IDs + jclass entryClass = env->FindClass("java/util/Map$Entry"); + + jmethodID getKey = + env->GetMethodID(entryClass, "getKey", "()Ljava/lang/Object;"); + + jmethodID getValue = + env->GetMethodID(entryClass, "getValue", "()Ljava/lang/Object;"); + + // Iterate over the entry Set + while (env->CallBooleanMethod(iter, hasNext)) { + jobject entry = env->CallObjectMethod(iter, next); + jstring key = (jstring) env->CallObjectMethod(entry, getKey); + jstring value = (jstring) env->CallObjectMethod(entry, getValue); + + const char* keyStr = env->GetStringUTFChars(key, NULL); + if (!keyStr) { // Out of memory + jniThrowException( + env, "java/lang/RuntimeException", "Out of memory"); + return; + } + + const char* valueStr = env->GetStringUTFChars(value, NULL); + if (!valueStr) { // Out of memory + jniThrowException( + env, "java/lang/RuntimeException", "Out of memory"); + return; + } + + headersVector.add(String8(keyStr), String8(valueStr)); + + env->DeleteLocalRef(entry); + env->ReleaseStringUTFChars(key, keyStr); + env->DeleteLocalRef(key); + env->ReleaseStringUTFChars(value, valueStr); + env->DeleteLocalRef(value); + } + + env->DeleteLocalRef(entryClass); + env->DeleteLocalRef(iteratorClass); + env->DeleteLocalRef(iter); + env->DeleteLocalRef(setClass); + env->DeleteLocalRef(set); + env->DeleteLocalRef(mapClass); + } + LOGV("setDataSource: path %s", pathStr); - status_t opStatus = mp->setDataSource(pathStr); + status_t opStatus = + mp->setDataSource( + String8(pathStr), + headers ? &headersVector : NULL); // Make sure that local ref is released before a potential exception env->ReleaseStringUTFChars(path, pathStr); - process_media_player_call( env, thiz, opStatus, "java/io/IOException", "setDataSource failed." ); + + process_media_player_call( + env, thiz, opStatus, "java/io/IOException", + "setDataSource failed." ); +} + +static void +android_media_MediaPlayer_setDataSource(JNIEnv *env, jobject thiz, jstring path) +{ + android_media_MediaPlayer_setDataSourceAndHeaders(env, thiz, path, 0); } static void @@ -610,6 +696,7 @@ android_media_MediaPlayer_snoop(JNIEnv* env, jobject thiz, jobject data, jint ki static JNINativeMethod gMethods[] = { {"setDataSource", "(Ljava/lang/String;)V", (void *)android_media_MediaPlayer_setDataSource}, + {"setDataSource", "(Ljava/lang/String;Ljava/util/Map;)V",(void *)android_media_MediaPlayer_setDataSourceAndHeaders}, {"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD}, {"_setVideoSurface", "()V", (void *)android_media_MediaPlayer_setVideoSurface}, {"prepare", "()V", (void *)android_media_MediaPlayer_prepare}, diff --git a/media/libmedia/IMediaPlayerService.cpp b/media/libmedia/IMediaPlayerService.cpp index cca3e9b..71c5f86 100644 --- a/media/libmedia/IMediaPlayerService.cpp +++ b/media/libmedia/IMediaPlayerService.cpp @@ -56,13 +56,26 @@ public: return interface_cast<IMediaMetadataRetriever>(reply.readStrongBinder()); } - virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url) - { + virtual sp<IMediaPlayer> create( + pid_t pid, const sp<IMediaPlayerClient>& client, + const char* url, const KeyedVector<String8, String8> *headers) { Parcel data, reply; data.writeInterfaceToken(IMediaPlayerService::getInterfaceDescriptor()); data.writeInt32(pid); data.writeStrongBinder(client->asBinder()); data.writeCString(url); + + if (headers == NULL) { + data.writeInt32(0); + } else { + // serialize the headers + data.writeInt32(headers->size()); + for (size_t i = 0; i < headers->size(); ++i) { + data.writeString8(headers->keyAt(i)); + data.writeString8(headers->valueAt(i)); + } + } + remote()->transact(CREATE_URL, data, &reply); return interface_cast<IMediaPlayer>(reply.readStrongBinder()); } @@ -142,9 +155,21 @@ status_t BnMediaPlayerService::onTransact( case CREATE_URL: { CHECK_INTERFACE(IMediaPlayerService, data, reply); pid_t pid = data.readInt32(); - sp<IMediaPlayerClient> client = interface_cast<IMediaPlayerClient>(data.readStrongBinder()); + sp<IMediaPlayerClient> client = + interface_cast<IMediaPlayerClient>(data.readStrongBinder()); const char* url = data.readCString(); - sp<IMediaPlayer> player = create(pid, client, url); + + KeyedVector<String8, String8> headers; + int32_t numHeaders = data.readInt32(); + for (int i = 0; i < numHeaders; ++i) { + String8 key = data.readString8(); + String8 value = data.readString8(); + headers.add(key, value); + } + + sp<IMediaPlayer> player = create( + pid, client, url, numHeaders > 0 ? &headers : NULL); + reply->writeStrongBinder(player->asBinder()); return NO_ERROR; } break; diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index c0664f3..cb5ee4b 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -32,6 +32,9 @@ #include <binder/MemoryBase.h> +#include <utils/KeyedVector.h> +#include <utils/String8.h> + namespace android { MediaPlayer::MediaPlayer() @@ -122,14 +125,16 @@ status_t MediaPlayer::setDataSource(const sp<IMediaPlayer>& player) return err; } -status_t MediaPlayer::setDataSource(const char *url) +status_t MediaPlayer::setDataSource( + const char *url, const KeyedVector<String8, String8> *headers) { LOGV("setDataSource(%s)", url); status_t err = BAD_VALUE; if (url != NULL) { const sp<IMediaPlayerService>& service(getMediaPlayerService()); if (service != 0) { - sp<IMediaPlayer> player(service->create(getpid(), this, url)); + sp<IMediaPlayer> player( + service->create(getpid(), this, url, headers)); err = setDataSource(player); } } diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 5b061b1..8e61011 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -254,12 +254,14 @@ sp<IMediaMetadataRetriever> MediaPlayerService::createMetadataRetriever(pid_t pi return retriever; } -sp<IMediaPlayer> MediaPlayerService::create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url) +sp<IMediaPlayer> MediaPlayerService::create( + pid_t pid, const sp<IMediaPlayerClient>& client, const char* url, + const KeyedVector<String8, String8> *headers) { int32_t connId = android_atomic_inc(&mNextConnId); sp<Client> c = new Client(this, pid, connId, client); LOGV("Create new client(%d) from pid %d, url=%s, connId=%d", connId, pid, url, connId); - if (NO_ERROR != c->setDataSource(url)) + if (NO_ERROR != c->setDataSource(url, headers)) { c.clear(); return c; @@ -803,7 +805,8 @@ sp<MediaPlayerBase> MediaPlayerService::Client::createPlayer(player_type playerT return p; } -status_t MediaPlayerService::Client::setDataSource(const char *url) +status_t MediaPlayerService::Client::setDataSource( + const char *url, const KeyedVector<String8, String8> *headers) { LOGV("setDataSource(%s)", url); if (url == NULL) @@ -838,7 +841,7 @@ status_t MediaPlayerService::Client::setDataSource(const char *url) // now set data source LOGV(" setDataSource"); - mStatus = p->setDataSource(url); + mStatus = p->setDataSource(url, headers); if (mStatus == NO_ERROR) { mPlayer = p; } else { diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index d243b96..ffe1ba0 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -23,6 +23,7 @@ #include <utils/List.h> #include <utils/Errors.h> #include <utils/KeyedVector.h> +#include <utils/String8.h> #include <utils/Vector.h> #include <ui/SurfaceComposerClient.h> @@ -181,7 +182,10 @@ public: virtual sp<IMediaMetadataRetriever> createMetadataRetriever(pid_t pid); // House keeping for media player clients - virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, const char* url); + virtual sp<IMediaPlayer> create( + pid_t pid, const sp<IMediaPlayerClient>& client, const char* url, + const KeyedVector<String8, String8> *headers); + virtual sp<IMediaPlayer> create(pid_t pid, const sp<IMediaPlayerClient>& client, int fd, int64_t offset, int64_t length); virtual sp<IMemory> decode(const char* url, uint32_t *pSampleRate, int* pNumChannels, int* pFormat); virtual sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat); @@ -219,7 +223,11 @@ private: Parcel *reply); sp<MediaPlayerBase> createPlayer(player_type playerType); - status_t setDataSource(const char *url); + + status_t setDataSource( + const char *url, + const KeyedVector<String8, String8> *headers); + status_t setDataSource(int fd, int64_t offset, int64_t length); static void notify(void* cookie, int msg, int ext1, int ext2); diff --git a/media/libmediaplayerservice/MidiFile.cpp b/media/libmediaplayerservice/MidiFile.cpp index e9cbb97..1b0b05f 100644 --- a/media/libmediaplayerservice/MidiFile.cpp +++ b/media/libmediaplayerservice/MidiFile.cpp @@ -115,8 +115,8 @@ MidiFile::~MidiFile() { release(); } -status_t MidiFile::setDataSource(const char* path) -{ +status_t MidiFile::setDataSource( + const char* path, const KeyedVector<String8, String8> *) { LOGV("MidiFile::setDataSource url=%s", path); Mutex::Autolock lock(mMutex); diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h index 25d4a1b..4a60ece 100644 --- a/media/libmediaplayerservice/MidiFile.h +++ b/media/libmediaplayerservice/MidiFile.h @@ -30,7 +30,10 @@ public: ~MidiFile(); virtual status_t initCheck(); - virtual status_t setDataSource(const char* path); + + virtual status_t setDataSource( + const char* path, const KeyedVector<String8, String8> *headers); + virtual status_t setDataSource(int fd, int64_t offset, int64_t length); virtual status_t setVideoSurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; } virtual status_t prepare(); diff --git a/media/libmediaplayerservice/MidiMetadataRetriever.cpp b/media/libmediaplayerservice/MidiMetadataRetriever.cpp index 3795b7b..ad95fac 100644 --- a/media/libmediaplayerservice/MidiMetadataRetriever.cpp +++ b/media/libmediaplayerservice/MidiMetadataRetriever.cpp @@ -43,7 +43,8 @@ status_t MidiMetadataRetriever::setDataSource(const char *url) if (mMidiPlayer == 0) { mMidiPlayer = new MidiFile(); } - return mMidiPlayer->setDataSource(url); + // TODO: support headers in MetadataRetriever interface! + return mMidiPlayer->setDataSource(url, NULL /* headers */); } status_t MidiMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length) diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp index 5915105..3135d0c 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.cpp +++ b/media/libmediaplayerservice/StagefrightPlayer.cpp @@ -28,8 +28,9 @@ status_t StagefrightPlayer::initCheck() { return OK; } -status_t StagefrightPlayer::setDataSource(const char *url) { - LOGV("setDataSource('%s')", url); +status_t StagefrightPlayer::setDataSource( + const char *url, const KeyedVector<String8, String8> *) { + LOGI("setDataSource('%s')", url); return mPlayer->setDataSource(url); } diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h index 9d005cb..9e6674a 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.h +++ b/media/libmediaplayerservice/StagefrightPlayer.h @@ -30,7 +30,10 @@ public: virtual ~StagefrightPlayer(); virtual status_t initCheck(); - virtual status_t setDataSource(const char *url); + + virtual status_t setDataSource( + const char *url, const KeyedVector<String8, String8> *headers); + virtual status_t setDataSource(int fd, int64_t offset, int64_t length); virtual status_t setVideoSurface(const sp<ISurface> &surface); virtual status_t prepare(); diff --git a/media/libmediaplayerservice/TestPlayerStub.cpp b/media/libmediaplayerservice/TestPlayerStub.cpp index aa49429..169e49a 100644 --- a/media/libmediaplayerservice/TestPlayerStub.cpp +++ b/media/libmediaplayerservice/TestPlayerStub.cpp @@ -112,8 +112,8 @@ status_t TestPlayerStub::parseUrl() // Load the dynamic library. // Create the test player. // Call setDataSource on the test player with the url in param. -status_t TestPlayerStub::setDataSource(const char *url) -{ +status_t TestPlayerStub::setDataSource( + const char *url, const KeyedVector<String8, String8> *headers) { if (!isTestUrl(url) || NULL != mHandle) { return INVALID_OPERATION; } @@ -162,7 +162,7 @@ status_t TestPlayerStub::setDataSource(const char *url) } mPlayer = (*mNewPlayer)(); - return mPlayer->setDataSource(mContentUrl); + return mPlayer->setDataSource(mContentUrl, headers); } // Internal cleanup. diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h index 80d53a8..6e6c3cd 100644 --- a/media/libmediaplayerservice/TestPlayerStub.h +++ b/media/libmediaplayerservice/TestPlayerStub.h @@ -65,7 +65,8 @@ class TestPlayerStub : public MediaPlayerInterface { virtual status_t initCheck(); // @param url Should be a test url. See class comment. - virtual status_t setDataSource(const char* url); + virtual status_t setDataSource( + 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/VorbisMetadataRetriever.cpp b/media/libmediaplayerservice/VorbisMetadataRetriever.cpp index e981678..eac74fc 100644 --- a/media/libmediaplayerservice/VorbisMetadataRetriever.cpp +++ b/media/libmediaplayerservice/VorbisMetadataRetriever.cpp @@ -39,7 +39,8 @@ status_t VorbisMetadataRetriever::setDataSource(const char *url) if (mVorbisPlayer == 0) { mVorbisPlayer = new VorbisPlayer(); } - return mVorbisPlayer->setDataSource(url); + // TODO: support headers in MetadataRetriever interface! + return mVorbisPlayer->setDataSource(url, NULL /* headers */); } status_t VorbisMetadataRetriever::setDataSource(int fd, int64_t offset, int64_t length) diff --git a/media/libmediaplayerservice/VorbisPlayer.cpp b/media/libmediaplayerservice/VorbisPlayer.cpp index 7f0ef21..8181999 100644 --- a/media/libmediaplayerservice/VorbisPlayer.cpp +++ b/media/libmediaplayerservice/VorbisPlayer.cpp @@ -86,9 +86,9 @@ VorbisPlayer::~VorbisPlayer() { release(); } -status_t VorbisPlayer::setDataSource(const char* path) -{ - return setdatasource(path, -1, 0, 0x7ffffffffffffffLL); // intentionally less than LONG_MAX +status_t VorbisPlayer::setDataSource( + const char *uri, const KeyedVector<String8, String8> *headers) { + return setdatasource(uri, -1, 0, 0x7ffffffffffffffLL); // intentionally less than LONG_MAX } status_t VorbisPlayer::setDataSource(int fd, int64_t offset, int64_t length) diff --git a/media/libmediaplayerservice/VorbisPlayer.h b/media/libmediaplayerservice/VorbisPlayer.h index 4024654..4a50835 100644 --- a/media/libmediaplayerservice/VorbisPlayer.h +++ b/media/libmediaplayerservice/VorbisPlayer.h @@ -37,7 +37,10 @@ public: virtual void onFirstRef(); virtual status_t initCheck(); - virtual status_t setDataSource(const char* path); + + virtual status_t setDataSource( + const char *uri, const KeyedVector<String8, String8> *headers); + virtual status_t setDataSource(int fd, int64_t offset, int64_t length); virtual status_t setVideoSurface(const sp<ISurface>& surface) { return UNKNOWN_ERROR; } virtual status_t prepare(); diff --git a/media/tests/players/invoke_mock_media_player.cpp b/media/tests/players/invoke_mock_media_player.cpp index 77bb5b2..b3cc8b6 100644 --- a/media/tests/players/invoke_mock_media_player.cpp +++ b/media/tests/players/invoke_mock_media_player.cpp @@ -35,6 +35,8 @@ using android::UNKNOWN_ERROR; using android::player_type; using android::sp; using android::status_t; +using android::String8; +using android::KeyedVector; // This file contains a test player that is loaded via the // TestPlayerStub class. The player contains various implementation @@ -53,7 +55,9 @@ class Player: public MediaPlayerBase virtual status_t initCheck() {return OK;} virtual bool hardwareOutput() {return true;} - virtual status_t setDataSource(const char *url) { + virtual status_t setDataSource( + const char *url, + const KeyedVector<String8, String8> *) { LOGV("setDataSource %s", url); mTest = TEST_UNKNOWN; if (strncmp(url, kPing, strlen(kPing)) == 0) { |