MediaPlayer2: use protobuf instead of parcel for notification message

Test: MediaPlayer2Test
Bug: 112767225
Change-Id: Ifed7c5c63623ad2b0f17806a38cd020470174dad
This commit is contained in:
Dongwon Kang
2018-09-09 08:31:41 -07:00
parent 0d2b287e90
commit 63f28a9e4c
4 changed files with 91 additions and 44 deletions

View File

@@ -2769,8 +2769,8 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
{
if (msg.obj == null) {
Log.w(TAG, "MEDIA_DRM_INFO msg.obj=NULL");
} else if (msg.obj instanceof Parcel) {
// The parcel was parsed already in postEventFromNative
} else if (msg.obj instanceof byte[]) {
// The PlayerMessage was parsed already in postEventFromNative
final DrmInfoImpl drmInfo;
synchronized (mDrmLock) {
@@ -2975,10 +2975,15 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
case MEDIA_TIMED_TEXT:
{
final TimedText text;
if (msg.obj instanceof Parcel) {
Parcel parcel = (Parcel)msg.obj;
text = new TimedText(parcel);
parcel.recycle();
if (msg.obj instanceof byte[]) {
PlayerMessage playerMsg;
try {
playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
} catch (InvalidProtocolBufferException e) {
Log.w(TAG, "Failed to parse timed text.", e);
return;
}
text = null; // TODO: convert PlayerMessage to new TimedText(playerMsg);
} else {
text = null;
}
@@ -2994,10 +2999,20 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
case MEDIA_SUBTITLE_DATA:
{
if (msg.obj instanceof Parcel) {
Parcel parcel = (Parcel) msg.obj;
SubtitleData data = new SubtitleData(parcel);
parcel.recycle();
if (msg.obj instanceof byte[]) {
PlayerMessage playerMsg;
try {
playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
} catch (InvalidProtocolBufferException e) {
Log.w(TAG, "Failed to parse subtitle data.", e);
return;
}
Iterator<Value> in = playerMsg.getValuesList().iterator();
SubtitleData data = new SubtitleData(
in.next().getInt32Value(), // trackIndex
in.next().getInt64Value(), // startTimeUs
in.next().getInt64Value(), // durationUs
in.next().getBytesValue().toByteArray()); // data
synchronized (mEventCbLock) {
for (Pair<Executor, EventCallback> cb : mEventCallbackRecords) {
cb.first.execute(() -> cb.second.onSubtitleData(
@@ -3011,10 +3026,18 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
case MEDIA_META_DATA:
{
final TimedMetaData data;
if (msg.obj instanceof Parcel) {
Parcel parcel = (Parcel) msg.obj;
data = TimedMetaData.createTimedMetaDataFromParcel(parcel);
parcel.recycle();
if (msg.obj instanceof byte[]) {
PlayerMessage playerMsg;
try {
playerMsg = PlayerMessage.parseFrom((byte[]) msg.obj);
} catch (InvalidProtocolBufferException e) {
Log.w(TAG, "Failed to parse timed meta data.", e);
return;
}
Iterator<Value> in = playerMsg.getValuesList().iterator();
data = new TimedMetaData(
in.next().getInt64Value(), // timestampUs
in.next().getBytesValue().toByteArray()); // metaData
} else {
data = null;
}
@@ -3062,7 +3085,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
* the cookie passed to native_setup().)
*/
private static void postEventFromNative(Object mediaplayer2_ref, long srcId,
int what, int arg1, int arg2, Object obj)
int what, int arg1, int arg2, byte[] obj)
{
final MediaPlayer2Impl mp = (MediaPlayer2Impl)((WeakReference)mediaplayer2_ref).get();
if (mp == null) {
@@ -3076,9 +3099,15 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
// notification looper so its handleMessage might process the event after prepare()
// has returned.
Log.v(TAG, "postEventFromNative MEDIA_DRM_INFO");
if (obj instanceof Parcel) {
Parcel parcel = (Parcel)obj;
DrmInfoImpl drmInfo = new DrmInfoImpl(parcel);
if (obj != null) {
PlayerMessage playerMsg;
try {
playerMsg = PlayerMessage.parseFrom(obj);
} catch (InvalidProtocolBufferException e) {
Log.w(TAG, "MEDIA_DRM_INFO failed to parse msg.obj " + obj);
break;
}
DrmInfoImpl drmInfo = new DrmInfoImpl(playerMsg);
synchronized (mp.mDrmLock) {
mp.mDrmInfoImpl = drmInfo;
}
@@ -3745,22 +3774,21 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
supportedSchemes = SupportedSchemes;
}
private DrmInfoImpl(Parcel parcel) {
Log.v(TAG, "DrmInfoImpl(" + parcel + ") size " + parcel.dataSize());
private DrmInfoImpl(PlayerMessage msg) {
Log.v(TAG, "DrmInfoImpl(" + msg + ")");
int psshsize = parcel.readInt();
byte[] pssh = new byte[psshsize];
parcel.readByteArray(pssh);
Iterator<Value> in = msg.getValuesList().iterator();
byte[] pssh = in.next().getBytesValue().toByteArray();
Log.v(TAG, "DrmInfoImpl() PSSH: " + arrToHex(pssh));
mapPssh = parsePSSH(pssh, psshsize);
mapPssh = parsePSSH(pssh, pssh.length);
Log.v(TAG, "DrmInfoImpl() PSSH: " + mapPssh);
int supportedDRMsCount = parcel.readInt();
int supportedDRMsCount = in.next().getInt32Value();
supportedSchemes = new UUID[supportedDRMsCount];
for (int i = 0; i < supportedDRMsCount; i++) {
byte[] uuid = new byte[16];
parcel.readByteArray(uuid);
in.next().getBytesValue().copyTo(uuid, uuid.length);
supportedSchemes[i] = bytesToUUID(uuid);
@@ -3768,7 +3796,7 @@ public final class MediaPlayer2Impl extends MediaPlayer2 {
supportedSchemes[i]);
}
Log.v(TAG, "DrmInfoImpl() Parcel psshsize: " + psshsize +
Log.v(TAG, "DrmInfoImpl() Parcel psshsize: " + pssh.length +
" supportedDRMsCount: " + supportedDRMsCount);
}

View File

@@ -79,6 +79,14 @@ public final class SubtitleData
}
}
/** @hide */
public SubtitleData(int trackIndex, long startTimeUs, long durationUs, byte[] data) {
mTrackIndex = trackIndex;
mStartTimeUs = startTimeUs;
mDurationUs = durationUs;
mData = data;
}
/**
* Returns the index of the MediaPlayer track which contains this subtitle data.
* @return an index in the array returned by {@link MediaPlayer#getTrackInfo()}.

View File

@@ -47,6 +47,14 @@ public final class TimedMetaData {
}
}
/**
* @hide
*/
public TimedMetaData(long timestampUs, byte[] metaData) {
mTimestampUs = timestampUs;
mMetaData = metaData;
}
/**
* @return the timestamp associated with this metadata access unit in microseconds;
* 0 denotes playback start.

View File

@@ -161,7 +161,7 @@ public:
JNIMediaPlayer2Listener(JNIEnv* env, jobject thiz, jobject weak_thiz);
~JNIMediaPlayer2Listener();
virtual void notify(int64_t srcId, int msg, int ext1, int ext2,
const Parcel *obj = NULL) override;
const PlayerMessage *obj = NULL) override;
private:
JNIMediaPlayer2Listener();
jclass mClass; // Reference to MediaPlayer2 class
@@ -194,23 +194,26 @@ JNIMediaPlayer2Listener::~JNIMediaPlayer2Listener()
env->DeleteGlobalRef(mClass);
}
void JNIMediaPlayer2Listener::notify(int64_t srcId, int msg, int ext1, int ext2, const Parcel *obj)
void JNIMediaPlayer2Listener::notify(int64_t srcId, int msg, int ext1, int ext2,
const PlayerMessage* obj)
{
JNIEnv *env = JavaVMHelper::getJNIEnv();
if (obj && obj->dataSize() > 0) {
jobject jParcel = createJavaParcelObject(env);
if (jParcel != NULL) {
// TODO: replace the following Parcel usages with proto.
// 1. MEDIA_DRM_INFO : DrmInfo
// 2. MEDIA_TIMED_TEXT : TimedText
// 2. MEDIA_SUBTITLE_DATA : SubtitleData
// 4. MEDIA_META_DATA : TimedMetaData
Parcel* nativeParcel = parcelForJavaObject(env, jParcel);
nativeParcel->setData(obj->data(), obj->dataSize());
env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
srcId, msg, ext1, ext2, jParcel);
env->DeleteLocalRef(jParcel);
}
if (obj != NULL) {
// TODO: replace the following Parcel usages with proto.
// 1. MEDIA_DRM_INFO : DrmInfo
// 2. MEDIA_TIMED_TEXT : TimedText
// 2. MEDIA_SUBTITLE_DATA : SubtitleData
// 4. MEDIA_META_DATA : TimedMetaData
int size = obj->ByteSize();
jbyte* temp = new jbyte[size];
obj->SerializeToArray(temp, size);
// return the response as a byte array.
jbyteArray out = env->NewByteArray(size);
env->SetByteArrayRegion(out, 0, size, temp);
env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
srcId, msg, ext1, ext2, out);
delete[] temp;
} else {
env->CallStaticVoidMethod(mClass, fields.post_event, mObject,
srcId, msg, ext1, ext2, NULL);
@@ -1089,7 +1092,7 @@ android_media_MediaPlayer2_native_init(JNIEnv *env)
}
fields.post_event = env->GetStaticMethodID(clazz, "postEventFromNative",
"(Ljava/lang/Object;JIIILjava/lang/Object;)V");
"(Ljava/lang/Object;JIII[B)V");
if (fields.post_event == NULL) {
return;
}