用jni实现基于opengl的yuv格式的视频渲染

来源:互联网 发布:udp和tcp的端口号 编辑:程序博客网 时间:2024/05/19 19:30

由于项目需要,需要在android上面实现视频流的解码显示,综合考虑决定使用ffmpeg解码,opengl渲染视频。

技术选型确定以后,开始写demo,不做不知道,一做才发现网上的东西太不靠谱了,基于jni实现的opengl不是直接渲染yuv格式的数据,都是yuv转rgb以后在显示的,有实现的资料都是在java层做的,我不是java出生,所以对那个不感冒,综合考虑之后决定自己通过jni来实现,由于以前基于webrtc开发了一款产品,用的是webrtc的c++接口开发(现在的webrtc都基于浏览器开发了,更加成熟了,接口也更加简单,^_^我觉得还是挖c++代码出来自己实现接口层有意思,我那个项目就是这样搞的),废话不多说,开始讲述实现步骤。


注意:android2.3.3版本才开始支持opengl。

写jni的时候需要在Android.mk里面加上opengl的库连接,这里我发一个我的Android.mk出来供大家参考一下:

[cpp] view plaincopy
  1. LOCAL_PATH := $(call my-dir)  
  2.   
  3. MY_LIBS_PATH := /Users/chenjianjun/Documents/work/ffmpeg-android/build/lib  
  4. MY_INCLUDE_PATH := /Users/chenjianjun/Documents/work/ffmpeg-android/build/include  
  5.   
  6.   
  7. include $(CLEAR_VARS)  
  8. LOCAL_MODULE := libavcodec  
  9. LOCAL_SRC_FILES :=  $(MY_LIBS_PATH)/libavcodec.a  
  10. include $(PREBUILT_STATIC_LIBRARY)  
  11.   
  12. include $(CLEAR_VARS)  
  13. LOCAL_MODULE := libavfilter  
  14. LOCAL_SRC_FILES :=  $(MY_LIBS_PATH)/libavfilter.a  
  15. include $(PREBUILT_STATIC_LIBRARY)  
  16.   
  17. include $(CLEAR_VARS)  
  18. LOCAL_MODULE := libavformat  
  19. LOCAL_SRC_FILES :=  $(MY_LIBS_PATH)/libavformat.a  
  20. include $(PREBUILT_STATIC_LIBRARY)  
  21.   
  22. include $(CLEAR_VARS)  
  23. LOCAL_MODULE := libavresample  
  24. LOCAL_SRC_FILES :=  $(MY_LIBS_PATH)/libavresample.a  
  25. include $(PREBUILT_STATIC_LIBRARY)  
  26.   
  27. include $(CLEAR_VARS)  
  28. LOCAL_MODULE := libavutil  
  29. LOCAL_SRC_FILES :=  $(MY_LIBS_PATH)/libavutil.a  
  30. include $(PREBUILT_STATIC_LIBRARY)  
  31.   
  32. include $(CLEAR_VARS)  
  33. LOCAL_MODULE := libpostproc  
  34. LOCAL_SRC_FILES :=  $(MY_LIBS_PATH)/libpostproc.a  
  35. include $(PREBUILT_STATIC_LIBRARY)  
  36.   
  37. include $(CLEAR_VARS)  
  38. LOCAL_MODULE := libswresample  
  39. LOCAL_SRC_FILES :=  $(MY_LIBS_PATH)/libswresample.a  
  40. include $(PREBUILT_STATIC_LIBRARY)  
  41.   
  42. include $(CLEAR_VARS)  
  43. LOCAL_MODULE := libswscale  
  44. LOCAL_SRC_FILES :=  $(MY_LIBS_PATH)/libswscale.a  
  45. include $(PREBUILT_STATIC_LIBRARY)  
  46.   
  47.   
  48. include $(CLEAR_VARS)  
  49. LOCAL_MODULE_TAGS := MICloudPub  
  50. LOCAL_MODULE := libMICloudPub  
  51.   
  52. LOCAL_SRC_FILES := H264Decoder.cpp \              #我的H264基于ffmpeg的解码接口代码  
  53.                    render_opengles20.cpp \        #opengl的渲染代码  
  54.                    test.cpp                       #测试接口代码  
  55. LOCAL_CFLAGS :=  
  56.   
  57. LOCAL_C_INCLUDES := $(MY_INCLUDE_PATH)  
  58. LOCAL_CPP_INCLUDES := $(MY_INCLUDE_PATH)  
  59.   
  60. LOCAL_LDLIBS := \  
  61.     -llog \  
  62.     -lgcc \  
  63.     <span style="font-size:32px;color:#FF0000;">-lGLESv2 \</span>  
  64.     -lz  
  65.       
  66. LOCAL_WHOLE_STATIC_LIBRARIES := \  
  67.     libavcodec \  
  68.     libavfilter \  
  69.     libavformat \  
  70.     libavresample \  
  71.     libavutil \  
  72.     libpostproc \  
  73.     libswresample \  
  74.     libswscale  
  75.   
  76. include $(BUILD_SHARED_LIBRARY)  
  77.    
上面红色的是opengl的库,我是mac电脑上面编译的,其他系统的不知道是不是叫这个名字哈(不过这么弱智的应该不会变哈).


第一步:

写java代码(主要是为了jni里面的代码回调java的代码实现,其中的妙用大家后面便知)

我把webrtc里面的代码拿出来改动了一下,就没自己去写了(不用重复造轮子)

ViEAndroidGLES20.java

