- * The object wraps an encoder running on a dedicated thread. The various control messages - * may be sent from arbitrary threads (typically the app UI thread). The encoder thread - * manages both sides of the encoder (feeding and draining); the only external input is - * the GL texture. - *
- * The design is complicated slightly by the need to create an EGL context that shares state - * with a view that gets restarted if (say) the device orientation changes. When the view - * in question is a GLSurfaceView, we don't have full control over the EGL context creation - * on that side, so we have to bend a bit backwards here. - *
- * To use: - *
- * TODO: tweak the API (esp. textureId) so it's less awkward for simple use cases. - */ -public abstract class BaseMovieEncoder implements Runnable { - - static final int MSG_START_RECORDING = 0; - static final int MSG_STOP_RECORDING = 1; - static final int MSG_FRAME_AVAILABLE = 2; - static final int MSG_QUIT = 4; - - // ----- accessed exclusively by encoder thread ----- - private WindowSurface mInputWindowSurface; - private EglCore mEglCore; - - private MediaEncoderCore mVideoEncoder; - - private AudioEncoderCore mAudioEncoder; - - // ----- accessed by multiple threads ----- - protected volatile EncoderHandler mHandler; - - private Object mReadyFence = new Object(); // guards ready/running - private volatile boolean mReady; - private volatile boolean mRunning; - - protected Context mContext; - - protected int mWidth, mHeight; - - private boolean useHevc = false; - - public BaseMovieEncoder(Context context, int width, int height, boolean hevc) { - mContext = context; - mWidth = width; - mHeight = height; - useHevc = hevc; - } - - /** - * Encoder configuration. - *
- * Object is immutable, which means we can safely pass it between threads without - * explicit synchronization (and don't need to worry about it getting tweaked out from - * under us). - *
- * TODO: make frame rate and iframe interval configurable? Maybe use builder pattern - * with reasonable defaults for those and bit rate. - */ - public static class EncoderConfig { - AndroidMuxer mMuxer; - - final EGLContext mEglContext; - - public EncoderConfig(EGLContext sharedEglContext) { - mEglContext = sharedEglContext; - mMuxer = new AndroidMuxer(); - } - - @Override - public String toString() { - return "EncoderConfig: " + "' ctxt=" + mEglContext; - } - } - - /** - * Tells the video recorder to start recording. (Call from non-encoder thread.) - *
- * Creates a new thread, which will create an encoder using the provided configuration. - *
- * Returns after the recorder thread has started and is ready to accept Messages. The - * encoder may not yet be fully configured. - */ - public void startRecording(EncoderConfig config) { - synchronized (mReadyFence) { - if (mRunning) { - return; - } - mRunning = true; - new Thread(this, "TextureMovieEncoder").start(); - while (!mReady) { - try { - mReadyFence.wait(); - } catch (InterruptedException ie) { - // ignore - } - } - } - - LogUtils.v(String.format("startRecording called")); - mHandler.sendMessage(mHandler.obtainMessage(MSG_START_RECORDING, config)); - } - - /** - * Tells the video recorder to stop recording. (Call from non-encoder thread.) - *
- * Returns immediately; the encoder/muxer may not yet be finished creating the movie. - *
- * TODO: have the encoder thread invoke a callback on the UI thread just before it shuts down - * so we can provide reasonable status UI (and let the caller know that movie encoding - * has completed). - */ - public void stopRecording() { - mHandler.sendMessage(mHandler.obtainMessage(MSG_STOP_RECORDING)); - mHandler.sendMessage(mHandler.obtainMessage(MSG_QUIT)); - // We don't know when these will actually finish (or even start). We don't want to - // delay the UI thread though, so we return immediately. - } - - /** - * Returns true if recording has been started. - */ - public boolean isRecording() { - synchronized (mReadyFence) { - return mRunning; - } - } - - public abstract void onPrepareEncoder(); - - public abstract void onFrameAvailable(Object o, long timestamp); - - /** - * Tells the video recorder that a new frame is available. (Call from non-encoder thread.) - *
- * This function sends a message and returns immediately. This isn't sufficient -- we - * don't want the caller to latch a new frame until we're done with this one -- but we - * can get away with it so long as the input frame rate is reasonable and the encoder - * thread doesn't stall. - *
- * TODO: either block here until the texture has been rendered onto the encoder surface, - * or have a separate "block if still busy" method that the caller can execute immediately - * before it calls updateTexImage(). The latter is preferred because we don't want to - * stall the caller while this thread does work. - */ - public void frameAvailable(Object object, long timestamp) { - synchronized (mReadyFence) { - if (!mReady) { - return; - } - } - - if (timestamp == 0) { - // Seeing this after device is toggled off/on with power button. The - // first frame back has a zero timestamp. - // - // MPEG4Writer thinks this is cause to abort() in native code, so it's very - // important that we just ignore the frame. - return; - } - - onFrameAvailable(object, timestamp); - } - - /** - * Encoder thread entry point. Establishes Looper/Handler and waits for messages. - *
- *
- * @see Thread#run()
- */
- @Override
- public void run() {
- // Establish a Looper for this thread, and define a Handler for it.
- Looper.prepare();
- synchronized (mReadyFence) {
- mHandler = new EncoderHandler(this);
- mReady = true;
- mReadyFence.notify();
- }
- Looper.loop();
-
- synchronized (mReadyFence) {
- mReady = mRunning = false;
- mHandler = null;
- }
- }
-
-
- /**
- * Handles encoder state change requests. The handler is created on the encoder thread.
- */
- static class EncoderHandler extends Handler {
- private WeakReference
- * The texture is rendered onto the encoder's input surface, along with a moving
- * box (just because we can).
- *
- *
- * @param timestampNanos The frame's timestamp, from SurfaceTexture.
- */
- private void handleFrameAvailable(long timestampNanos) {
- mVideoEncoder.start();
- mAudioEncoder.start();
-
- onFrameAvailable();
-
- mInputWindowSurface.setPresentationTime(timestampNanos);
- mInputWindowSurface.swapBuffers();
- }
-
- public abstract void onFrameAvailable();
-
- /**
- * Handles a request to stop encoding.
- */
- private void handleStopRecording() {
- mVideoEncoder.stop();
- mAudioEncoder.stop();
- releaseEncoder();
- }
-
- private void prepareEncoder(AndroidMuxer muxer, EGLContext sharedContext, int width, int height) {
- mWidth = width;
- mHeight = height;
-
- if (useHevc){
- mVideoEncoder = new VideoEncoderCoreHevc(muxer, width, height);
- }else {
- mVideoEncoder = new VideoEncoderCoreAvc(muxer, width, height);
- }
-
- mAudioEncoder = new AudioEncoderCore(muxer);
-
- mEglCore = new EglCore(sharedContext, EglCore.FLAG_RECORDABLE);
-
- mInputWindowSurface = new WindowSurface(mEglCore, mVideoEncoder.getInputSurface(), true);
- mInputWindowSurface.makeCurrent();
- }
-
- private void releaseEncoder() {
- mVideoEncoder.release();
-
- if (mInputWindowSurface != null) {
- mInputWindowSurface.release();
- mInputWindowSurface = null;
- }
- if (mEglCore != null) {
- mEglCore.release();
- mEglCore = null;
- }
- }
-}
diff --git a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/CameraHelper.java b/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/CameraHelper.java
deleted file mode 100644
index 6655e46..0000000
--- a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/CameraHelper.java
+++ /dev/null
@@ -1,216 +0,0 @@
-package com.yinuo.library.vlc.encoder;
-
-import android.annotation.TargetApi;
-import android.app.Activity;
-import android.hardware.Camera;
-import android.os.Build;
-import android.os.Environment;
-import android.view.Surface;
-
-import java.io.File;
-import java.text.SimpleDateFormat;
-import java.util.List;
-import java.util.Locale;
-
-/**
- * Created by liwentian on 2017/8/29.
- */
-
-public class CameraHelper {
-
- public static final int MEDIA_TYPE_IMAGE = 1;
- public static final int MEDIA_TYPE_VIDEO = 2;
-
- public static int getFrontCameraId() {
- int frontIdx = 0;
- Camera.CameraInfo cameraInfo = new Camera.CameraInfo();
- for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
- Camera.getCameraInfo(i, cameraInfo);
-
- if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
- frontIdx = i;
- break;
- }
- }
- return frontIdx;
- }
-
- public static int getDisplayOrientation(Activity activity, int cameraId) {
- Camera.CameraInfo info = new Camera.CameraInfo();
- Camera.getCameraInfo(cameraId, info);
- int rotation = activity.getWindowManager().getDefaultDisplay().getRotation();
-
- int degrees = 0;
- switch (rotation) {
- case Surface.ROTATION_0:
- degrees = 0;
- break;
- case Surface.ROTATION_90:
- degrees = 90;
- break;
- case Surface.ROTATION_180:
- degrees = 180;
- break;
- case Surface.ROTATION_270:
- degrees = 270;
- break;
- }
- int result;
- if (info.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {
- result = (info.orientation + degrees) % 360;
- result = (360 - result) % 360; // compensate the mirror
- } else {
- // back-facing
- result = (info.orientation - degrees + 360) % 360;
- }
-
- return result;
- }
-
- /**
- * Iterate over supported camera video sizes to see which one best fits the
- * dimensions of the given view while maintaining the aspect ratio. If none can,
- * be lenient with the aspect ratio.
- *
- * @param supportedVideoSizes Supported camera video sizes.
- * @param previewSizes Supported camera preview sizes.
- * @param w The width of the view.
- * @param h The height of the view.
- * @return Best match camera video size to fit in the view.
- */
- public static Camera.Size getOptimalVideoSize(List
- * The EGLContext must only be attached to one thread at a time. This class is not thread-safe.
- */
-public final class EglCore {
- private static final String TAG = GlUtil.TAG;
-
- /**
- * Constructor flag: surface must be recordable. This discourages EGL from using a
- * pixel format that cannot be converted efficiently to something usable by the video
- * encoder.
- */
- public static final int FLAG_RECORDABLE = 0x01;
-
- /**
- * Constructor flag: ask for GLES3, fall back to GLES2 if not available. Without this
- * flag, GLES2 is used.
- */
- public static final int FLAG_TRY_GLES3 = 0x02;
-
- // Android-specific extension.
- private static final int EGL_RECORDABLE_ANDROID = 0x3142;
-
- private EGLDisplay mEGLDisplay = EGL14.EGL_NO_DISPLAY;
- private EGLContext mEGLContext = EGL14.EGL_NO_CONTEXT;
- private EGLConfig mEGLConfig = null;
- private int mGlVersion = -1;
-
-
- /**
- * Prepares EGL display and context.
- *
- * Equivalent to EglCore(null, 0).
- */
- public EglCore() {
- this(null, 0);
- }
-
- /**
- * Prepares EGL display and context.
- *
- * @param sharedContext The context to share, or null if sharing is not desired.
- * @param flags Configuration bit flags, e.g. FLAG_RECORDABLE.
- */
- public EglCore(EGLContext sharedContext, int flags) {
- if (mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
- throw new RuntimeException("EGL already set up");
- }
-
- if (sharedContext == null) {
- sharedContext = EGL14.EGL_NO_CONTEXT;
- }
-
- mEGLDisplay = EGL14.eglGetDisplay(EGL14.EGL_DEFAULT_DISPLAY);
- if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
- throw new RuntimeException("unable to get EGL14 display");
- }
- int[] version = new int[2];
- if (!EGL14.eglInitialize(mEGLDisplay, version, 0, version, 1)) {
- mEGLDisplay = null;
- throw new RuntimeException("unable to initialize EGL14");
- }
-
- // Try to get a GLES3 context, if requested.
- if ((flags & FLAG_TRY_GLES3) != 0) {
- //Log.d(TAG, "Trying GLES 3");
- EGLConfig config = getConfig(flags, 3);
- if (config != null) {
- int[] attrib3_list = {
- EGL14.EGL_CONTEXT_CLIENT_VERSION, 3,
- EGL14.EGL_NONE
- };
- EGLContext context = EGL14.eglCreateContext(mEGLDisplay, config, sharedContext,
- attrib3_list, 0);
-
- if (EGL14.eglGetError() == EGL14.EGL_SUCCESS) {
- //Log.d(TAG, "Got GLES 3 config");
- mEGLConfig = config;
- mEGLContext = context;
- mGlVersion = 3;
- }
- }
- }
- if (mEGLContext == EGL14.EGL_NO_CONTEXT) { // GLES 2 only, or GLES 3 attempt failed
- //Log.d(TAG, "Trying GLES 2");
- EGLConfig config = getConfig(flags, 2);
- if (config == null) {
- throw new RuntimeException("Unable to find a suitable EGLConfig");
- }
- int[] attrib2_list = {
- EGL14.EGL_CONTEXT_CLIENT_VERSION, 2,
- EGL14.EGL_NONE
- };
- EGLContext context = EGL14.eglCreateContext(mEGLDisplay, config, sharedContext,
- attrib2_list, 0);
- checkEglError("eglCreateContext");
- mEGLConfig = config;
- mEGLContext = context;
- mGlVersion = 2;
- }
-
- // Confirm with query.
- int[] values = new int[1];
- EGL14.eglQueryContext(mEGLDisplay, mEGLContext, EGL14.EGL_CONTEXT_CLIENT_VERSION,
- values, 0);
- Log.d(TAG, "EGLContext created, client version " + values[0]);
- }
-
- /**
- * Finds a suitable EGLConfig.
- *
- * @param flags Bit flags from constructor.
- * @param version Must be 2 or 3.
- */
- private EGLConfig getConfig(int flags, int version) {
- int renderableType = EGL14.EGL_OPENGL_ES2_BIT;
- if (version >= 3) {
- renderableType |= EGLExt.EGL_OPENGL_ES3_BIT_KHR;
- }
-
- // The actual surface is generally RGBA or RGBX, so situationally omitting alpha
- // doesn't really help. It can also lead to a huge performance hit on glReadPixels()
- // when reading into a GL_RGBA buffer.
- int[] attribList = {
- EGL14.EGL_RED_SIZE, 8,
- EGL14.EGL_GREEN_SIZE, 8,
- EGL14.EGL_BLUE_SIZE, 8,
- EGL14.EGL_ALPHA_SIZE, 8,
- //EGL14.EGL_DEPTH_SIZE, 16,
- //EGL14.EGL_STENCIL_SIZE, 8,
- EGL14.EGL_RENDERABLE_TYPE, renderableType,
- EGL14.EGL_NONE, 0, // placeholder for recordable [@-3]
- EGL14.EGL_NONE
- };
- if ((flags & FLAG_RECORDABLE) != 0) {
- attribList[attribList.length - 3] = EGL_RECORDABLE_ANDROID;
- attribList[attribList.length - 2] = 1;
- }
- EGLConfig[] configs = new EGLConfig[1];
- int[] numConfigs = new int[1];
- if (!EGL14.eglChooseConfig(mEGLDisplay, attribList, 0, configs, 0, configs.length,
- numConfigs, 0)) {
- Log.w(TAG, "unable to find RGB8888 / " + version + " EGLConfig");
- return null;
- }
- return configs[0];
- }
-
- /**
- * Discards all resources held by this class, notably the EGL context. This must be
- * called from the thread where the context was created.
- *
- * On completion, no context will be current.
- */
- public void release() {
- if (mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
- // Android is unusual in that it uses a reference-counted EGLDisplay. So for
- // every eglInitialize() we need an eglTerminate().
- EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE,
- EGL14.EGL_NO_CONTEXT);
- EGL14.eglDestroyContext(mEGLDisplay, mEGLContext);
- EGL14.eglReleaseThread();
- EGL14.eglTerminate(mEGLDisplay);
- }
-
- mEGLDisplay = EGL14.EGL_NO_DISPLAY;
- mEGLContext = EGL14.EGL_NO_CONTEXT;
- mEGLConfig = null;
- }
-
- @Override
- protected void finalize() throws Throwable {
- try {
- if (mEGLDisplay != EGL14.EGL_NO_DISPLAY) {
- // We're limited here -- finalizers don't run on the thread that holds
- // the EGL state, so if a surface or context is still current on another
- // thread we can't fully release it here. Exceptions thrown from here
- // are quietly discarded. Complain in the log file.
- Log.w(TAG, "WARNING: EglCore was not explicitly released -- state may be leaked");
- release();
- }
- } finally {
- super.finalize();
- }
- }
-
- /**
- * Destroys the specified surface. Note the EGLSurface won't actually be destroyed if it's
- * still current in a context.
- */
- public void releaseSurface(EGLSurface eglSurface) {
- EGL14.eglDestroySurface(mEGLDisplay, eglSurface);
- }
-
- /**
- * Creates an EGL surface associated with a Surface.
- *
- * If this is destined for MediaCodec, the EGLConfig should have the "recordable" attribute.
- */
- public EGLSurface createWindowSurface(Object surface) {
- if (!(surface instanceof Surface) && !(surface instanceof SurfaceTexture)) {
- throw new RuntimeException("invalid surface: " + surface);
- }
-
- // Create a window surface, and attach it to the Surface we received.
- int[] surfaceAttribs = {
- EGL14.EGL_NONE
- };
- EGLSurface eglSurface = EGL14.eglCreateWindowSurface(mEGLDisplay, mEGLConfig, surface,
- surfaceAttribs, 0);
- checkEglError("eglCreateWindowSurface");
- if (eglSurface == null) {
- throw new RuntimeException("surface was null");
- }
- return eglSurface;
- }
-
- /**
- * Creates an EGL surface associated with an offscreen buffer.
- */
- public EGLSurface createOffscreenSurface(int width, int height) {
- int[] surfaceAttribs = {
- EGL14.EGL_WIDTH, width,
- EGL14.EGL_HEIGHT, height,
- EGL14.EGL_NONE
- };
- EGLSurface eglSurface = EGL14.eglCreatePbufferSurface(mEGLDisplay, mEGLConfig,
- surfaceAttribs, 0);
- checkEglError("eglCreatePbufferSurface");
- if (eglSurface == null) {
- throw new RuntimeException("surface was null");
- }
- return eglSurface;
- }
-
- /**
- * Makes our EGL context current, using the supplied surface for both "draw" and "read".
- */
- public void makeCurrent(EGLSurface eglSurface) {
- if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
- // called makeCurrent() before create?
- Log.d(TAG, "NOTE: makeCurrent w/o display");
- }
- if (!EGL14.eglMakeCurrent(mEGLDisplay, eglSurface, eglSurface, mEGLContext)) {
- throw new RuntimeException("eglMakeCurrent failed");
- }
- }
-
- /**
- * Makes our EGL context current, using the supplied "draw" and "read" surfaces.
- */
- public void makeCurrent(EGLSurface drawSurface, EGLSurface readSurface) {
- if (mEGLDisplay == EGL14.EGL_NO_DISPLAY) {
- // called makeCurrent() before create?
- Log.d(TAG, "NOTE: makeCurrent w/o display");
- }
- if (!EGL14.eglMakeCurrent(mEGLDisplay, drawSurface, readSurface, mEGLContext)) {
- throw new RuntimeException("eglMakeCurrent(draw,read) failed");
- }
- }
-
- /**
- * Makes no context current.
- */
- public void makeNothingCurrent() {
- if (!EGL14.eglMakeCurrent(mEGLDisplay, EGL14.EGL_NO_SURFACE, EGL14.EGL_NO_SURFACE,
- EGL14.EGL_NO_CONTEXT)) {
- throw new RuntimeException("eglMakeCurrent failed");
- }
- }
-
- /**
- * Calls eglSwapBuffers. Use this to "publish" the current frame.
- *
- * @return false on failure
- */
- public boolean swapBuffers(EGLSurface eglSurface) {
- return EGL14.eglSwapBuffers(mEGLDisplay, eglSurface);
- }
-
- /**
- * Sends the presentation time stamp to EGL. Time is expressed in nanoseconds.
- */
- public void setPresentationTime(EGLSurface eglSurface, long nsecs) {
- EGLExt.eglPresentationTimeANDROID(mEGLDisplay, eglSurface, nsecs);
- }
-
- /**
- * Returns true if our context and the specified surface are current.
- */
- public boolean isCurrent(EGLSurface eglSurface) {
- return mEGLContext.equals(EGL14.eglGetCurrentContext()) &&
- eglSurface.equals(EGL14.eglGetCurrentSurface(EGL14.EGL_DRAW));
- }
-
- /**
- * Performs a simple surface query.
- */
- public int querySurface(EGLSurface eglSurface, int what) {
- int[] value = new int[1];
- EGL14.eglQuerySurface(mEGLDisplay, eglSurface, what, value, 0);
- return value[0];
- }
-
- /**
- * Queries a string value.
- */
- public String queryString(int what) {
- return EGL14.eglQueryString(mEGLDisplay, what);
- }
-
- /**
- * Returns the GLES version this context is configured for (currently 2 or 3).
- */
- public int getGlVersion() {
- return mGlVersion;
- }
-
- /**
- * Writes the current display, context, and surface to the log.
- */
- public static void logCurrent(String msg) {
- EGLDisplay display;
- EGLContext context;
- EGLSurface surface;
-
- display = EGL14.eglGetCurrentDisplay();
- context = EGL14.eglGetCurrentContext();
- surface = EGL14.eglGetCurrentSurface(EGL14.EGL_DRAW);
- Log.i(TAG, "Current EGL (" + msg + "): display=" + display + ", context=" + context +
- ", surface=" + surface);
- }
-
- /**
- * Checks for EGL errors. Throws an exception if an error has been raised.
- */
- private void checkEglError(String msg) {
- int error;
- if ((error = EGL14.eglGetError()) != EGL14.EGL_SUCCESS) {
- throw new RuntimeException(msg + ": EGL error: 0x" + Integer.toHexString(error));
- }
- }
-
- public EGLContext getEGLContext() {
- return mEGLContext;
- }
-}
diff --git a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/EglSurfaceBase.java b/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/EglSurfaceBase.java
deleted file mode 100644
index e7b4815..0000000
--- a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/EglSurfaceBase.java
+++ /dev/null
@@ -1,197 +0,0 @@
-/*
- * Copyright 2013 Google Inc. All rights reserved.
- *
- * 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 com.yinuo.library.vlc.encoder;
-
-import android.graphics.Bitmap;
-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.FileOutputStream;
-import java.io.IOException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * Common base class for EGL surfaces.
- *
- * There can be multiple surfaces associated with a single context.
- */
-public class EglSurfaceBase {
- protected static final String TAG = GlUtil.TAG;
-
- // EglCore 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 eglCore) {
- mEglCore = eglCore;
- }
-
- /**
- * Creates a window surface.
- *
- * @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);
-
- // Don't cache width/height here, because the size of the underlying surface can change
- // out from under us (see e.g. HardwareScalerActivity).
- //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.
- *
- * If this is called on a window surface, and the underlying surface is in the process
- * of changing size, we may not see the new size right away (e.g. in the "surfaceChanged"
- * callback). The size should match after the next buffer swap.
- */
- public int getWidth() {
- if (mWidth < 0) {
- return mEglCore.querySurface(mEGLSurface, EGL14.EGL_WIDTH);
- } else {
- return mWidth;
- }
- }
-
- /**
- * Returns the surface's height, in pixels.
- */
- public int getHeight() {
- if (mHeight < 0) {
- return mEglCore.querySurface(mEGLSurface, EGL14.EGL_HEIGHT);
- } else {
- 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.
- *
- * Expects that this object's EGL surface is current.
- */
- public void saveFrame(File file) throws IOException {
- if (!mEglCore.isCurrent(mEGLSurface)) {
- throw new RuntimeException("Expected EGL context/surface is not current");
- }
-
- // glReadPixels fills in a "direct" ByteBuffer with what is essentially big-endian RGBA
- // data (i.e. a byte of red, followed by a byte of green...). While the Bitmap
- // constructor that takes an int[] wants little-endian ARGB (blue/red swapped), the
- // Bitmap "copy pixels" method wants the same format GL provides.
- //
- // Ideally we'd have some way to re-use the ByteBuffer, especially if we're calling
- // here often.
- //
- // 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.
-
- String filename = file.toString();
-
- int width = getWidth();
- int height = getHeight();
- ByteBuffer buf = ByteBuffer.allocateDirect(width * height * 4);
- buf.order(ByteOrder.LITTLE_ENDIAN);
- GLES20.glReadPixels(0, 0, width, height,
- GLES20.GL_RGBA, GLES20.GL_UNSIGNED_BYTE, buf);
- GlUtil.checkGlError("glReadPixels");
- buf.rewind();
-
- BufferedOutputStream bos = null;
- try {
- bos = new BufferedOutputStream(new FileOutputStream(filename));
- Bitmap bmp = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
- bmp.copyPixelsFromBuffer(buf);
- bmp.compress(Bitmap.CompressFormat.PNG, 90, bos);
- bmp.recycle();
- } finally {
- if (bos != null) bos.close();
- }
- Log.d(TAG, "Saved " + width + "x" + height + " frame as '" + filename + "'");
- }
-}
diff --git a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/GlUtil.java b/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/GlUtil.java
deleted file mode 100644
index ad0c0d6..0000000
--- a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/GlUtil.java
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All rights reserved.
- *
- * 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 com.yinuo.library.vlc.encoder;
-
-import android.opengl.GLES20;
-import android.opengl.GLES30;
-import android.opengl.Matrix;
-import android.util.Log;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-
-/**
- * Some OpenGL utility functions.
- */
-public class GlUtil {
- public static final String TAG = "Grafika";
-
- /** Identity matrix for general use. Don't modify or life will get weird. */
- public static final float[] IDENTITY_MATRIX;
- static {
- IDENTITY_MATRIX = new float[16];
- Matrix.setIdentityM(IDENTITY_MATRIX, 0);
- }
-
- private static final int SIZEOF_FLOAT = 4;
-
-
- private GlUtil() {} // do not instantiate
-
- /**
- * Creates a new program from the supplied vertex and fragment shaders.
- *
- * @return A handle to the program, or 0 on failure.
- */
- public static int createProgram(String vertexSource, String fragmentSource) {
- int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
- if (vertexShader == 0) {
- return 0;
- }
- int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
- if (pixelShader == 0) {
- return 0;
- }
-
- int program = GLES20.glCreateProgram();
- checkGlError("glCreateProgram");
- if (program == 0) {
- Log.e(TAG, "Could not create program");
- }
- GLES20.glAttachShader(program, vertexShader);
- checkGlError("glAttachShader");
- GLES20.glAttachShader(program, pixelShader);
- checkGlError("glAttachShader");
- GLES20.glLinkProgram(program);
- int[] linkStatus = new int[1];
- GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
- if (linkStatus[0] != GLES20.GL_TRUE) {
- Log.e(TAG, "Could not link program: ");
- Log.e(TAG, GLES20.glGetProgramInfoLog(program));
- GLES20.glDeleteProgram(program);
- program = 0;
- }
- return program;
- }
-
- /**
- * Compiles the provided shader source.
- *
- * @return A handle to the shader, or 0 on failure.
- */
- public static int loadShader(int shaderType, String source) {
- int shader = GLES20.glCreateShader(shaderType);
- checkGlError("glCreateShader type=" + shaderType);
- GLES20.glShaderSource(shader, source);
- GLES20.glCompileShader(shader);
- int[] compiled = new int[1];
- GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
- if (compiled[0] == 0) {
- Log.e(TAG, "Could not compile shader " + shaderType + ":");
- Log.e(TAG, " " + GLES20.glGetShaderInfoLog(shader));
- GLES20.glDeleteShader(shader);
- shader = 0;
- }
- return shader;
- }
-
- /**
- * Checks to see if a GLES error has been raised.
- */
- public static void checkGlError(String op) {
- int error = GLES20.glGetError();
- if (error != GLES20.GL_NO_ERROR) {
- String msg = op + ": glError 0x" + Integer.toHexString(error);
- Log.e(TAG, msg);
- throw new RuntimeException(msg);
- }
- }
-
- /**
- * Checks to see if the location we obtained is valid. GLES returns -1 if a label
- * could not be found, but does not set the GL error.
- *
- * Throws a RuntimeException if the location is invalid.
- */
- public static void checkLocation(int location, String label) {
- if (location < 0) {
- throw new RuntimeException("Unable to locate '" + label + "' in program");
- }
- }
-
- /**
- * Creates a texture from raw data.
- *
- * @param data Image data, in a "direct" ByteBuffer.
- * @param width Texture width, in pixels (not bytes).
- * @param height Texture height, in pixels.
- * @param format Image data format (use constant appropriate for glTexImage2D(), e.g. GL_RGBA).
- * @return Handle to texture.
- */
- public static int createImageTexture(ByteBuffer data, int width, int height, int format) {
- int[] textureHandles = new int[1];
- int textureHandle;
-
- GLES20.glGenTextures(1, textureHandles, 0);
- textureHandle = textureHandles[0];
- GlUtil.checkGlError("glGenTextures");
-
- // Bind the texture handle to the 2D texture target.
- GLES20.glBindTexture(GLES20.GL_TEXTURE_2D, textureHandle);
-
- // Configure min/mag filtering, i.e. what scaling method do we use if what we're rendering
- // is smaller or larger than the source image.
- GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MIN_FILTER,
- GLES20.GL_LINEAR);
- GLES20.glTexParameteri(GLES20.GL_TEXTURE_2D, GLES20.GL_TEXTURE_MAG_FILTER,
- GLES20.GL_LINEAR);
- GlUtil.checkGlError("loadImageTexture");
-
- // Load the data from the buffer into the texture handle.
- GLES20.glTexImage2D(GLES20.GL_TEXTURE_2D, /*level*/ 0, format,
- width, height, /*border*/ 0, format, GLES20.GL_UNSIGNED_BYTE, data);
- GlUtil.checkGlError("loadImageTexture");
-
- return textureHandle;
- }
-
- /**
- * Allocates a direct float buffer, and populates it with the float array data.
- */
- public static FloatBuffer createFloatBuffer(float[] coords) {
- // Allocate a direct ByteBuffer, using 4 bytes per float, and copy coords into it.
- ByteBuffer bb = ByteBuffer.allocateDirect(coords.length * SIZEOF_FLOAT);
- bb.order(ByteOrder.nativeOrder());
- FloatBuffer fb = bb.asFloatBuffer();
- fb.put(coords);
- fb.position(0);
- return fb;
- }
-
- /**
- * Writes GL version info to the log.
- */
- public static void logVersionInfo() {
- Log.i(TAG, "vendor : " + GLES20.glGetString(GLES20.GL_VENDOR));
- Log.i(TAG, "renderer: " + GLES20.glGetString(GLES20.GL_RENDERER));
- Log.i(TAG, "version : " + GLES20.glGetString(GLES20.GL_VERSION));
-
- if (false) {
- int[] values = new int[1];
- GLES30.glGetIntegerv(GLES30.GL_MAJOR_VERSION, values, 0);
- int majorVersion = values[0];
- GLES30.glGetIntegerv(GLES30.GL_MINOR_VERSION, values, 0);
- int minorVersion = values[0];
- if (GLES30.glGetError() == GLES30.GL_NO_ERROR) {
- Log.i(TAG, "iversion: " + majorVersion + "." + minorVersion);
- }
- }
- }
-}
diff --git a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/MediaEncoderCore.java b/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/MediaEncoderCore.java
deleted file mode 100644
index b1635e2..0000000
--- a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/MediaEncoderCore.java
+++ /dev/null
@@ -1,118 +0,0 @@
-package com.yinuo.library.vlc.encoder;
-
-import android.media.MediaCodec;
-import android.os.Build;
-import android.os.Bundle;
-import android.view.Surface;
-
-import com.yinuo.library.vlc.utils.LogUtils;
-
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-
-/**
- * Created by liwentian on 17/8/1.
- */
-
-public abstract class MediaEncoderCore {
-
- protected final String TAG = getClass().getSimpleName();
-
- protected static final boolean VERBOSE = true;
-
- protected AndroidMuxer mMuxer;
-
- protected MediaCodec mEncoder;
-
- protected int mTrackIndex = -1;
-
- protected volatile boolean mRecording;
-
- protected MediaCodec.BufferInfo mBufferInfo;
-
- public MediaEncoderCore(AndroidMuxer muxer) {
- LogUtils.v(String.format("%s
- * If endOfStream is not set, this returns when there is no more data to drain. If it
- * is set, we send EOS to the encoder, and then iterate until we see EOS on the output.
- * Calling this with endOfStream set should be done once, right before stopping the muxer.
- *
- * We're just using the muxer to get a .mp4 file (instead of a raw H.264 stream). We're
- * not recording audio.
- */
- long timeStamp;
-
- public abstract Surface getInputSurface();
-
- public abstract void drainEncoder(boolean endOfStream);
-
- void buildKeyFrame() {
- if (System.currentTimeMillis() - timeStamp >= 1000) {//1000毫秒后,设置参数
- timeStamp = System.currentTimeMillis();
- if (Build.VERSION.SDK_INT >= 23) {
- Bundle params = new Bundle();
- params.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
- mEncoder.setParameters(params);
- }
- }
- }
-
- public void release() {
- LogUtils.v(String.format("%s.release", getClass().getSimpleName()));
-
- if (mEncoder != null) {
- mEncoder.stop();
- mEncoder.release();
- mEncoder = null;
- }
-
- if (mMuxer != null) {
- mMuxer.release();
- }
- }
-
- protected abstract boolean isSurfaceInput();
-
-
- /**
- * 保存数据到本地
- *
- * @param buffer 要保存的数据
- * @param offset 要保存数据的起始位置
- * @param length 要保存数据长度
- * @param path 保存路径
- * @param append 是否追加
- */
- public static void save(byte[] buffer, int offset, int length, String path, boolean append) {
- FileOutputStream fos = null;
- try {
- fos = new FileOutputStream(path, append);
- fos.write(buffer, offset, length);
- } catch (FileNotFoundException e) {
- e.printStackTrace();
- } catch (IOException e) {
- e.printStackTrace();
- } finally {
- if (fos != null) {
- try {
- fos.flush();
- fos.close();
- } catch (IOException e) {
- e.printStackTrace();
- }
- }
- }
- }
-
-}
diff --git a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/MovieEncoder1.java b/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/MovieEncoder1.java
deleted file mode 100644
index 5f2d913..0000000
--- a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/MovieEncoder1.java
+++ /dev/null
@@ -1,63 +0,0 @@
-package com.yinuo.library.vlc.encoder;
-
-import android.content.Context;
-
-import com.yinuo.library.vlc.RGBProgram;
-import com.yinuo.library.vlc.utils.LogUtils;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-
-/**
- * Created by liwentian on 2017/10/31.
- */
-
-public class MovieEncoder1 extends BaseMovieEncoder {
-
- private volatile RGBProgram mRGBProgram;
- private volatile ByteBuffer mYUVBuffer;
-
- public MovieEncoder1(Context context, int width, int height, boolean hevc) {
- super(context, width, height, hevc);
- }
-
- @Override
- public void onPrepareEncoder() {
- LogUtils.v(String.format("onPrepareEncoder width = %d, height = %d", mWidth, mHeight));
- mRGBProgram = new RGBProgram(mContext, mWidth, mHeight);
- mYUVBuffer = ByteBuffer.allocateDirect(mWidth * mHeight * 4)
- .order(ByteOrder.nativeOrder());
- }
-
- @Override
- public void onFrameAvailable(Object object, long timestamp) {
- byte[] data = (byte[]) object;
-
- if (mYUVBuffer == null) {
- return;
- }
-
-// LogUtils.v(String.format("onFrameAvailable: data = %d, buffer = %d", data.length, mYUVBuffer.capacity()));
-
- synchronized (mYUVBuffer) {
- mYUVBuffer.position(0);
- int len = Math.min(mYUVBuffer.capacity(), data.length);
- mYUVBuffer.put(data, 0, len);
- }
- if (mHandler != null) {
- mHandler.sendMessage(mHandler.obtainMessage(MSG_FRAME_AVAILABLE,
- (int) (timestamp >> 32), (int) timestamp));
- }
- }
-
- @Override
- public void onFrameAvailable() {
- mRGBProgram.useProgram();
-
- synchronized (mYUVBuffer) {
- mRGBProgram.setUniforms(mYUVBuffer.array());
- }
-
- mRGBProgram.draw();
- }
-}
diff --git a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/VideoEncoderCoreAvc.java b/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/VideoEncoderCoreAvc.java
deleted file mode 100644
index f85255c..0000000
--- a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/VideoEncoderCoreAvc.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All rights reserved.
- *
- * 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 com.yinuo.library.vlc.encoder;
-
-import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
-import android.media.MediaFormat;
-import android.util.Log;
-import android.view.Surface;
-
-import com.yinuo.library.vlc.PushHelper;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-/**
- * This class wraps up the core components used for surface-input video encoding.
- *
- * Once created, frames are fed to the input surface. Remember to provide the presentation
- * time stamp, and always call drainEncoder() before swapBuffers() to ensure that the
- * producer side doesn't get backed up.
- *
- * This class is not thread-safe, with one exception: it is valid to use the input surface
- * on one thread, and drain the output on a different thread.
- */
-public class VideoEncoderCoreAvc extends MediaEncoderCore {
-
- // TODO: these ought to be configurable as well
- private static final String MIME_TYPE = "video/avc"; // H.264 Advanced Video Coding
- private static final int FRAME_RATE = 24; // 30fps
- private static final int IFRAME_INTERVAL = 1; // 5 seconds between I-frames
- private static final int BIT_RATE = 4000000;
-
- private Surface mInputSurface;
-
- /**
- * Configures encoder and muxer state, and prepares the input Surface.
- */
- public VideoEncoderCoreAvc(AndroidMuxer muxer, int width, int height) {
- super(muxer);
- prepareEncoder(width, height);
- PushHelper.INSTANCE.startStream(false);
- }
-
- private void prepareEncoder(int width, int height) {
- mBufferInfo = new MediaCodec.BufferInfo();
-
- MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, width, height);
-
- // Set some properties. Failing to specify some of these can cause the MediaCodec
- // configure() call to throw an unhelpful exception.
- format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
- MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
- format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
- format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
- format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
- if (VERBOSE) Log.d(TAG, "format: " + format);
-
- // Create a MediaCodec encoder, and configure it with our format. Get a Surface
- // we can use for input and wrap it with a class that handles the EGL work.
-
- try {
- mEncoder = MediaCodec.createEncoderByType(MIME_TYPE);
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
- mInputSurface = mEncoder.createInputSurface();
- mEncoder.start();
- }
-
- @Override
- public void drainEncoder(boolean endOfStream) {
- buildKeyFrame();
- final int TIMEOUT_USEC = 10000;
- if (VERBOSE) Log.d(TAG, "drainEncoder(" + endOfStream + ")");
-
- if (endOfStream && isSurfaceInput()) {
- if (VERBOSE) Log.d(TAG, "sending EOS to encoder");
- mEncoder.signalEndOfInputStream();
- }
- byte[] mSpsPps = new byte[0];
- ByteBuffer[] encoderOutputBuffers = mEncoder.getOutputBuffers();
- int encoderStatus = mEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
-
- if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
- // no output available yet
- if (!endOfStream) {
- } else {
- if (VERBOSE) Log.d(TAG, "no output available, spinning to await EOS");
- }
- } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
- // not expected for an encoder
- encoderOutputBuffers = mEncoder.getOutputBuffers();
- } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
- // should happen before receiving buffers, and should only happen once
- MediaFormat newFormat = mEncoder.getOutputFormat();
- Log.d(TAG, "encoder output format changed: " + newFormat);
-
- // now that we have the Magic Goodies, start the muxer
- mTrackIndex = mMuxer.addTrack(newFormat);
- } else if (encoderStatus < 0) {
- Log.w(TAG, "unexpected result from encoder.dequeueOutputBuffer: " +
- encoderStatus);
- // let's ignore it
- } else {
- ByteBuffer encodedData = encoderOutputBuffers[encoderStatus];
- if (encodedData == null) {
- throw new RuntimeException("encoderOutputBuffer " + encoderStatus +
- " was null");
- }
-
- if (!mMuxer.isStarted()) {
- mBufferInfo.size = 0;
- }
-
- if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
- // The codec config data was pulled out and fed to the muxer when we got
- // the INFO_OUTPUT_FORMAT_CHANGED status. Ignore it.
- if (VERBOSE) Log.d(TAG, "ignoring BUFFER_FLAG_CODEC_CONFIG");
- mBufferInfo.size = 0;
- }
-
- if (mBufferInfo.size != 0) {
- // adjust the ByteBuffer values to match BufferInfo (not needed?)
- encodedData.position(mBufferInfo.offset);
- encodedData.limit(mBufferInfo.offset + mBufferInfo.size);
-
- mMuxer.writeSampleData(mTrackIndex, encodedData, mBufferInfo);
- if (VERBOSE) {
- Log.d(TAG, "sent " + mBufferInfo.size + " bytes to muxer, ts=" +
- mBufferInfo.presentationTimeUs);
- }
-
- byte[] outData = new byte[mBufferInfo.size];
- //从buff中读取数据到outData中
- encodedData.get(outData);
- //记录pps和sps,pps和sps数据开头是0x00 0x00 0x00 0x01 0x67,
- // 0x67对应十进制103
- if (outData[0] == 0 && outData[1] == 0 && outData[2] == 0
- && outData[3] == 1 && outData[4] == 103) {
- mSpsPps = outData;
- } else if (outData[0] == 0 && outData[1] == 0 && outData[2] == 0
- && outData[3] == 1 && outData[4] == 101) {
- //关键帧开始规则是0x00 0x00 0x00 0x01 0x65,0x65对应十进制101
- //在关键帧前面加上pps和sps数据
- byte[] iframeData = new byte[mSpsPps.length + outData.length];
- System.arraycopy(mSpsPps, 0, iframeData, 0, mSpsPps.length);
- System.arraycopy(outData, 0, iframeData, mSpsPps.length, outData.length);
- outData = iframeData;
- }
- //save(outData, 0, outData.length, Environment.getExternalStorageDirectory() + "/easy.h264", true);
- PushHelper.INSTANCE.pushData(outData, outData.length, mBufferInfo.presentationTimeUs / 1000);
- }
-
- mEncoder.releaseOutputBuffer(encoderStatus, false);
-
- if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
- if (!endOfStream) {
- Log.w(TAG, "reached end of stream unexpectedly");
- } else {
- if (VERBOSE) Log.d(TAG, "end of stream reached");
- }
- }
- }
- }
-
- /**
- * Returns the encoder's input surface.
- */
- @Override
- public Surface getInputSurface() {
- return mInputSurface;
- }
-
- @Override
- public void start() {
- drainEncoder(false);
- }
-
- @Override
- public void stop() {
- drainEncoder(true);
- }
-
- @Override
- protected boolean isSurfaceInput() {
- return true;
- }
-}
diff --git a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/VideoEncoderCoreHevc.java b/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/VideoEncoderCoreHevc.java
deleted file mode 100644
index 6b54311..0000000
--- a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/VideoEncoderCoreHevc.java
+++ /dev/null
@@ -1,205 +0,0 @@
-/*
- * Copyright 2014 Google Inc. All rights reserved.
- *
- * 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 com.yinuo.library.vlc.encoder;
-
-import android.media.MediaCodec;
-import android.media.MediaCodecInfo;
-import android.media.MediaFormat;
-import android.util.Log;
-import android.view.Surface;
-
-import com.yinuo.library.vlc.PushHelper;
-
-import java.io.IOException;
-import java.nio.ByteBuffer;
-
-/**
- * This class wraps up the core components used for surface-input video encoding.
- *
- * Once created, frames are fed to the input surface. Remember to provide the presentation
- * time stamp, and always call drainEncoder() before swapBuffers() to ensure that the
- * producer side doesn't get backed up.
- *
- * This class is not thread-safe, with one exception: it is valid to use the input surface
- * on one thread, and drain the output on a different thread.
- */
-public class VideoEncoderCoreHevc extends MediaEncoderCore {
-
- // TODO: these ought to be configurable as well
- private static final String MIME_TYPE = "video/hevc"; // H.264 Advanced Video Coding
- private static final int FRAME_RATE = 24; // 30fps
- private static final int IFRAME_INTERVAL = 1; // 5 seconds between I-frames
- private static final int BIT_RATE = 4000000;
-
- private Surface mInputSurface;
-
- /**
- * Configures encoder and muxer state, and prepares the input Surface.
- */
- public VideoEncoderCoreHevc(AndroidMuxer muxer, int width, int height) {
- super(muxer);
- prepareEncoder(width, height);
- PushHelper.INSTANCE.startStream(true);
- }
-
- private void prepareEncoder(int width, int height) {
- mBufferInfo = new MediaCodec.BufferInfo();
-
- MediaFormat format = MediaFormat.createVideoFormat(MIME_TYPE, width, height);
-
- // Set some properties. Failing to specify some of these can cause the MediaCodec
- // configure() call to throw an unhelpful exception.
- format.setInteger(MediaFormat.KEY_COLOR_FORMAT,
- MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
- format.setInteger(MediaFormat.KEY_BIT_RATE, BIT_RATE);
- format.setInteger(MediaFormat.KEY_FRAME_RATE, FRAME_RATE);
- format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, IFRAME_INTERVAL);
- if (VERBOSE) Log.d(TAG, "format: " + format);
-
- // Create a MediaCodec encoder, and configure it with our format. Get a Surface
- // we can use for input and wrap it with a class that handles the EGL work.
- try {
- mEncoder = MediaCodec.createEncoderByType(MIME_TYPE);
- } catch (IOException e) {
- e.printStackTrace();
- }
-
- mEncoder.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
- mInputSurface = mEncoder.createInputSurface();
- mEncoder.start();
- }
-
- /**
- * Returns the encoder's input surface.
- */
- @Override
- public Surface getInputSurface() {
- return mInputSurface;
- }
-
- public static final int NAL_I = 19;
- public static final int NAL_VPS = 32;
- private byte[] vps_sps_pps_buf;
-
- @Override
- public void drainEncoder(boolean endOfStream) {
- buildKeyFrame();
- final int TIMEOUT_USEC = 10000;
- if (VERBOSE) Log.d(TAG, "drainEncoder(" + endOfStream + ")");
-
- if (endOfStream && isSurfaceInput()) {
- if (VERBOSE) Log.d(TAG, "sending EOS to encoder");
- mEncoder.signalEndOfInputStream();
- }
- byte[] mSpsPps = new byte[0];
- ByteBuffer[] encoderOutputBuffers = mEncoder.getOutputBuffers();
- int encoderStatus = mEncoder.dequeueOutputBuffer(mBufferInfo, TIMEOUT_USEC);
-
- if (encoderStatus == MediaCodec.INFO_TRY_AGAIN_LATER) {
- // no output available yet
- if (!endOfStream) {
- } else {
- if (VERBOSE) Log.d(TAG, "no output available, spinning to await EOS");
- }
- } else if (encoderStatus == MediaCodec.INFO_OUTPUT_BUFFERS_CHANGED) {
- // not expected for an encoder
- encoderOutputBuffers = mEncoder.getOutputBuffers();
- } else if (encoderStatus == MediaCodec.INFO_OUTPUT_FORMAT_CHANGED) {
- // should happen before receiving buffers, and should only happen once
- MediaFormat newFormat = mEncoder.getOutputFormat();
- Log.d(TAG, "encoder output format changed: " + newFormat);
-
- // now that we have the Magic Goodies, start the muxer
- mTrackIndex = mMuxer.addTrack(newFormat);
- } else if (encoderStatus < 0) {
- Log.w(TAG, "unexpected result from encoder.dequeueOutputBuffer: " +
- encoderStatus);
- // let's ignore it
- } else {
- ByteBuffer encodedData = encoderOutputBuffers[encoderStatus];
- if (encodedData == null) {
- throw new RuntimeException("encoderOutputBuffer " + encoderStatus +
- " was null");
- }
-
- if (!mMuxer.isStarted()) {
- mBufferInfo.size = 0;
- }
-
- if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_CODEC_CONFIG) != 0) {
- // The codec config data was pulled out and fed to the muxer when we got
- // the INFO_OUTPUT_FORMAT_CHANGED status. Ignore it.
- if (VERBOSE) Log.d(TAG, "ignoring BUFFER_FLAG_CODEC_CONFIG");
- mBufferInfo.size = 0;
- }
-
- if (mBufferInfo.size != 0) {
- // adjust the ByteBuffer values to match BufferInfo (not needed?)
- encodedData.position(mBufferInfo.offset);
- encodedData.limit(mBufferInfo.offset + mBufferInfo.size);
-
- mMuxer.writeSampleData(mTrackIndex, encodedData, mBufferInfo);
- if (VERBOSE) {
- Log.d(TAG, "sent " + mBufferInfo.size + " bytes to muxer, ts=" +
- mBufferInfo.presentationTimeUs);
- }
-
- byte[] outData = new byte[mBufferInfo.size];
- encodedData.get(outData);
- int offset = 4;
- if (outData[2] == 0x01) {
- offset = 3;
- }
- int type = (outData[offset] & 0x7E) >> 1;
- if (type == NAL_VPS) {
- vps_sps_pps_buf = outData;
- } else if (type == NAL_I) {
- byte[] newBuf = new byte[vps_sps_pps_buf.length + outData.length];
- System.arraycopy(vps_sps_pps_buf, 0, newBuf, 0, vps_sps_pps_buf.length);
- System.arraycopy(outData, 0, newBuf, vps_sps_pps_buf.length, outData.length);
- outData = newBuf;
- }
- PushHelper.INSTANCE.pushData(outData, outData.length, mBufferInfo.presentationTimeUs / 1000);
- }
-
- mEncoder.releaseOutputBuffer(encoderStatus, false);
-
- if ((mBufferInfo.flags & MediaCodec.BUFFER_FLAG_END_OF_STREAM) != 0) {
- if (!endOfStream) {
- Log.w(TAG, "reached end of stream unexpectedly");
- } else {
- if (VERBOSE) Log.d(TAG, "end of stream reached");
- }
- }
- }
- }
-
- @Override
- public void start() {
- drainEncoder(false);
- }
-
- @Override
- public void stop() {
- drainEncoder(true);
- }
-
- @Override
- protected boolean isSurfaceInput() {
- return true;
- }
-}
diff --git a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/WindowSurface.java b/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/WindowSurface.java
deleted file mode 100644
index 768ab28..0000000
--- a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/WindowSurface.java
+++ /dev/null
@@ -1,90 +0,0 @@
-/*
- * Copyright 2013 Google Inc. All rights reserved.
- *
- * 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 com.yinuo.library.vlc.encoder;
-
-import android.graphics.SurfaceTexture;
-import android.view.Surface;
-
-/**
- * Recordable EGL window surface.
- *
- * It's good practice to explicitly release() the surface, preferably from a "finally" block.
- */
-public class WindowSurface extends EglSurfaceBase {
- private Surface mSurface;
- private boolean mReleaseSurface;
-
- /**
- * Associates an EGL surface with the native window surface.
- *
- * Set releaseSurface to true if you want the Surface to be released when release() is
- * called. This is convenient, but can interfere with framework classes that expect to
- * manage the Surface themselves (e.g. if you release a SurfaceView's Surface, the
- * surfaceDestroyed() callback won't fire).
- */
- public WindowSurface(EglCore eglCore, Surface surface, boolean releaseSurface) {
- super(eglCore);
- createWindowSurface(surface);
- mSurface = surface;
- mReleaseSurface = releaseSurface;
- }
-
- /**
- * Associates an EGL surface with the SurfaceTexture.
- */
- public WindowSurface(EglCore eglCore, SurfaceTexture surfaceTexture) {
- super(eglCore);
- createWindowSurface(surfaceTexture);
- }
-
- /**
- * Releases any resources associated with the EGL surface (and, if configured to do so,
- * with the Surface as well).
- *
- * Does not require that the surface's EGL context be current.
- */
- public void release() {
- releaseEglSurface();
- if (mSurface != null) {
- if (mReleaseSurface) {
- mSurface.release();
- }
- mSurface = null;
- }
- }
-
- /**
- * Recreate the EGLSurface, using the new EglBase. The caller should have already
- * freed the old EGLSurface with releaseEglSurface().
- *
- * This is useful when we want to update the EGLSurface associated with a Surface.
- * For example, if we want to share with a different EGLContext, which can only
- * be done by tearing down and recreating the context. (That's handled by the caller;
- * this just creates a new EGLSurface for the Surface we were handed earlier.)
- *
- * If the previous EGLSurface isn't fully destroyed, e.g. it's still current on a
- * context somewhere, the create call will fail with complaints from the Surface
- * about already being connected.
- */
- public void recreate(EglCore newEglCore) {
- if (mSurface == null) {
- throw new RuntimeException("not yet implemented for SurfaceTexture");
- }
- mEglCore = newEglCore; // switch to new context
- createWindowSurface(mSurface); // create new surface
- }
-}
diff --git a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/YUVProgram.java b/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/YUVProgram.java
deleted file mode 100644
index 61faa6a..0000000
--- a/library-vlc/src/main/java/com/yinuo/library/vlc/encoder/YUVProgram.java
+++ /dev/null
@@ -1,190 +0,0 @@
-package com.yinuo.library.vlc.encoder;
-
-import android.content.Context;
-import android.content.res.Configuration;
-import android.opengl.GLES20;
-import android.opengl.Matrix;
-
-import com.yinuo.library.vlc.R;
-import com.yinuo.library.vlc.ShaderProgram;
-
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
-import java.nio.FloatBuffer;
-
-import static android.opengl.GLES20.GL_CLAMP_TO_EDGE;
-import static android.opengl.GLES20.GL_FLOAT;
-import static android.opengl.GLES20.GL_LINEAR;
-import static android.opengl.GLES20.GL_LUMINANCE;
-import static android.opengl.GLES20.GL_LUMINANCE_ALPHA;
-import static android.opengl.GLES20.GL_TEXTURE0;
-import static android.opengl.GLES20.GL_TEXTURE1;
-import static android.opengl.GLES20.GL_TEXTURE_2D;
-import static android.opengl.GLES20.GL_TEXTURE_MAG_FILTER;
-import static android.opengl.GLES20.GL_TEXTURE_MIN_FILTER;
-import static android.opengl.GLES20.GL_TEXTURE_WRAP_S;
-import static android.opengl.GLES20.GL_TEXTURE_WRAP_T;
-import static android.opengl.GLES20.GL_TRIANGLE_STRIP;
-import static android.opengl.GLES20.GL_UNSIGNED_BYTE;
-import static android.opengl.GLES20.glActiveTexture;
-import static android.opengl.GLES20.glBindTexture;
-import static android.opengl.GLES20.glDrawArrays;
-import static android.opengl.GLES20.glEnableVertexAttribArray;
-import static android.opengl.GLES20.glGenTextures;
-import static android.opengl.GLES20.glGetAttribLocation;
-import static android.opengl.GLES20.glGetUniformLocation;
-import static android.opengl.GLES20.glTexImage2D;
-import static android.opengl.GLES20.glTexParameterf;
-import static android.opengl.GLES20.glUniform1i;
-import static android.opengl.GLES20.glVertexAttribPointer;
-
-/**
- * Created by liwentian on 17/8/16.
- */
-
-/**
- * 输入Camera的预览NV21数据
- */
-public class YUVProgram extends ShaderProgram {
-
- protected final int mUniformYTextureLocation;
- protected final int mUniformUVTextureLocation;
-
- static final float CUBE[] = {
- -1.0f, -1.0f,
- 1.0f, -1.0f,
- -1.0f, 1.0f,
- 1.0f, 1.0f,
- };
-
- public static final float TEXTURE_UPSIDE_DOWN[] = {
- 0.0f, 1.0f,
- 1.0f, 1.0f,
- 0.0f, 0.0f,
- 1.0f, 0.0f,
- };
-
- public static final float TEXTURE_NO_ROTATION[] = {
- 0.0f, 0.0f,
- 1.0f, 0.0f,
- 0.0f, 1.0f,
- 1.0f, 1.0f,
- };
-
- // Attribute locations
- private final int aPositionLocation;
- private final int aTextureCoordinatesLocation;
-
- private final int uMVPMatrixLocation;
-
- private final FloatBuffer mGLCubeBuffer;
- private final FloatBuffer mGLTextureBuffer;
-
- private int mYTestureId, mUVTextureId;
-
- private ByteBuffer mYBuffer, mUVBuffer;
-
- public YUVProgram(Context context, int width, int height) {
- super(context, R.raw.yuv_vertex, R.raw.yuv_fragment, width, height);
-
- mUniformYTextureLocation = glGetUniformLocation(program, "y_texture");
- mUniformUVTextureLocation = glGetUniformLocation(program, "uv_texture");
- uMVPMatrixLocation = glGetUniformLocation(program, "uMVPMatrix");
-
- aPositionLocation = glGetAttribLocation(program, "a_Position");
- aTextureCoordinatesLocation = glGetAttribLocation(program, "a_TextureCoordinates");
-
- mGLCubeBuffer = ByteBuffer.allocateDirect(CUBE.length * 4)
- .order(ByteOrder.nativeOrder())
- .asFloatBuffer();
- mGLCubeBuffer.put(CUBE).position(0);
-
- mGLTextureBuffer = ByteBuffer.allocateDirect(TEXTURE_NO_ROTATION.length * 4)
- .order(ByteOrder.nativeOrder())
- .asFloatBuffer();
-
- mYBuffer = ByteBuffer.allocateDirect(width * height)
- .order(ByteOrder.nativeOrder());
-
- mUVBuffer = ByteBuffer.allocateDirect(width * height / 2)
- .order(ByteOrder.nativeOrder());
-
- int[] textures = new int[2];
- glGenTextures(2, textures, 0);
-
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, textures[0]);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- mYTestureId = textures[0];
-
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, textures[1]);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
- glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
- mUVTextureId = textures[1];
-
- mGLCubeBuffer.clear();
- mGLCubeBuffer.put(CUBE).position(0);
-
- mGLTextureBuffer.clear();
- mGLTextureBuffer.put(TEXTURE_NO_ROTATION).position(0);
- }
-
- public void setUpsideDown() {
- mGLTextureBuffer.clear();
- mGLTextureBuffer.put(TEXTURE_UPSIDE_DOWN).position(0);
- }
-
- public void setUniforms(byte[] data) {
- mYBuffer.position(0);
- mYBuffer.put(data, 0, width * height);
-
- mUVBuffer.position(0);
- mUVBuffer.put(data, width * height, width * height / 2);
-
- mYBuffer.position(0);
- glActiveTexture(GL_TEXTURE0);
- glBindTexture(GL_TEXTURE_2D, mYTestureId);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height,
- 0, GL_LUMINANCE, GL_UNSIGNED_BYTE, mYBuffer);
- glUniform1i(mUniformYTextureLocation, 0);
-
- GlUtil.checkGlError("init YTexture");
-
- mUVBuffer.position(0);
- glActiveTexture(GL_TEXTURE1);
- glBindTexture(GL_TEXTURE_2D, mUVTextureId);
- glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE_ALPHA, width / 2, height / 2,
- 0, GL_LUMINANCE_ALPHA, GL_UNSIGNED_BYTE, mUVBuffer);
- glUniform1i(mUniformUVTextureLocation, 1);
-
-
- float[] matrix = new float[16];
- Matrix.setIdentityM(matrix, 0);
- int orientation = context.getResources().getConfiguration().orientation;
-
- int degrees = orientation == Configuration.ORIENTATION_LANDSCAPE ? 0 : -90;
- Matrix.rotateM(matrix, 0, degrees, 0.0f, 0.0f, 1.0f);
-
- GLES20.glUniformMatrix4fv(uMVPMatrixLocation, 1, false, matrix, 0);
-
- GlUtil.checkGlError("init UVTexture");
-
- mGLCubeBuffer.position(0);
- glVertexAttribPointer(aPositionLocation, 2, GL_FLOAT, false, 0, mGLCubeBuffer);
- glEnableVertexAttribArray(aPositionLocation);
-
- mGLTextureBuffer.position(0);
- glVertexAttribPointer(aTextureCoordinatesLocation, 2, GL_FLOAT, false, 0, mGLTextureBuffer);
- glEnableVertexAttribArray(aTextureCoordinatesLocation);
- }
-
- public void draw() {
- glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
- }
-}
diff --git a/library-vlc/src/main/java/com/yinuo/library/vlc/utils/BitmapUtil.java b/library-vlc/src/main/java/com/yinuo/library/vlc/utils/BitmapUtil.java
deleted file mode 100644
index dcd6757..0000000
--- a/library-vlc/src/main/java/com/yinuo/library/vlc/utils/BitmapUtil.java
+++ /dev/null
@@ -1,36 +0,0 @@
-package com.yinuo.library.vlc.utils;
-
-import android.graphics.Bitmap;
-import android.graphics.Canvas;
-
-public class BitmapUtil {
-
- /**
- * 把两个位图覆盖合成为一个位图,以底层位图的长宽为基准
- *
- * @param backBitmap 在底部的位图
- * @param frontBitmap 盖在上面的位图
- * @return
- */
- public static Bitmap mergeBitmap(Bitmap backBitmap, Bitmap frontBitmap) {
-
- if (backBitmap == null || backBitmap.isRecycled()
- || frontBitmap == null || frontBitmap.isRecycled()) {
- return backBitmap;
- }
- //create the new blank bitmap 创建一个新的和SRC长度宽度一样的位图
- Bitmap newbmp = Bitmap.createBitmap(backBitmap.getWidth(), backBitmap.getHeight(), Bitmap.Config.ARGB_8888);
- Canvas cv = new Canvas(newbmp);
- //draw bg into
- cv.drawBitmap(backBitmap, 0, 0, null);//在 0,0坐标开始画入bg
- //draw fg into
- cv.drawBitmap(frontBitmap, 100, 100, null);//在 0,0坐标开始画入fg ,可以从任意位置画入
- //save all clip
- cv.save();//保存
- //store
- cv.restore();//存储
- // 回收内存
- backBitmap.recycle();
- return newbmp;
- }
-}
diff --git a/library-vlc/src/main/java/com/yinuo/library/vlc/utils/LogUtils.java b/library-vlc/src/main/java/com/yinuo/library/vlc/utils/LogUtils.java
deleted file mode 100644
index f41cb6f..0000000
--- a/library-vlc/src/main/java/com/yinuo/library/vlc/utils/LogUtils.java
+++ /dev/null
@@ -1,61 +0,0 @@
-package com.yinuo.library.vlc.utils;
-
-import android.util.Log;
-
-import java.io.PrintWriter;
-import java.io.StringWriter;
-import java.io.Writer;
-
-/**
- * Created by liwentian on 17/8/16.
- */
-
-public class LogUtils {
-
- private static final String TAG = "watcher";
-
- public static void v(String msg) {
- Log.v(TAG, msg);
- }
-
- public static void v(String tag, String msg) {
- Log.v(tag, msg);
- }
-
- public static void e(String msg) {
- Log.e(TAG, msg);
- }
-
- public static void e(String tag, String msg) {
- Log.e(tag, msg);
- }
-
- public static void w(String msg) {
- Log.w(TAG, msg);
- }
-
- public static void w(String tag, String msg) {
- Log.w(tag, msg);
- }
-
- public static void e(Throwable e) {
- String s = getThrowableString(e);
- e(s);
- }
-
- private static String getThrowableString(Throwable e) {
- Writer writer = new StringWriter();
- PrintWriter printWriter = new PrintWriter(writer);
-
- while (e != null) {
- e.printStackTrace(printWriter);
- e = e.getCause();
- }
-
- String text = writer.toString();
-
- printWriter.close();
-
- return text;
- }
-}
diff --git a/library-vlc/src/main/res/raw/rect_fragment.glsl b/library-vlc/src/main/res/raw/rect_fragment.glsl
deleted file mode 100644
index d187661..0000000
--- a/library-vlc/src/main/res/raw/rect_fragment.glsl
+++ /dev/null
@@ -1,7 +0,0 @@
-precision mediump float;
-
-varying vec4 v_Color;
-
-void main() {
- gl_FragColor = v_Color;
-}
\ No newline at end of file
diff --git a/library-vlc/src/main/res/raw/rect_vertex.glsl b/library-vlc/src/main/res/raw/rect_vertex.glsl
deleted file mode 100644
index 7c5351d..0000000
--- a/library-vlc/src/main/res/raw/rect_vertex.glsl
+++ /dev/null
@@ -1,11 +0,0 @@
-attribute vec4 a_Position;
-attribute vec4 a_Color;
-
-varying vec4 v_Color;
-
-uniform mat4 u_Matrix;
-
-void main() {
- v_Color = a_Color;
- gl_Position = u_Matrix * a_Position;
-}
\ No newline at end of file
diff --git a/library-vlc/src/main/res/raw/rgb_fragment.glsl b/library-vlc/src/main/res/raw/rgb_fragment.glsl
deleted file mode 100644
index a93c350..0000000
--- a/library-vlc/src/main/res/raw/rgb_fragment.glsl
+++ /dev/null
@@ -1,15 +0,0 @@
-precision mediump float;
-
-varying vec2 v_TextureCoordinates;
-
-uniform sampler2D s_texture;
-
-void main() {
- float r, g, b;
-
- r = texture2D(s_texture, v_TextureCoordinates).r;
- g = texture2D(s_texture, v_TextureCoordinates).g;
- b = texture2D(s_texture, v_TextureCoordinates).b;
-
- gl_FragColor = vec4(r, g, b, 1.0);
-}
\ No newline at end of file
diff --git a/library-vlc/src/main/res/raw/rgb_vertex.glsl b/library-vlc/src/main/res/raw/rgb_vertex.glsl
deleted file mode 100644
index ae2f7e6..0000000
--- a/library-vlc/src/main/res/raw/rgb_vertex.glsl
+++ /dev/null
@@ -1,11 +0,0 @@
-attribute vec4 a_Position;
-attribute vec2 a_TextureCoordinates;
-
-varying vec2 v_TextureCoordinates;
-
-uniform mat4 u_Matrix;
-
-void main() {
- v_TextureCoordinates = a_TextureCoordinates;
- gl_Position = u_Matrix * a_Position;
-}
\ No newline at end of file
diff --git a/library-vlc/src/main/res/raw/tex_fragment.glsl b/library-vlc/src/main/res/raw/tex_fragment.glsl
deleted file mode 100644
index 7017493..0000000
--- a/library-vlc/src/main/res/raw/tex_fragment.glsl
+++ /dev/null
@@ -1,14 +0,0 @@
-precision mediump float;
-
-varying vec2 v_TextureCoordinates;
-
-uniform sampler2D s_texture;
-
-void main() {
- gl_FragColor = texture2D(s_texture, v_TextureCoordinates);
-
-// float r = texture2D(s_texture, v_TextureCoordinates).r;
-// float g = texture2D(s_texture, v_TextureCoordinates).g;
-// float b = texture2D(s_texture, v_TextureCoordinates).b;
-// gl_FragColor = vec4(1.0, g, b, 1.0);
-}
\ No newline at end of file
diff --git a/library-vlc/src/main/res/raw/tex_vertex.glsl b/library-vlc/src/main/res/raw/tex_vertex.glsl
deleted file mode 100644
index ee977d3..0000000
--- a/library-vlc/src/main/res/raw/tex_vertex.glsl
+++ /dev/null
@@ -1,9 +0,0 @@
-attribute vec4 a_Position;
-attribute vec2 a_TextureCoordinates;
-
-varying vec2 v_TextureCoordinates;
-
-void main() {
- v_TextureCoordinates = a_TextureCoordinates;
- gl_Position = a_Position;
-}
\ No newline at end of file
diff --git a/library-vlc/src/main/res/raw/yuv_fragment.glsl b/library-vlc/src/main/res/raw/yuv_fragment.glsl
deleted file mode 100644
index 1b54cca..0000000
--- a/library-vlc/src/main/res/raw/yuv_fragment.glsl
+++ /dev/null
@@ -1,20 +0,0 @@
-precision mediump float;
-
-varying vec2 v_TextureCoordinates;
-
-uniform sampler2D y_texture;
-uniform sampler2D uv_texture;
-
-void main() {
- float r, g, b, y, u, v;
-
- y = texture2D(y_texture, v_TextureCoordinates).r;
- u = texture2D(uv_texture, v_TextureCoordinates).a - 0.5;
- v = texture2D(uv_texture, v_TextureCoordinates).r - 0.5;
-
- r = y + 1.13983 * v;
- g = y - 0.39465 * u - 0.58060 * v;
- b = y + 2.03211 * u;
-
- gl_FragColor = vec4(r, g, b, 1.0);
-}
\ No newline at end of file
diff --git a/library-vlc/src/main/res/raw/yuv_vertex.glsl b/library-vlc/src/main/res/raw/yuv_vertex.glsl
deleted file mode 100644
index a64be6c..0000000
--- a/library-vlc/src/main/res/raw/yuv_vertex.glsl
+++ /dev/null
@@ -1,11 +0,0 @@
-attribute vec4 a_Position;
-attribute vec2 a_TextureCoordinates;
-
-uniform mat4 uMVPMatrix;
-
-varying vec2 v_TextureCoordinates;
-
-void main() {
- v_TextureCoordinates = a_TextureCoordinates;
- gl_Position = uMVPMatrix * a_Position;
-}
\ No newline at end of file
diff --git a/library-vlc/src/main/res/values/strings.xml b/library-vlc/src/main/res/values/strings.xml
deleted file mode 100644
index 8c5db9f..0000000
--- a/library-vlc/src/main/res/values/strings.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-