当前位置:网站首页>NDK learning notes (12) native graphics API, using avilib to create an avi video player
NDK learning notes (12) native graphics API, using avilib to create an avi video player
2022-06-11 05:34:00 【Come and go】
List of articles
1. Practice hands , Use AVILib Create a AVI Video player
(1) First download transcode, And configuration avilib.
http://www.linuxfromscratch.org/blfs/view/svn/multimedia/transcode.html
take transcode Medium avilib Copy files to project .

edit platform.h file
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
stay avilib establish CMakeLists.txt
add_library( # Sets the name of the library.
avi-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
avilib.c
platform_posix.c)
(2) establish AbstractPlayerActivity And implement native Method
Extract the shared code and abstract it into a class
public abstract class AbstractPlayerActivity extends Activity {
public static final String EXTRA_FILE_NAME = "cn.study.aviplayer.EXTRA_FILE_NAME";
protected long avi = 0;
@Override
protected void onStart() {
super.onStart();
try {
avi = open(getFileName());
} catch (IOException e) {
new AlertDialog.Builder(this)
.setTitle(" Error message ")
.setMessage(e.getMessage())
.show();
}
}
@Override
protected void onStop() {
super.onStop();
if (0 != avi) {
close(avi);
avi = 0;
}
}
protected String getFileName() {
return getIntent().getExtras().getString(EXTRA_FILE_NAME);
}
/** * Open the specified avi file * * @return */
protected native static long open(String fileName) throws IOException;
/** * Get the video width * * @param avi * @return */
protected native static int getWidth(long avi);
/** * Get video height * * @param avi * @return */
protected native static int getHeight(long avi);
/** * Get frame rate * * @param avi * @return */
protected native static double getFrameRate(long avi);
/** * Closes the specified based on the given file descriptor avi file * * @param avi */
protected native static void close(long avi);
}
Use javah To generate .h file .
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class cn_study_aviplayer_AbstractPlayerActivity */
#ifndef _Included_cn_study_aviplayer_AbstractPlayerActivity
#define _Included_cn_study_aviplayer_AbstractPlayerActivity
#ifdef __cplusplus
extern "C" {
#endif
/* * Class: cn_study_aviplayer_AbstractPlayerActivity * Method: open * Signature: (Ljava/lang/String;)J */
JNIEXPORT jlong JNICALL Java_cn_study_aviplayer_AbstractPlayerActivity_open
(JNIEnv *, jclass, jstring);
/* * Class: cn_study_aviplayer_AbstractPlayerActivity * Method: getWidth * Signature: (J)I */
JNIEXPORT jint JNICALL Java_cn_study_aviplayer_AbstractPlayerActivity_getWidth
(JNIEnv *, jclass, jlong);
/* * Class: cn_study_aviplayer_AbstractPlayerActivity * Method: getHeight * Signature: (J)I */
JNIEXPORT jint JNICALL Java_cn_study_aviplayer_AbstractPlayerActivity_getHeight
(JNIEnv *, jclass, jlong);
/* * Class: cn_study_aviplayer_AbstractPlayerActivity * Method: getFrameRate * Signature: (J)D */
JNIEXPORT jdouble JNICALL Java_cn_study_aviplayer_AbstractPlayerActivity_getFrameRate
(JNIEnv *, jclass, jlong);
/* * Class: cn_study_aviplayer_AbstractPlayerActivity * Method: close * Signature: (J)V */
JNIEXPORT void JNICALL Java_cn_study_aviplayer_AbstractPlayerActivity_close
(JNIEnv *, jclass, jlong);
#ifdef __cplusplus
}
#endif
#endif
stay native-lib.cpp Import avilib.h need .
extern "C" {
#include "avilib/avilib.h"
}
native-lib.cpp
#include <jni.h>
#include <string>
#include "cn_study_aviplayer_AbstractPlayerActivity.h"
#include "Common.h"
#include <android/bitmap.h>
extern "C" {
#include "avilib/avilib.h"
}
extern "C" JNIEXPORT jstring JNICALL
Java_cn_study_aviplayer_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C"
JNIEXPORT jlong JNICALL
Java_cn_study_aviplayer_AbstractPlayerActivity_open(JNIEnv *env, jclass clazz, jstring file_name) {
avi_t *avi = 0;
// Get the file name and convert it to a string variable
const char *cFileName = env->GetStringUTFChars(file_name, 0);
if (0 == cFileName) {
goto exit;
}
avi = AVI_open_input_file(cFileName, 1);
env->ReleaseStringUTFChars(file_name, cFileName);
if (0 == avi) {
ThrowException(env, "java/io/IOException", AVI_strerror());
}
exit:
return (jlong) avi;
}
extern "C"
JNIEXPORT jint JNICALL
Java_cn_study_aviplayer_AbstractPlayerActivity_getWidth(JNIEnv *env, jclass clazz, jlong avi) {
return AVI_video_width((avi_t *) avi);
}
extern "C"
JNIEXPORT jint JNICALL
Java_cn_study_aviplayer_AbstractPlayerActivity_getHeight(JNIEnv *env, jclass clazz, jlong avi) {
return AVI_video_height((avi_t *) avi);
}
extern "C"
JNIEXPORT jdouble JNICALL
Java_cn_study_aviplayer_AbstractPlayerActivity_getFrameRate(JNIEnv *env, jclass clazz, jlong avi) {
return AVI_frame_rate((avi_t *) avi);
}
extern "C"
JNIEXPORT void JNICALL
Java_cn_study_aviplayer_AbstractPlayerActivity_close(JNIEnv *env, jclass clazz, jlong avi) {
AVI_close((avi_t *) avi);
}
(3) To configure native-lib, Turn on jnigraphics, Connect avi-lib
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)
# 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( # Sets the name of the path variable.
jnigraphics-lib
jnigraphics)
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${
jnigraphics-lib}# Turn on jnigraphics
${
log-lib}
avi-lib)
(4)jni graphics api
retrieval bitmap Object information , Such as size 、 Pixel format . Successfully returns 0, Failure returns a negative number .
int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,AndroidBitmapInfo* info);
Access the native pixel cache , Lock the pixel cache to ensure that the pixel's memory does not move .
Successfully returns 0, Failure returns a negative number .
int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr);
Free the native pixel cache
Successfully returns 0, Failure returns a negative number
int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap);
(5) Use bitmap Render to update avi player
public class BitmapPlayerActivity extends AbstractPlayerActivity {
private final AtomicBoolean isPlaying = new AtomicBoolean();
private SurfaceHolder surfaceHolder;
private SurfaceView surfaceView;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_bitmap_player);
surfaceView = findViewById(R.id.surface_view);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(shCallback);
}
private final SurfaceHolder.Callback shCallback = new SurfaceHolder.Callback2() {
@Override
public void surfaceRedrawNeeded(SurfaceHolder holder) {
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
isPlaying.set(true);
new Thread(renderer).start();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
isPlaying.set(false);
}
};
private final Runnable renderer = new Runnable() {
@Override
public void run() {
Paint paint = new Paint();
paint.setAntiAlias(true);
paint.setColor(Color.BLACK);
paint.setStyle(Paint.Style.FILL);
int width = getWidth(avi);
int height = getHeight(avi);
Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.RGB_565);
float sx = 2.0f;
float sy = 2.0f;
Matrix matrix = new Matrix();
matrix.postScale(sx, sy);
int vWidth = (int) (width * sx);
int vHeight = (int) (height * sy);
int x = (1080 - vWidth) / 2;
int y = (1920 - vHeight) / 2;
matrix.postTranslate(x, y);
// Delay
long frameDelay = (long) (1000 / getFrameRate(avi));
while (isPlaying.get()) {
render(avi, bitmap);
Canvas canvas = surfaceHolder.lockCanvas();
canvas.drawBitmap(bitmap, matrix, null);
surfaceHolder.unlockCanvasAndPost(canvas);
// Wait for the next stitch
try {
Thread.sleep(frameDelay);
} catch (InterruptedException e) {
break;
}
}
}
};
/** * from avi The file descriptor is output to the specified bitmap To render frames * * @param avi * @param bitmap * @return */
private native static boolean render(long avi, Bitmap bitmap);
}
cn_study_aviplayer_BitmapPlayerActivity.cpp
#include "Common.h"
#include "cn_study_aviplayer_BitmapPlayerActivity.h"
extern "C" {
#include "avilib/avilib.h"
}
#include <android/bitmap.h>
extern "C"
JNIEXPORT jboolean JNICALL
Java_cn_study_aviplayer_BitmapPlayerActivity_render(JNIEnv *env, jclass clazz, jlong avi,
jobject bitmap) {
jboolean isFrameRead = JNI_FALSE;
char *frameBuffer = 0;
long frameSize = 0;
int keyFrame = 0;
if (0 > AndroidBitmap_lockPixels(env, bitmap, (void **) &frameBuffer)) {
ThrowException(env, "java/io/IOException", " Cannot lock pixels ");
goto exit;
}
// take avi frame byte Read bitmap in
frameSize = AVI_read_frame((avi_t *) avi, frameBuffer, &keyFrame);
// Unlock
if (0 > AndroidBitmap_unlockPixels(env, bitmap)) {
ThrowException(env, "java/io/IOException", " Cannot unlock pixels ");
goto exit;
}
// Whether the reading is successful
if (0 < frameSize) {
isFrameRead = JNI_TRUE;
}
exit:
return isFrameRead;
}
Want to use this avi player , The video file format must be avi Format , I hope the video load is through RGB565 The uncompressed original frame of color space .
Put the video in the specified directory , The operation effect is as follows :
Detailed code and video files
https://gitee.com/xd_box/AviPlayer
2.android studio To configure javah
file>Setting>Tools>External Tools Click on + Number .
program:$JDKPath$\bin\javah.exe
arguments:-classpath . -jni -d $ModuleFileDir$\src\main\cpp $FileClass$
working directory:$ModuleFileDir$\src\main\java