[java] view plaincopy
  1. package hzcw.opengl;  
  2.   
  3. import java.util.concurrent.locks.ReentrantLock;  
  4.   
  5. import javax.microedition.khronos.egl.EGL10;  
  6. import javax.microedition.khronos.egl.EGLConfig;  
  7. import javax.microedition.khronos.egl.EGLContext;  
  8. import javax.microedition.khronos.egl.EGLDisplay;  
  9. import javax.microedition.khronos.opengles.GL10;  
  10.   
  11. import android.app.ActivityManager;  
  12. import android.content.Context;  
  13. import android.content.pm.ConfigurationInfo;  
  14. import android.graphics.PixelFormat;  
  15. import android.opengl.GLSurfaceView;  
  16. import android.util.Log;  
  17.   
  18. public class ViEAndroidGLES20 extends GLSurfaceView implements GLSurfaceView.Renderer  
  19. {  
  20.     private static String TAG = "MICloudPub";  
  21.     private static final boolean DEBUG = false;  
  22.     // True if onSurfaceCreated has been called.  
  23.     private boolean surfaceCreated = false;  
  24.     private boolean openGLCreated = false;  
  25.     // True if NativeFunctionsRegistered has been called.  
  26.     private boolean nativeFunctionsRegisted = false;  
  27.     private ReentrantLock nativeFunctionLock = new ReentrantLock();  
  28.     // Address of Native object that will do the drawing.  
  29.     private long nativeObject = 0;  
  30.     private int viewWidth = 0;  
  31.     private int viewHeight = 0;  
  32.   
  33.     public static boolean UseOpenGL2(Object renderWindow) {  
  34.         return ViEAndroidGLES20.class.isInstance(renderWindow);  
  35.     }  
  36.   
  37.     public ViEAndroidGLES20(Context context) {  
  38.         super(context);  
  39.         init(false00);  
  40.     }  
  41.   
  42.     public ViEAndroidGLES20(Context context, boolean translucent,  
  43.             int depth, int stencil) {  
  44.         super(context);  
  45.         init(translucent, depth, stencil);  
  46.     }  
  47.   
  48.     private void init(boolean translucent, int depth, int stencil) {  
  49.   
  50.         // By default, GLSurfaceView() creates a RGB_565 opaque surface.  
  51.         // If we want a translucent one, we should change the surface's  
  52.         // format here, using PixelFormat.TRANSLUCENT for GL Surfaces  
  53.         // is interpreted as any 32-bit surface with alpha by SurfaceFlinger.  
  54.         if (translucent) {  
  55.             this.getHolder().setFormat(PixelFormat.TRANSLUCENT);  
  56.         }  
  57.   
  58.         // Setup the context factory for 2.0 rendering.  
  59.         // See ContextFactory class definition below  
  60.         setEGLContextFactory(new ContextFactory());  
  61.   
  62.         // We need to choose an EGLConfig that matches the format of  
  63.         // our surface exactly. This is going to be done in our  
  64.         // custom config chooser. See ConfigChooser class definition  
  65.         // below.  
  66.         setEGLConfigChooser( translucent ?  
  67.                              new ConfigChooser(8888, depth, stencil) :  
  68.                              new ConfigChooser(5650, depth, stencil) );  
  69.   
  70.         // Set the renderer responsible for frame rendering  
  71.         this.setRenderer(this);  
  72.         this.setRenderMode(GLSurfaceView.RENDERMODE_WHEN_DIRTY);  
  73.     }  
  74.   
  75.     private static class ContextFactory implements GLSurfaceView.EGLContextFactory {  
  76.         private static int EGL_CONTEXT_CLIENT_VERSION = 0x3098;  
  77.         public EGLContext createContext(EGL10 egl, EGLDisplay display, EGLConfig eglConfig) {  
  78.             Log.w(TAG, "creating OpenGL ES 2.0 context");  
  79.             checkEglError("Before eglCreateContext", egl);  
  80.             int[] attrib_list = {EGL_CONTEXT_CLIENT_VERSION, 2, EGL10.EGL_NONE };  
  81.             EGLContext context = egl.eglCreateContext(display, eglConfig,  
  82.                     EGL10.EGL_NO_CONTEXT, attrib_list);  
  83.             checkEglError("After eglCreateContext", egl);  
  84.             return context;  
  85.         }  
  86.   
  87.         public void destroyContext(EGL10 egl, EGLDisplay display, EGLContext context) {  
  88.             egl.eglDestroyContext(display, context);  
  89.         }  
  90.     }  
  91.   
  92.     private static void checkEglError(String prompt, EGL10 egl) {  
  93.         int error;  
  94.         while ((error = egl.eglGetError()) != EGL10.EGL_SUCCESS) {  
  95.             Log.e(TAG, String.format("%s: EGL error: 0x%x", prompt, error));  
  96.         }  
  97.     }  
  98.   
  99.     private static class ConfigChooser implements GLSurfaceView.EGLConfigChooser {  
  100.   
  101.         public ConfigChooser(int r, int g, int b, int a, int depth, int stencil) {  
  102.             mRedSize = r;  
  103.             mGreenSize = g;  
  104.             mBlueSize = b;  
  105.             mAlphaSize = a;  
  106.             mDepthSize = depth;  
  107.             mStencilSize = stencil;  
  108.         }  
  109.   
  110.         // This EGL config specification is used to specify 2.0 rendering.  
  111.         // We use a minimum size of 4 bits for red/green/blue, but will  
  112.         // perform actual matching in chooseConfig() below.  
  113.         private static int EGL_OPENGL_ES2_BIT = 4;  
  114.         private static int[] s_configAttribs2 =  
  115.         {  
  116.             EGL10.EGL_RED_SIZE, 4,  
  117.             EGL10.EGL_GREEN_SIZE, 4,  
  118.             EGL10.EGL_BLUE_SIZE, 4,  
  119.             EGL10.EGL_RENDERABLE_TYPE, EGL_OPENGL_ES2_BIT,  
  120.             EGL10.EGL_NONE  
  121.         };  
  122.   
  123.         public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display) {  
  124.   
  125.             // Get the number of minimally matching EGL configurations  
  126.             int[] num_config = new int[1];  
  127.             egl.eglChooseConfig(display, s_configAttribs2, null0, num_config);  
  128.   
  129.             int numConfigs = num_config[0];  
  130.   
  131.             if (numConfigs <= 0) {  
  132.                 throw new IllegalArgumentException("No configs match configSpec");  
  133.             }  
  134.   
  135.             // Allocate then read the array of minimally matching EGL configs  
  136.             EGLConfig[] configs = new EGLConfig[numConfigs];  
  137.             egl.eglChooseConfig(display, s_configAttribs2, configs, numConfigs, num_config);  
  138.   
  139.             if (DEBUG) {  
  140.                 printConfigs(egl, display, configs);  
  141.             }  
  142.             // Now return the "best" one  
  143.             return chooseConfig(egl, display, configs);  
  144.         }  
  145.   
  146.         public EGLConfig chooseConfig(EGL10 egl, EGLDisplay display,  
  147.                 EGLConfig[] configs) {  
  148.             for(EGLConfig config : configs) {  
  149.                 int d = findConfigAttrib(egl, display, config,  
  150.                         EGL10.EGL_DEPTH_SIZE, 0);  
  151.                 int s = findConfigAttrib(egl, display, config,  
  152.                         EGL10.EGL_STENCIL_SIZE, 0);  
  153.   
  154.                 // We need at least mDepthSize and mStencilSize bits  
  155.                 if (d < mDepthSize || s < mStencilSize)  
  156.                     continue;  
  157.   
  158.                 // We want an *exact* match for red/green/blue/alpha  
  159.                 int r = findConfigAttrib(egl, display, config,  
  160.                         EGL10.EGL_RED_SIZE, 0);  
  161.                 int g = findConfigAttrib(egl, display, config,  
  162.                             EGL10.EGL_GREEN_SIZE, 0);  
  163.                 int b = findConfigAttrib(egl, display, config,  
  164.                             EGL10.EGL_BLUE_SIZE, 0);  
  165.                 int a = findConfigAttrib(egl, display, config,  
  166.                         EGL10.EGL_ALPHA_SIZE, 0);  
  167.   
  168.                 if (r == mRedSize && g == mGreenSize && b == mBlueSize && a == mAlphaSize)  
  169.                     return config;  
  170.             }  
  171.             return null;  
  172.         }  
  173.   
  174.         private int findConfigAttrib(EGL10 egl, EGLDisplay display,  
  175.                 EGLConfig config, int attribute, int defaultValue) {  
  176.   
  177.             if (egl.eglGetConfigAttrib(display, config, attribute, mValue)) {  
  178.                 return mValue[0];  
  179.             }  
  180.             return defaultValue;  
  181.         }  
  182.   
  183.         private void printConfigs(EGL10 egl, EGLDisplay display,  
  184.             EGLConfig[] configs) {  
  185.             int numConfigs = configs.length;  
  186.             Log.w(TAG, String.format("%d configurations", numConfigs));  
  187.             for (int i = 0; i < numConfigs; i++) {  
  188.                 Log.w(TAG, String.format("Configuration %d:\n", i));  
  189.                 printConfig(egl, display, configs[i]);  
  190.             }  
  191.         }  
  192.   
  193.         private void printConfig(EGL10 egl, EGLDisplay display,  
  194.                 EGLConfig config) {  
  195.             int[] attributes = {  
  196.                     EGL10.EGL_BUFFER_SIZE,  
  197.                     EGL10.EGL_ALPHA_SIZE,  
  198.                     EGL10.EGL_BLUE_SIZE,  
  199.                     EGL10.EGL_GREEN_SIZE,  
  200.                     EGL10.EGL_RED_SIZE,  
  201.                     EGL10.EGL_DEPTH_SIZE,  
  202.                     EGL10.EGL_STENCIL_SIZE,  
  203.                     EGL10.EGL_CONFIG_CAVEAT,  
  204.                     EGL10.EGL_CONFIG_ID,  
  205.                     EGL10.EGL_LEVEL,  
  206.                     EGL10.EGL_MAX_PBUFFER_HEIGHT,  
  207.                     EGL10.EGL_MAX_PBUFFER_PIXELS,  
  208.                     EGL10.EGL_MAX_PBUFFER_WIDTH,  
  209.                     EGL10.EGL_NATIVE_RENDERABLE,  
  210.                     EGL10.EGL_NATIVE_VISUAL_ID,  
  211.                     EGL10.EGL_NATIVE_VISUAL_TYPE,  
  212.                     0x3030// EGL10.EGL_PRESERVED_RESOURCES,  
  213.                     EGL10.EGL_SAMPLES,  
  214.                     EGL10.EGL_SAMPLE_BUFFERS,  
  215.                     EGL10.EGL_SURFACE_TYPE,  
  216.                     EGL10.EGL_TRANSPARENT_TYPE,  
  217.                     EGL10.EGL_TRANSPARENT_RED_VALUE,  
  218.                     EGL10.EGL_TRANSPARENT_GREEN_VALUE,  
  219.                     EGL10.EGL_TRANSPARENT_BLUE_VALUE,  
  220.                     0x3039// EGL10.EGL_BIND_TO_TEXTURE_RGB,  
  221.                     0x303A// EGL10.EGL_BIND_TO_TEXTURE_RGBA,  
  222.                     0x303B// EGL10.EGL_MIN_SWAP_INTERVAL,  
  223.                     0x303C// EGL10.EGL_MAX_SWAP_INTERVAL,  
  224.                     EGL10.EGL_LUMINANCE_SIZE,  
  225.                     EGL10.EGL_ALPHA_MASK_SIZE,  
  226.                     EGL10.EGL_COLOR_BUFFER_TYPE,  
  227.                     EGL10.EGL_RENDERABLE_TYPE,  
  228.                     0x3042 // EGL10.EGL_CONFORMANT  
  229.             };  
  230.             String[] names = {  
  231.                     "EGL_BUFFER_SIZE",  
  232.                     "EGL_ALPHA_SIZE",  
  233.                     "EGL_BLUE_SIZE",  
  234.                     "EGL_GREEN_SIZE",  
  235.                     "EGL_RED_SIZE",  
  236.                     "EGL_DEPTH_SIZE",  
  237.                     "EGL_STENCIL_SIZE",  
  238.                     "EGL_CONFIG_CAVEAT",  
  239.                     "EGL_CONFIG_ID",  
  240.                     "EGL_LEVEL",  
  241.                     "EGL_MAX_PBUFFER_HEIGHT",  
  242.                     "EGL_MAX_PBUFFER_PIXELS",  
  243.                     "EGL_MAX_PBUFFER_WIDTH",  
  244.                     "EGL_NATIVE_RENDERABLE",  
  245.                     "EGL_NATIVE_VISUAL_ID",  
  246.                     "EGL_NATIVE_VISUAL_TYPE",  
  247.                     "EGL_PRESERVED_RESOURCES",  
  248.                     "EGL_SAMPLES",  
  249.                     "EGL_SAMPLE_BUFFERS",  
  250.                     "EGL_SURFACE_TYPE",  
  251.                     "EGL_TRANSPARENT_TYPE",  
  252.                     "EGL_TRANSPARENT_RED_VALUE",  
  253.                     "EGL_TRANSPARENT_GREEN_VALUE",  
  254.                     "EGL_TRANSPARENT_BLUE_VALUE",  
  255.                     "EGL_BIND_TO_TEXTURE_RGB",  
  256.                     "EGL_BIND_TO_TEXTURE_RGBA",  
  257.                     "EGL_MIN_SWAP_INTERVAL",  
  258.                     "EGL_MAX_SWAP_INTERVAL",  
  259.                     "EGL_LUMINANCE_SIZE",  
  260.                     "EGL_ALPHA_MASK_SIZE",  
  261.                     "EGL_COLOR_BUFFER_TYPE",  
  262.                     "EGL_RENDERABLE_TYPE",  
  263.                     "EGL_CONFORMANT"  
  264.             };  
  265.             int[] value = new int[1];  
  266.             for (int i = 0; i < attributes.length; i++) {  
  267.                 int attribute = attributes[i];  
  268.                 String name = names[i];  
  269.                 if (egl.eglGetConfigAttrib(display, config, attribute, value)) {  
  270.                     Log.w(TAG, String.format("  %s: %d\n", name, value[0]));  
  271.                 } else {  
  272.                     // Log.w(TAG, String.format("  %s: failed\n", name));  
  273.                     while (egl.eglGetError() != EGL10.EGL_SUCCESS);  
  274.                 }  
  275.             }  
  276.         }  
  277.   
  278.         // Subclasses can adjust these values:  
  279.         protected int mRedSize;  
  280.         protected int mGreenSize;  
  281.         protected int mBlueSize;  
  282.         protected int mAlphaSize;  
  283.         protected int mDepthSize;  
  284.         protected int mStencilSize;  
  285.         private int[] mValue = new int[1];  
  286.     }  
  287.   
  288.     // IsSupported  
  289.     // Return true if this device support Open GL ES 2.0 rendering.  
  290.     public static boolean IsSupported(Context context) {  
  291.         ActivityManager am =  
  292.                 (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);  
  293.         ConfigurationInfo info = am.getDeviceConfigurationInfo();  
  294.         if(info.reqGlEsVersion >= 0x20000) {  
  295.             // Open GL ES 2.0 is supported.  
  296.             return true;  
  297.         }  
  298.         return false;  
  299.     }  
  300.   
  301.     public void onDrawFrame(GL10 gl) {  
  302.         nativeFunctionLock.lock();  
  303.         if(!nativeFunctionsRegisted || !surfaceCreated) {  
  304.             nativeFunctionLock.unlock();  
  305.             return;  
  306.         }  
  307.   
  308.         if(!openGLCreated) {  
  309.             if(0 != CreateOpenGLNative(nativeObject, viewWidth, viewHeight)) {  
  310.                 return// Failed to create OpenGL  
  311.             }  
  312.             openGLCreated = true// Created OpenGL successfully  
  313.         }  
  314.         DrawNative(nativeObject); // Draw the new frame  
  315.         nativeFunctionLock.unlock();  
  316.     }  
  317.   
  318.     public void onSurfaceChanged(GL10 gl, int width, int height) {  
  319.         surfaceCreated = true;  
  320.         viewWidth = width;  
  321.         viewHeight = height;  
  322.   
  323.         nativeFunctionLock.lock();  
  324.         if(nativeFunctionsRegisted) {  
  325.             if(CreateOpenGLNative(nativeObject,width,height) == 0)  
  326.                 openGLCreated = true;  
  327.         }  
  328.         nativeFunctionLock.unlock();  
  329.     }  
  330.   
  331.     public void onSurfaceCreated(GL10 gl, EGLConfig config) {  
  332.     }  
  333.   
  334.     public void RegisterNativeObject(long nativeObject) {  
  335.         nativeFunctionLock.lock();  
  336.         this.nativeObject = nativeObject;  
  337.         nativeFunctionsRegisted = true;  
  338.         nativeFunctionLock.unlock();  
  339.     }  
  340.   
  341.     public void DeRegisterNativeObject() {  
  342.         nativeFunctionLock.lock();  
  343.         nativeFunctionsRegisted = false;  
  344.         openGLCreated = false;  
  345.         this.nativeObject = 0;  
  346.         nativeFunctionLock.unlock();  
  347.     }  
  348.   
  349.     public void ReDraw() {// jni层解码以后的数据回调,然后由系统调用onDrawFrame显示  
  350.         if(surfaceCreated) {  
  351.             // Request the renderer to redraw using the render thread context.  
  352.             this.requestRender();  
  353.         }  
  354.     }  
  355.   
  356.     private native int CreateOpenGLNative(long nativeObject, int width, int height);  
  357.     private native void DrawNative(long nativeObject);  
  358. }  
