• 树莓派移植FFmepg记录(x264、硬件编码支持)


    树莓派移植FFmepg记录(x264、硬件编码支持)

    参考链接:

    本次移植为FFmpeg添加了x264软件编码器、Omx-rpi硬件编码的支持

    1.x264交叉编译

    进入源码目录,根据configure --help,编写一个脚本:

    #!/bin/sh
    
    ./configure --prefix=./pi_install \
    --enable-strip \
    --disable-asm \
    --host=arm-linux \
    --cross-prefix=arm-linux-gnueabihf- \
    --sysroot=/opt/rpi_tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/arm-linux-gnueabihf/sysroot \
    --enable-shared \
    # --disable-cli #配置该项不会生成可执行文件
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    执行后会生成makefile,执行编译命令:

    make 或make -j8 #多线程编译,提高编译速度
    
    • 1

    编译完成后使用make install命令则会将生成的文件拷贝到安装目录:

    boy@ubuntu:~/opensource/x264/pi_install$ tree .
    .
    ├── bin
    │   └── x264
    ├── include
    │   ├── x264_config.h
    │   └── x264.h
    └── lib
        ├── libx264.so -> libx264.so.164
        ├── libx264.so.164
        └── pkgconfig
            └── x264.pc
    
    4 directories, 6 files
    boy@ubuntu:~/opensource/x264/pi_install$
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    可以看到已经根据我们的configure配置项,生成了so动态库、可执行文件等。

    2.ffmpeg交叉编译

    源码下载链接:Download FFmpeg

    解压:

    tar -jxvf ffmpeg-snapshot.tar.bz2
    
    • 1

    与配置x264类似,使用configure --help可以查看到有很多选项配置,这里使用参考前人的配置编写一个合适的脚本:

    #!/bin/sh
    
    ./configure \
    --enable-shared \
    --enable-static \
    --prefix=`pwd`/pi_install \
    --extra-cflags=-I/home/boy/opensource/x264/pi_install/include \ #添加外部头文件路径
    --extra-ldflags=-L/home/boy/opensource/x264/pi_install/lib \    #添加外部库文件路径
    --enable-libx264 #使能x264编码器
    --enable-cross-compile \
    --cross-prefix=arm-linux-gnueabihf- \
    --arch=arm \
    --target-os=linux \
    --enable-gpl \
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    **注:**这些选项貌似会有一定的先后顺序,刚开始–extra-cflags、–extra-ldflags放在后面一直编译不成功。。

    生成makefile后执行make -j8进行编译,代码比较多,编译会比较慢,编译完成后make install安装到相应路径:

    .
    ├── bin
    │   ├── ffmpeg
    │   └── ffprobe
    ├── include
    │   ├── libavcodec
    │   │   ├── ac3_parser.h
    │   │   ├── adts_parser.h
    │   │   ├── avcodec.h
    │   │   ├── avdct.h
    │   │   ├── avfft.h
    │   │   ├── bsf.h
    │   │   ├── codec_desc.h
    │   │   ├── codec.h
    │   │   ├── codec_id.h
    │   │   ├── codec_par.h
    │   │   ├── d3d11va.h
    │   │   ├── defs.h
    │   │   ├── dirac.h
    │   │   ├── dv_profile.h
    │   │   ├── dxva2.h
    │   │   ├── jni.h
    │   │   ├── mediacodec.h
    │   │   ├── packet.h
    │   │   ├── qsv.h
    │   │   ├── vdpau.h
    │   │   ├── version.h
    │   │   ├── version_major.h
    │   │   ├── videotoolbox.h
    │   │   ├── vorbis_parser.h
    │   │   └── xvmc.h
    │   ├── libavdevice
    │   │   ├── avdevice.h
    │   │   ├── version.h
    │   │   └── version_major.h
    │   ├── libavfilter
    │   │   ├── avfilter.h
    │   │   ├── buffersink.h
    │   │   ├── buffersrc.h
    │   │   ├── version.h
    │   │   └── version_major.h
    │   ├── libavformat
    │   │   ├── avformat.h
    │   │   ├── avio.h
    │   │   ├── version.h
    │   │   └── version_major.h
    │   ├── libavutil
    │   │   ├── adler32.h
    │   │   ├── aes_ctr.h
    │   │   ├── aes.h
    │   │   ├── attributes.h
    │   │   ├── audio_fifo.h
    │   │   ├── avassert.h
    │   │   ├── avconfig.h
    │   │   ├── avstring.h
    │   │   ├── avutil.h
    │   │   ├── base64.h
    │   │   ├── blowfish.h
    │   │   ├── bprint.h
    │   │   ├── bswap.h
    │   │   ├── buffer.h
    │   │   ├── camellia.h
    │   │   ├── cast5.h
    │   │   ├── channel_layout.h
    │   │   ├── common.h
    │   │   ├── cpu.h
    │   │   ├── crc.h
    │   │   ├── des.h
    │   │   ├── detection_bbox.h
    │   │   ├── dict.h
    │   │   ├── display.h
    │   │   ├── dovi_meta.h
    │   │   ├── downmix_info.h
    │   │   ├── encryption_info.h
    │   │   ├── error.h
    │   │   ├── eval.h
    │   │   ├── ffversion.h
    │   │   ├── fifo.h
    │   │   ├── file.h
    │   │   ├── film_grain_params.h
    │   │   ├── frame.h
    │   │   ├── hash.h
    │   │   ├── hdr_dynamic_metadata.h
    │   │   ├── hdr_dynamic_vivid_metadata.h
    │   │   ├── hmac.h
    │   │   ├── hwcontext_cuda.h
    │   │   ├── hwcontext_d3d11va.h
    │   │   ├── hwcontext_drm.h
    │   │   ├── hwcontext_dxva2.h
    │   │   ├── hwcontext.h
    │   │   ├── hwcontext_mediacodec.h
    │   │   ├── hwcontext_opencl.h
    │   │   ├── hwcontext_qsv.h
    │   │   ├── hwcontext_vaapi.h
    │   │   ├── hwcontext_vdpau.h
    │   │   ├── hwcontext_videotoolbox.h
    │   │   ├── hwcontext_vulkan.h
    │   │   ├── imgutils.h
    │   │   ├── intfloat.h
    │   │   ├── intreadwrite.h
    │   │   ├── lfg.h
    │   │   ├── log.h
    │   │   ├── lzo.h
    │   │   ├── macros.h
    │   │   ├── mastering_display_metadata.h
    │   │   ├── mathematics.h
    │   │   ├── md5.h
    │   │   ├── mem.h
    │   │   ├── motion_vector.h
    │   │   ├── murmur3.h
    │   │   ├── opt.h
    │   │   ├── parseutils.h
    │   │   ├── pixdesc.h
    │   │   ├── pixelutils.h
    │   │   ├── pixfmt.h
    │   │   ├── random_seed.h
    │   │   ├── rational.h
    │   │   ├── rc4.h
    │   │   ├── replaygain.h
    │   │   ├── ripemd.h
    │   │   ├── samplefmt.h
    │   │   ├── sha512.h
    │   │   ├── sha.h
    │   │   ├── spherical.h
    │   │   ├── stereo3d.h
    │   │   ├── tea.h
    │   │   ├── threadmessage.h
    │   │   ├── timecode.h
    │   │   ├── time.h
    │   │   ├── timestamp.h
    │   │   ├── tree.h
    │   │   ├── twofish.h
    │   │   ├── tx.h
    │   │   ├── version.h
    │   │   ├── video_enc_params.h
    │   │   └── xtea.h
    │   ├── libpostproc
    │   │   ├── postprocess.h
    │   │   ├── version.h
    │   │   └── version_major.h
    │   ├── libswresample
    │   │   ├── swresample.h
    │   │   ├── version.h
    │   │   └── version_major.h
    │   └── libswscale
    │       ├── swscale.h
    │       ├── version.h
    │       └── version_major.h
    ├── lib
    │   ├── libavcodec.a
    │   ├── libavcodec.so -> libavcodec.so.59.25.100
    │   ├── libavcodec.so.59 -> libavcodec.so.59.25.100
    │   ├── libavcodec.so.59.25.100
    │   ├── libavdevice.a
    │   ├── libavdevice.so -> libavdevice.so.59.6.100
    │   ├── libavdevice.so.59 -> libavdevice.so.59.6.100
    │   ├── libavdevice.so.59.6.100
    │   ├── libavfilter.a
    │   ├── libavfilter.so -> libavfilter.so.8.29.100
    │   ├── libavfilter.so.8 -> libavfilter.so.8.29.100
    │   ├── libavfilter.so.8.29.100
    │   ├── libavformat.a
    │   ├── libavformat.so -> libavformat.so.59.20.101
    │   ├── libavformat.so.59 -> libavformat.so.59.20.101
    │   ├── libavformat.so.59.20.101
    │   ├── libavutil.a
    │   ├── libavutil.so -> libavutil.so.57.24.101
    │   ├── libavutil.so.57 -> libavutil.so.57.24.101
    │   ├── libavutil.so.57.24.101
    │   ├── libpostproc.a
    │   ├── libpostproc.so -> libpostproc.so.56.5.100
    │   ├── libpostproc.so.56 -> libpostproc.so.56.5.100
    │   ├── libpostproc.so.56.5.100
    │   ├── libswresample.a
    │   ├── libswresample.so -> libswresample.so.4.6.100
    │   ├── libswresample.so.4 -> libswresample.so.4.6.100
    │   ├── libswresample.so.4.6.100
    │   ├── libswscale.a
    │   ├── libswscale.so -> libswscale.so.6.6.100
    │   ├── libswscale.so.6 -> libswscale.so.6.6.100
    │   ├── libswscale.so.6.6.100
    │   └── pkgconfig
    │       ├── libavcodec.pc
    │       ├── libavdevice.pc
    │       ├── libavfilter.pc
    │       ├── libavformat.pc
    │       ├── libavutil.pc
    │       ├── libpostproc.pc
    │       ├── libswresample.pc
    │       └── libswscale.pc
    ├── share
    │   ├── ffmpeg
    │   │   ├── examples
    │   │   │   ├── avio_list_dir.c
    │   │   │   ├── avio_reading.c
    │   │   │   ├── decode_audio.c
    │   │   │   ├── decode_video.c
    │   │   │   ├── demuxing_decoding.c
    │   │   │   ├── encode_audio.c
    │   │   │   ├── encode_video.c
    │   │   │   ├── extract_mvs.c
    │   │   │   ├── filter_audio.c
    │   │   │   ├── filtering_audio.c
    │   │   │   ├── filtering_video.c
    │   │   │   ├── http_multiclient.c
    │   │   │   ├── hw_decode.c
    │   │   │   ├── Makefile
    │   │   │   ├── metadata.c
    │   │   │   ├── muxing.c
    │   │   │   ├── qsvdec.c
    │   │   │   ├── README
    │   │   │   ├── remuxing.c
    │   │   │   ├── resampling_audio.c
    │   │   │   ├── scaling_video.c
    │   │   │   ├── transcode_aac.c
    │   │   │   ├── transcoding.c
    │   │   │   ├── vaapi_encode.c
    │   │   │   └── vaapi_transcode.c
    │   │   ├── ffprobe.xsd
    │   │   ├── libvpx-1080p50_60.ffpreset
    │   │   ├── libvpx-1080p.ffpreset
    │   │   ├── libvpx-360p.ffpreset
    │   │   ├── libvpx-720p50_60.ffpreset
    │   │   └── libvpx-720p.ffpreset
    │   └── man
    │       ├── man1
    │       │   ├── ffmpeg.1
    │       │   ├── ffmpeg-all.1
    │       │   ├── ffmpeg-bitstream-filters.1
    │       │   ├── ffmpeg-codecs.1
    │       │   ├── ffmpeg-devices.1
    │       │   ├── ffmpeg-filters.1
    │       │   ├── ffmpeg-formats.1
    │       │   ├── ffmpeg-protocols.1
    │       │   ├── ffmpeg-resampler.1
    │       │   ├── ffmpeg-scaler.1
    │       │   ├── ffmpeg-utils.1
    │       │   ├── ffprobe.1
    │       │   └── ffprobe-all.1
    │       └── man3
    │           ├── libavcodec.3
    │           ├── libavdevice.3
    │           ├── libavfilter.3
    │           ├── libavformat.3
    │           ├── libavutil.3
    │           ├── libswresample.3
    │           └── libswscale.3
    └── tree.txt
    
    18 directories, 229 files
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250

    编译完成即可拷贝头文件、库文件到自己的工程目录,编写相关应用程序。

    3.添加硬件编码支持

    ​ libx264是使用CPU进行编码转换的,即软件编码,运行起来CPU占用率非常高。为了降低CPU占用率,决定使用硬件加速编码。

    首先,需要知道两个比较关键的东西:

    • omx-rpi 树莓派的硬编码加速
    • mmal 树莓派的硬解码加速

    PS:博主只用到编码,因此只添加硬件编码支持,硬件解码的添加应该大同小异,有空再折腾。

    ​ 树莓派交叉编译添加硬件编码支持的资料非常少,折腾了非常久( ~ . ~痛苦面具),最后在某歌搜索到一个比较有用的博客:为树莓派交叉编译FFMPEG工具 | Sunrise 博客 (yjdwbj.github.io)

    ①.获取树莓派omx库、头文件

    根据该博客的指导,在树莓派/opt/vc目录下包含有omxmmal相关的库文件、头文件以及相关的demo,如下所示,将这些拷贝到ubuntu宿主机。

    boy@ubuntu:~/opensource/vc$ tree .
    .
    ├── bin
    │   ├── containers_check_frame_int
    │   ├── containers_datagram_receiver
    │   ├── containers_datagram_sender
    │   ├── containers_dump_pktfile
    │   ├── containers_rtp_decoder
    │   ├── containers_stream_client
    │   ├── containers_stream_server
    │   ├── containers_test
    │   ├── containers_test_bits
    │   ├── containers_test_uri
    │   ├── containers_uri_pipe
    │   ├── dtmerge
    │   ├── dtoverlay
    │   ├── dtoverlay-post
    │   ├── dtoverlay-pre
    │   ├── dtparam -> dtoverlay
    │   ├── edidparser
    │   ├── mmal_vc_diag
    │   ├── raspistill
    │   ├── raspivid
    │   ├── raspividyuv
    │   ├── raspiyuv
    │   ├── tvservice
    │   ├── vcdbg
    │   ├── vcgencmd
    │   ├── vchiq_test
    │   ├── vcmailbox
    │   └── vcsmem
    ├── include
    │   ├── bcm_host.h
    │   ├── EGL
    │   │   ├── eglext_android.h
    │   │   ├── eglext_brcm.h
    │   │   ├── eglext.h
    │   │   ├── eglext_nvidia.h
    │   │   ├── egl.h
    │   │   └── eglplatform.h
    │   ├── GLES
    │   │   ├── glext.h
    │   │   ├── gl.h
    │   │   └── glplatform.h
    │   ├── GLES2
    │   │   ├── gl2ext.h
    │   │   ├── gl2.h
    │   │   └── gl2platform.h
    │   ├── IL
    │   │   ├── OMX_Audio.h
    │   │   ├── OMX_Broadcom.h
    │   │   ├── OMX_Component.h
    │   │   ├── OMX_Core.h
    │   │   ├── OMX_ILCS.h
    │   │   ├── OMX_Image.h
    │   │   ├── OMX_Index.h
    │   │   ├── OMX_IVCommon.h
    │   │   ├── OMX_Other.h
    │   │   ├── OMX_Types.h
    │   │   └── OMX_Video.h
    │   ├── interface
    │   │   ├── debug_sym
    │   │   │   └── debug_sym.h
    │   │   ├── mmal
    │   │   │   ├── core
    │   │   │   │   ├── mmal_buffer_private.h
    │   │   │   │   ├── mmal_clock_private.h
    │   │   │   │   ├── mmal_component_private.h
    │   │   │   │   ├── mmal_core_private.h
    │   │   │   │   ├── mmal_events_private.h
    │   │   │   │   └── mmal_port_private.h
    │   │   │   ├── mmal_buffer.h
    │   │   │   ├── mmal_clock.h
    │   │   │   ├── mmal_common.h
    │   │   │   ├── mmal_component.h
    │   │   │   ├── mmal_encodings.h
    │   │   │   ├── mmal_events.h
    │   │   │   ├── mmal_format.h
    │   │   │   ├── mmal.h
    │   │   │   ├── mmal_logging.h
    │   │   │   ├── mmal_parameters_audio.h
    │   │   │   ├── mmal_parameters_camera.h
    │   │   │   ├── mmal_parameters_clock.h
    │   │   │   ├── mmal_parameters_common.h
    │   │   │   ├── mmal_parameters.h
    │   │   │   ├── mmal_parameters_video.h
    │   │   │   ├── mmal_pool.h
    │   │   │   ├── mmal_port.h
    │   │   │   ├── mmal_queue.h
    │   │   │   ├── mmal_types.h
    │   │   │   ├── util
    │   │   │   │   ├── mmal_component_wrapper.h
    │   │   │   │   ├── mmal_connection.h
    │   │   │   │   ├── mmal_default_components.h
    │   │   │   │   ├── mmal_graph.h
    │   │   │   │   ├── mmal_il.h
    │   │   │   │   ├── mmal_list.h
    │   │   │   │   ├── mmal_param_convert.h
    │   │   │   │   ├── mmal_util.h
    │   │   │   │   ├── mmal_util_params.h
    │   │   │   │   └── mmal_util_rational.h
    │   │   │   └── vc
    │   │   │       ├── mmal_vc_api_drm.h
    │   │   │       ├── mmal_vc_api.h
    │   │   │       ├── mmal_vc_client_priv.h
    │   │   │       ├── mmal_vc_msgnames.h
    │   │   │       ├── mmal_vc_msgs.h
    │   │   │       ├── mmal_vc_opaque_alloc.h
    │   │   │       └── mmal_vc_shm.h
    │   │   ├── peer
    │   │   │   └── vc_vchi_dispmanx_common.h
    │   │   ├── vchi
    │   │   │   ├── common
    │   │   │   │   └── endian.h
    │   │   │   ├── connections
    │   │   │   │   └── connection.h
    │   │   │   ├── message_drivers
    │   │   │   │   └── message.h
    │   │   │   ├── vchi_cfg.h
    │   │   │   ├── vchi_cfg_internal.h
    │   │   │   ├── vchi_common.h
    │   │   │   ├── vchi.h
    │   │   │   └── vchi_mh.h
    │   │   ├── vchiq_arm
    │   │   │   ├── vchiq_cfg.h
    │   │   │   ├── vchiq.h
    │   │   │   ├── vchiq_if.h
    │   │   │   ├── vchiq_ioctl.h
    │   │   │   ├── vchiq_test.h
    │   │   │   ├── vchiq_test_if.h
    │   │   │   └── vchiq_util.h
    │   │   ├── vcos
    │   │   │   ├── generic
    │   │   │   │   ├── vcos_common.h
    │   │   │   │   ├── vcos_deprecated.h
    │   │   │   │   ├── vcos_generic_blockpool.h
    │   │   │   │   ├── vcos_generic_event_flags.h
    │   │   │   │   ├── vcos_generic_named_sem.h
    │   │   │   │   ├── vcos_generic_quickslow_mutex.h
    │   │   │   │   ├── vcos_generic_reentrant_mtx.h
    │   │   │   │   ├── vcos_generic_tls.h
    │   │   │   │   ├── vcos_joinable_thread_from_plain.h
    │   │   │   │   ├── vcos_latch_from_sem.h
    │   │   │   │   ├── vcos_mem_from_malloc.h
    │   │   │   │   ├── vcos_mutexes_are_reentrant.h
    │   │   │   │   └── vcos_thread_reaper.h
    │   │   │   ├── pthreads
    │   │   │   │   ├── vcos_futex_mutex.h
    │   │   │   │   ├── vcos_platform.h
    │   │   │   │   └── vcos_platform_types.h
    │   │   │   ├── user_nodefs.h
    │   │   │   ├── vcos_assert.h
    │   │   │   ├── vcos_atomic_flags.h
    │   │   │   ├── vcos_attr.h
    │   │   │   ├── vcos_blockpool.h
    │   │   │   ├── vcos_build_info.h
    │   │   │   ├── vcos_cfg.h
    │   │   │   ├── vcos_cmd.h
    │   │   │   ├── vcos_ctype.h
    │   │   │   ├── vcos_dlfcn.h
    │   │   │   ├── vcos_event_flags.h
    │   │   │   ├── vcos_event.h
    │   │   │   ├── vcos.h
    │   │   │   ├── vcos_init.h
    │   │   │   ├── vcos_inttypes.h
    │   │   │   ├── vcos_isr.h
    │   │   │   ├── vcos_legacy_isr.h
    │   │   │   ├── vcos_logging_control.h
    │   │   │   ├── vcos_logging.h
    │   │   │   ├── vcos_lowlevel_thread.h
    │   │   │   ├── vcos_mem.h
    │   │   │   ├── vcos_mempool.h
    │   │   │   ├── vcos_msgqueue.h
    │   │   │   ├── vcos_mutex.h
    │   │   │   ├── vcos_named_semaphore.h
    │   │   │   ├── vcos_once.h
    │   │   │   ├── vcos_queue.h
    │   │   │   ├── vcos_quickslow_mutex.h
    │   │   │   ├── vcos_reentrant_mutex.h
    │   │   │   ├── vcos_semaphore.h
    │   │   │   ├── vcos_stdbool.h
    │   │   │   ├── vcos_stdint.h
    │   │   │   ├── vcos_string.h
    │   │   │   ├── vcos_thread_attr.h
    │   │   │   ├── vcos_thread.h
    │   │   │   ├── vcos_timer.h
    │   │   │   ├── vcos_tls.h
    │   │   │   └── vcos_types.h
    │   │   ├── vcsm
    │   │   │   └── user-vcsm.h
    │   │   ├── vctypes
    │   │   │   ├── vc_display_types.h
    │   │   │   ├── vc_image_structs.h
    │   │   │   └── vc_image_types.h
    │   │   └── vmcs_host
    │   │       ├── khronos
    │   │       │   └── IL
    │   │       │       ├── OMX_Audio.h
    │   │       │       ├── OMX_Broadcom.h
    │   │       │       ├── OMX_Component.h
    │   │       │       ├── OMX_Core.h
    │   │       │       ├── OMX_ILCS.h
    │   │       │       ├── OMX_Image.h
    │   │       │       ├── OMX_Index.h
    │   │       │       ├── OMX_IVCommon.h
    │   │       │       ├── OMX_Other.h
    │   │       │       ├── OMX_Types.h
    │   │       │       └── OMX_Video.h
    │   │       ├── linux
    │   │       │   └── vchost_config.h
    │   │       ├── vc_cec.h
    │   │       ├── vc_cecservice_defs.h
    │   │       ├── vc_cecservice.h
    │   │       ├── vc_cma.h
    │   │       ├── vc_dispmanx.h
    │   │       ├── vc_dispmanx_types.h
    │   │       ├── vc_dispservice_defs.h
    │   │       ├── vc_dispservice_x_defs.h
    │   │       ├── vc_gencmd_defs.h
    │   │       ├── vcgencmd.h
    │   │       ├── vc_hdmi.h
    │   │       ├── vc_hdmi_property.h
    │   │       ├── vchost.h
    │   │       ├── vchost_platform_config.h
    │   │       ├── vcilcs_common.h
    │   │       ├── vc_ilcs_defs.h
    │   │       ├── vcilcs.h
    │   │       ├── vc_imageconv_defs.h
    │   │       ├── vc_sdtv.h
    │   │       ├── vc_service_common.h
    │   │       ├── vc_tvservice_defs.h
    │   │       ├── vc_tvservice.h
    │   │       ├── vc_vchi_audioserv_defs.h
    │   │       ├── vc_vchi_bufman_defs.h
    │   │       ├── vc_vchi_bufman.h
    │   │       ├── vc_vchi_dispmanx.h
    │   │       ├── vc_vchi_gencmd.h
    │   │       └── vc_vchi_gpuserv.h
    │   ├── KHR
    │   │   └── khrplatform.h
    │   ├── vcinclude
    │   │   ├── common.h
    │   │   ├── vc_image_types.h
    │   │   └── vcore.h
    │   ├── VG
    │   │   ├── openvg.h
    │   │   ├── vgext.h
    │   │   ├── vgplatform.h
    │   │   └── vgu.h
    │   └── WF
    │       ├── wfc.h
    │       └── wfcplatform.h
    ├── lib
    │   ├── libbcm_host.so
    │   ├── libbrcmEGL.so
    │   ├── libbrcmGLESv2.so
    │   ├── libbrcmOpenVG.so
    │   ├── libbrcmWFC.so
    │   ├── libcontainers.so
    │   ├── libdebug_sym.so
    │   ├── libdebug_sym_static.a
    │   ├── libdtovl.so
    │   ├── libEGL_static.a
    │   ├── libelftoolchain.so
    │   ├── libGLESv2_static.a
    │   ├── libkhrn_client.a
    │   ├── libkhrn_static.a
    │   ├── libmmal_components.so
    │   ├── libmmal_core.so
    │   ├── libmmal.so
    │   ├── libmmal_util.so
    │   ├── libmmal_vc_client.so
    │   ├── libopenmaxil.so
    │   ├── libvchiq_arm.so
    │   ├── libvchostif.a
    │   ├── libvcilcs.a
    │   ├── libvcos.so
    │   ├── libvcsm.so
    │   ├── pkgconfig
    │   │   ├── bcm_host.pc
    │   │   ├── brcmegl.pc
    │   │   ├── brcmglesv2.pc
    │   │   ├── brcmvg.pc
    │   │   ├── mmal.pc
    │   │   └── vcsm.pc
    │   └── plugins
    │       └── plugins
    │           ├── reader_asf.so
    │           ├── reader_avi.so
    │           ├── reader_binary.so
    │           ├── reader_flv.so
    │           ├── reader_metadata_id3.so
    │           ├── reader_mkv.so
    │           ├── reader_mp4.so
    │           ├── reader_mpga.so
    │           ├── reader_ps.so
    │           ├── reader_qsynth.so
    │           ├── reader_raw_video.so
    │           ├── reader_rcv.so
    │           ├── reader_rtp.so
    │           ├── reader_rtsp.so
    │           ├── reader_rv9.so
    │           ├── reader_simple.so
    │           ├── reader_wav.so
    │           ├── writer_asf.so
    │           ├── writer_avi.so
    │           ├── writer_binary.so
    │           ├── writer_dummy.so
    │           ├── writer_mp4.so
    │           ├── writer_raw_video.so
    │           └── writer_simple.so
    └── src
        └── hello_pi
            ├── hello_audio
            │   ├── audio.c
            │   ├── audioplay.h
            │   ├── Makefile
            │   └── sinewave.c
            ├── hello_dispmanx
            │   ├── dispmanx.c
            │   └── Makefile
            ├── hello_encode
            │   ├── encode.c
            │   └── Makefile
            ├── hello_fft
            │   ├── gpu_fft_base.c
            │   ├── gpu_fft.c
            │   ├── gpu_fft.h
            │   ├── gpu_fft_shaders.c
            │   ├── gpu_fft_trans.c
            │   ├── gpu_fft_trans.h
            │   ├── gpu_fft_twiddles.c
            │   ├── gpu_fft.txt
            │   ├── hello_fft_2d_bitmap.h
            │   ├── hello_fft_2d.c
            │   ├── hello_fft.c
            │   ├── hex
            │   │   ├── shader_1024k.hex
            │   │   ├── shader_128k.hex
            │   │   ├── shader_16k.hex
            │   │   ├── shader_1k.hex
            │   │   ├── shader_2048k.hex
            │   │   ├── shader_256.hex
            │   │   ├── shader_256k.hex
            │   │   ├── shader_2k.hex
            │   │   ├── shader_32k.hex
            │   │   ├── shader_4096k.hex
            │   │   ├── shader_4k.hex
            │   │   ├── shader_512.hex
            │   │   ├── shader_512k.hex
            │   │   ├── shader_64k.hex
            │   │   ├── shader_8k.hex
            │   │   └── shader_trans.hex
            │   ├── mailbox.c
            │   ├── mailbox.h
            │   ├── makefile
            │   └── qasm
            │       ├── gpu_fft_1024k.qasm
            │       ├── gpu_fft_128k.qasm
            │       ├── gpu_fft_16k.qasm
            │       ├── gpu_fft_1k.qasm
            │       ├── gpu_fft_2048k.qasm
            │       ├── gpu_fft_2048k.qinc
            │       ├── gpu_fft_256k.qasm
            │       ├── gpu_fft_256.qasm
            │       ├── gpu_fft_2k.qasm
            │       ├── gpu_fft_32k.qasm
            │       ├── gpu_fft_4096k.qasm
            │       ├── gpu_fft_4k.qasm
            │       ├── gpu_fft_512k.qasm
            │       ├── gpu_fft_512.qasm
            │       ├── gpu_fft_64k.qasm
            │       ├── gpu_fft_8k.qasm
            │       ├── gpu_fft_ex.qinc
            │       ├── gpu_fft.qinc
            │       └── gpu_fft_trans.qasm
            ├── hello_font
            │   ├── main.c
            │   ├── Makefile
            │   └── Vera.ttf
            ├── hello_jpeg
            │   ├── jpeg.c
            │   ├── jpeg.h
            │   └── Makefile
            ├── hello_mmal_encode
            │   ├── Makefile
            │   └── mmal_encode.c
            ├── hello_teapot
            │   ├── cube_texture_and_coords.h
            │   ├── Makefile
            │   ├── models.c
            │   ├── models.h
            │   ├── README.md
            │   ├── teapot.obj.dat
            │   ├── triangle.c
            │   ├── triangle.h
            │   └── video.c
            ├── hello_tiger
            │   ├── license.txt
            │   ├── main.c
            │   ├── Makefile
            │   ├── readme.txt
            │   ├── tiger.c
            │   └── tiger.h
            ├── hello_triangle
            │   ├── cube_texture_and_coords.h
            │   ├── Djenne_128_128.raw
            │   ├── Gaudi_128_128.raw
            │   ├── Lucca_128_128.raw
            │   ├── Makefile
            │   └── triangle.c
            ├── hello_triangle2
            │   ├── Makefile
            │   └── triangle2.c
            ├── hello_video
            │   ├── Makefile
            │   ├── README
            │   ├── test.h264
            │   └── video.c
            ├── hello_videocube
            │   ├── cube_texture_and_coords.h
            │   ├── Makefile
            │   ├── README.md
            │   ├── triangle.c
            │   ├── triangle.h
            │   └── video.c
            ├── hello_world
            │   ├── Makefile
            │   └── world.c
            ├── libs
            │   ├── ilclient
            │   │   ├── ilclient.c
            │   │   ├── ilclient.h
            │   │   ├── ilcore.c
            │   │   └── Makefile
            │   ├── revision
            │   │   ├── Makefile
            │   │   ├── revision.c
            │   │   └── revision.h
            │   └── vgfont
            │       ├── font.c
            │       ├── graphics.c
            │       ├── graphics_x_private.h
            │       ├── Makefile
            │       ├── vgfont.h
            │       ├── vgft.c
            │       └── vgft.h
            ├── Makefile
            ├── Makefile.include
            ├── README
            └── rebuild.sh
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216
    • 217
    • 218
    • 219
    • 220
    • 221
    • 222
    • 223
    • 224
    • 225
    • 226
    • 227
    • 228
    • 229
    • 230
    • 231
    • 232
    • 233
    • 234
    • 235
    • 236
    • 237
    • 238
    • 239
    • 240
    • 241
    • 242
    • 243
    • 244
    • 245
    • 246
    • 247
    • 248
    • 249
    • 250
    • 251
    • 252
    • 253
    • 254
    • 255
    • 256
    • 257
    • 258
    • 259
    • 260
    • 261
    • 262
    • 263
    • 264
    • 265
    • 266
    • 267
    • 268
    • 269
    • 270
    • 271
    • 272
    • 273
    • 274
    • 275
    • 276
    • 277
    • 278
    • 279
    • 280
    • 281
    • 282
    • 283
    • 284
    • 285
    • 286
    • 287
    • 288
    • 289
    • 290
    • 291
    • 292
    • 293
    • 294
    • 295
    • 296
    • 297
    • 298
    • 299
    • 300
    • 301
    • 302
    • 303
    • 304
    • 305
    • 306
    • 307
    • 308
    • 309
    • 310
    • 311
    • 312
    • 313
    • 314
    • 315
    • 316
    • 317
    • 318
    • 319
    • 320
    • 321
    • 322
    • 323
    • 324
    • 325
    • 326
    • 327
    • 328
    • 329
    • 330
    • 331
    • 332
    • 333
    • 334
    • 335
    • 336
    • 337
    • 338
    • 339
    • 340
    • 341
    • 342
    • 343
    • 344
    • 345
    • 346
    • 347
    • 348
    • 349
    • 350
    • 351
    • 352
    • 353
    • 354
    • 355
    • 356
    • 357
    • 358
    • 359
    • 360
    • 361
    • 362
    • 363
    • 364
    • 365
    • 366
    • 367
    • 368
    • 369
    • 370
    • 371
    • 372
    • 373
    • 374
    • 375
    • 376
    • 377
    • 378
    • 379
    • 380
    • 381
    • 382
    • 383
    • 384
    • 385
    • 386
    • 387
    • 388
    • 389
    • 390
    • 391
    • 392
    • 393
    • 394
    • 395
    • 396
    • 397
    • 398
    • 399
    • 400
    • 401
    • 402
    • 403
    • 404
    • 405
    • 406
    • 407
    • 408
    • 409
    • 410
    • 411
    • 412
    • 413
    • 414
    • 415
    • 416
    • 417
    • 418
    • 419
    • 420
    • 421
    • 422
    • 423
    • 424
    • 425
    • 426
    • 427
    • 428
    • 429
    • 430
    • 431
    • 432
    • 433
    • 434
    • 435
    • 436
    • 437
    • 438
    • 439
    • 440
    • 441
    • 442
    • 443
    • 444
    • 445
    • 446
    • 447
    • 448
    • 449
    • 450
    • 451
    • 452

    这些文件博主也不确定是否是系统刷好后就有的,因为中途折腾的时候安装过一些依赖,并且博主的系统自带了FFmpeg程序。常见需要安装的依赖有:libomxil-bellagio-dev等。

    sudo apt-get install libomxil-bellagio-dev #在树莓派上安装
    
    • 1

    ②.编写配置脚本

    注意:最好不要在这个脚本中添加注释,或者把注释放到最后,续航符号\加上注释有时候会导致命令错误、配置出错。

    #!/bin/sh
    
    ./configure \
    --enable-shared \
    --disable-static \
    --prefix=`pwd`/pi_install \
    --extra-cflags=-I/home/boy/opensource/vc/include/IL \
    --extra-cflags=-I/home/boy/opensource/x264/pi_install/include \
    --extra-ldflags=-L/home/boy/opensource/x264/pi_install/lib \
    --extra-ldflags=-L/home/boy/opensource/vc/lib \
    --enable-omx \
    --enable-omx-rpi \
    --enable-encoder=h264_omx \
    --enable-libx264 \
    --enable-cross-compile \
    --cross-prefix=arm-linux-gnueabihf- \
    --arch=arm \
    --target-os=linux \
    --enable-gpl
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    这几条即为配置omx硬件编码支持的选项:

    --enable-omx \
    --enable-omx-rpi \
    --enable-encoder=h264_omx \
    
    • 1
    • 2
    • 3

    若出现提示缺少头文件等错误:

    boy@ubuntu:~/opensource/ffmpeg$ ./pi_config.sh 
    ERROR: OpenMAX IL headers from raspberrypi/firmware not found
    
    • 1
    • 2

    通过extra-cflags、extra-ldflags添加外部头文件、库文件搜索路径可尝试解决,如下:

    --extra-cflags=-I/home/boy/opensource/vc/include/IL \ #复制自树莓派/opt/vc目录,添加OpenMAX IL头文件路径
    --extra-cflags=-I/home/boy/opensource/x264/pi_install/include \ #x264头文件路径
    --extra-ldflags=-L/home/boy/opensource/x264/pi_install/lib \ #x264库文件路径
    --extra-ldflags=-L/home/boy/opensource/vc/lib \ #复制自树莓派/opt/vc目录,omx、mmal等库路径
    
    • 1
    • 2
    • 3
    • 4

    ③.编译、安装

    上一步没问题后,就会生成相应的makefile,执行make -j8多线程编译,完成后再make install即可在安装到相应路径:

    boy@ubuntu:~/opensource/ffmpeg$ cd pi_install/
    boy@ubuntu:~/opensource/ffmpeg/pi_install$ ls
    bin  include  lib  share
    boy@ubuntu:~/opensource/ffmpeg/pi_install$ 
    
    • 1
    • 2
    • 3
    • 4

    相应的头文件、库文件添加到应用工程即可编译,在树莓派中调用的时候再添加这些相关的so库到库文件搜索路径即可。

    使用硬件编码的程序,后续项目用上再放出来,未完待续~~

    编码Demo测试

    在doc/example目录下的encode_video.c有完整的FFmpeg的视频编码demo,将yuv420p编码为H264:

    /*
     * Copyright (c) 2001 Fabrice Bellard
     *
     * Permission is hereby granted, free of charge, to any person obtaining a copy
     * of this software and associated documentation files (the "Software"), to deal
     * in the Software without restriction, including without limitation the rights
     * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     * copies of the Software, and to permit persons to whom the Software is
     * furnished to do so, subject to the following conditions:
     *
     * The above copyright notice and this permission notice shall be included in
     * all copies or substantial portions of the Software.
     *
     * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
     * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
     * THE SOFTWARE.
     */
    
    /**
     * @file
     * video encoding with libavcodec API example
     *
     * @example encode_video.c
     */
    
    #include 
    #include 
    #include 
    
    #include 
    
    #include 
    #include 
    
    static void encode(AVCodecContext *enc_ctx, AVFrame *frame, AVPacket *pkt,
                       FILE *outfile)
    {
        int ret;
    
        /* send the frame to the encoder */
        if (frame)
            printf("Send frame %3"PRId64"\n", frame->pts);
    
        ret = avcodec_send_frame(enc_ctx, frame);
        if (ret < 0) {
            fprintf(stderr, "Error sending a frame for encoding\n");
            exit(1);
        }
    
        while (ret >= 0) {
            ret = avcodec_receive_packet(enc_ctx, pkt);
            if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
                return;
            else if (ret < 0) {
                fprintf(stderr, "Error during encoding\n");
                exit(1);
            }
    
            printf("Write packet %3"PRId64" (size=%5d)\n", pkt->pts, pkt->size);
            fwrite(pkt->data, 1, pkt->size, outfile);
            av_packet_unref(pkt);
        }
    }
    
    int main(int argc, char **argv)
    {
        const char *filename, *codec_name;
        const AVCodec *codec;
        AVCodecContext *c= NULL;
        int i, ret, x, y;
        FILE *f;
        AVFrame *frame;
        AVPacket *pkt;
        uint8_t endcode[] = { 0, 0, 1, 0xb7 };
    
        if (argc <= 2) {
            fprintf(stderr, "Usage: %s  \n", argv[0]);
            exit(0);
        }
        filename = argv[1];
        codec_name = argv[2];
    
        /* find the mpeg1video encoder */
        codec = avcodec_find_encoder_by_name(codec_name);
        if (!codec) {
            fprintf(stderr, "Codec '%s' not found\n", codec_name);
            exit(1);
        }
    
        c = avcodec_alloc_context3(codec);
        if (!c) {
            fprintf(stderr, "Could not allocate video codec context\n");
            exit(1);
        }
    
        pkt = av_packet_alloc();
        if (!pkt)
            exit(1);
    
        /* put sample parameters */
        c->bit_rate = 400000;
        /* resolution must be a multiple of two */
        c->width = 352;
        c->height = 288;
        /* frames per second */
        c->time_base = (AVRational){1, 25};
        c->framerate = (AVRational){25, 1};
    
        /* emit one intra frame every ten frames
         * check frame pict_type before passing frame
         * to encoder, if frame->pict_type is AV_PICTURE_TYPE_I
         * then gop_size is ignored and the output of encoder
         * will always be I frame irrespective to gop_size
         */
        c->gop_size = 10;
        c->max_b_frames = 1;
        c->pix_fmt = AV_PIX_FMT_YUV420P;
    
        if (codec->id == AV_CODEC_ID_H264)
            av_opt_set(c->priv_data, "preset", "slow", 0);
    
        /* open it */
        ret = avcodec_open2(c, codec, NULL);
        if (ret < 0) {
            fprintf(stderr, "Could not open codec: %s\n", av_err2str(ret));
            exit(1);
        }
    
        f = fopen(filename, "wb");
        if (!f) {
            fprintf(stderr, "Could not open %s\n", filename);
            exit(1);
        }
    
        frame = av_frame_alloc();
        if (!frame) {
            fprintf(stderr, "Could not allocate video frame\n");
            exit(1);
        }
        frame->format = c->pix_fmt;
        frame->width  = c->width;
        frame->height = c->height;
    
        ret = av_frame_get_buffer(frame, 0);
        if (ret < 0) {
            fprintf(stderr, "Could not allocate the video frame data\n");
            exit(1);
        }
    
        /* encode 1 second of video */
        for (i = 0; i < 25; i++) {
            fflush(stdout);
    
            /* Make sure the frame data is writable.
               On the first round, the frame is fresh from av_frame_get_buffer()
               and therefore we know it is writable.
               But on the next rounds, encode() will have called
               avcodec_send_frame(), and the codec may have kept a reference to
               the frame in its internal structures, that makes the frame
               unwritable.
               av_frame_make_writable() checks that and allocates a new buffer
               for the frame only if necessary.
             */
            ret = av_frame_make_writable(frame);
            if (ret < 0)
                exit(1);
    
            /* Prepare a dummy image.
               In real code, this is where you would have your own logic for
               filling the frame. FFmpeg does not care what you put in the
               frame.
             */
            /* Y */
            for (y = 0; y < c->height; y++) {
                for (x = 0; x < c->width; x++) {
                    frame->data[0][y * frame->linesize[0] + x] = x + y + i * 3;
                }
            }
    
            /* Cb and Cr */
            for (y = 0; y < c->height/2; y++) {
                for (x = 0; x < c->width/2; x++) {
                    frame->data[1][y * frame->linesize[1] + x] = 128 + y + i * 2;
                    frame->data[2][y * frame->linesize[2] + x] = 64 + x + i * 5;
                }
            }
    
            frame->pts = i;
    
            /* encode the image */
            encode(c, frame, pkt, f);
        }
    
        /* flush the encoder */
        encode(c, NULL, pkt, f);
    
        /* Add sequence end code to have a real MPEG file.
           It makes only sense because this tiny examples writes packets
           directly. This is called "elementary stream" and only works for some
           codecs. To create a valid file, you usually need to write packets
           into a proper file format or protocol; see muxing.c.
         */
        if (codec->id == AV_CODEC_ID_MPEG1VIDEO || codec->id == AV_CODEC_ID_MPEG2VIDEO)
            fwrite(endcode, 1, sizeof(endcode), f);
        fclose(f);
    
        avcodec_free_context(&c);
        av_frame_free(&frame);
        av_packet_free(&pkt);
    
        return 0;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98
    • 99
    • 100
    • 101
    • 102
    • 103
    • 104
    • 105
    • 106
    • 107
    • 108
    • 109
    • 110
    • 111
    • 112
    • 113
    • 114
    • 115
    • 116
    • 117
    • 118
    • 119
    • 120
    • 121
    • 122
    • 123
    • 124
    • 125
    • 126
    • 127
    • 128
    • 129
    • 130
    • 131
    • 132
    • 133
    • 134
    • 135
    • 136
    • 137
    • 138
    • 139
    • 140
    • 141
    • 142
    • 143
    • 144
    • 145
    • 146
    • 147
    • 148
    • 149
    • 150
    • 151
    • 152
    • 153
    • 154
    • 155
    • 156
    • 157
    • 158
    • 159
    • 160
    • 161
    • 162
    • 163
    • 164
    • 165
    • 166
    • 167
    • 168
    • 169
    • 170
    • 171
    • 172
    • 173
    • 174
    • 175
    • 176
    • 177
    • 178
    • 179
    • 180
    • 181
    • 182
    • 183
    • 184
    • 185
    • 186
    • 187
    • 188
    • 189
    • 190
    • 191
    • 192
    • 193
    • 194
    • 195
    • 196
    • 197
    • 198
    • 199
    • 200
    • 201
    • 202
    • 203
    • 204
    • 205
    • 206
    • 207
    • 208
    • 209
    • 210
    • 211
    • 212
    • 213
    • 214
    • 215
    • 216

    简单构建一个工程(基于CMake构建),工程目录如下:

    boy@ubuntu:~/encode_test$ ls -l
    总用量 20
    -rwxrwxr-x  1 boy boy  285 45 23:04 build.sh
    -rw-rw-r--  1 boy boy  864 41 23:39 CMakeLists.txt
    drwxrwxr-x 10 boy boy 4096 41 23:30 include
    drwxrwxr-x  2 boy boy 4096 41 23:31 lib
    drwxrwxr-x  2 boy boy 4096 41 23:32 src
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    lib下即交叉编译生成的相应so库文件,include为对应的头文件,src即为encode_video.c源码,CMake如下:

    cmake_minimum_required(VERSION 3.0.0)
    # 设置编译工具链
    set(GCC "/opt/rpi_tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-gcc")
    set(GXX "/opt/rpi_tools/arm-bcm2708/arm-rpi-4.9.3-linux-gnueabihf/bin/arm-linux-gnueabihf-g++")
    set(CMAKE_C_COMPLIER ${GCC})
    set(CMAKE_CXX_COMPLIER ${GXX})
    # 工程名
    project(enc_test VERSION 0.1.0)
    
    # 设置头文件查找路径
    include_directories(
        ${PROJECT_SOURCE_DIR}/include
    )
    # 查找src目录下的源文件,赋值到SRCS变量
    aux_source_directory(${PROJECT_SOURCE_DIR}/src SRCS)
    # 设置库文件搜索路径
    link_directories(
        "${PROJECT_SOURCE_DIR}/lib"
    )
    # 生成可执行文件
    add_executable(${PROJECT_NAME} ${SRCS})
    
    #指定链接库
    target_link_libraries(
        ${PROJECT_NAME}
        avcodec
        avdevice
        avfilter
        avformat
        avutil
        postproc
        swresample
        swscale
    )
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    cmake生成makefile后,将make得到的可执行文件即可放到树莓派中运行测试。

    添加相关so库

    将x264和FFmpeg编译生成的库文件放到树莓派的库搜索路径中,然后运行测试:

    pi@raspberrypi:~ $ ./enc_test out.h264 libx264
    
    • 1

    此时就会调用x264编码器,将ffmpeg生成的yuv420p格式的帧转换为h264帧输出到文件out.h264中:

    [libx264 @ 0x1e20020] using cpu capabilities: none!
    [libx264 @ 0x1e20020] profile High, level 1.3, 4:2:0, 8-bit
    Send frame   0
    Send frame   1
    Send frame   2
    Send frame   3
    Send frame   4
    Send frame   5
    Send frame   6
    Send frame   7
    Send frame   8
    Send frame   9
    Send frame  10
    Send frame  11
    Send frame  12
    Send frame  13
    Send frame  14
    Send frame  15
    Send frame  16
    Send frame  17
    Send frame  18
    Write packet   0 (size= 2068)
    Send frame  19
    Write packet   2 (size=  674)
    Send frame  20
    Write packet   1 (size=  133)
    Send frame  21
    Write packet   4 (size=  767)
    Send frame  22
    Write packet   3 (size=  193)
    Send frame  23
    Write packet   6 (size=  682)
    Send frame  24
    Write packet   5 (size=  521)
    Write packet   8 (size=  868)
    Write packet   7 (size=  484)
    Write packet   9 (size=  638)
    Write packet  10 (size= 2304)
    Write packet  12 (size= 1311)
    Write packet  11 (size=  829)
    Write packet  14 (size=  866)
    Write packet  13 (size=  523)
    Write packet  16 (size=  831)
    Write packet  15 (size=  635)
    Write packet  18 (size= 1034)
    Write packet  17 (size=  576)
    Write packet  19 (size=  682)
    Write packet  20 (size= 2477)
    Write packet  22 (size= 1415)
    Write packet  21 (size=  997)
    Write packet  24 (size=  862)
    Write packet  23 (size=  878)
    [libx264 @ 0x1e20020] frame I:3     Avg QP:24.66  size:  2283
    [libx264 @ 0x1e20020] frame P:12    Avg QP:23.14  size:   886
    [libx264 @ 0x1e20020] frame B:10    Avg QP:27.26  size:   577
    [libx264 @ 0x1e20020] consecutive B-frames: 20.0% 80.0%
    [libx264 @ 0x1e20020] mb I  I16..4: 77.3% 12.6% 10.1%
    [libx264 @ 0x1e20020] mb P  I16..4: 76.7%  1.1%  0.2%  P16..4: 20.4%  1.2%  0.4%  0.0%  0.0%    skip: 0.0%
    [libx264 @ 0x1e20020] mb B  I16..4:  0.0%  0.0%  0.0%  B16..8: 13.9%  0.2%  0.0%  direct:12.4%  skip:73.5%  L0:25.0% L1:57.0% BI:18.1%
    [libx264 @ 0x1e20020] final ratefactor: 15.47
    [libx264 @ 0x1e20020] 8x8 transform intra:4.2% inter:16.2%
    [libx264 @ 0x1e20020] direct mvs  spatial:0.0% temporal:100.0%
    [libx264 @ 0x1e20020] coded y,uvDC,uvAC intra: 5.4% 30.6% 4.6% inter: 1.3% 39.8% 9.0%
    [libx264 @ 0x1e20020] i16 v,h,dc,p:  0%  0%  0% 100%
    [libx264 @ 0x1e20020] i8 v,h,dc,ddl,ddr,vr,hd,vl,hu:  1% 38% 12% 48%  0%  0%  0%  0%  1%
    [libx264 @ 0x1e20020] i4 v,h,dc,ddl,ddr,vr,hd,vl,hu:  8%  5% 13% 54%  1%  6%  5%  5%  2%
    [libx264 @ 0x1e20020] i8c dc,h,v,p:  1%  7%  5% 87%
    [libx264 @ 0x1e20020] Weighted P-Frames: Y:0.0% UV:0.0%
    [libx264 @ 0x1e20020] ref P L0: 97.5%  0.6%  1.5%  0.2%  0.1%  0.1%
    [libx264 @ 0x1e20020] ref B L0: 60.6% 33.1%  6.2%
    [libx264 @ 0x1e20020] kb/s:185.98	
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71

    效果

    生成H264文件使用VLC播放器播放如下:

    [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pAAmYzoZ-1666404462192)(resources/f07f1a9831034fdbb4d7d1cf79a75d61.png)]

  • 相关阅读:
    SpringCloud-4-基础工程-创建服务提供者
    进程最后的遗言
    Centos 7 下配置Samba服务
    HTTP代理反爬虫技术详解
    vivado里那些看不懂的原语
    用户注册场景
    Eureka 平滑迁移 Nacos 方案
    辽宁2022农民丰收节 国稻种芯:4个主会场31个分会场同步
    机器人制作开源方案 | 桌面级全向底盘--本体说明+驱动控制
    跟我学Python图像处理丨何为图像的灰度非线性变换
  • 原文地址:https://blog.csdn.net/qq_41790078/article/details/127458178