diff options
30 files changed, 342 insertions, 65 deletions
diff --git a/graphics/java/android/graphics/SurfaceTexture.java b/graphics/java/android/graphics/SurfaceTexture.java index 1fc27220af40..2d23fe91551a 100644 --- a/graphics/java/android/graphics/SurfaceTexture.java +++ b/graphics/java/android/graphics/SurfaceTexture.java @@ -24,11 +24,12 @@ import android.os.Message; /** * Captures frames from an image stream as an OpenGL ES texture. * - * <p>The image stream may come from either camera preview. A SurfaceTexture may be used in place - * of a SurfaceHolder when specifying the output destination of a {@link android.hardware.Camera} + * <p>The image stream may come from either camera preview or video decode. A SurfaceTexture + * may be used in place of a SurfaceHolder when specifying the output destination of a + * {@link android.hardware.Camera} or {@link android.media.MediaPlayer} * object. Doing so will cause all the frames from the image stream to be sent to the * SurfaceTexture object rather than to the device's display. When {@link #updateTexImage} is - * called, the contents of the texture object specified when the SurfaceTexture was created is + * called, the contents of the texture object specified when the SurfaceTexture was created are * updated to contain the most recent image from the image stream. This may cause some frames of * the stream to be skipped. * @@ -129,6 +130,8 @@ public class SurfaceTexture { * 16 elements. */ public void getTransformMatrix(float[] mtx) { + // Note we intentionally don't check mtx for null, so this will result in a + // NullPointerException. But it's safe because it happens before the call to native. if (mtx.length != 16) { throw new IllegalArgumentException(); } diff --git a/include/media/IMediaPlayer.h b/include/media/IMediaPlayer.h index bba7ed7292ed..70519ef3d510 100644 --- a/include/media/IMediaPlayer.h +++ b/include/media/IMediaPlayer.h @@ -26,6 +26,7 @@ namespace android { class Parcel; class ISurface; class Surface; +class ISurfaceTexture; class IMediaPlayer: public IInterface { @@ -35,6 +36,8 @@ public: virtual void disconnect() = 0; virtual status_t setVideoSurface(const sp<Surface>& surface) = 0; + virtual status_t setVideoSurfaceTexture( + const sp<ISurfaceTexture>& surfaceTexture) = 0; virtual status_t prepareAsync() = 0; virtual status_t start() = 0; virtual status_t stop() = 0; diff --git a/include/media/MediaPlayerInterface.h b/include/media/MediaPlayerInterface.h index 048f04179e98..117d7eb3dbcf 100644 --- a/include/media/MediaPlayerInterface.h +++ b/include/media/MediaPlayerInterface.h @@ -34,6 +34,7 @@ namespace android { class Parcel; class ISurface; class Surface; +class ISurfaceTexture; template<typename T> class SortedVector; @@ -112,7 +113,13 @@ public: return INVALID_OPERATION; } + // pass the buffered Surface to the media player service virtual status_t setVideoSurface(const sp<Surface>& surface) = 0; + + // pass the buffered ISurfaceTexture to the media player service + virtual status_t setVideoSurfaceTexture( + const sp<ISurfaceTexture>& surfaceTexture) = 0; + virtual status_t prepare() = 0; virtual status_t prepareAsync() = 0; virtual status_t start() = 0; @@ -177,7 +184,7 @@ protected: sp<AudioSink> mAudioSink; }; -// Implement this class for media players that output directo to hardware +// Implement this class for media players that output audio directly to hardware class MediaPlayerHWInterface : public MediaPlayerBase { public: diff --git a/include/media/mediaplayer.h b/include/media/mediaplayer.h index 88b0c3e2919a..528eeb91c257 100644 --- a/include/media/mediaplayer.h +++ b/include/media/mediaplayer.h @@ -28,6 +28,7 @@ namespace android { class Surface; +class ISurfaceTexture; enum media_event_type { MEDIA_NOP = 0, // interface test message @@ -146,6 +147,8 @@ public: status_t setDataSource(int fd, int64_t offset, int64_t length); status_t setVideoSurface(const sp<Surface>& surface); + status_t setVideoSurfaceTexture( + const sp<ISurfaceTexture>& surfaceTexture); status_t setListener(const sp<MediaPlayerListener>& listener); status_t prepare(); status_t prepareAsync(); diff --git a/include/media/stagefright/NativeWindowWrapper.h b/include/media/stagefright/NativeWindowWrapper.h new file mode 100644 index 000000000000..f323cbc1935c --- /dev/null +++ b/include/media/stagefright/NativeWindowWrapper.h @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2011 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 NATIVE_WINDOW_WRAPPER_H_ + +#define NATIVE_WINDOW_WRAPPER_H_ + +#include <surfaceflinger/Surface.h> +#include <gui/SurfaceTextureClient.h> + +namespace android { + +// Both Surface and SurfaceTextureClient are RefBase that implement the +// ANativeWindow interface, but at different addresses. ANativeWindow is not +// a RefBase but acts like one for use with sp<>. This wrapper converts a +// Surface or SurfaceTextureClient into a single reference-counted object +// that holds an sp reference to the underlying Surface or SurfaceTextureClient, +// It provides a method to get the ANativeWindow. + +struct NativeWindowWrapper : RefBase { + NativeWindowWrapper( + const sp<Surface> &surface) : + mSurface(surface) { } + + NativeWindowWrapper( + const sp<SurfaceTextureClient> &surfaceTextureClient) : + mSurfaceTextureClient(surfaceTextureClient) { } + + sp<ANativeWindow> getNativeWindow() const { + if (mSurface != NULL) { + return mSurface; + } else { + return mSurfaceTextureClient; + } + } + + // If needed later we can provide a method to ask what kind of native window + +private: + // At most one of mSurface and mSurfaceTextureClient will be non-NULL + const sp<Surface> mSurface; + const sp<SurfaceTextureClient> mSurfaceTextureClient; + + DISALLOW_EVIL_CONSTRUCTORS(NativeWindowWrapper); +}; + +} // namespace android + +#endif // NATIVE_WINDOW_WRAPPER_H_ diff --git a/media/java/android/media/MediaPlayer.java b/media/java/android/media/MediaPlayer.java index 9c92ace2f47e..8b29ea84d1bd 100644 --- a/media/java/android/media/MediaPlayer.java +++ b/media/java/android/media/MediaPlayer.java @@ -30,6 +30,7 @@ import android.util.Log; import android.view.Surface; import android.view.SurfaceHolder; import android.graphics.Bitmap; +import android.graphics.SurfaceTexture; import android.media.AudioManager; import java.io.FileDescriptor; @@ -379,6 +380,11 @@ import java.lang.ref.WeakReference; * <td>{} </p></td> * <td>This method can be called in any state and calling it does not change * the object state. </p></td></tr> + * <tr><td>setTexture </p></td> + * <td>any </p></td> + * <td>{} </p></td> + * <td>This method can be called in any state and calling it does not change + * the object state. </p></td></tr> * <tr><td>setLooping </p></td> * <td>{Idle, Initialized, Stopped, Prepared, Started, Paused, * PlaybackCompleted}</p></td> @@ -503,6 +509,7 @@ public class MediaPlayer private int mListenerContext; // accessed by native methods private Surface mSurface; // accessed by native methods private SurfaceHolder mSurfaceHolder; + private SurfaceTexture mSurfaceTexture; // accessed by native methods private EventHandler mEventHandler; private PowerManager.WakeLock mWakeLock = null; private boolean mScreenOnWhilePlaying; @@ -533,9 +540,10 @@ public class MediaPlayer } /* - * Update the MediaPlayer ISurface. Call after updating mSurface. + * Update the MediaPlayer ISurface and ISurfaceTexture. + * Call after updating mSurface and/or mSurfaceTexture. */ - private native void _setVideoSurface(); + private native void _setVideoSurfaceOrSurfaceTexture(); /** * Create a request parcel which can be routed to the native media @@ -577,12 +585,21 @@ public class MediaPlayer } /** - * Sets the SurfaceHolder to use for displaying the video portion of the media. - * This call is optional. Not calling it when playing back a video will + * Sets the {@link SurfaceHolder} to use for displaying the video + * portion of the media. A surface must be set if a display is + * needed. Not calling this method when playing back a video will * result in only the audio track being played. * * @param sh the SurfaceHolder to use for video display */ + /* + * This portion of comment has a non-Javadoc prefix so as not to refer to a + * hidden method. When unhidden, merge it with the previous javadoc comment. + * + * Either a surface or surface texture must be set if a display or video sink + * is needed. Not calling this method or {@link #setTexture(SurfaceTexture)} + * when playing back a video will result in only the audio track being played. + */ public void setDisplay(SurfaceHolder sh) { mSurfaceHolder = sh; if (sh != null) { @@ -590,7 +607,29 @@ public class MediaPlayer } else { mSurface = null; } - _setVideoSurface(); + mSurfaceTexture = null; + _setVideoSurfaceOrSurfaceTexture(); + updateSurfaceScreenOn(); + } + + /** + * Sets the {@link SurfaceTexture} to be used as the sink for the + * video portion of the media. Either a surface or surface texture + * must be set if a video sink is needed. The same surface texture + * can be re-set without harm. Setting a surface texture will un-set + * any surface that was set via {@link #setDisplay(SurfaceHolder)}. + * Not calling this method or {@link #setDisplay(SurfaceHolder)} + * when playing back a video will result in only the audio track + * being played. Note that if a SurfaceTexture is used, the value + * set via setScreenOnWhilePlaying has no effect. + * + * @hide + */ + public void setTexture(SurfaceTexture st) { + mSurfaceHolder = null; + mSurface = null; + mSurfaceTexture = st; + _setVideoSurfaceOrSurfaceTexture(); updateSurfaceScreenOn(); } @@ -645,6 +684,8 @@ public class MediaPlayer return null; } + // Note no convenience method to create a MediaPlayer with SurfaceTexture sink. + /** * Convenience method to create a MediaPlayer for a given resource id. * On success, {@link #prepare()} will already have been called and must not be called again. diff --git a/media/jni/android_media_MediaPlayer.cpp b/media/jni/android_media_MediaPlayer.cpp index ca544328952c..6d074e9a6e00 100644 --- a/media/jni/android_media_MediaPlayer.cpp +++ b/media/jni/android_media_MediaPlayer.cpp @@ -35,6 +35,8 @@ #include "utils/String8.h" #include "android_util_Binder.h" #include <binder/Parcel.h> +#include <gui/SurfaceTexture.h> +#include <gui/ISurfaceTexture.h> #include <surfaceflinger/Surface.h> #include <binder/IPCThreadState.h> #include <binder/IServiceManager.h> @@ -48,8 +50,11 @@ using namespace android; struct fields_t { jfieldID context; jfieldID surface; + jfieldID surfaceTexture; /* actually in android.view.Surface XXX */ jfieldID surface_native; + // actually in android.graphics.SurfaceTexture + jfieldID surfaceTexture_native; jmethodID post_event; }; @@ -110,6 +115,13 @@ static Surface* get_surface(JNIEnv* env, jobject clazz) return (Surface*)env->GetIntField(clazz, fields.surface_native); } +sp<ISurfaceTexture> getSurfaceTexture(JNIEnv* env, jobject clazz) +{ + sp<ISurfaceTexture> surfaceTexture( + (ISurfaceTexture*)env->GetIntField(clazz, fields.surfaceTexture_native)); + return surfaceTexture; +} + static sp<MediaPlayer> getMediaPlayer(JNIEnv* env, jobject thiz) { Mutex::Autolock l(sLock); @@ -288,26 +300,40 @@ android_media_MediaPlayer_setDataSourceFD(JNIEnv *env, jobject thiz, jobject fil process_media_player_call( env, thiz, mp->setDataSource(fd, offset, length), "java/io/IOException", "setDataSourceFD failed." ); } -static void setVideoSurface(const sp<MediaPlayer>& mp, JNIEnv *env, jobject thiz) +static void setVideoSurfaceOrSurfaceTexture( + const sp<MediaPlayer>& mp, JNIEnv *env, jobject thiz, const char *prefix) { + // The Java MediaPlayer class makes sure that at most one of mSurface and + // mSurfaceTexture is non-null. But just in case, we give priority to + // mSurface over mSurfaceTexture. jobject surface = env->GetObjectField(thiz, fields.surface); if (surface != NULL) { - const sp<Surface> native_surface = get_surface(env, surface); - LOGV("prepare: surface=%p (id=%d)", + sp<Surface> native_surface(get_surface(env, surface)); + LOGV("%s: surface=%p (id=%d)", prefix, native_surface.get(), native_surface->getIdentity()); mp->setVideoSurface(native_surface); + } else { + jobject surfaceTexture = env->GetObjectField(thiz, fields.surfaceTexture); + if (surfaceTexture != NULL) { + sp<ISurfaceTexture> native_surfaceTexture( + getSurfaceTexture(env, surfaceTexture)); + LOGV("%s: texture=%p (id=%d)", prefix, + native_surfaceTexture.get(), native_surfaceTexture->getIdentity()); + mp->setVideoSurfaceTexture(native_surfaceTexture); + } } } static void -android_media_MediaPlayer_setVideoSurface(JNIEnv *env, jobject thiz) +android_media_MediaPlayer_setVideoSurfaceOrSurfaceTexture(JNIEnv *env, jobject thiz) { sp<MediaPlayer> mp = getMediaPlayer(env, thiz); if (mp == NULL ) { jniThrowException(env, "java/lang/IllegalStateException", NULL); return; } - setVideoSurface(mp, env, thiz); + setVideoSurfaceOrSurfaceTexture(mp, env, thiz, + "_setVideoSurfaceOrSurfaceTexture"); } static void @@ -318,7 +344,7 @@ android_media_MediaPlayer_prepare(JNIEnv *env, jobject thiz) jniThrowException(env, "java/lang/IllegalStateException", NULL); return; } - setVideoSurface(mp, env, thiz); + setVideoSurfaceOrSurfaceTexture(mp, env, thiz, "prepare"); process_media_player_call( env, thiz, mp->prepare(), "java/io/IOException", "Prepare failed." ); } @@ -330,13 +356,7 @@ android_media_MediaPlayer_prepareAsync(JNIEnv *env, jobject thiz) jniThrowException(env, "java/lang/IllegalStateException", NULL); return; } - jobject surface = env->GetObjectField(thiz, fields.surface); - if (surface != NULL) { - const sp<Surface> native_surface = get_surface(env, surface); - LOGV("prepareAsync: surface=%p (id=%d)", - native_surface.get(), native_surface->getIdentity()); - mp->setVideoSurface(native_surface); - } + setVideoSurfaceOrSurfaceTexture(mp, env, thiz, "prepareAsync"); process_media_player_call( env, thiz, mp->prepareAsync(), "java/io/IOException", "Prepare Async failed." ); } @@ -640,9 +660,34 @@ android_media_MediaPlayer_native_init(JNIEnv *env) fields.surface_native = env->GetFieldID(surface, ANDROID_VIEW_SURFACE_JNI_ID, "I"); if (fields.surface_native == NULL) { - jniThrowException(env, "java/lang/RuntimeException", "Can't find Surface.mSurface"); + jniThrowException(env, "java/lang/RuntimeException", + "Can't find Surface." ANDROID_VIEW_SURFACE_JNI_ID); return; } + + fields.surfaceTexture = env->GetFieldID(clazz, "mSurfaceTexture", + "Landroid/graphics/SurfaceTexture;"); + if (fields.surfaceTexture == NULL) { + jniThrowException(env, "java/lang/RuntimeException", + "Can't find MediaPlayer.mSurfaceTexture"); + return; + } + + jclass surfaceTexture = env->FindClass("android/graphics/SurfaceTexture"); + if (surfaceTexture == NULL) { + jniThrowException(env, "java/lang/RuntimeException", + "Can't find android/graphics/SurfaceTexture"); + return; + } + + fields.surfaceTexture_native = env->GetFieldID(surfaceTexture, + ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID, "I"); + if (fields.surfaceTexture_native == NULL) { + jniThrowException(env, "java/lang/RuntimeException", + "Can't find SurfaceTexture." ANDROID_GRAPHICS_SURFACETEXTURE_JNI_ID); + return; + } + } static void @@ -746,7 +791,7 @@ 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}, + {"_setVideoSurfaceOrSurfaceTexture", "()V", (void *)android_media_MediaPlayer_setVideoSurfaceOrSurfaceTexture}, {"prepare", "()V", (void *)android_media_MediaPlayer_prepare}, {"prepareAsync", "()V", (void *)android_media_MediaPlayer_prepareAsync}, {"_start", "()V", (void *)android_media_MediaPlayer_start}, diff --git a/media/libmedia/Android.mk b/media/libmedia/Android.mk index 74fb5310803a..fd4c6c6a91bb 100644 --- a/media/libmedia/Android.mk +++ b/media/libmedia/Android.mk @@ -37,7 +37,8 @@ LOCAL_SRC_FILES:= \ LOCAL_SHARED_LIBRARIES := \ libui libcutils libutils libbinder libsonivox libicuuc libexpat \ - libsurfaceflinger_client libcamera_client libstagefright_foundation + libsurfaceflinger_client libcamera_client libstagefright_foundation \ + libgui LOCAL_MODULE:= libmedia diff --git a/media/libmedia/IMediaPlayer.cpp b/media/libmedia/IMediaPlayer.cpp index c287c0af2103..2399216b49ed 100644 --- a/media/libmedia/IMediaPlayer.cpp +++ b/media/libmedia/IMediaPlayer.cpp @@ -23,6 +23,7 @@ #include <media/IMediaPlayer.h> #include <surfaceflinger/ISurface.h> #include <surfaceflinger/Surface.h> +#include <gui/ISurfaceTexture.h> namespace android { @@ -45,7 +46,8 @@ enum { SET_METADATA_FILTER, GET_METADATA, SET_AUX_EFFECT_SEND_LEVEL, - ATTACH_AUX_EFFECT + ATTACH_AUX_EFFECT, + SET_VIDEO_SURFACETEXTURE, }; class BpMediaPlayer: public BpInterface<IMediaPlayer> @@ -64,6 +66,7 @@ public: remote()->transact(DISCONNECT, data, &reply); } + // pass the buffered Surface to the media player service status_t setVideoSurface(const sp<Surface>& surface) { Parcel data, reply; @@ -73,6 +76,17 @@ public: return reply.readInt32(); } + // pass the buffered ISurfaceTexture to the media player service + status_t setVideoSurfaceTexture(const sp<ISurfaceTexture>& surfaceTexture) + { + Parcel data, reply; + data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor()); + sp<IBinder> b(surfaceTexture->asBinder()); + data.writeStrongBinder(b); + remote()->transact(SET_VIDEO_SURFACETEXTURE, data, &reply); + return reply.readInt32(); + } + status_t prepareAsync() { Parcel data, reply; @@ -220,6 +234,7 @@ public: remote()->transact(ATTACH_AUX_EFFECT, data, &reply); return reply.readInt32(); } + }; IMPLEMENT_META_INTERFACE(MediaPlayer, "android.media.IMediaPlayer"); @@ -241,6 +256,13 @@ status_t BnMediaPlayer::onTransact( reply->writeInt32(setVideoSurface(surface)); return NO_ERROR; } break; + case SET_VIDEO_SURFACETEXTURE: { + CHECK_INTERFACE(IMediaPlayer, data, reply); + sp<ISurfaceTexture> surfaceTexture = + interface_cast<ISurfaceTexture>(data.readStrongBinder()); + reply->writeInt32(setVideoSurfaceTexture(surfaceTexture)); + return NO_ERROR; + } break; case PREPARE_ASYNC: { CHECK_INTERFACE(IMediaPlayer, data, reply); reply->writeInt32(prepareAsync()); diff --git a/media/libmedia/mediaplayer.cpp b/media/libmedia/mediaplayer.cpp index 87c8fe432336..0ee0249a6773 100644 --- a/media/libmedia/mediaplayer.cpp +++ b/media/libmedia/mediaplayer.cpp @@ -201,6 +201,16 @@ status_t MediaPlayer::setVideoSurface(const sp<Surface>& surface) return mPlayer->setVideoSurface(surface); } +status_t MediaPlayer::setVideoSurfaceTexture( + const sp<ISurfaceTexture>& surfaceTexture) +{ + LOGV("setVideoSurfaceTexture"); + Mutex::Autolock _l(mLock); + if (mPlayer == 0) return NO_INIT; + + return mPlayer->setVideoSurfaceTexture(surfaceTexture); +} + // must call with lock held status_t MediaPlayer::prepareAsync_l() { diff --git a/media/libmediaplayerservice/Android.mk b/media/libmediaplayerservice/Android.mk index f7f0d951db2c..e65f6d85f516 100644 --- a/media/libmediaplayerservice/Android.mk +++ b/media/libmediaplayerservice/Android.mk @@ -32,7 +32,8 @@ LOCAL_SHARED_LIBRARIES := \ libstagefright \ libstagefright_omx \ libstagefright_foundation \ - libsurfaceflinger_client + libsurfaceflinger_client \ + libgui LOCAL_STATIC_LIBRARIES := \ libstagefright_rtsp \ diff --git a/media/libmediaplayerservice/MediaPlayerService.cpp b/media/libmediaplayerservice/MediaPlayerService.cpp index 8c6f76b19996..ec6188f01ee2 100644 --- a/media/libmediaplayerservice/MediaPlayerService.cpp +++ b/media/libmediaplayerservice/MediaPlayerService.cpp @@ -935,6 +935,15 @@ status_t MediaPlayerService::Client::setVideoSurface(const sp<Surface>& surface) return p->setVideoSurface(surface); } +status_t MediaPlayerService::Client::setVideoSurfaceTexture( + const sp<ISurfaceTexture>& surfaceTexture) +{ + LOGV("[%d] setVideoSurfaceTexture(%p)", mConnId, surfaceTexture.get()); + sp<MediaPlayerBase> p = getPlayer(); + if (p == 0) return UNKNOWN_ERROR; + return p->setVideoSurfaceTexture(surfaceTexture); +} + status_t MediaPlayerService::Client::invoke(const Parcel& request, Parcel *reply) { diff --git a/media/libmediaplayerservice/MediaPlayerService.h b/media/libmediaplayerservice/MediaPlayerService.h index 9f41db034028..1175ed0389c0 100644 --- a/media/libmediaplayerservice/MediaPlayerService.h +++ b/media/libmediaplayerservice/MediaPlayerService.h @@ -236,6 +236,8 @@ private: // IMediaPlayer interface virtual void disconnect(); virtual status_t setVideoSurface(const sp<Surface>& surface); + virtual status_t setVideoSurfaceTexture( + const sp<ISurfaceTexture>& surfaceTexture); virtual status_t prepareAsync(); virtual status_t start(); virtual status_t stop(); diff --git a/media/libmediaplayerservice/MidiFile.h b/media/libmediaplayerservice/MidiFile.h index aa8f3f0ec3ea..a98231c27dcc 100644 --- a/media/libmediaplayerservice/MidiFile.h +++ b/media/libmediaplayerservice/MidiFile.h @@ -36,6 +36,9 @@ public: virtual status_t setDataSource(int fd, int64_t offset, int64_t length); virtual status_t setVideoSurface(const sp<Surface>& surface) { return UNKNOWN_ERROR; } + virtual status_t setVideoSurfaceTexture( + const sp<ISurfaceTexture>& surfaceTexture) + { return UNKNOWN_ERROR; } virtual status_t prepare(); virtual status_t prepareAsync(); virtual status_t start(); diff --git a/media/libmediaplayerservice/StagefrightPlayer.cpp b/media/libmediaplayerservice/StagefrightPlayer.cpp index da564dce9d5a..fdb475456fac 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.cpp +++ b/media/libmediaplayerservice/StagefrightPlayer.cpp @@ -55,6 +55,14 @@ status_t StagefrightPlayer::setVideoSurface(const sp<Surface> &surface) { return OK; } +status_t StagefrightPlayer::setVideoSurfaceTexture( + const sp<ISurfaceTexture> &surfaceTexture) { + LOGV("setVideoSurfaceTexture"); + + mPlayer->setSurfaceTexture(surfaceTexture); + return OK; +} + status_t StagefrightPlayer::prepare() { return mPlayer->prepare(); } diff --git a/media/libmediaplayerservice/StagefrightPlayer.h b/media/libmediaplayerservice/StagefrightPlayer.h index fc72bfbf13df..e2796d2f3080 100644 --- a/media/libmediaplayerservice/StagefrightPlayer.h +++ b/media/libmediaplayerservice/StagefrightPlayer.h @@ -39,6 +39,8 @@ public: virtual status_t setDataSource(const sp<IStreamSource> &source); virtual status_t setVideoSurface(const sp<Surface> &surface); + virtual status_t setVideoSurfaceTexture( + const sp<ISurfaceTexture> &surfaceTexture); virtual status_t prepare(); virtual status_t prepareAsync(); virtual status_t start(); diff --git a/media/libmediaplayerservice/TestPlayerStub.h b/media/libmediaplayerservice/TestPlayerStub.h index 6abd8e3c21cf..d9c3db36b69b 100644 --- a/media/libmediaplayerservice/TestPlayerStub.h +++ b/media/libmediaplayerservice/TestPlayerStub.h @@ -78,6 +78,10 @@ class TestPlayerStub : public MediaPlayerInterface { virtual status_t setVideoSurface(const android::sp<android::Surface>& s) { return mPlayer->setVideoSurface(s); } + virtual status_t setVideoSurfaceTexture( + const android::sp<android::ISurfaceTexture>& st) { + return mPlayer->setVideoSurfaceTexture(st); + } virtual status_t prepare() {return mPlayer->prepare();} virtual status_t prepareAsync() {return mPlayer->prepareAsync();} virtual status_t start() {return mPlayer->start();} diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp index 1fcf92b71024..48b517e2867a 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.cpp @@ -37,6 +37,7 @@ #include <media/stagefright/MediaErrors.h> #include <media/stagefright/MetaData.h> #include <surfaceflinger/Surface.h> +#include <gui/ISurfaceTexture.h> namespace android { @@ -76,8 +77,16 @@ void NuPlayer::setDataSource( } void NuPlayer::setVideoSurface(const sp<Surface> &surface) { - sp<AMessage> msg = new AMessage(kWhatSetVideoSurface, id()); - msg->setObject("surface", surface); + sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id()); + msg->setObject("native-window", new NativeWindowWrapper(surface)); + msg->post(); +} + +void NuPlayer::setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) { + sp<AMessage> msg = new AMessage(kWhatSetVideoNativeWindow, id()); + sp<SurfaceTextureClient> surfaceTextureClient(surfaceTexture != NULL ? + new SurfaceTextureClient(surfaceTexture) : NULL); + msg->setObject("native-window", new NativeWindowWrapper(surfaceTextureClient)); msg->post(); } @@ -144,14 +153,14 @@ void NuPlayer::onMessageReceived(const sp<AMessage> &msg) { break; } - case kWhatSetVideoSurface: + case kWhatSetVideoNativeWindow: { - LOGV("kWhatSetVideoSurface"); + LOGV("kWhatSetVideoNativeWindow"); sp<RefBase> obj; - CHECK(msg->findObject("surface", &obj)); + CHECK(msg->findObject("native-window", &obj)); - mSurface = static_cast<Surface *>(obj.get()); + mNativeWindow = static_cast<NativeWindowWrapper *>(obj.get()); break; } @@ -529,7 +538,8 @@ status_t NuPlayer::instantiateDecoder(bool audio, sp<Decoder> *decoder) { new AMessage(audio ? kWhatAudioNotify : kWhatVideoNotify, id()); - *decoder = new Decoder(notify, audio ? NULL : mSurface); + *decoder = audio ? new Decoder(notify) : + new Decoder(notify, mNativeWindow); looper()->registerHandler(*decoder); (*decoder)->configure(meta); diff --git a/media/libmediaplayerservice/nuplayer/NuPlayer.h b/media/libmediaplayerservice/nuplayer/NuPlayer.h index bb651629bbd1..e7c6a4262933 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayer.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayer.h @@ -20,6 +20,9 @@ #include <media/MediaPlayerInterface.h> #include <media/stagefright/foundation/AHandler.h> +#include <media/stagefright/NativeWindowWrapper.h> +#include <gui/SurfaceTextureClient.h> +#include <surfaceflinger/Surface.h> namespace android { @@ -38,6 +41,7 @@ struct NuPlayer : public AHandler { const char *url, const KeyedVector<String8, String8> *headers); void setVideoSurface(const sp<Surface> &surface); + void setVideoSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture); void setAudioSink(const sp<MediaPlayerBase::AudioSink> &sink); void start(); @@ -65,7 +69,7 @@ private: enum { kWhatSetDataSource, - kWhatSetVideoSurface, + kWhatSetVideoNativeWindow, kWhatSetAudioSink, kWhatMoreDataQueued, kWhatStart, @@ -81,7 +85,7 @@ private: wp<NuPlayerDriver> mDriver; sp<Source> mSource; - sp<Surface> mSurface; + sp<NativeWindowWrapper> mNativeWindow; sp<MediaPlayerBase::AudioSink> mAudioSink; sp<Decoder> mVideoDecoder; sp<Decoder> mAudioDecoder; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp index 761dfa4260bf..517acc94fa9e 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.cpp @@ -31,13 +31,15 @@ #include <media/stagefright/MetaData.h> #include <media/stagefright/Utils.h> #include <surfaceflinger/Surface.h> +#include <gui/ISurfaceTexture.h> namespace android { NuPlayer::Decoder::Decoder( - const sp<AMessage> ¬ify, const sp<Surface> &surface) + const sp<AMessage> ¬ify, + const sp<NativeWindowWrapper> &nativeWindow) : mNotify(notify), - mSurface(surface) { + mNativeWindow(nativeWindow) { } NuPlayer::Decoder::~Decoder() { @@ -55,8 +57,8 @@ void NuPlayer::Decoder::configure(const sp<MetaData> &meta) { sp<AMessage> format = makeFormat(meta); - if (mSurface != NULL) { - format->setObject("surface", mSurface); + if (mNativeWindow != NULL) { + format->setObject("native-window", mNativeWindow); } if (!strcasecmp(mime, MEDIA_MIMETYPE_AUDIO_AAC)) { diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h index 3874cfec5720..732f0903b103 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDecoder.h @@ -28,7 +28,8 @@ struct ABuffer; struct DecoderWrapper; struct NuPlayer::Decoder : public AHandler { - Decoder(const sp<AMessage> ¬ify, const sp<Surface> &surface = NULL); + Decoder(const sp<AMessage> ¬ify, + const sp<NativeWindowWrapper> &nativeWindow = NULL); void configure(const sp<MetaData> &meta); @@ -47,7 +48,7 @@ private: }; sp<AMessage> mNotify; - sp<Surface> mSurface; + sp<NativeWindowWrapper> mNativeWindow; sp<ACodec> mCodec; sp<DecoderWrapper> mWrapper; diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp index ac19a2f86d23..0eca958aff86 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.cpp @@ -86,6 +86,13 @@ status_t NuPlayerDriver::setVideoSurface(const sp<Surface> &surface) { return OK; } +status_t NuPlayerDriver::setVideoSurfaceTexture( + const sp<ISurfaceTexture> &surfaceTexture) { + mPlayer->setVideoSurfaceTexture(surfaceTexture); + + return OK; +} + status_t NuPlayerDriver::prepare() { return OK; } diff --git a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h index e3a5de4a7cd6..67d0f3e0c250 100644 --- a/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h +++ b/media/libmediaplayerservice/nuplayer/NuPlayerDriver.h @@ -36,6 +36,8 @@ struct NuPlayerDriver : public MediaPlayerInterface { virtual status_t setDataSource(const sp<IStreamSource> &source); virtual status_t setVideoSurface(const sp<Surface> &surface); + virtual status_t setVideoSurfaceTexture( + const sp<ISurfaceTexture> &surfaceTexture); virtual status_t prepare(); virtual status_t prepareAsync(); virtual status_t start(); diff --git a/media/libstagefright/ACodec.cpp b/media/libstagefright/ACodec.cpp index 505d9d46ab98..b0ae3d8661e4 100644 --- a/media/libstagefright/ACodec.cpp +++ b/media/libstagefright/ACodec.cpp @@ -11,9 +11,11 @@ #include <media/stagefright/foundation/AMessage.h> #include <media/stagefright/MediaDefs.h> +#include <media/stagefright/NativeWindowWrapper.h> #include <media/stagefright/OMXClient.h> #include <surfaceflinger/Surface.h> +#include <gui/SurfaceTextureClient.h> #include <OMX_Component.h> @@ -1633,8 +1635,11 @@ void ACodec::UninitializedState::onSetup( mCodec->configureCodec(mime.c_str(), msg); sp<RefBase> obj; - if (msg->findObject("surface", &obj)) { - mCodec->mNativeWindow = static_cast<Surface *>(obj.get()); + if (msg->findObject("native-window", &obj)) { + sp<NativeWindowWrapper> nativeWindow( + static_cast<NativeWindowWrapper *>(obj.get())); + CHECK(nativeWindow != NULL); + mCodec->mNativeWindow = nativeWindow->getNativeWindow(); } CHECK_EQ((status_t)OK, mCodec->initNativeWindow()); diff --git a/media/libstagefright/Android.mk b/media/libstagefright/Android.mk index 80eb59ffc06e..88069e93fab6 100644 --- a/media/libstagefright/Android.mk +++ b/media/libstagefright/Android.mk @@ -74,7 +74,8 @@ LOCAL_SHARED_LIBRARIES := \ libcamera_client \ libdrmframework \ libcrypto \ - libssl + libssl \ + libgui LOCAL_STATIC_LIBRARIES := \ libstagefright_color_conversion \ diff --git a/media/libstagefright/AwesomePlayer.cpp b/media/libstagefright/AwesomePlayer.cpp index 1b63ab2461c4..36623f694fbf 100644 --- a/media/libstagefright/AwesomePlayer.cpp +++ b/media/libstagefright/AwesomePlayer.cpp @@ -43,6 +43,8 @@ #include <media/stagefright/OMXCodec.h> #include <surfaceflinger/Surface.h> +#include <gui/ISurfaceTexture.h> +#include <gui/SurfaceTextureClient.h> #include <media/stagefright/foundation/ALooper.h> #include <media/stagefright/foundation/AMessage.h> @@ -83,8 +85,8 @@ private: struct AwesomeLocalRenderer : public AwesomeRenderer { AwesomeLocalRenderer( - const sp<Surface> &surface, const sp<MetaData> &meta) - : mTarget(new SoftwareRenderer(surface, meta)) { + const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta) + : mTarget(new SoftwareRenderer(nativeWindow, meta)) { } virtual void render(MediaBuffer *buffer) { @@ -889,7 +891,7 @@ void AwesomePlayer::notifyVideoSize_l() { } void AwesomePlayer::initRenderer_l() { - if (mSurface == NULL) { + if (mNativeWindow == NULL) { return; } @@ -920,13 +922,13 @@ void AwesomePlayer::initRenderer_l() { // directly to ANativeBuffers, so we must use a renderer that // just pushes those buffers to the ANativeWindow. mVideoRenderer = - new AwesomeNativeWindowRenderer(mSurface, rotationDegrees); + new AwesomeNativeWindowRenderer(mNativeWindow, rotationDegrees); } else { // Other decoders are instantiated locally and as a consequence // allocate their buffers in local address space. This renderer // then performs a color conversion and copy to get the data // into the ANativeBuffer. - mVideoRenderer = new AwesomeLocalRenderer(mSurface, meta); + mVideoRenderer = new AwesomeLocalRenderer(mNativeWindow, meta); } } @@ -986,6 +988,17 @@ void AwesomePlayer::setSurface(const sp<Surface> &surface) { Mutex::Autolock autoLock(mLock); mSurface = surface; + mNativeWindow = surface; +} + +void AwesomePlayer::setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture) { + Mutex::Autolock autoLock(mLock); + + mSurface.clear(); + if (surfaceTexture != NULL) { + mNativeWindow = new SurfaceTextureClient(surfaceTexture); + } + } void AwesomePlayer::setAudioSink( @@ -1164,7 +1177,7 @@ status_t AwesomePlayer::initVideoDecoder(uint32_t flags) { mClient.interface(), mVideoTrack->getFormat(), false, // createEncoder mVideoTrack, - NULL, flags, USE_SURFACE_ALLOC ? mSurface : NULL); + NULL, flags, USE_SURFACE_ALLOC ? mNativeWindow : NULL); if (mVideoSource != NULL) { int64_t durationUs; diff --git a/media/libstagefright/colorconversion/SoftwareRenderer.cpp b/media/libstagefright/colorconversion/SoftwareRenderer.cpp index 70408d741b5a..31afc43fe86d 100644 --- a/media/libstagefright/colorconversion/SoftwareRenderer.cpp +++ b/media/libstagefright/colorconversion/SoftwareRenderer.cpp @@ -26,14 +26,15 @@ #include <surfaceflinger/Surface.h> #include <ui/android_native_buffer.h> #include <ui/GraphicBufferMapper.h> +#include <gui/ISurfaceTexture.h> namespace android { SoftwareRenderer::SoftwareRenderer( - const sp<Surface> &surface, const sp<MetaData> &meta) + const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta) : mConverter(NULL), mYUVMode(None), - mSurface(surface) { + mNativeWindow(nativeWindow) { int32_t tmp; CHECK(meta->findInt32(kKeyColorFormat, &tmp)); mColorFormat = (OMX_COLOR_FORMATTYPE)tmp; @@ -65,22 +66,22 @@ SoftwareRenderer::SoftwareRenderer( break; } - CHECK(mSurface.get() != NULL); + CHECK(mNativeWindow != NULL); CHECK(mWidth > 0); CHECK(mHeight > 0); CHECK(mConverter == NULL || mConverter->isValid()); CHECK_EQ(0, native_window_set_usage( - mSurface.get(), + mNativeWindow.get(), GRALLOC_USAGE_SW_READ_NEVER | GRALLOC_USAGE_SW_WRITE_OFTEN | GRALLOC_USAGE_HW_TEXTURE | GRALLOC_USAGE_EXTERNAL_DISP)); - CHECK_EQ(0, native_window_set_buffer_count(mSurface.get(), 2)); + CHECK_EQ(0, native_window_set_buffer_count(mNativeWindow.get(), 2)); // Width must be multiple of 32??? CHECK_EQ(0, native_window_set_buffers_geometry( - mSurface.get(), + mNativeWindow.get(), mCropRight - mCropLeft + 1, mCropBottom - mCropTop + 1, halFormat)); @@ -96,7 +97,7 @@ SoftwareRenderer::SoftwareRenderer( if (transform) { CHECK_EQ(0, native_window_set_buffers_transform( - mSurface.get(), transform)); + mNativeWindow.get(), transform)); } } @@ -109,12 +110,12 @@ void SoftwareRenderer::render( const void *data, size_t size, void *platformPrivate) { android_native_buffer_t *buf; int err; - if ((err = mSurface->dequeueBuffer(mSurface.get(), &buf)) != 0) { + if ((err = mNativeWindow->dequeueBuffer(mNativeWindow.get(), &buf)) != 0) { LOGW("Surface::dequeueBuffer returned error %d", err); return; } - CHECK_EQ(0, mSurface->lockBuffer(mSurface.get(), buf)); + CHECK_EQ(0, mNativeWindow->lockBuffer(mNativeWindow.get(), buf)); GraphicBufferMapper &mapper = GraphicBufferMapper::get(); @@ -140,7 +141,7 @@ void SoftwareRenderer::render( CHECK_EQ(0, mapper.unlock(buf->handle)); - if ((err = mSurface->queueBuffer(mSurface.get(), buf)) != 0) { + if ((err = mNativeWindow->queueBuffer(mNativeWindow.get(), buf)) != 0) { LOGW("Surface::queueBuffer returned error %d", err); } buf = NULL; diff --git a/media/libstagefright/include/AwesomePlayer.h b/media/libstagefright/include/AwesomePlayer.h index 1497732a2c7e..0e36492be0b9 100644 --- a/media/libstagefright/include/AwesomePlayer.h +++ b/media/libstagefright/include/AwesomePlayer.h @@ -36,6 +36,7 @@ struct MediaBuffer; struct MediaExtractor; struct MediaSource; struct NuCachedSource2; +struct ISurfaceTexture; struct ALooper; struct ARTSPController; @@ -80,6 +81,7 @@ struct AwesomePlayer { bool isPlaying() const; void setSurface(const sp<Surface> &surface); + void setSurfaceTexture(const sp<ISurfaceTexture> &surfaceTexture); void setAudioSink(const sp<MediaPlayerBase::AudioSink> &audioSink); status_t setLooping(bool shouldLoop); @@ -133,6 +135,7 @@ private: wp<MediaPlayerBase> mListener; sp<Surface> mSurface; + sp<ANativeWindow> mNativeWindow; sp<MediaPlayerBase::AudioSink> mAudioSink; SystemTimeSource mSystemTimeSource; diff --git a/media/libstagefright/include/SoftwareRenderer.h b/media/libstagefright/include/SoftwareRenderer.h index 90d3fe11d562..78037b97a2f3 100644 --- a/media/libstagefright/include/SoftwareRenderer.h +++ b/media/libstagefright/include/SoftwareRenderer.h @@ -20,16 +20,16 @@ #include <media/stagefright/ColorConverter.h> #include <utils/RefBase.h> +#include <ui/android_native_buffer.h> namespace android { struct MetaData; -class Surface; class SoftwareRenderer { public: SoftwareRenderer( - const sp<Surface> &surface, const sp<MetaData> &meta); + const sp<ANativeWindow> &nativeWindow, const sp<MetaData> &meta); ~SoftwareRenderer(); @@ -44,7 +44,7 @@ private: OMX_COLOR_FORMATTYPE mColorFormat; ColorConverter *mConverter; YUVMode mYUVMode; - sp<Surface> mSurface; + sp<ANativeWindow> mNativeWindow; int32_t mWidth, mHeight; int32_t mCropLeft, mCropTop, mCropRight, mCropBottom; diff --git a/media/tests/players/invoke_mock_media_player.cpp b/media/tests/players/invoke_mock_media_player.cpp index 1e3731e3c802..d571106fd661 100644 --- a/media/tests/players/invoke_mock_media_player.cpp +++ b/media/tests/players/invoke_mock_media_player.cpp @@ -25,8 +25,8 @@ #include <utils/Errors.h> using android::INVALID_OPERATION; -using android::ISurface; using android::Surface; +using android::ISurfaceTexture; using android::MediaPlayerBase; using android::OK; using android::Parcel; @@ -69,6 +69,8 @@ class Player: public MediaPlayerBase virtual status_t setDataSource(int fd, int64_t offset, int64_t length) {return OK;} virtual status_t setVideoSurface(const sp<Surface>& surface) {return OK;} + virtual status_t setVideoSurfaceTexture( + const sp<ISurfaceTexture>& surfaceTexture) {return OK;} virtual status_t prepare() {return OK;} virtual status_t prepareAsync() {return OK;} virtual status_t start() {return OK;} |