ViERenderer.java
[java] view plaincopy
  1. package hzcw.opengl;  
  2.   
  3. import android.content.Context;  
  4. import android.view.SurfaceView;  
  5.   
  6. public class ViERenderer  
  7. {  
  8.     public static SurfaceView CreateRenderer(Context context) {  
  9.         return CreateRenderer(context, false);  
  10.     }  
  11.   
  12.     public static SurfaceView CreateRenderer(Context context,  
  13.             boolean useOpenGLES2) {  
  14.         if(useOpenGLES2 == true && ViEAndroidGLES20.IsSupported(context))  
  15.             return new ViEAndroidGLES20(context);  
  16.         else  
  17.             return null;  
  18.     }  
  19. }  

GL2JNILib.java (native接口代码)

[java] view plaincopy
  1. package com.example.filltriangle;  
  2.   
  3. public class GL2JNILib {    
  4.         
  5.       static {    
  6.           System.loadLibrary("MICloudPub");  
  7.       }    
  8.         
  9.      /**  
  10.       */    
  11.       public static native void init(Object glSurface);  
  12.       public static native void step(String filepath);  
  13. }  

第二步:写jni代码

com_example_filltriangle_GL2JNILib.h (javah自动生成的)

[cpp] view plaincopy
  1. /* DO NOT EDIT THIS FILE - it is machine generated */  
  2. #include <jni.h>  
  3. /* Header for class com_example_filltriangle_GL2JNILib */  
  4.   
  5. #ifndef _Included_com_example_filltriangle_GL2JNILib  
  6. #define _Included_com_example_filltriangle_GL2JNILib  
  7. #ifdef __cplusplus  
  8. extern "C" {  
  9. #endif  
  10. /* 
  11.  * Class:     com_example_filltriangle_GL2JNILib 
  12.  * Method:    init 
  13.  * Signature: (II)V 
  14.  */  
  15. JNIEXPORT void JNICALL Java_com_example_filltriangle_GL2JNILib_init  
  16.   (JNIEnv *, jclass, jobject);  
  17.   
  18. /* 
  19.  * Class:     com_example_filltriangle_GL2JNILib 
  20.  * Method:    step 
  21.  * Signature: ()V 
  22.  */  
  23. JNIEXPORT void JNICALL Java_com_example_filltriangle_GL2JNILib_step  
  24.     (JNIEnv *, jclass, jstring);  
  25.   
  26. #ifdef __cplusplus  
  27. }  
  28. #endif  
  29. #endif  

