当前位置:网站首页>NDK learning notes (14) create an avi video player using avilib+window

NDK learning notes (14) create an avi video player using avilib+window

2022-06-11 05:34:00 Come and go

1.window api

(1) from surface Object window

 from surface Retrieve objects from window
ANativeWindow* ANativeWindow_fromSurface(JNIEnv* env, jobject surface);

(2) Get native window Application in the example

void ANativeWindow_acquire(ANativeWindow* window);

(3) Release native window quote

void ANativeWindow_release(ANativeWindow* window);

(4) Retrieve native window Information

 Width 
int32_t ANativeWindow_getWidth(ANativeWindow* window);
 Width 
int32_t ANativeWindow_getHeight(ANativeWindow* window);
 Pixel format 
int32_t ANativeWindow_getFormat(ANativeWindow* window);

(5) Set native window Buffer Geometry

int32_t ANativeWindow_setBuffersGeometry(ANativeWindow* window,
        int32_t width, int32_t height, int32_t format);

(6) Access native window buffer

int32_t ANativeWindow_lock(ANativeWindow* window, ANativeWindow_Buffer* outBuffer,
        ARect* inOutDirtyBounds);

(7) Release native window buffer

int32_t ANativeWindow_unlockAndPost(ANativeWindow* window);

2. Main code

java

public class NativeWindowPlayerActivity extends AbstractPlayerActivity {
    

    private final AtomicBoolean isPlaying = new AtomicBoolean();

    private SurfaceHolder surfaceHolder;
    SurfaceView surfaceView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
    
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_native_window_player);

        surfaceView = findViewById(R.id.surface_view);

        surfaceHolder = surfaceView.getHolder();
        surfaceHolder.addCallback(callback);
    }

    @Override
    protected void onStart() {
    
        super.onStart();

        int w = getWidth(avi);
        int h = getHeight(avi);

        // Set up surfaceView Band size of , Prevent autofill 
        ViewGroup.LayoutParams viewGroup = surfaceView.getLayoutParams();
        viewGroup.width = w;
        viewGroup.height = h;

        surfaceView.setX(50);
        surfaceView.setY(50);

    }

    private final SurfaceHolder.Callback callback = new SurfaceHolder.Callback2() {
    
        @Override
        public void surfaceRedrawNeeded(SurfaceHolder holder) {
    

        }

        @Override
        public void surfaceCreated(SurfaceHolder holder) {
    

            isPlaying.set(true);
        }

        @Override
        public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
    

            isPlaying.set(true);
            new Thread(renderer).start();
        }

        @Override
        public void surfaceDestroyed(SurfaceHolder holder) {
    

            isPlaying.set(false);
        }
    };


    private Runnable renderer = new Runnable() {
    
        @Override
        public void run() {
    

            Surface surface = surfaceHolder.getSurface();

            init(avi, surface);

            long frameDelay = (long) (1000 / getFrameRate(avi));

            while (isPlaying.get()) {
    

                render(avi, surface);

                try {
    

                    Thread.sleep(frameDelay);
                } catch (InterruptedException e) {
    

                    break;
                }

            }
        }
    };


    /** *  Initialize native window * * @param avi * @param surface */
    private native static void init(long avi, Surface surface);

    /** *  Rendering  * @param avi * @param surface * @return */
    private native static boolean render(long avi, Surface surface);
}

Native code

#include "cn_study_aviplayer_NativeWindowPlayerActivity.h"

extern "C" {
    
#include "avilib/avilib.h"
}

#include <android/native_window.h>
#include <android/native_window_jni.h>
#include "Common.h"


extern "C"
JNIEXPORT void JNICALL
Java_cn_study_aviplayer_NativeWindowPlayerActivity_init(JNIEnv *env, jclass clazz, jlong avi,
                                                        jobject surface) {
    

    // from surface Get native from window
    ANativeWindow *nativeWindow = ANativeWindow_fromSurface(env, surface);
    if (0 == nativeWindow) {
    

        ThrowException(env, "java/io/RuntimeException", " Can't all get window");
        goto exit;
    }
    // Set up buffer The size is avi Resolution of video frames 
    // If and window The physical size of is inconsistent 
    //buffer Will be scaled to match this size 
    if (0 > ANativeWindow_setBuffersGeometry(nativeWindow, AVI_video_width((avi_t *) avi),
                                             AVI_video_height((avi_t *) avi),
                                             WINDOW_FORMAT_RGB_565)) {
    

        ThrowException(env, "java/io/RuntimeException", " Cannot set buffers");
        nativeWindow = 0;
    }

    exit:
    return;

}


extern "C"
JNIEXPORT jboolean JNICALL
Java_cn_study_aviplayer_NativeWindowPlayerActivity_render(JNIEnv *env, jclass clazz, jlong avi,
                                                          jobject surface) {
    

    jboolean isFrameRead = JNI_FALSE;

    long frameSize = 0;
    int keyFrame = 0;

    ANativeWindow *nativeWindow = ANativeWindow_fromSurface(env, surface);
    if (0 == nativeWindow) {
    
        ThrowException(env, "java/io/RuntimeException", " Can't get window");
        goto exit;
    }

    // Lock native window And access the original buffer
    ANativeWindow_Buffer windowBuffer;
    if (0 > ANativeWindow_lock(nativeWindow, &windowBuffer, 0)) {
    

        ThrowException(env, "java/io/RuntimeException", " Cannot be locked window");
        goto release;
    }
    // take avi The bit stream of the frame is read to the original buffer 
    frameSize = AVI_read_frame((avi_t *) avi, (char *) windowBuffer.bits, &keyFrame);

    // Whether the reading is successful 
    if (0 < frameSize) {
    

        isFrameRead = JNI_TRUE;
    }

    // Unlock and output buffer to display 
    if (0 > ANativeWindow_unlockAndPost(nativeWindow)) {
    

        ThrowException(env, "java/io/RuntimeException", " Cannot unlock window");
        goto release;
    }

    release:
    ANativeWindow_release(nativeWindow);
    nativeWindow = 0;
    exit:
    return isFrameRead;

}

To configure cmake
jnigraphics And android There will be conflict , So the prefix is added -l.

cmake_minimum_required(VERSION 3.4.1)


add_library( # Sets the name of the library.
        native-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        native-lib.cpp
        Common.cpp
        cn_study_aviplayer_BitmapPlayerActivity.cpp
        cn_study_aviplayer_OpenGLPlayerActivity.cpp
        cn_study_aviplayer_NativeWindowPlayerActivity.cpp)
# Add subdirectories 
add_subdirectory(avilib)


find_library( # Sets the name of the path variable.
        log-lib

        # Specifies the name of the NDK library that
        # you want CMake to locate.
        log)

find_library(
        GLESv2-lib
        -lGLESv2)

find_library(
        android-lib
        -landroid)


target_link_libraries( # Specifies the target library.
        native-lib
        # Links the target library to the log library
        # included in the NDK.

        -ljnigraphics# Turn on jnigraphics
        ${
    android-lib}# Use window
        ${
    log-lib}
        ${
    GLESv2-lib}
        avi-lib)

3. Realization effect

 Insert picture description here

原网站

版权声明
本文为[Come and go]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/03/202203020538239313.html