文章目录

  • 1.练练手,使用AVILib创建一个AVI视频播放器
    • (1)首先下载transcode,并配置avilib。
    • (2)创建AbstractPlayerActivity并实现native方法
    • (3)配置native-lib,开启jnigraphics,连接avi-lib
    • (4)jni graphics api
    • (5)使用bitmap渲染来更新avi player
  • 2.android studio 配置javah

1.练练手,使用AVILib创建一个AVI视频播放器

(1)首先下载transcode,并配置avilib。

http://www.linuxfromscratch.org/blfs/view/svn/multimedia/transcode.html

将transcode中的avilib文件复制到项目中。


编辑platform.h文件

#ifdef  HAVE_CONFIG_H#include "config.h"#endif

在avilib创建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)创建AbstractPlayerActivity并实现native方法

提取共用代码抽象成一个类

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("错误提示")                    .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);    }    /**     * 打开指定的avi文件     *     * @return     */    protected native static long open(String fileName) throws IOException;    /**     * 获取视频宽度     *     * @param avi     * @return     */    protected native static int getWidth(long avi);    /**     * 获取视频高度     *     * @param avi     * @return     */    protected native static int getHeight(long avi);    /**     * 获取帧速     *     * @param avi     * @return     */    protected native static double getFrameRate(long avi);    /**     * 基于给定的文件描述符关闭指定的avi文件     *     * @param avi     */    protected native static void close(long avi);}

使用javah来生成.h文件。

/* DO NOT EDIT THIS FILE - it is machine generated */#include /* Header for class cn_study_aviplayer_AbstractPlayerActivity */#ifndef _Included_cn_study_aviplayer_AbstractPlayerActivity#define _Included_cn_study_aviplayer_AbstractPlayerActivity#ifdef __cplusplusextern "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

在native-lib.cpp中导入avilib.h需要。

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

native-lib.cpp

#include #include #include "cn_study_aviplayer_AbstractPlayerActivity.h"#include "Common.h"#include extern "C" {     #include "avilib/avilib.h"}extern "C" JNIEXPORT jstring JNICALLJava_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 JNICALLJava_cn_study_aviplayer_AbstractPlayerActivity_open(JNIEnv *env, jclass clazz, jstring file_name) {         avi_t *avi = 0;    //获取文件名字并转换成字符串变量    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 JNICALLJava_cn_study_aviplayer_AbstractPlayerActivity_getWidth(JNIEnv *env, jclass clazz, jlong avi) {         return AVI_video_width((avi_t *) avi);}extern "C"JNIEXPORT jint JNICALLJava_cn_study_aviplayer_AbstractPlayerActivity_getHeight(JNIEnv *env, jclass clazz, jlong avi) {         return AVI_video_height((avi_t *) avi);}extern "C"JNIEXPORT jdouble JNICALLJava_cn_study_aviplayer_AbstractPlayerActivity_getFrameRate(JNIEnv *env, jclass clazz, jlong avi) {         return AVI_frame_rate((avi_t *) avi);}extern "C"JNIEXPORT void JNICALLJava_cn_study_aviplayer_AbstractPlayerActivity_close(JNIEnv *env, jclass clazz, jlong avi) {         AVI_close((avi_t *) avi);}

(3)配置native-lib,开启jnigraphics,连接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_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}#开启jnigraphics        ${     log-lib}        avi-lib)

(4)jni graphics api

检索bitmap对象信息,如大小、像素格式。成功返回0,失败返回一个负数。int AndroidBitmap_getInfo(JNIEnv* env, jobject jbitmap,AndroidBitmapInfo* info);
访问原生像素缓存,锁定像素缓存以确保像素的内存不会移动。成功返回0,失败返回负数。int AndroidBitmap_lockPixels(JNIEnv* env, jobject jbitmap, void** addrPtr);
释放原生像素缓存成功返回0,失败返回负数int AndroidBitmap_unlockPixels(JNIEnv* env, jobject jbitmap);

(5)使用bitmap渲染来更新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);            //延迟            long frameDelay = (long) (1000 / getFrameRate(avi));            while (isPlaying.get()) {                     render(avi, bitmap);                Canvas canvas = surfaceHolder.lockCanvas();                canvas.drawBitmap(bitmap, matrix, null);                surfaceHolder.unlockCanvasAndPost(canvas);                //等待下一针                try {                         Thread.sleep(frameDelay);                } catch (InterruptedException e) {                         break;                }            }        }    };    /**     * 从avi文件描述符输出到指定bitmap来渲染帧     *     * @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 extern "C"JNIEXPORT jboolean JNICALLJava_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", "不能够锁定像素");        goto exit;    }    //将avi帧byte读取到bitmap中    frameSize = AVI_read_frame((avi_t *) avi, frameBuffer, &keyFrame);    //解锁    if (0 > AndroidBitmap_unlockPixels(env, bitmap)) {             ThrowException(env, "java/io/IOException", "不能够解锁像素");        goto exit;    }    //是否读取成功    if (0 < frameSize) {             isFrameRead = JNI_TRUE;    }    exit:    return isFrameRead;}

想使用这个avi播放器,视频文件格式必须是avi格式,希望视频负载是通过RGB565颜色空间的未压缩原始帧来提供的。
将视频放到指定目录,运行效果如下:

详细代码和视频文件

https://gitee.com/xd_box/AviPlayer

2.android studio 配置javah

file>Setting>Tools>External Tools 点击+号。

program:$JDKPath$\bin\javah.exearguments:-classpath . -jni -d $ModuleFileDir$\src\main\cpp $FileClass$working directory:$ModuleFileDir$\src\main\java

更多相关文章

  1. Android(安卓)Monkey 脚本编写与检查内存泄露
  2. Android需要提升权限的操作方法
  3. adnroid 学习笔记(一)
  4. 永久破解Tattoo root权限
  5. android sdk 让SDK Manager来自动安装上面下载的文件
  6. Android(安卓)极光推送
  7. eclipse 开发 jni
  8. Project has no default.properties file! Edit the project pro
  9. Android(安卓)Studio升级提示 Connection failed. Please check

随机推荐

  1. 浅谈SVM三特征模型的可视化与拟合度的分
  2. 聚类分析算法对文本分类之分词和构建词袋
  3. 翻译:《实用的Python编程》01_02_Hello_wo
  4. 如何让高校科研更有意义?
  5. J. Cole 的 InnoDB 系列 - 3. InnoDB空间
  6. 对vSAN使用较小的磁盘大小可能会导致VM故
  7. “手撕”BP算法——使用MATLAB搭建简单的
  8. 什么是DevOps?
  9. 3-23(类与对象终结)
  10. 2019年研究生全国数学数模竞赛F题分析(1-2