test.cpp

[cpp] view plaincopy
  1. #include <jni.h>  
  2. #include <stdlib.h>  
  3. #include <stdio.h>  
  4.   
  5. #include "render_opengles20.h"  
  6. #include "com_example_filltriangle_GL2JNILib.h"  
  7. #include "H264Decoder.h"  
  8.   
  9. class AndroidNativeOpenGl2Channel  
  10. {  
  11. public:  
  12.     AndroidNativeOpenGl2Channel(JavaVM* jvm,  
  13.                                 void* window)  
  14.     {  
  15.         _jvm = jvm;  
  16.         _ptrWindow = window;  
  17.         _buffer = (uint8_t*)malloc(1024000);  
  18.     }  
  19.       
  20.     ~AndroidNativeOpenGl2Channel()  
  21.     {  
  22.         if (_jvm)  
  23.         {  
  24.             bool isAttached = false;  
  25.             JNIEnv* env = NULL;  
  26.             if (_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {  
  27.                 // try to attach the thread and get the env  
  28.                 // Attach this thread to JVM  
  29.                 jint res = _jvm->AttachCurrentThread(&env, NULL);  
  30.                   
  31.                 // Get the JNI env for this thread  
  32.                 if ((res < 0) || !env) {  
  33.                     WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,  
  34.                                  "%s: Could not attach thread to JVM (%d, %p)",  
  35.                                  __FUNCTION__, res, env);  
  36.                     env = NULL;  
  37.                 } else {  
  38.                     isAttached = true;  
  39.                 }  
  40.             }  
  41.               
  42.             if (env && _deRegisterNativeCID) {  
  43.                 env->CallVoidMethod(_javaRenderObj, _deRegisterNativeCID);  
  44.             }  
  45.               
  46.             env->DeleteGlobalRef(_javaRenderObj);  
  47.             env->DeleteGlobalRef(_javaRenderClass);  
  48.               
  49.             if (isAttached) {  
  50.                 if (_jvm->DetachCurrentThread() < 0) {  
  51.                     WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, _id,  
  52.                                  "%s: Could not detach thread from JVM",  
  53.                                  __FUNCTION__);  
  54.                 }  
  55.             }  
  56.         }  
  57.           
  58.         free(_buffer);  
  59.     }  
  60.       
  61.     int32_t Init()  
  62.     {  
  63.         if (!_ptrWindow)  
  64.         {  
  65.             WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, _id,  
  66.                          "(%s): No window have been provided.", __FUNCTION__);  
  67.             return -1;  
  68.         }  
  69.           
  70.         if (!_jvm)  
  71.         {  
  72.             WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, _id,  
  73.                          "(%s): No JavaVM have been provided.", __FUNCTION__);  
  74.             return -1;  
  75.         }  
  76.           
  77.         // get the JNI env for this thread  
  78.         bool isAttached = false;  
  79.         JNIEnv* env = NULL;  
  80.         if (_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {  
  81.             // try to attach the thread and get the env  
  82.             // Attach this thread to JVM  
  83.             jint res = _jvm->AttachCurrentThread(&env, NULL);  
  84.               
  85.             // Get the JNI env for this thread  
  86.             if ((res < 0) || !env) {  
  87.                 WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,  
  88.                              "%s: Could not attach thread to JVM (%d, %p)",  
  89.                              __FUNCTION__, res, env);  
  90.                 return -1;  
  91.             }  
  92.             isAttached = true;  
  93.         }  
  94.           
  95.         // get the ViEAndroidGLES20 class  
  96.         jclass javaRenderClassLocal = reinterpret_cast<jclass> (env->FindClass("hzcw/opengl/ViEAndroidGLES20"));  
  97.         if (!javaRenderClassLocal) {  
  98.             WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,  
  99.                          "%s: could not find ViEAndroidGLES20", __FUNCTION__);  
  100.             return -1;  
  101.         }  
  102.           
  103.         _javaRenderClass = reinterpret_cast<jclass> (env->NewGlobalRef(javaRenderClassLocal));  
  104.         if (!_javaRenderClass) {  
  105.             WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,  
  106.                          "%s: could not create Java SurfaceHolder class reference",  
  107.                          __FUNCTION__);  
  108.             return -1;  
  109.         }  
  110.   
  111.         // Delete local class ref, we only use the global ref  
  112.         env->DeleteLocalRef(javaRenderClassLocal);  
  113.         jmethodID cidUseOpenGL = env->GetStaticMethodID(_javaRenderClass,  
  114.                                                         "UseOpenGL2",  
  115.                                                         "(Ljava/lang/Object;)Z");  
  116.         if (cidUseOpenGL == NULL) {  
  117.             WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, -1,  
  118.                          "%s: could not get UseOpenGL ID", __FUNCTION__);  
  119.             return false;  
  120.         }  
  121.         jboolean res = env->CallStaticBooleanMethod(_javaRenderClass,  
  122.                                                     cidUseOpenGL, (jobject) _ptrWindow);  
  123.           
  124.         // create a reference to the object (to tell JNI that we are referencing it  
  125.         // after this function has returned)  
  126.         _javaRenderObj = reinterpret_cast<jobject> (env->NewGlobalRef((jobject)_ptrWindow));  
  127.         if (!_javaRenderObj)  
  128.         {  
  129.             WEBRTC_TRACE(  
  130.                          kTraceError,  
  131.                          kTraceVideoRenderer,  
  132.                          _id,  
  133.                          "%s: could not create Java SurfaceRender object reference",  
  134.                          __FUNCTION__);  
  135.             return -1;  
  136.         }  
  137.           
  138.         // get the method ID for the ReDraw function  
  139.         _redrawCid = env->GetMethodID(_javaRenderClass, "ReDraw""()V");  
  140.         if (_redrawCid == NULL) {  
  141.             WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,  
  142.                          "%s: could not get ReDraw ID", __FUNCTION__);  
  143.             return -1;  
  144.         }  
  145.           
  146.         _registerNativeCID = env->GetMethodID(_javaRenderClass,  
  147.                                               "RegisterNativeObject""(J)V");  
  148.         if (_registerNativeCID == NULL) {  
  149.             WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,  
  150.                          "%s: could not get RegisterNativeObject ID", __FUNCTION__);  
  151.             return -1;  
  152.         }  
  153.           
  154.         _deRegisterNativeCID = env->GetMethodID(_javaRenderClass,  
  155.                                                 "DeRegisterNativeObject""()V");  
  156.         if (_deRegisterNativeCID == NULL) {  
  157.             WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,  
  158.                          "%s: could not get DeRegisterNativeObject ID",  
  159.                          __FUNCTION__);  
  160.             return -1;  
  161.         }  
  162.           
  163.         JNINativeMethod nativeFunctions[2] = {  
  164.             { "DrawNative",  
  165.                 "(J)V",  
  166.                 (void*) &AndroidNativeOpenGl2Channel::DrawNativeStatic, },  
  167.             { "CreateOpenGLNative",  
  168.                 "(JII)I",  
  169.                 (void*) &AndroidNativeOpenGl2Channel::CreateOpenGLNativeStatic },  
  170.         };  
  171.         if (env->RegisterNatives(_javaRenderClass, nativeFunctions, 2) == 0) {  
  172.             WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, -1,  
  173.                          "%s: Registered native functions", __FUNCTION__);  
  174.         }  
  175.         else {  
  176.             WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, -1,  
  177.                          "%s: Failed to register native functions", __FUNCTION__);  
  178.             return -1;  
  179.         }  
  180.           
  181.         env->CallVoidMethod(_javaRenderObj, _registerNativeCID, (jlong) this);  
  182.           
  183.         if (isAttached) {  
  184.             if (_jvm->DetachCurrentThread() < 0) {  
  185.                 WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, _id,  
  186.                              "%s: Could not detach thread from JVM", __FUNCTION__);  
  187.             }  
  188.         }  
  189.           
  190.         WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id, "%s done",  
  191.                      __FUNCTION__);  
  192.           
  193. //        if (_openGLRenderer.SetCoordinates(zOrder, left, top, right, bottom) != 0) {  
  194. //            return -1;  
  195. //        }  
  196.           
  197.         return 0;  
  198.     }  
  199.       
  200.     void DeliverFrame(int32_t widht, int32_t height)  
  201.     {  
  202.         if (_jvm)  
  203.         {  
  204.             bool isAttached = false;  
  205.             JNIEnv* env = NULL;  
  206.             if (_jvm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {  
  207.                 // try to attach the thread and get the env  
  208.                 // Attach this thread to JVM  
  209.                 jint res = _jvm->AttachCurrentThread(&env, NULL);  
  210.                   
  211.                 // Get the JNI env for this thread  
  212.                 if ((res < 0) || !env) {  
  213.                     WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,  
  214.                                  "%s: Could not attach thread to JVM (%d, %p)",  
  215.                                  __FUNCTION__, res, env);  
  216.                     env = NULL;  
  217.                 } else {  
  218.                     isAttached = true;  
  219.                 }  
  220.             }  
  221.               
  222.             if (env && _redrawCid)  
  223.             {  
  224.                 _widht = widht;  
  225.                 _height = height;  
  226.                   
  227.                 env->CallVoidMethod(_javaRenderObj, _redrawCid);  
  228.             }  
  229.               
  230.             if (isAttached) {  
  231.                 if (_jvm->DetachCurrentThread() < 0) {  
  232.                     WEBRTC_TRACE(kTraceWarning, kTraceVideoRenderer, _id,  
  233.                                  "%s: Could not detach thread from JVM",  
  234.                                  __FUNCTION__);  
  235.                 }  
  236.             }  
  237.         }  
  238.     }  
  239.       
  240.     void GetDataBuf(uint8_t*& pbuf, int32_t& isize)  
  241.     {  
  242.         pbuf = _buffer;  
  243.         isize = 1024000;  
  244.     }  
  245.       
  246.     static jint CreateOpenGLNativeStatic(JNIEnv * env,  
  247.                                         jobject,  
  248.                                         jlong context,  
  249.                                         jint width,  
  250.                                         jint height)  
  251.     {  
  252.         AndroidNativeOpenGl2Channel* renderChannel =  
  253.         reinterpret_cast<AndroidNativeOpenGl2Channel*> (context);  
  254.           
  255.         WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, -1, "%s:", __FUNCTION__);  
  256.           
  257.         return renderChannel->CreateOpenGLNative(width, height);  
  258.     }  
  259.       
  260.     static void DrawNativeStatic(JNIEnv * env,jobject, jlong context)  
  261.     {  
  262.         AndroidNativeOpenGl2Channel* renderChannel =  
  263.         reinterpret_cast<AndroidNativeOpenGl2Channel*>(context);  
  264.         renderChannel->DrawNative();  
  265.     }  
  266.       
  267.     jint CreateOpenGLNative(int width, int height)  
  268.     {  
  269.         return _openGLRenderer.Setup(width, height);  
  270.     }  
  271.       
  272.     void DrawNative()  
  273.     {  
  274.         _openGLRenderer.Render(_buffer, _widht, _height);  
  275.     }  
  276.       
  277. private:  
  278.     JavaVM*     _jvm;  
  279.     void* _ptrWindow;  
  280.       
  281.     jobject _javaRenderObj;  
  282.     jclass _javaRenderClass;  
  283.     JNIEnv* _javaRenderJniEnv;  
  284.       
  285.     jmethodID      _redrawCid;  
  286.     jmethodID      _registerNativeCID;  
  287.     jmethodID      _deRegisterNativeCID;  
  288.       
  289.     RenderOpenGles20 _openGLRenderer;  
  290.       
  291.     uint8_t* _buffer;  
  292.     int32_t _widht;  
  293.     int32_t _height;  
  294. };  
  295.   
  296. static JavaVM* g_jvm = NULL;  
  297. static AndroidNativeOpenGl2Channel* p_opengl_channel = NULL;  
  298.   
  299. extern "C"  
  300. {  
  301.     JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void *reserved)  
  302.     {  
  303.         JNIEnv* env = NULL;  
  304.         jint result = -1;  
  305.           
  306.         if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK)  
  307.             return -1;  
  308.           
  309.         g_jvm = vm;  
  310.           
  311.         return JNI_VERSION_1_4;  
  312.     }  
  313. }  
  314.   
  315. extern "C"  
  316. {  
  317.     int mTrans = 0x0F0F0F0F;  
  318.     int MergeBuffer(uint8_t *NalBuf, int NalBufUsed, uint8_t *SockBuf, int SockBufUsed, int SockRemain)  
  319.     {  
  320.         //把读取的数剧分割成NAL块  
  321.         int i = 0;  
  322.         char Temp;  
  323.           
  324.         for (i = 0; i < SockRemain; i++) {  
  325.             Temp = SockBuf[i + SockBufUsed];  
  326.             NalBuf[i + NalBufUsed] = Temp;  
  327.               
  328.             mTrans <<= 8;  
  329.             mTrans |= Temp;  
  330.               
  331.             if (mTrans == 1) // 找到一个开始字  
  332.             {  
  333.                 i++;  
  334.                 break;  
  335.             }  
  336.         }  
  337.           
  338.         return i;  
  339.     }  
  340.       
  341.     JNIEXPORT void JNICALL Java_com_example_filltriangle_GL2JNILib_init  
  342.     (JNIEnv *env, jclass oclass, jobject glSurface)  
  343.     {  
  344.         if (p_opengl_channel)  
  345.         {  
  346.             WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, -1, "初期化失败[%d].", __LINE__);  
  347.             return;  
  348.         }  
  349.           
  350.         p_opengl_channel = new AndroidNativeOpenGl2Channel(g_jvm, glSurface);  
  351.         if (p_opengl_channel->Init() != 0)  
  352.         {  
  353.             WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, -1, "初期化失败[%d].", __LINE__);  
  354.             return;  
  355.         }  
  356.     }  
  357.       
  358.     JNIEXPORT void JNICALL Java_com_example_filltriangle_GL2JNILib_step(JNIEnv* env, jclass tis, jstring filepath)  
  359.     {  
  360.         const char *filename = env->GetStringUTFChars(filepath, NULL);  
  361.           
  362.         WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, -1, "step[%d].", __LINE__);  
  363.           
  364.         FILE *_imgFileHandle =  fopen(filename, "rb");  
  365.         if (_imgFileHandle == NULL)  
  366.         {  
  367.             WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, -1, "File No Exist[%s][%d].", filename, __LINE__);  
  368.             return;  
  369.         }  
  370.           
  371.         H264Decoder* pMyH264 = new H264Decoder();  
  372.         X264_DECODER_H handle = pMyH264->X264Decoder_Init();  
  373.         if (handle <= 0)  
  374.         {  
  375.             WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, -1, "X264Decoder_Init Error[%d].", __LINE__);  
  376.             return;  
  377.         }  
  378.           
  379.         int iTemp = 0;  
  380.         int nalLen;  
  381.         int bytesRead = 0;  
  382.         int NalBufUsed = 0;  
  383.         int SockBufUsed = 0;  
  384.           
  385.         bool bFirst = true;  
  386.         bool bFindPPS = true;  
  387.           
  388.         uint8_t *SockBuf = (uint8_t *)malloc(204800);  
  389.         uint8_t *NalBuf = (uint8_t *)malloc(4098000);  
  390.           
  391.           
  392.         int nWidth, nHeight;  
  393.         memset(SockBuf, 0, 204800);  
  394.           
  395.         uint8_t *buffOut = NULL;  
  396.         int outSize = 0;  
  397.         p_opengl_channel->GetDataBuf(buffOut, outSize);  
  398.           
  399.           
  400.         uint8_t *IIBuf = (uint8_t *)malloc(204800);  
  401.         int IILen = 0;  
  402.           
  403.           
  404.         do {  
  405.             bytesRead = fread(SockBuf, 1, 204800, _imgFileHandle);  
  406.             WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, -1, "bytesRead  = %d", bytesRead);  
  407.             if (bytesRead <= 0) {  
  408.                 break;  
  409.             }  
  410.               
  411.             SockBufUsed = 0;  
  412.             while (bytesRead - SockBufUsed > 0) {  
  413.                 nalLen = MergeBuffer(NalBuf, NalBufUsed, SockBuf, SockBufUsed,  
  414.                                      bytesRead - SockBufUsed);  
  415.                 NalBufUsed += nalLen;  
  416.                 SockBufUsed += nalLen;  
  417.                   
  418.                 while (mTrans == 1) {  
  419.                     mTrans = 0xFFFFFFFF;  
  420.                     if (bFirst == true// the first start flag  
  421.                     {  
  422.                         bFirst = false;  
  423.                     }  
  424.                     else // a complete NAL data, include 0x00000001 trail.  
  425.                     {  
  426.                         if (bFindPPS == true// true  
  427.                         {  
  428.                             if ((NalBuf[4] & 0x1F) == 7 || (NalBuf[4] & 0x1F) == 8)  
  429.                             {  
  430.                                 bFindPPS = false;  
  431.                             }  
  432.                             else  
  433.                             {  
  434.                                 NalBuf[0] = 0;  
  435.                                 NalBuf[1] = 0;  
  436.                                 NalBuf[2] = 0;  
  437.                                 NalBuf[3] = 1;  
  438.                                   
  439.                                 NalBufUsed = 4;  
  440.                                   
  441.                                 break;  
  442.                             }  
  443.                         }  
  444.   
  445.                         if (NalBufUsed == 16 || NalBufUsed == 10 || NalBufUsed == 54 || NalBufUsed == 12 || NalBufUsed == 20) {  
  446.                             memcpy(IIBuf + IILen, NalBuf, NalBufUsed);  
  447.                             IILen += NalBufUsed;  
  448.                         }  
  449.                         else  
  450.                         {  
  451.                             memcpy(IIBuf + IILen, NalBuf, NalBufUsed);  
  452.                             IILen += NalBufUsed;  
  453.                               
  454.                             //  decode nal  
  455.                             iTemp = pMyH264->X264Decoder_Decode(handle, (uint8_t *)IIBuf,  
  456.                                                                 IILen, (uint8_t *)buffOut,  
  457.                                                                 outSize, &nWidth, &nHeight);  
  458.                             if (iTemp == 0) {  
  459.                                 WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, -1, "解码成功,宽度:%d高度:%d,解码数据长度:%d.", nWidth, nHeight, iTemp);  
  460. //                                [self.glView setVideoSize:nWidth height:nHeight];  
  461. //                                [self.glView displayYUV420pData:buffOut  
  462. //                                                          width:nWidth  
  463. //                                                         height:nHeight];  
  464.                                 p_opengl_channel->DeliverFrame(nWidth, nHeight);  
  465.                             }  
  466.                             else  
  467.                             {  
  468.                                 WEBRTC_TRACE(kTraceInfo, kTraceVideoRenderer, -1, "解码失败.");  
  469.                             }  
  470.                               
  471.                             IILen = 0;  
  472.                         }  
  473.                     }  
  474.                       
  475.                     NalBuf[0]=0;  
  476.                     NalBuf[1]=0;  
  477.                     NalBuf[2]=0;  
  478.                     NalBuf[3]=1;  
  479.                       
  480.                     NalBufUsed=4;  
  481.                 }  
  482.             }  
  483.         }while (bytesRead>0);  
  484.           
  485.           
  486.         fclose(_imgFileHandle);  
  487.         pMyH264->X264Decoder_UnInit(handle);  
  488.           
  489.         free(SockBuf);  
  490.         free(NalBuf);  
  491.         delete pMyH264;  
  492.           
  493.         env->ReleaseStringUTFChars(filepath, filename);  
  494.     }  
  495. }  

