Android Open Source - kickflip-android-sdk Egl Surface Base






From Project

Back to project page kickflip-android-sdk.

License

The source code is released under:

Apache License

If you think the Android project kickflip-android-sdk listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright 2013 Google Inc. All rights reserved.
 */*  w ww  .j  a  v  a2 s.c om*/
 * 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.
 */

package io.kickflip.sdk.av;

import android.graphics.Bitmap;
import android.graphics.Matrix;
import android.opengl.EGL14;
import android.opengl.EGLSurface;
import android.opengl.GLES20;
import android.util.Log;

import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;

/**
 * Common base class for EGL surfaces.
 * <p/>
 * There can be multiple surfaces associated with a single context.
 * @hide
 */
public class EglSurfaceBase {
    protected static final String TAG = "EglSurfaceBase";

    // EglBase object we're associated with.  It may be associated with multiple surfaces.
    protected EglCore mEglCore;

    private EGLSurface mEGLSurface = EGL14.EGL_NO_SURFACE;
    private int mWidth = -1;
    private int mHeight = -1;

    protected EglSurfaceBase(EglCore eglBase) {
        mEglCore = eglBase;
    }

    /**
     * Creates a window surface.
     * <p/>
     *
     * @param surface May be a Surface or SurfaceTexture.
     */
    public void createWindowSurface(Object surface) {
        if (mEGLSurface != EGL14.EGL_NO_SURFACE) {
            throw new IllegalStateException("surface already created");
        }
        mEGLSurface = mEglCore.createWindowSurface(surface);
        mWidth = mEglCore.querySurface(mEGLSurface, EGL14.EGL_WIDTH);
        mHeight = mEglCore.querySurface(mEGLSurface, EGL14.EGL_HEIGHT);
    }

    /**
     * Creates an off-screen surface.
     */
    public void createOffscreenSurface(int width, int height) {
        if (mEGLSurface != EGL14.EGL_NO_SURFACE) {
            throw new IllegalStateException("surface already created");
        }
        mEGLSurface = mEglCore.createOffscreenSurface(width, height);
        mWidth = width;
        mHeight = height;
    }

    /**
     * Returns the surface's width, in pixels.
     */
    public int getWidth() {
        return mWidth;
    }

    /**
     * Returns the surface's height, in pixels.
     */
    public int getHeight() {
        return mHeight;
    }

    /**
     * Release the EGL surface.
     */
    public void releaseEglSurface() {
        mEglCore.releaseSurface(mEGLSurface);
        mEGLSurface = EGL14.EGL_NO_SURFACE;
        mWidth = mHeight = -1;
    }

    /**
     * Makes our EGL context and surface current.
     */
    public void makeCurrent() {
        mEglCore.makeCurrent(mEGLSurface);
    }

    /**
     * Makes our EGL context and surface current for drawing, using the supplied surface
     * for reading.
     */
    public void makeCurrentReadFrom(EglSurfaceBase readSurface) {
        mEglCore.makeCurrent(mEGLSurface, readSurface.mEGLSurface);
    }

    /**
     * Calls eglSwapBuffers.  Use this to "publish" the current frame.
     *
     * @return false on failure
     */
    public boolean swapBuffers() {
        boolean result = mEglCore.swapBuffers(mEGLSurface);
        if (!result) {
            Log.d(TAG, "WARNING: swapBuffers() failed");
        }
        return result;
    }

    /**
     * Sends the presentation time stamp to EGL.
     *
     * @param nsecs Timestamp, in nanoseconds.
     */
    public void setPresentationTime(long nsecs) {
        mEglCore.setPresentationTime(mEGLSurface, nsecs);
    }

