ffmpeg开发教程(1) 准备C++开发环境

本文介绍下C++常用的开发环境和工具,C++项目参见github的ffmpeg-tutorial 。目前我常用的开发环境有 Windows 10, Mac 和 Ubuntu,C++的开发IDE有CLion, XCode,Visual Studio ,VSCode。编译基于CMake,生成Ninja 编译文件。使用vcpkg来管理C++的软件包。

IDE 其中CLion和VSCode是三个平台都可以使用的,具体如下图所示:

Windows Mac Ubuntu
Clion X X X
Vscode X X X
Xcode X
Visual Studio 2017 X

vcpkg安装可以参考github上的说明,clone vcpkg repo ,运行bootstrap-vcpkg.bat(Windows)或 bootstrap-vcpkg.sh (Mac 和 Linux) .

安装好vcpkg之后,可以配置下面几个环节变量:

Linux和Mac

export VCPKG_ROOT=~/Workspace/vcpkg
export VCPKG_DEFAULT_TRIPLET=x64-osx
export CMAKE_GENERATOR=Ninja

其中VCPKG_ROOT 为vcpkg的安装目录,VCPKG_DEFAULT_TRIPLET 为C++软件包的缺省配置,比如64位还是32位,编译成动态库还是静态库,CMAKE_GENERATOR 缺省生成的编译文件的格式,比如Makefile,或是Ninja,或是XCode,Visual Studio 的项目文件。

目前大部分计算机都是64位机器,我们的教程基本是使用动态链接库的形式,因此我们可以使用如下的vcpkg, triplet的配置,可以修改缺省的triplet 或者创建新的triplet文件。vcpkg安装后,triplets目录下定义了一些常用的triplet文件:

Mac下的x64-osx缺省使用静态库,我们可以修改x64-osx.cmake

set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE dynamic)

set(VCPKG_CMAKE_SYSTEM_NAME Darwin)

在Ubuntu下,同样,我们复制x64-linux.cmake ,创建一个新的x64-ubuntu.cmake

set(VCPKG_TARGET_ARCHITECTURE x64)
set(VCPKG_CRT_LINKAGE dynamic)
set(VCPKG_LIBRARY_LINKAGE dynamic)

set(VCPKG_CMAKE_SYSTEM_NAME Linux)

Windows下直接使用x64-windows.cmake

有了vcpkg之后,安装C++软件包就非常简单,比如安装我们教程中用到的几个软件包SDL2, ffmpeg,可以直接运行:

vcpkg install SDL2 ffmpeg

安装成功后,可以使用vcpkg list列出安装好的软件包的版本和简要说明,比如Mac下:

catch2:x64-osx                                     2.11.1           A modern, header-only test framework for unit te...
ffmpeg:x64-osx                                     4.2-5            a library to decode, encode, transcode, mux, dem...
ffmpeg[avresample]:x64-osx                                          Libav audio resampling library support in ffmpeg
libjpeg-turbo:x64-osx                              2.0.4            libjpeg-turbo is a JPEG image codec that uses SI...
liblzma:x64-osx                                    5.2.4-4          Compression library with an API similar to that ...
libpng:x64-osx                                     1.6.37-6         libpng is a library implementing an interface fo...
libwebp:x64-osx                                    1.1.0            WebP codec: library to encode and decode images ...
libwebp[nearlossless]:x64-osx                                       Enable near-lossless encoding
libwebp[simd]:x64-osx                                               Enable any SIMD optimization.
opencv4:x64-osx                                    4.1.1-3          computer vision library
opencv4[dnn]:x64-osx                                                Enable dnn module
opencv4[jpeg]:x64-osx                                               JPEG support for opencv
opencv4[opengl]:x64-osx                                             opengl support for opencv
opencv4[png]:x64-osx                                                PNG support for opencv
opencv4[tiff]:x64-osx                                               TIFF support for opencv
opencv4[webp]:x64-osx                                               WebP support for opencv
opengl:x64-osx                                     0.0-5            Open Graphics Library (OpenGL)[3][4][5] is a cro...
protobuf:x64-osx                                   3.11.3           Protocol Buffers - Google's data interchange format
tiff:x64-osx                                       4.0.10-8         A library that supports the manipulation of TIFF...
zlib:x64-osx                                       1.2.11-6         A compression library

Ubuntu下