render_opengles20.cpp

[cpp] view plaincopy
  1. #include <GLES2/gl2.h>  
  2. #include <GLES2/gl2ext.h>  
  3. #include <stdio.h>  
  4. #include <stdlib.h>  
  5. #include <stdio.h>  
  6.   
  7. #include "render_opengles20.h"  
  8.   
  9.   
  10. const char RenderOpenGles20::g_indices[] = { 0, 3, 2, 0, 2, 1 };  
  11.   
  12. const char RenderOpenGles20::g_vertextShader[] = {  
  13.     "attribute vec4 aPosition;\n"  
  14.     "attribute vec2 aTextureCoord;\n"  
  15.     "varying vec2 vTextureCoord;\n"  
  16.     "void main() {\n"  
  17.     "  gl_Position = aPosition;\n"  
  18.     "  vTextureCoord = aTextureCoord;\n"  
  19.     "}\n" };  
  20.   
  21. // The fragment shader.  
  22. // Do YUV to RGB565 conversion.  
  23. const char RenderOpenGles20::g_fragmentShader[] = {  
  24.     "precision mediump float;\n"  
  25.     "uniform sampler2D Ytex;\n"  
  26.     "uniform sampler2D Utex,Vtex;\n"  
  27.     "varying vec2 vTextureCoord;\n"  
  28.     "void main(void) {\n"  
  29.     "  float nx,ny,r,g,b,y,u,v;\n"  
  30.     "  mediump vec4 txl,ux,vx;"  
  31.     "  nx=vTextureCoord[0];\n"  
  32.     "  ny=vTextureCoord[1];\n"  
  33.     "  y=texture2D(Ytex,vec2(nx,ny)).r;\n"  
  34.     "  u=texture2D(Utex,vec2(nx,ny)).r;\n"  
  35.     "  v=texture2D(Vtex,vec2(nx,ny)).r;\n"  
  36.       
  37.     //"  y = v;\n"+  
  38.     "  y=1.1643*(y-0.0625);\n"  
  39.     "  u=u-0.5;\n"  
  40.     "  v=v-0.5;\n"  
  41.       
  42.     "  r=y+1.5958*v;\n"  
  43.     "  g=y-0.39173*u-0.81290*v;\n"  
  44.     "  b=y+2.017*u;\n"  
  45.     "  gl_FragColor=vec4(r,g,b,1.0);\n"  
  46.     "}\n" };  
  47.   
  48. RenderOpenGles20::RenderOpenGles20() :  
  49. _id(0),  
  50. _textureWidth(-1),  
  51. _textureHeight(-1)  
  52. {  
  53.     WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id, "%s: id %d",  
  54.                  __FUNCTION__, (int) _id);  
  55.       
  56.     const GLfloat vertices[20] = {  
  57.         // X, Y, Z, U, V  
  58.         -1, -1, 0, 1, 0, // Bottom Left  
  59.         1, -1, 0, 0, 0, //Bottom Right  
  60.         1, 1, 0, 0, 1, //Top Right  
  61.         -1, 1, 0, 1, 1 }; //Top Left  
  62.       
  63.     memcpy(_vertices, vertices, sizeof(_vertices));  
  64. }  
  65.   
  66. RenderOpenGles20::~RenderOpenGles20() {  
  67.     glDeleteTextures(3, _textureIds);  
  68. }  
  69.   
  70. int32_t RenderOpenGles20::Setup(int32_t width, int32_t height) {  
  71.     WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id,  
  72.                  "%s: width %d, height %d", __FUNCTION__, (int) width,  
  73.                  (int) height);  
  74.       
  75.     printGLString("Version", GL_VERSION);  
  76.     printGLString("Vendor", GL_VENDOR);  
  77.     printGLString("Renderer", GL_RENDERER);  
  78.     printGLString("Extensions", GL_EXTENSIONS);  
  79.       
  80.     int maxTextureImageUnits[2];  
  81.     int maxTextureSize[2];  
  82.     glGetIntegerv(GL_MAX_TEXTURE_IMAGE_UNITS, maxTextureImageUnits);  
  83.     glGetIntegerv(GL_MAX_TEXTURE_SIZE, maxTextureSize);  
  84.       
  85.     WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id,  
  86.                  "%s: number of textures %d, size %d", __FUNCTION__,  
  87.                  (int) maxTextureImageUnits[0], (int) maxTextureSize[0]);  
  88.       
  89.     _program = createProgram(g_vertextShader, g_fragmentShader);  
  90.     if (!_program) {  
  91.         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,  
  92.                      "%s: Could not create program", __FUNCTION__);  
  93.         return -1;  
  94.     }  
  95.       
  96.     int positionHandle = glGetAttribLocation(_program, "aPosition");  
  97.     checkGlError("glGetAttribLocation aPosition");  
  98.     if (positionHandle == -1) {  
  99.         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,  
  100.                      "%s: Could not get aPosition handle", __FUNCTION__);  
  101.         return -1;  
  102.     }  
  103.       
  104.     int textureHandle = glGetAttribLocation(_program, "aTextureCoord");  
  105.     checkGlError("glGetAttribLocation aTextureCoord");  
  106.     if (textureHandle == -1) {  
  107.         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,  
  108.                      "%s: Could not get aTextureCoord handle", __FUNCTION__);  
  109.         return -1;  
  110.     }  
  111.       
  112.     // set the vertices array in the shader  
  113.     // _vertices contains 4 vertices with 5 coordinates.  
  114.     // 3 for (xyz) for the vertices and 2 for the texture  
  115.     glVertexAttribPointer(positionHandle, 3, GL_FLOAT, false,  
  116.                           5 * sizeof(GLfloat), _vertices);  
  117.     checkGlError("glVertexAttribPointer aPosition");  
  118.       
  119.     glEnableVertexAttribArray(positionHandle);  
  120.     checkGlError("glEnableVertexAttribArray positionHandle");  
  121.       
  122.     // set the texture coordinate array in the shader  
  123.     // _vertices contains 4 vertices with 5 coordinates.  
  124.     // 3 for (xyz) for the vertices and 2 for the texture  
  125.     glVertexAttribPointer(textureHandle, 2, GL_FLOAT, false, 5  
  126.                           * sizeof(GLfloat), &_vertices[3]);  
  127.     checkGlError("glVertexAttribPointer maTextureHandle");  
  128.     glEnableVertexAttribArray(textureHandle);  
  129.     checkGlError("glEnableVertexAttribArray textureHandle");  
  130.       
  131.     glUseProgram(_program);  
  132.     int i = glGetUniformLocation(_program, "Ytex");  
  133.     checkGlError("glGetUniformLocation");  
  134.     glUniform1i(i, 0); /* Bind Ytex to texture unit 0 */  
  135.     checkGlError("glUniform1i Ytex");  
  136.       
  137.     i = glGetUniformLocation(_program, "Utex");  
  138.     checkGlError("glGetUniformLocation Utex");  
  139.     glUniform1i(i, 1); /* Bind Utex to texture unit 1 */  
  140.     checkGlError("glUniform1i Utex");  
  141.       
  142.     i = glGetUniformLocation(_program, "Vtex");  
  143.     checkGlError("glGetUniformLocation");  
  144.     glUniform1i(i, 2); /* Bind Vtex to texture unit 2 */  
  145.     checkGlError("glUniform1i");  
  146.       
  147.     glViewport(0, 0, width, height);  
  148.     checkGlError("glViewport");  
  149.     return 0;  
  150. }  
  151.   
  152. // SetCoordinates  
  153. // Sets the coordinates where the stream shall be rendered.  
  154. // Values must be between 0 and 1.  
  155. int32_t RenderOpenGles20::SetCoordinates(int32_t zOrder,  
  156.                                          const float left,  
  157.                                          const float top,  
  158.                                          const float right,  
  159.                                          const float bottom) {  
  160.     if ((top > 1 || top < 0) || (right > 1 || right < 0) ||  
  161.         (bottom > 1 || bottom < 0) || (left > 1 || left < 0)) {  
  162.         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,  
  163.                      "%s: Wrong coordinates", __FUNCTION__);  
  164.         return -1;  
  165.     }  
  166.       
  167.     //  X, Y, Z, U, V  
  168.     // -1, -1, 0, 0, 1, // Bottom Left  
  169.     //  1, -1, 0, 1, 1, //Bottom Right  
  170.     //  1,  1, 0, 1, 0, //Top Right  
  171.     // -1,  1, 0, 0, 0  //Top Left  
  172.       
  173.     // Bottom Left  
  174.     _vertices[0] = (left * 2) - 1;  
  175.     _vertices[1] = -1 * (2 * bottom) + 1;  
  176.     _vertices[2] = zOrder;  
  177.       
  178.     //Bottom Right  
  179.     _vertices[5] = (right * 2) - 1;  
  180.     _vertices[6] = -1 * (2 * bottom) + 1;  
  181.     _vertices[7] = zOrder;  
  182.       
  183.     //Top Right  
  184.     _vertices[10] = (right * 2) - 1;  
  185.     _vertices[11] = -1 * (2 * top) + 1;  
  186.     _vertices[12] = zOrder;  
  187.       
  188.     //Top Left  
  189.     _vertices[15] = (left * 2) - 1;  
  190.     _vertices[16] = -1 * (2 * top) + 1;  
  191.     _vertices[17] = zOrder;  
  192.       
  193.     return 0;  
  194. }  
  195.   
  196. GLuint RenderOpenGles20::loadShader(GLenum shaderType, const char* pSource)  
  197. {  
  198.     GLuint shader = glCreateShader(shaderType);  
  199.     if (shader) {  
  200.         glShaderSource(shader, 1, &pSource, NULL);  
  201.         glCompileShader(shader);  
  202.         GLint compiled = 0;  
  203.         glGetShaderiv(shader, GL_COMPILE_STATUS, &compiled);  
  204.         if (!compiled) {  
  205.             GLint infoLen = 0;  
  206.             glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &infoLen);  
  207.             if (infoLen) {  
  208.                 char* buf = (char*) malloc(infoLen);  
  209.                 if (buf) {  
  210.                     glGetShaderInfoLog(shader, infoLen, NULL, buf);  
  211.                     WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,  
  212.                                  "%s: Could not compile shader %d: %s",  
  213.                                  __FUNCTION__, shaderType, buf);  
  214.                     free(buf);  
  215.                 }  
  216.                 glDeleteShader(shader);  
  217.                 shader = 0;  
  218.             }  
  219.         }  
  220.     }  
  221.     return shader;  
  222. }  
  223.   
  224. GLuint RenderOpenGles20::createProgram(const char* pVertexSource,  
  225.                                        const char* pFragmentSource) {  
  226.     GLuint vertexShader = loadShader(GL_VERTEX_SHADER, pVertexSource);  
  227.     if (!vertexShader) {  
  228.         return 0;  
  229.     }  
  230.       
  231.     GLuint pixelShader = loadShader(GL_FRAGMENT_SHADER, pFragmentSource);  
  232.     if (!pixelShader) {  
  233.         return 0;  
  234.     }  
  235.       
  236.     GLuint program = glCreateProgram();  
  237.     if (program) {  
  238.         glAttachShader(program, vertexShader);  
  239.         checkGlError("glAttachShader");  
  240.         glAttachShader(program, pixelShader);  
  241.         checkGlError("glAttachShader");  
  242.         glLinkProgram(program);  
  243.         GLint linkStatus = GL_FALSE;  
  244.         glGetProgramiv(program, GL_LINK_STATUS, &linkStatus);  
  245.         if (linkStatus != GL_TRUE) {  
  246.             GLint bufLength = 0;  
  247.             glGetProgramiv(program, GL_INFO_LOG_LENGTH, &bufLength);  
  248.             if (bufLength) {  
  249.                 char* buf = (char*) malloc(bufLength);  
  250.                 if (buf) {  
  251.                     glGetProgramInfoLog(program, bufLength, NULL, buf);  
  252.                     WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,  
  253.                                  "%s: Could not link program: %s",  
  254.                                  __FUNCTION__, buf);  
  255.                     free(buf);  
  256.                 }  
  257.             }  
  258.             glDeleteProgram(program);  
  259.             program = 0;  
  260.         }  
  261.     }  
  262.     return program;  
  263. }  
  264.   
  265. void RenderOpenGles20::printGLString(const char *name, GLenum s) {  
  266.     const char *v = (const char *) glGetString(s);  
  267.     WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id, "GL %s = %s\n",  
  268.                  name, v);  
  269. }  
  270.   
  271. void RenderOpenGles20::checkGlError(const char* op) {  
  272. #ifdef ANDROID_LOG  
  273.     for (GLint error = glGetError(); error; error = glGetError()) {  
  274.         WEBRTC_TRACE(kTraceError, kTraceVideoRenderer, _id,  
  275.                      "after %s() glError (0x%x)\n", op, error);  
  276.     }  
  277. #else  
  278.     return;  
  279. #endif  
  280. }  
  281.   
  282. static void InitializeTexture(int name, int id, int width, int height) {  
  283.     glActiveTexture(name);  
  284.     glBindTexture(GL_TEXTURE_2D, id);  
  285.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);  
  286.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);  
  287.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);  
  288.     glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);  
  289.     glTexImage2D(GL_TEXTURE_2D, 0, GL_LUMINANCE, width, height, 0,  
  290.                  GL_LUMINANCE, GL_UNSIGNED_BYTE, NULL);  
  291. }  
  292.   
  293. // Uploads a plane of pixel data, accounting for stride != width*bpp.  
  294. static void GlTexSubImage2D(GLsizei width, GLsizei height, int stride,  
  295.                             const uint8_t* plane) {  
  296.     if (stride == width) {  
  297.         // Yay!  We can upload the entire plane in a single GL call.  
  298.         glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, width, height, GL_LUMINANCE,  
  299.                         GL_UNSIGNED_BYTE,  
  300.                         static_cast<const GLvoid*>(plane));  
  301.     } else {  
  302.         // Boo!  Since GLES2 doesn't have GL_UNPACK_ROW_LENGTH and Android doesn't  
  303.         // have GL_EXT_unpack_subimage we have to upload a row at a time.  Ick.  
  304.         for (int row = 0; row < height; ++row) {  
  305.             glTexSubImage2D(GL_TEXTURE_2D, 0, 0, row, width, 1, GL_LUMINANCE,  
  306.                             GL_UNSIGNED_BYTE,  
  307.                             static_cast<const GLvoid*>(plane + (row * stride)));  
  308.         }  
  309.     }  
  310. }  
  311.   
  312. int32_t RenderOpenGles20::Render(void * data, int32_t widht, int32_t height)  
  313. {  
  314.     WEBRTC_TRACE(kTraceDebug, kTraceVideoRenderer, _id, "%s: id %d",  
  315.                  __FUNCTION__, (int) _id);  
  316.       
  317.     glUseProgram(_program);  
  318.     checkGlError("glUseProgram");  
  319.       
  320.     if (_textureWidth != (GLsizei) widht || _textureHeight != (GLsizei) height) {  
  321.         SetupTextures(widht, height);  
  322.     }  
  323.     UpdateTextures(data, widht, height);  
  324.       
  325.     glDrawElements(GL_TRIANGLES, 6, GL_UNSIGNED_BYTE, g_indices);  
  326.     checkGlError("glDrawArrays");  
  327.       
  328.     return 0;  
  329. }  
  330.   
  331. void RenderOpenGles20::SetupTextures(int32_t width, int32_t height)  
  332. {  
  333.     glDeleteTextures(3, _textureIds);  
  334.     glGenTextures(3, _textureIds); //Generate  the Y, U and V texture  
  335.     InitializeTexture(GL_TEXTURE0, _textureIds[0], width, height);  
  336.     InitializeTexture(GL_TEXTURE1, _textureIds[1], width / 2, height / 2);  
  337.     InitializeTexture(GL_TEXTURE2, _textureIds[2], width / 2, height / 2);  
  338.       
  339.     checkGlError("SetupTextures");  
  340.       
  341.     _textureWidth = width;  
  342.     _textureHeight = height;  
  343. }  
  344.   
  345. void RenderOpenGles20::UpdateTextures(void* data, int32_t widht, int32_t height)  
  346. {  
  347.     glActiveTexture(GL_TEXTURE0);  
  348.     glBindTexture(GL_TEXTURE_2D, _textureIds[0]);  
  349.     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, widht, height, GL_LUMINANCE, GL_UNSIGNED_BYTE,  
  350.                     data);  
  351.       
  352.     glActiveTexture(GL_TEXTURE1);  
  353.     glBindTexture(GL_TEXTURE_2D, _textureIds[1]);  
  354.     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, widht / 2, height / 2, GL_LUMINANCE,  
  355.                     GL_UNSIGNED_BYTE, (char *)data + widht * height);  
  356.       
  357.     glActiveTexture(GL_TEXTURE2);  
  358.     glBindTexture(GL_TEXTURE_2D, _textureIds[2]);  
  359.     glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, widht / 2, height / 2, GL_LUMINANCE,  
  360.                     GL_UNSIGNED_BYTE, (char *)data + widht * height * 5 / 4);  
  361.       
  362.     checkGlError("UpdateTextures");  
  363. }  

