Basic plumbing to retrieve metadata from the native player.
IMediaPlayer.h Added a getMetadata method that mirrors the on in MediaPlayer.java. MediaPlayer.java Added a native method to get the metadata from the native player. Parse the parcel into a Metadata object. Metadata.java Added a stub to parse the Parcel returned by the native player into a set of metadata. android_media_MediaPlayer.cpp JNI call to forward the getMetadata call. MediaPlayerService.cpp MediaPlayerService::Client implements the new getMetadata method added in IMediaPlayer.h
This commit is contained in:
@@ -59,6 +59,23 @@ public:
|
||||
// @param filter A set of allow and drop rules serialized in a Parcel.
|
||||
// @return OK if the invocation was made successfully.
|
||||
virtual status_t setMetadataFilter(const Parcel& filter) = 0;
|
||||
|
||||
// Retrieve a set of metadata.
|
||||
// @param update_only Include only the metadata that have changed
|
||||
// since the last invocation of getMetadata.
|
||||
// The set is built using the unfiltered
|
||||
// notifications the native player sent to the
|
||||
// MediaPlayerService during that period of
|
||||
// time. If false, all the metadatas are considered.
|
||||
// @param apply_filter If true, once the metadata set has been built based
|
||||
// on the value update_only, the current filter is
|
||||
// applied.
|
||||
// @param[out] metadata On exit contains a set (possibly empty) of metadata.
|
||||
// Valid only if the call returned OK.
|
||||
// @return OK if the invocation was made successfully.
|
||||
virtual status_t getMetadata(bool update_only,
|
||||
bool apply_filter,
|
||||
Parcel *metadata) = 0;
|
||||
};
|
||||
|
||||
// ----------------------------------------------------------------------------
|
||||
|
||||
@@ -155,6 +155,7 @@ public:
|
||||
static sp<IMemory> decode(int fd, int64_t offset, int64_t length, uint32_t *pSampleRate, int* pNumChannels, int* pFormat);
|
||||
status_t invoke(const Parcel& request, Parcel *reply);
|
||||
status_t setMetadataFilter(const Parcel& filter);
|
||||
status_t getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
|
||||
private:
|
||||
void clear_l();
|
||||
status_t seekTo_l(int msec);
|
||||
|
||||
@@ -930,8 +930,21 @@ public class MediaPlayer
|
||||
*/
|
||||
public Metadata getMetadata(final boolean update_only,
|
||||
final boolean apply_filter) {
|
||||
// FIXME: Implement.
|
||||
return new Metadata();
|
||||
Parcel reply = Parcel.obtain();
|
||||
Metadata data = new Metadata();
|
||||
|
||||
if (!native_getMetadata(update_only, apply_filter, reply)) {
|
||||
reply.recycle();
|
||||
return null;
|
||||
}
|
||||
|
||||
// Metadata takes over the parcel, don't recycle it unless
|
||||
// there is an error.
|
||||
if (!data.parse(reply)) {
|
||||
reply.recycle();
|
||||
return null;
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1064,11 +1077,29 @@ public class MediaPlayer
|
||||
* @param request Parcel destinated to the media player. The
|
||||
* Interface token must be set to the IMediaPlayer
|
||||
* one to be routed correctly through the system.
|
||||
* @param reply Parcel that will contain the reply.
|
||||
* @param reply[out] Parcel that will contain the reply.
|
||||
* @return The status code.
|
||||
*/
|
||||
private native final int native_invoke(Parcel request, Parcel reply);
|
||||
|
||||
|
||||
/**
|
||||
* @param update_only If true fetch only the set of metadata that have
|
||||
* changed since the last invocation of getMetadata.
|
||||
* The set is built using the unfiltered
|
||||
* notifications the native player sent to the
|
||||
* MediaPlayerService during that period of
|
||||
* time. If false, all the metadatas are considered.
|
||||
* @param apply_filter If true, once the metadata set has been built based on
|
||||
* the value update_only, the current filter is applied.
|
||||
* @param reply[out] On return contains the serialized
|
||||
* metadata. Valid only if the call was successful.
|
||||
* @return The status code.
|
||||
*/
|
||||
private native final boolean native_getMetadata(boolean update_only,
|
||||
boolean apply_filter,
|
||||
Parcel reply);
|
||||
|
||||
/**
|
||||
* @param request Parcel with the 2 serialized lists of allowed
|
||||
* metadata types followed by the one to be
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
package android.media;
|
||||
|
||||
import android.graphics.Bitmap;
|
||||
import android.os.Parcel;
|
||||
import android.util.Log;
|
||||
|
||||
import java.util.Collections;
|
||||
@@ -24,6 +25,7 @@ import java.util.Date;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
Class to hold the media's metadata. Metadata are used
|
||||
for human consumption and can be embedded in the media (e.g
|
||||
@@ -100,6 +102,12 @@ public class Metadata
|
||||
public static final Set<Integer> MATCH_NONE = Collections.EMPTY_SET;
|
||||
public static final Set<Integer> MATCH_ALL = Collections.singleton(ANY);
|
||||
|
||||
private static final int STRING_VAL = 1;
|
||||
private static final int INTEGER_VAL = 2;
|
||||
private static final int LONG_VAL = 3;
|
||||
private static final int DOUBLE_VAL = 4;
|
||||
private static final int TIMED_TEXT_VAL = 2;
|
||||
|
||||
/**
|
||||
* Helper class to hold a pair (time, text). Can be used to implement caption.
|
||||
*/
|
||||
@@ -119,6 +127,11 @@ public class Metadata
|
||||
|
||||
/* package */ Metadata() {}
|
||||
|
||||
/* package */ boolean parse(Parcel data) {
|
||||
// FIXME: Implement.
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the number of element in this metadata set.
|
||||
*/
|
||||
|
||||
@@ -479,9 +479,39 @@ android_media_MediaPlayer_setMetadataFilter(JNIEnv *env, jobject thiz, jobject r
|
||||
|
||||
Parcel *filter = parcelForJavaObject(env, request);
|
||||
|
||||
if (filter == NULL ) {
|
||||
jniThrowException(env, "java/lang/RuntimeException", "Filter is null");
|
||||
return UNKNOWN_ERROR;
|
||||
}
|
||||
|
||||
return media_player->setMetadataFilter(*filter);
|
||||
}
|
||||
|
||||
static jboolean
|
||||
android_media_MediaPlayer_getMetadata(JNIEnv *env, jobject thiz, jboolean update_only,
|
||||
jboolean apply_filter, jobject reply)
|
||||
{
|
||||
sp<MediaPlayer> media_player = getMediaPlayer(env, thiz);
|
||||
if (media_player == NULL ) {
|
||||
jniThrowException(env, "java/lang/IllegalStateException", NULL);
|
||||
return false;
|
||||
}
|
||||
|
||||
Parcel *metadata = parcelForJavaObject(env, reply);
|
||||
|
||||
if (metadata == NULL ) {
|
||||
jniThrowException(env, "java/lang/RuntimeException", "Reply parcel is null");
|
||||
return false;
|
||||
}
|
||||
|
||||
metadata->freeData();
|
||||
// On return metadata is positioned at the beginning of the
|
||||
// metadata. Note however that the parcel actually starts with the
|
||||
// return code so you should not rewind the parcel using
|
||||
// setDataPosition(0).
|
||||
return media_player->getMetadata(update_only, apply_filter, metadata) == OK;
|
||||
}
|
||||
|
||||
|
||||
static void
|
||||
android_media_MediaPlayer_native_setup(JNIEnv *env, jobject thiz, jobject weak_this)
|
||||
@@ -546,6 +576,7 @@ static JNINativeMethod gMethods[] = {
|
||||
{"getFrameAt", "(I)Landroid/graphics/Bitmap;", (void *)android_media_MediaPlayer_getFrameAt},
|
||||
{"native_invoke", "(Landroid/os/Parcel;Landroid/os/Parcel;)I",(void *)android_media_MediaPlayer_invoke},
|
||||
{"native_setMetadataFilter", "(Landroid/os/Parcel;)I", (void *)android_media_MediaPlayer_setMetadataFilter},
|
||||
{"native_getMetadata", "(ZZLandroid/os/Parcel;)Z", (void *)android_media_MediaPlayer_getMetadata},
|
||||
{"native_setup", "(Ljava/lang/Object;)V", (void *)android_media_MediaPlayer_native_setup},
|
||||
{"native_finalize", "()V", (void *)android_media_MediaPlayer_native_finalize},
|
||||
};
|
||||
|
||||
@@ -42,6 +42,7 @@ enum {
|
||||
SET_VOLUME,
|
||||
INVOKE,
|
||||
SET_METADATA_FILTER,
|
||||
GET_METADATA,
|
||||
};
|
||||
|
||||
class BpMediaPlayer: public BpInterface<IMediaPlayer>
|
||||
@@ -176,8 +177,7 @@ public:
|
||||
status_t invoke(const Parcel& request, Parcel *reply)
|
||||
{ // Avoid doing any extra copy. The interface descriptor should
|
||||
// have been set by MediaPlayer.java.
|
||||
status_t retcode = remote()->transact(INVOKE, request, reply);
|
||||
return retcode;
|
||||
return remote()->transact(INVOKE, request, reply);
|
||||
}
|
||||
|
||||
status_t setMetadataFilter(const Parcel& request)
|
||||
@@ -188,6 +188,17 @@ public:
|
||||
remote()->transact(SET_METADATA_FILTER, request, &reply);
|
||||
return reply.readInt32();
|
||||
}
|
||||
|
||||
status_t getMetadata(bool update_only, bool apply_filter, Parcel *reply)
|
||||
{
|
||||
Parcel request;
|
||||
request.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
|
||||
// TODO: Burning 2 ints for 2 boolean. Should probably use flags in an int here.
|
||||
request.writeInt32(update_only);
|
||||
request.writeInt32(apply_filter);
|
||||
remote()->transact(GET_METADATA, request, reply);
|
||||
return reply->readInt32();
|
||||
}
|
||||
};
|
||||
|
||||
IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer");
|
||||
@@ -288,6 +299,14 @@ status_t BnMediaPlayer::onTransact(
|
||||
reply->writeInt32(setMetadataFilter(data));
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
case GET_METADATA: {
|
||||
CHECK_INTERFACE(IMediaPlayer, data, reply);
|
||||
const status_t retcode = getMetadata(data.readInt32(), data.readInt32(), reply);
|
||||
reply->setDataPosition(0);
|
||||
reply->writeInt32(retcode);
|
||||
reply->setDataPosition(0);
|
||||
return NO_ERROR;
|
||||
} break;
|
||||
default:
|
||||
return BBinder::onTransact(code, data, reply, flags);
|
||||
}
|
||||
|
||||
@@ -211,14 +211,23 @@ status_t MediaPlayer::invoke(const Parcel& request, Parcel *reply)
|
||||
status_t MediaPlayer::setMetadataFilter(const Parcel& filter)
|
||||
{
|
||||
LOGD("setMetadataFilter");
|
||||
Mutex::Autolock _l(mLock);
|
||||
if (mPlayer == NULL)
|
||||
{
|
||||
Mutex::Autolock lock(mLock);
|
||||
if (mPlayer == NULL) {
|
||||
return NO_INIT;
|
||||
}
|
||||
return mPlayer->setMetadataFilter(filter);
|
||||
}
|
||||
|
||||
status_t MediaPlayer::getMetadata(bool update_only, bool apply_filter, Parcel *metadata)
|
||||
{
|
||||
LOGD("getMetadata");
|
||||
Mutex::Autolock lock(mLock);
|
||||
if (mPlayer == NULL) {
|
||||
return NO_INIT;
|
||||
}
|
||||
return mPlayer->getMetadata(update_only, apply_filter, metadata);
|
||||
}
|
||||
|
||||
status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface)
|
||||
{
|
||||
LOGV("setVideoSurface");
|
||||
|
||||
@@ -846,6 +846,16 @@ status_t MediaPlayerService::Client::setMetadataFilter(const Parcel& filter)
|
||||
return status;
|
||||
}
|
||||
|
||||
status_t MediaPlayerService::Client::getMetadata(bool update_only, bool apply_filter, Parcel *metadata)
|
||||
{
|
||||
status_t status;
|
||||
metadata->writeInt32(-1); // Placeholder for the return code
|
||||
|
||||
// FIXME: Implement, query the native player and do the optional filtering, etc...
|
||||
status = OK;
|
||||
return status;
|
||||
}
|
||||
|
||||
status_t MediaPlayerService::Client::prepareAsync()
|
||||
{
|
||||
LOGV("[%d] prepareAsync", mConnId);
|
||||
|
||||
@@ -191,6 +191,7 @@ private:
|
||||
virtual status_t setVolume(float leftVolume, float rightVolume);
|
||||
virtual status_t invoke(const Parcel& request, Parcel *reply);
|
||||
virtual status_t setMetadataFilter(const Parcel& filter);
|
||||
virtual status_t getMetadata(bool update_only, bool apply_filter, Parcel *metadata);
|
||||
|
||||
sp<MediaPlayerBase> createPlayer(player_type playerType);
|
||||
status_t setDataSource(const char *url);
|
||||
|
||||
Reference in New Issue
Block a user