catch2:x64-ubuntu                                  2.11.1           A modern, header-only test framework for unit te...
ffmpeg:x64-ubuntu                                  4.2-5            a library to decode, encode, transcode, mux, dem...
ffmpeg[avresample]:x64-ubuntu                                       Libav audio resampling library support in ffmpeg
libjpeg-turbo:x64-ubuntu                           2.0.4            libjpeg-turbo is a JPEG image codec that uses SI...
liblzma:x64-ubuntu                                 5.2.4-4          Compression library with an API similar to that ...
libpng:x64-ubuntu                                  1.6.37-6         libpng is a library implementing an interface fo...
libwebp:x64-ubuntu                                 1.1.0            WebP codec: library to encode and decode images ...
libwebp[nearlossless]:x64-ubuntu                                    Enable near-lossless encoding
libwebp[simd]:x64-ubuntu                                            Enable any SIMD optimization.
opencv4:x64-ubuntu                                 4.1.1-3          computer vision library
opencv4[dnn]:x64-ubuntu                                             Enable dnn module
opencv4[jpeg]:x64-ubuntu                                            JPEG support for opencv
opencv4[opengl]:x64-ubuntu                                          opengl support for opencv
opencv4[png]:x64-ubuntu                                             PNG support for opencv
opencv4[tiff]:x64-ubuntu                                            TIFF support for opencv
opencv4[webp]:x64-ubuntu                                            WebP support for opencv
opengl:x64-ubuntu                                  0.0-5            Open Graphics Library (OpenGL)[3][4][5] is a cro...
protobuf:x64-ubuntu                                3.11.3           Protocol Buffers - Google's data interchange format
sdl2:x64-ubuntu                                    2.0.10-3         Simple DirectMedia Layer is a cross-platform dev...
tiff:x64-ubuntu                                    4.0.10-8         A library that supports the manipulation of TIFF...
zlib:x64-ubuntu                                    1.2.11-6         A compression library

Windows下:

catch2:x64-windows                                 2.11.1           A modern, header-only test framework for unit te...
ffmpeg:x64-windows                                 4.2-5            a library to decode, encode, transcode, mux, dem...
ffmpeg[avresample]:x64-windows                                      Libav audio resampling library support in ffmpeg
libjpeg-turbo:x64-windows                          2.0.4            libjpeg-turbo is a JPEG image codec that uses SI...
liblzma:x64-windows                                5.2.4-4          Compression library with an API similar to that ...
libpng:x64-windows                                 1.6.37-6         libpng is a library implementing an interface fo...
libwebp:x64-windows                                1.1.0            WebP codec: library to encode and decode images ...
libwebp[nearlossless]:x64-windows                                   Enable near-lossless encoding
libwebp[simd]:x64-windows                                           Enable any SIMD optimization.
libwebp[unicode]:x64-windows                                        Build Unicode executables. (Adds definition UNIC...
opencv4:x64-windows                                4.1.1-3          computer vision library
opencv4[dnn]:x64-windows                                            Enable dnn module
opencv4[jpeg]:x64-windows                                           JPEG support for opencv
opencv4[opengl]:x64-windows                                         opengl support for opencv
opencv4[png]:x64-windows                                            PNG support for opencv
opencv4[tiff]:x64-windows                                           TIFF support for opencv
opencv4[webp]:x64-windows                                           WebP support for opencv
opencv:x64-windows                                 4.1.1-1          Computer vision library
opencv[dnn]:x64-windows                                             Enable dnn module
opencv[jpeg]:x64-windows                                            JPEG support for opencv
opencv[opengl]:x64-windows                                          opengl support for opencv
opencv[png]:x64-windows                                             PNG support for opencv
opencv[tiff]:x64-windows                                            TIFF support for opencv
opencv[webp]:x64-windows                                            WebP support for opencv
opengl:x64-windows                                 0.0-5            Open Graphics Library (OpenGL)[3][4][5] is a cro...
protobuf:x64-windows                               3.11.3           Protocol Buffers - Google's data interchange format
sdl2:x64-windows                                   2.0.10-2         Simple DirectMedia Layer is a cross-platform dev...
tiff:x64-windows                                   4.0.10-8         A library that supports the manipulation of TIFF...
zlib:x64-windows                                   1.2.11-6         A compression library
zlib:x86-windows                                   1.2.11-6         A compression library

重拾C++

最近在做一个有趣的项目,想法来自于scrcpy. scrcpy是PC端控制Android手机人一个应用,和我之前用过的同类的软件相比,scrcpy视频的帧数非常高,通过PC控制Android设备响应非常迅速。想起之前学习人工智能时用过的Open AI Gym ,想着是否可以通过改进scrcpy,把任意的Android游戏改造成Gym的运行环境,然后可以通过机器学习的方式使用训练AI来玩如何任意的Android游戏,而不是局限Gym提供的环境。

scrcpy为开源,但本身是使用C语言写的。C语言(包括C++)之前我有过10多年的工作经验,但最近10多年基本是没有在碰过C语言,虽然基本概念还是记得很清楚,但C,C++经过这十多年的发展,已经不是当年我所知道的C语言了,一些在Python,C#等语言支持的语法结构比如Lambda,auto,closure在新版C++也提供了,开发的工具链(Toolchain)也有了大的改进。比如CMake,C++ 软件包管理工具(conan, vcpkg),集成开发环境,CLion, XCode, Visual Studio ,VSCode等等。

有必要重新了解下C++的开发。最近几周重新学习了C++(c17),CMake ,vcpkg。然后试着修改了scrcpy,加进了opencv,改造scrcpy变成通用Open AI Gym在技术上上可行的。

最近准备写些关于FFmpeg, OpenCV方面的文章,教程的C++项目框架ffmpeg-tutorial  ,使用CMake 作为编译工具,vcpkg作为C++ 软件包管理工具,Catch2作为单元测试框架。支持Ubuntu, Windows ,MacOS.

2020重新开始写博客

很久没有更新博客了,上次更新还是四年前,主要原因还是人的惰性,这期间业余也做了一些有趣的项目,是可以记录下来人,比如中国古典文学手机APP:

 

React 动画现实近二十年前15名GDP变化:

 

迷你小电脑

西澳留学圈

OPENCV计算机视觉:

 

以及人工智能和数据科学

 

等等有趣的项目,儿子也开始上中学了,也开始有些空余时间,可以再写点博客,开始还是侧重于人工智能和计算机视觉方面为主,人工智能很20多年前读书时也学过,当时接触到遗传算法的时候,非常兴奋,算法还可以这样实现,也用它解决了数字九宫图的问题,现在我还保留两本教科书,出国后还带在身边,没有扔掉:-),

 