H264Decoder.cpp (解码代码,前面的博客贴过代码,这里就不贴了)


第三步:编译jni,生成so文件

第四步:把生成的so文件拷贝到android工程里面去,这里贴一下我的Activity代码,如下:

[java] view plaincopy
  1. package com.example.filltriangle;  
  2.   
  3. import java.io.IOException;  
  4. import java.io.InputStream;  
  5.   
  6. import hzcw.opengl.ViERenderer;  
  7. import android.app.Activity;    
  8. import android.os.Bundle;     
  9. import android.os.Environment;  
  10. import android.util.Log;  
  11. import android.view.SurfaceView;  
  12.     
  13. public class FillTriangle extends Activity {    
  14.     
  15.     private SurfaceView mView = null;  
  16.       
  17.     static {    
  18.           System.loadLibrary("MICloudPub");  
  19.     }  
  20.     
  21.     @Override protected void onCreate(Bundle icicle) {    
  22.         super.onCreate(icicle);    
  23.         mView = ViERenderer.CreateRenderer(thistrue);  
  24.         if (mView == null) {  
  25.             Log.i("test""mView is null");  
  26.         }  
  27.         setContentView(mView);  
  28.           
  29.         GL2JNILib.init(mView);  
  30.           
  31.         new MyThread().start();  
  32.     }  
  33.       
  34.       
  35.       
  36.     public class MyThread extends Thread {    
  37.         public void run() {  
  38.             GL2JNILib.step("/sdcard/test.264");  
  39.         }    
  40.     }  
  41. }  