边栏推荐
- Deep learning distributed training
- ReferenceError: server is not defined
- 使用acme.sh自动申请免费SSL证书
- Tencent X5 kernel initialization failed tbsreaderview not support by:***
- SQLite installation and configuration tutorial +navicat operation
- Multi thread tutorial (30) meta sharing mode
- 【入门级基础】Node基础知识总结
- Get the full link address of the current project request URL
- Big meal count (time complexity) -- leetcode daily question
- mysql字符串转数组,合并结果集,转成数组
猜你喜欢

mysql字符串转数组,合并结果集,转成数组

Tightly coupled laser vision inertial navigation slam system: paper notes_ S2D. 66_ ICRA_ 2021_ LVI-SAM

How to make lamps intelligent? How to choose single fire and zero fire intelligent switches!

初步了解多任务学习

Recherche sur l'optimisation de Spark SQL basée sur CBO pour kangourou Cloud Stack

SQLite installation and configuration tutorial +navicat operation

Start the project using the locally configured gradle

Wechat applet text built-in component newline character does not newline reason

Multithreading tutorial (XXI) double checked locking problem

getBackgroundAudioManager控制音乐播放(类名的动态绑定)
随机推荐
If the MAC fails to connect with MySQL, it will start and report an error
[go deep into kotlin] - get to know flow for the first time
袋鼠雲數棧基於CBO在Spark SQL優化上的探索
Multi threading tutorial (XXIV) cas+volatile
Analysis while experiment - a little optimization of memory leakage in kotlin
自定义View基础之Layout
Zed2 camera calibration -- binocular, IMU, joint calibration
PageHelper page 2 collections in the same interface
22、生成括号
How much current can PCB wiring carry
Section I: classification and classification of urban roads
Section III: structural characteristics of cement concrete pavement
Preliminary test of running vins-fusion with zed2 binocular camera
Big meal count (time complexity) -- leetcode daily question
Multi thread tutorial (30) meta sharing mode
Manually splicing dynamic JSON strings
1. use alicloud object OSS (basic)
Combien de courant le câblage des PCB peut - il supporter?
Activity start process record
Flask develops and implements the like comment module of the online question and answer system