但基于当时的计算机计算能力(不及目前的手机),人工智能应用不普及,主要是专家系统,生产调度优化,现在随着计算机计算能力的大大提高(CPU和GPU),大数据,以及Google, AWS,提供的人工智能平台提供了成熟的算法库,使得人工智能的应用大大普及,个人也认为是今后计算机技术的一个发展趋势。

开始的文章主要是以翻译为主,对自己也是一个学习的过程。

F# 插入排序 和归并排序

插入排序 insertSort

let insertSort array =
    let length = Array.length array
    for i in [1..(length-1)] do
        let key = array.[i]
        //insert key to sub array[0..i-1]
        let mutable j = i-1
        while (j>=0 && array.[j]>key) do
            array.[j+1] <- array.[j]
            j <- j-1
        array.[j+1]<-key

let a=[|6;7;1;3;2;9;8;18;18;12|]

a |> insertSort

归并排序 mergesort


let merge array lo mid hi =
    let mutable i = lo
    let mutable j = mid
    let length = Array.length array
    let tempArray = Array.create length 0
    let mutable index =0
    while (i<mid && j<hi) do
        if array.[i]<array.[j] then
            tempArray.[index]<-array.[i]
            i<-i+1
            index<-index+1
        if array.[i]>=array.[j] then
            tempArray.[index]< -array.[j]
            j<-j+1
            index<-index+1

    //check if there's any remaining let
    if i<mid then 
        for k in [i .. (mid-1)] do
            tempArray.[index] <- array.[k]
            index<-index+1

    if j<hi then
        for k in [j .. (hi-1)] do
            tempArray.[index] <- array.[k]
            index<-index+1

    for i in [lo..(hi-1)] do
        array.[i] <- tempArray.[i-lo]

 
let rec mergeSort' array lo hi =
    let length = hi - lo
    if hi>1 + lo then
        let mid = (hi+lo)/2
        mergeSort' array lo mid
        mergeSort' array mid hi
        merge  array lo mid hi


let mergeSort array =
    mergeSort' array 0 (Array.length array)



let array =[|4;1;5;6;7;8;13;19;12|]

array |> mergeSort

F#开发教程(13):函数化编程(十二)

延迟计算