    /**
     * Saves the EGL surface to a file.
     * <p/>
     * Expects that this object's EGL surface is current.
     */
    public void saveFrame(File file, final int scaleFactor) throws IOException {
        if (!mEglCore.isCurrent(mEGLSurface)) {
            throw new RuntimeException("Expected EGL context/surface is not current");
        }

        // glReadPixels gives us a ByteBuffer filled with what is essentially big-endian RGBA
        // data (i.e. a byte of red, followed by a byte of green...).  We need an int[] filled
        // with little-endian ARGB data to feed to Bitmap.
        //
        // If we implement this as a series of buf.get() calls, we can spend 2.5 seconds just
        // copying data around for a 720p frame.  It's better to do a bulk get() and then
        // rearrange the data in memory.  (For comparison, the PNG compress takes about 500ms
        // for a trivial frame.)
        //
        // So... we set the ByteBuffer to little-endian, which should turn the bulk IntBuffer
        // get() into a straight memcpy on most Android devices.  Our ints will hold ABGR data.
        // Swapping B and R gives us ARGB.
        //
        // Making this even more interesting is the upside-down nature of GL, which means
        // our output will look upside-down relative to what appears on screen if the
        // typical GL conventions are used.

        final long startTime = System.currentTimeMillis();

        final String filename = file.toString();

        final ByteBuffer buf = ByteBuffer.allocateDirect(mWidth * mHeight * 4);
        buf.order(ByteOrder.LITTLE_ENDIAN);
        GLES20.glReadPixels(0, 0, mWidth, mHeight,
                GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf);
        buf.rewind();

        new Thread(new Runnable() {
            @Override
            public void run() {
                BufferedOutputStream bos = null;
                try {
                    bos = new BufferedOutputStream(new FileOutputStream(filename));
                    Bitmap fullBitmap = Bitmap.createBitmap(mWidth, mHeight, Bitmap.Config.ARGB_8888);
                    fullBitmap.copyPixelsFromBuffer(buf);
                    Matrix m = new Matrix();
                    m.preScale(1, -1);
                    if (scaleFactor != 1) {
                        Bitmap scaledBitmap = Bitmap.createScaledBitmap(fullBitmap, mWidth / scaleFactor, mHeight / scaleFactor, true);
                        Bitmap flippedScaledBitmap = Bitmap.createBitmap(scaledBitmap, 0, 0, scaledBitmap.getWidth(), scaledBitmap.getHeight(), m, true);
                        flippedScaledBitmap.compress(Bitmap.CompressFormat.JPEG, 90, bos);
                        scaledBitmap.recycle();
                        flippedScaledBitmap.recycle();
                    } else {
                        Bitmap flippedBitmap = Bitmap.createBitmap(fullBitmap, 0, 0, mWidth, mHeight, m, true);
                        flippedBitmap.compress(Bitmap.CompressFormat.JPEG, 90, bos);
                    }
                    fullBitmap.recycle();

                    Log.d(TAG, "Saved " + mWidth / scaleFactor + "x" + mHeight / scaleFactor + " frame as '" + filename + "' in " + (System.currentTimeMillis() - startTime) + " ms");
                } catch (FileNotFoundException e) {
                    e.printStackTrace();
                } finally {
                    if (bos != null) try {
                        bos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }

            }
        }).start();


    }
}




Java Source Code List

io.kickflip.sdk.FileUtils.java
io.kickflip.sdk.Kickflip.java
io.kickflip.sdk.Share.java
io.kickflip.sdk.Util.java
io.kickflip.sdk.activity.BroadcastActivity.java
io.kickflip.sdk.activity.GlassBroadcastActivity.java
io.kickflip.sdk.activity.ImmersiveActivity.java
io.kickflip.sdk.activity.MediaPlayerActivity.java
io.kickflip.sdk.api.KickflipApiClient.java
io.kickflip.sdk.api.KickflipCallback.java
io.kickflip.sdk.api.OAuthCallback.java
io.kickflip.sdk.api.OAuthClient.java
io.kickflip.sdk.api.OAuthConfig.java
io.kickflip.sdk.api.json.HlsStream.java
io.kickflip.sdk.api.json.Response.java
io.kickflip.sdk.api.json.StreamList.java
io.kickflip.sdk.api.json.Stream.java
io.kickflip.sdk.api.json.User.java
io.kickflip.sdk.api.s3.S3BroadcastManager.java
io.kickflip.sdk.api.s3.package-info.java
io.kickflip.sdk.av.AVRecorder.java
io.kickflip.sdk.av.AndroidEncoder.java
io.kickflip.sdk.av.AndroidMuxer.java
io.kickflip.sdk.av.AudioEncoderConfig.java
io.kickflip.sdk.av.AudioEncoderCore.java
io.kickflip.sdk.av.BroadcastListener.java
io.kickflip.sdk.av.Broadcaster.java
io.kickflip.sdk.av.CameraEncoder.java
io.kickflip.sdk.av.CameraSurfaceRenderer.java
io.kickflip.sdk.av.Drawable2d.java
io.kickflip.sdk.av.EglCore.java
io.kickflip.sdk.av.EglStateSaver.java
io.kickflip.sdk.av.EglSurfaceBase.java
io.kickflip.sdk.av.FFmpegMuxer.java
io.kickflip.sdk.av.Filters.java
io.kickflip.sdk.av.FullFrameRect.java
io.kickflip.sdk.av.GlUtil.java
io.kickflip.sdk.av.HlsFileObserver.java
io.kickflip.sdk.av.M3u8Parser.java
io.kickflip.sdk.av.MicrophoneEncoder.java
io.kickflip.sdk.av.Muxer.java
io.kickflip.sdk.av.SessionConfig.java
io.kickflip.sdk.av.SizeableFrameRect.java
io.kickflip.sdk.av.Texture2dProgram.java
io.kickflip.sdk.av.VideoEncoderConfig.java
io.kickflip.sdk.av.VideoEncoderCore.java
io.kickflip.sdk.av.WindowSurface.java
io.kickflip.sdk.event.BroadcastEvent.java
io.kickflip.sdk.event.BroadcastIsBufferingEvent.java
io.kickflip.sdk.event.BroadcastIsLiveEvent.java
io.kickflip.sdk.event.CameraOpenedEvent.java
io.kickflip.sdk.event.HlsManifestUploadedEvent.java
io.kickflip.sdk.event.HlsManifestWrittenEvent.java
io.kickflip.sdk.event.HlsSegmentUploadedEvent.java
io.kickflip.sdk.event.HlsSegmentWrittenEvent.java
io.kickflip.sdk.event.MuxerFinishedEvent.java
io.kickflip.sdk.event.S3FailedUploadEvent.java
io.kickflip.sdk.event.S3UploadEvent.java
io.kickflip.sdk.event.StreamLocationAddedEvent.java
io.kickflip.sdk.event.ThumbnailWrittenEvent.java
io.kickflip.sdk.event.UploadEvent.java
io.kickflip.sdk.event.package-info.java
io.kickflip.sdk.exception.KickflipException.java
io.kickflip.sdk.fragment.BroadcastFragment.java
io.kickflip.sdk.fragment.GlassBroadcastFragment.java
io.kickflip.sdk.fragment.MediaPlayerFragment.java
io.kickflip.sdk.fragment.package-info.java
io.kickflip.sdk.location.DeviceLocation.java
io.kickflip.sdk.location.package-info.java
io.kickflip.sdk.view.GLCameraEncoderView.java
io.kickflip.sdk.view.GLCameraView.java
io.kickflip.sdk.view.package-info.java
pro.dbro.ffmpegwrapper.FFmpegWrapper.java
pro.dbro.ffmpegwrapper.package-info.java