韦东山嵌入式Linux_3期之USB摄像头监控_手机App增加录像功能(一)

2024-07-11  

一、手机App功能简述

1) JZ2440开发板作为摄像头监控设备和流服务器,将采集到的摄像头视频数据,通过wifi实时传送到手机App上

2) 手机App作为客户端,通过wifi从流服务器接收摄像头视频,然后显示在屏幕上

3) 显示模式支持:全屏或者保持宽高比

4) 支持:显示FPS帧率

5) 支持拍照功能:把视频的某一帧保存为jpeg图片

6) 支持照片的浏览和删除

7)(新增)支持录像功能:把视频的某一段保存为mkv视频文件

8)(新增)支持录像的浏览和删除

回到顶部(go to top)

二、概要设计

2.1 技术方案

候选方案有三种:

方案1)在原框架的基础上,编写代码,实现录像功能

优点:可能代码量比较少

缺点:

- 技术难度比较高,实现比较困难

- 后期代码维护工作量比较大。如果拉流要支持另一种视频格式,则还要写代码来实现解码。如果录像要支持另一种视频格式,也要写代码来实现编码。

方案2)原框架的代码保留不变(或仅作少量改动)。仅录像功能,由JNI+FFmpeg来实现并暴露出JNI接口供原框架调用(比如当用户点击“开始录像”后,JAVA层调用JNI层接口)

优点:可能代码量较少。

缺点:

- 技术实现上可能比较困难(比如,怎样实现两者对视频流访问的共享和同步?),可供借鉴的网上资料比较少(目前查到的一种方案是修改ffmpeg源代码,把ffmpeg_cmd.c封装成一个类,由JNI按照形如ffmpeg -i videostream_URL -c:v copy -f avi -y output.avi 命令行参数的方式来调用。但很难实现任意一段视频的保存)

- 后期代码维护工作量比较大。原因同上。

方案3) 修改原框架,把涉及到视频处理的相关代码(比如拉流、解码、播放、存帧,加fps)全部转移到JNI+FFmpeg层

优点:

- 模块边界清晰,耦合度低。Java层只负责UI,而由FFmpeg负责所有视频处理的工作。

- App的扩展性强。由于FFmpeg广泛支持各种视频编解码格式(只需在编译时configure阶段加入对应的配置选项即可),所以手机App也可以很方便的支持显示各种摄像头视频格式,当然录像文件也可支持各种格式。

- 程序可以比较容易的移植到其它平台。FFmpeg支持跨平台(Windows、Linux、MacOS、Android),所以App的移植只需要修改UI相关的代码

- 后期代码维护较容易,由于FFmpeg功能强大,所以预期今后新的需求如果是和视频处理有关的,基本上都可以交给FFmpeg来实现

缺点:

- 修改原框架,实现新框架,涉及的工作量比较大

综合以上分析,决定采用方案3

2.2 开发计划

1) FFmpeg和FreeType的移植

2) App原框架的修改(原框架是基于Android SDK(包括从mjpeg解析出bmp并显示、加fps、拍照等),现要改为由JNI层调用FFmpeg来实现)

    实施思路:按功能模块划分,然后逐一实现每个模块,最后再把各个模块整合起来。模块划分如下:

    i) (主体模块)视频采集播放

   ii) 显示模式切换

   iii) 拍照

   iv) 录像

   v) fps显示

   vi) 录像的浏览和删除

回到顶部(go to top)

回到顶部(go to top)AndroidStudio多版本共存(2.3与3.0 )

3.1.3 项目结构(project struct)

1)gradle version

image

2) SDK location 和 NDK location

    注:SDK location 不能包含空格,否则会导致其下的NDK路径也包含空格,从而导致用cmake构建JNI项目时,把空格误认为文件分隔符,而报错

image

  3)Compile SDK version和Build Tools version

image

4)Target SDK version 和Min SDK version

image

   

http://wiki.100ask.org/Download,然后找到:002_JZ2440资料光盘_20180516(免费) )

c) 内核版本:4.13.0

d) gcc版本:5.4.0

e) NDK版本:android-ndk-r15c-linux-x86_64.zip

3.3 调试App时用的目标设备

华为畅享9S

回到顶部(go to top)https://pan.baidu.com/s/1HV-4TB95SPeUqyNDiK68Eg 提取码: 39xb

但在其它机器上没有测试过,不保证一定可用

注:安装NDK交叉编译环境、交叉编译FreeType和FFmpeg都需要在Ubuntu虚拟机中进行

https://dl.google.com/android/repository/android-ndk-r15c-linux-x86_64.zip?hl=zh_cn

下载完成后执行unzip android-ndk-r15c-linux-x86_64.zip解压即可

Android NDK Cross-Compile Setup (libpng and freetype)

https://download.savannah.gnu.org/releases/freetype/freetype-2.9.1.tar.gz

下载完成后执行tar –xzvf freetype-2.9.1.tar.gz解压即可

4.3.2 交叉编译FreeType-2.9.1

1)  进入/work/freetype-2.9.1文件夹,创建build_freetype.sh脚本文件,内容如下:

#!/bin/bash

NDK=/work/android-ndk-r15c

function configure