伴随函数化编程的是延迟计算。理论上认为,如果一个语言没有“副作用”的话,那么编译器或是程序运行时可以自由选择表达式的计算顺序。
F#允许函数有副作用,因此编译器或是运行时无法自由选择表达式的计算顺序。因此F#被认为具有严格的运算顺序。但是你仍然可以利用延迟计算,然而你必须指明哪些计算可以延后计算。也就是有有需要时才计算。
F#中使用lazy来定义一个延后计算。定义在延迟计算中的表达式只有在明确指明需要计算时才会计算。计算的结果保存在缓存中以后后续调用,而无需重新计算。

> let lazyValue = lazy ( 2+3);;

val lazyValue : Lazy<int> = Value is not created.

> lazyValue.Force();;
val it : int = 5

lazy 定义了一个延迟计算,后门一行强制计算,返回5. 要注意的是延迟表达式最多只会计算一次,计算后,结果被保存,即使结果抛出异常。比如下个例子

> let lazySideEffect = 
-     lazy 
-         (
-              let temp = 2 + 2
-              printfn "%i" temp
-              temp
-          );;

val lazySideEffect : Lazy<int> = Value is not created.

> lazySideEffect.Force();;
4
val it : int = 4
> lazySideEffect.Force();;
val it : int = 4

lazySideEffect表达式定义一个“副作用”,显示当前整数值,我们看以看到这段表达式只计算了一次,因此如果你依赖表达式的“副作用”来实现某些功能时,延迟计算可能就不太合适了。

延迟计算对于处理集合类型时比较有用,延迟集合类型的目的是只在需要集合的某个元素时才计算。F#中使用延迟计算的最常用的类型是序列Seq。
可能最重要也是最难理解的一个创建序列的函数是unfold。

// Signature:
Seq.unfold : ('State -> ('T * 'State) option) -> 'State -> seq<'T>

// Usage:
Seq.unfold generator state

如果我们联系起数列的递推公式,就可以比较容易的理解unfold。比如 Fibonacci数列的递推公式

S0=1; S1=1
Sn+2=Sn+ Sn+1

我们使用一个二元组作为参数(这里有两个初始值,二元组是个比较合适的类型)

> Seq.unfold ( fun state -> Some( fst state, ((snd state),(fst state)+(snd state)))) (1,1);;
val it : seq<int> = seq [1; 1; 2; 3; ...]

如果把state用二元组(ao,a1)的形式表示,可以简化为

> Seq.unfold ( fun (n0,n1) -> Some(n0,(n1,n0+n1))) (1,1);;
val it : seq<int> = seq [1; 1; 2; 3; ...]

F#开发教程(12):函数化编程(十一)

异常和异常处理

F#中定义异常和定义联合类似,异常处理类似于模式匹配。定义异常使用excpetion关键字,然后是异常的名称,再次为可选的异常数据类型。多个类型使用*分隔(其实是元组类型)
例如

exception WrongSecond of int

使用raise来抛出异常。F#中还有一个failwith函数可以抛出异常。

> exception WrongSecond of int
- let primes = [ 2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; 41; 43; 47; 53; 59 ];;

exception WrongSecond of int
val primes : int list =
  [2; 3; 5; 7; 11; 13; 17; 19; 23; 29; 31; 37; 41; 43; 47; 53; 59]

> let testSecond() =
-     try
-         let currentSecond = System.DateTime.Now.Second 
-         if List.exists (fun x -> x = currentSecond) primes then
-             failwith "A prime second"
-         else
-             raise (WrongSecond currentSecond)
-     with
-     WrongSecond x ->
-         printf "The current was %i,which is not prime" x;;

val testSecond : unit -> unit

> testSecond();;
The current was 1,which is not primeval it : unit = ()

try 和 with 用来处理异常,将可能会出现异常的表达式放在try 和 with 之间。with之后定义一个或多个异常类型的模式匹配。和普通的模式匹配最大的差异在于异常的模式匹配在没有没有完全定义所有异常模式处理时编译器不会给出警告,这是因为任何没有处理的异常都会逐步向上传播。
F#也支持finally,它和try一起使用。但finally不能和with一同使用。

// function to write to a file
let writeToFile() =
    // open a file
    let file = System.IO.File.CreateText("test.txt")
    try
// write to it
        file.WriteLine("Hello F# users")
    finally
        // close the file, this will happen even if
        // an exception occurs writing to the file
        file.Dispose()
// call the function
writeToFile()