Bug 3438258 Add SurfaceTexture as MediaPlayer sink
This change enables the use of a SurfaceTexture in place of a Surface as the video sink for an android.media.MediaPlayer. The new API MediaPlayer.setTexture is currently hidden. This includes: - New Java and C++ interfaces - C++ plumbing and implementation (JNI, Binder) - Stagefright AwesomePlayer and NuPlayer use ANativeWindow (either Surface or SurfaceTextureClient) Change-Id: I2b568bee143d9eaf3dfc6cc4533c1bebbd5afc51
This commit is contained in:
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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();
|
||||
|
||||
62
include/media/stagefright/NativeWindowWrapper.h
Normal file
62
include/media/stagefright/NativeWindowWrapper.h
Normal file
@@ -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_
|
||||
@@ -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.
|
||||
|
||||
@@ -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},
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -32,7 +32,8 @@ LOCAL_SHARED_LIBRARIES := \
|
||||
libstagefright \
|
||||
libstagefright_omx \
|
||||
libstagefright_foundation \
|
||||
libsurfaceflinger_client
|
||||
libsurfaceflinger_client \
|
||||
libgui
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
libstagefright_rtsp \
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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)) {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -74,7 +74,8 @@ LOCAL_SHARED_LIBRARIES := \
|
||||
libcamera_client \
|
||||
libdrmframework \
|
||||
libcrypto \
|
||||
libssl
|
||||
libssl \
|
||||
libgui
|
||||
|
||||
LOCAL_STATIC_LIBRARIES := \
|
||||
libstagefright_color_conversion \
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;}
|
||||
|
||||
Reference in New Issue
Block a user