{   

     CPU=$1

     PREFIX=$(pwd)/android/$CPU

     TOOLCHAIN=""

     SYSROOT=""

     HOST=""

     if [ "$CPU" == "armv7-a" ]

     then

         TOOLCHAIN=/opt/android-ext/bin/

         SYSROOT=$NDK/platforms/android-21/arch-arm/

         HOST=arm-linux-androideabi

     else

         TOOLCHAIN=/opt/android-ext-arm64/bin/

         SYSROOT=$NDK/platforms/android-21/arch-arm64/

         HOST=aarch64-linux-android

     fi

     export PATH=$TOOLCHAIN:$PATH

     ./configure

     --with-png=no

     --with-zlib=no

     --host=$HOST

     --prefix=$PREFIX

     --with-sysroot=$SYSROOT

}



build()

{

     make clean

     cpu=$1

     echo "build $cpu"

    

     configure $cpu

     echo "configure done. CFLAGS:$CFLAGSn PATH:$PATH"

     echo "start make..."

#mod on 2020-03-30 by zg

#    make -j4

     make -j2

     echo "make done."

     echo "start make install..."

     make install

     echo "make install done."

}


build arm64

build armv7-a


2) 在shell终端执行以下语句


chmod –R 777 build_freetype.sh


./build_freetype.sh


最终编译成功后,会:


- 在/work/freetype-2.9.1/android/arm64/lib中生成arm64版本的libfreetype.a静态库和libfreetype.so动态库


- 在/work/freetype-2.9.1/android/armv7-a/lib中生成armv7版本的libfreetype.a静态库和libfreetype.so动态库


4.4 移植FFmpeg到android

参考:FFmpeg一键编译Android arm64位和32位共享库


4.4.1 下载解压FFmpeg-n3.4.5(假设解压到/work/FFmpeg-n3.4.5文件夹下)

下载地址:https://github.com/FFmpeg/FFmpeg/archive/n3.4.5.tar.gz


下载完成后执行tar –xzvf FFmpeg-n3.4.5.tar.gz解压即可


4.4.2 下载解压X264

下载地址:https://code.videolan.org/videolan/x264/-/archive/stable/x264-stable.tar.gz


将x264下载到FFmpeg源码根目录,执行tar -zxvf x264-stable.tar.gz解压,然后将解压出来的目录x264-stable重命名为x264


4.4.3 交叉编译X264

1)进入x264源码目录,新建build.sh,内容如下:


#!/bin/bash

NDK=/work/android-ndk-r15c


configure()

{

    CPU=$1

    PREFIX=$(pwd)/android/$CPU

    HOST=""

    CROSS_PREFIX=""

    SYSROOT=""

    if [ "$CPU" == "armv7-a" ]

    then

        HOST=arm-linux

        SYSROOT=$NDK/platforms/android-26/arch-arm/

        CROSS_PREFIX=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-

    else

        HOST=aarch64-linux

        SYSROOT=$NDK/platforms/android-26/arch-arm64/

        CROSS_PREFIX=$NDK/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-

    fi

    ./configure

    --prefix=$PREFIX

    --host=$HOST

    --enable-pic

    --enable-static

    --enable-neon

    --extra-cflags="-fPIE -pie"

    --extra-ldflags="-fPIE -pie"

    --cross-prefix=$CROSS_PREFIX

    --sysroot=$SYSROOT

}


build()

{

    make clean

    cpu=$1

    echo "build $cpu"

    configure $cpu

    #-j

    make -j2

    make install

}


build arm64

build armv7-a


2) 在shell终端执行以下语句


chmod –R 777 build.sh


./build.sh


编译成功后,会分别在android/armv7-a/lib和android/arm64/lib目录下找到编译好的静态库libx264.a。


4.4.4 交叉编译FFmpeg-n3.4.5

1)修改configure


进入FFmpeg源码根目录,用vim打开configure,找到


SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)' 

LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"' 

SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)' 

SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR)$(SLIBNAME)' 


将其修改为


SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)' 

LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"' 

SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)' 

SLIB_INSTALL_LINKS='$(SLIBNAME)'  


2)进入FFmpeg源码根目录,新建build_ffmpeg.sh,内容如下:


#!/bin/bash

NDK=/work/android-ndk-r15c


ADDI_CFLAGS="-fPIE -pie"

ADDI_LDFLAGS="-fPIE -pie"

export TMPDIR="/tmp"

configure()

{

    CPU=$1

    PREFIX=$(pwd)/android/$CPU

    x264=$(pwd)/x264/android/$CPU

    HOST=""

    CROSS_PREFIX=""

    SYSROOT=""

    ARCH=""

    FREETYPE_INCLUDE=/work/freetype-2.9.1/android/$CPU/include

    FREETYPE_LIB=/work/freetype-2.9.1/android/$CPU/lib

    if [ "$CPU" == "armv7-a" ]

    then

echo "build $cpu"

        ARCH="arm"

        HOST=arm-linux

        SYSROOT=$NDK/platforms/android-21/arch-arm/

        CROSS_PREFIX=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-

    else

        ARCH="aarch64"

        HOST=aarch64-linux

        SYSROOT=$NDK/platforms/android-21/arch-arm64/

        CROSS_PREFIX=$NDK/toolchains/aarch64-linux-android-4.9/prebuilt/linux-x86_64/bin/aarch64-linux-android-

    fi

    ./configure

    --prefix=$PREFIX

    --disable-encoders

    --disable-decoders

    --enable-avdevice

    --disable-static

    --disable-doc

    --disable-ffplay

    --enable-network

    --disable-doc

    --disable-symver

    --enable-neon

    --enable-shared

    --enable-libx264

    --enable-gpl

    --enable-pic

    --enable-jni

    --enable-pthreads

    --enable-mediacodec

    --enable-encoder=aac

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。