Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit cc562a35 authored by Glenn Kasten's avatar Glenn Kasten
Browse files

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
parent 1beb4805
Loading
Loading
Loading
Loading
+6 −3
Original line number Diff line number Diff line
@@ -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();
        }
+3 −0
Original line number Diff line number Diff line
@@ -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;
+8 −1
Original line number Diff line number Diff line
@@ -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:
+3 −0
Original line number Diff line number Diff line
@@ -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 −0
Original line number Diff line number Diff line
/*
 * 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_
Loading