这个demo就是读一个视频文件,解码以后在界面显示出来。便于运行,最后上效果图哈,免得有人怀疑项目真实性。



这里打一个小广告,希望大家支持一下:

1.寻找android开发团队或者个人,有兴趣一起创业的朋友,(最好是成都本地的朋友,也欢迎有激情的应届毕业生加入)联系QQ:276775937。

2.承接ios,android应用系统开发,我们有很多成熟的案例。


原文:http://blog.csdn.net/cjj198561/article/details/34136187

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 寻常疣液氮冷冻后该怎么办 寻常疣冷冻后起水泡胀痛怎么办 冷冻后大水泡痒怎么办 19岁的宫颈糜烂怎么办 发面酸了没有碱怎么办 面发时间长酸了怎么办 丽珠兰打完红肿怎么办 美的冰柜冷藏室结冰怎么办 胃下午和晚上痛怎么办 二胡弓毛粗拉外弦触到里弦怎么办 电视成黑白的了怎么办 城市居民无钱入社保医保怎么办 老婆说离婚又找不到怎么办 爱一个人太累了怎么办 车凹陷漏底漆了怎么办 燕子窝掉下来了怎么办 文科没考上一本怎么办 学校午休小学孩子吵闹怎么办 老鼠死在空调里怎么办 公务员老公四十岁想辞职怎么办 打胎5次又怀孕怎么办 墙纸颜色太淡了怎么办 皮子腺囊肿有点疼痛怎么办 地板颜色选浅了怎么办 地板买的太暗了怎么办 木地板贴好后发现颜色不好看怎么办 鞋上鞋扣老是开怎么办 虚拟机的win10蓝屏重启怎么办 fs免拆模板专利怎么办 新买的床咯吱响怎么办 实木床一动就响怎么办 cad图纸是斜的怎么办 老房子土墙腻子老掉怎么办 生完孩子子宫大怎么办 刚开的店没人怎么办 刚开业的店没人怎么办 美容店没人进店怎么办 新店开业招不到营业员怎么办 无意开通了花呗怎么办? 花呗灰色用不了怎么办 花呗逾期用不了怎么办