本文将带您了解关于在Linux上使用FFmpeg从OpenCV3编写x264的新内容,另外,我们还将为您提供关于2023-03-07:x264的视频编码器,不用ffmpeg,用libx264.dll也
本文将带您了解关于在Linux上使用FFmpeg从OpenCV 3编写x264的新内容,另外,我们还将为您提供关于2023-03-07:x264的视频编码器,不用ffmpeg,用libx264.dll也行。请用go语言调用libx264.dll,将yuv文件编码成h264文件。、Android使用FFmpeg(五)--ffmpeg实现音频播放(使用openSL ES进行播放)、Android使用FFmpeg--Shell脚本编写与执行编译FFmpeg库、arm-linux Opencv+ffmpeg 交叉编译的实用信息。
本文目录一览:- 在Linux上使用FFmpeg从OpenCV 3编写x264
- 2023-03-07:x264的视频编码器,不用ffmpeg,用libx264.dll也行。请用go语言调用libx264.dll,将yuv文件编码成h264文件。
- Android使用FFmpeg(五)--ffmpeg实现音频播放(使用openSL ES进行播放)
- Android使用FFmpeg--Shell脚本编写与执行编译FFmpeg库
- arm-linux Opencv+ffmpeg 交叉编译
在Linux上使用FFmpeg从OpenCV 3编写x264
我在通过FFmpeg(“’X’,‘2’,‘6’,‘4’” FOURCC)用OpenCV
3编写h264视频时遇到问题。到目前为止,我已经看过所有与SO相关的文章,但是没有任何帮助。码:
cv::VideoWriter writer(output_path.string(), CV_FOURCC(''X'',''2'',''6'',''4''), 60, frame_size);
输出:
OpenCV:FFMPEG:标签0x34363258 /’X264’不支持编解码器ID 28和格式’mp4 / MP4(MPEG-4 Part
14)’OpenCV:FFMPEG:后退以使用标签0x00000021 /’!???’
产生的视频非常小(按字节),并且不可读。将four_cc设置为-1会导致FFmpeg产生“未知标签”,我没有得到任何提示来选择编解码器,就像其他人建议的那样。
OpenCV 3文档指出:
带有MP4容器的FFMPEG后端本机使用其他值作为fourcc代码:请参见ObjectType,因此您可能会从OpenCV收到有关fourcc代码转换的警告消息。
有任何建议/解决方法吗?
PS ffmpeg是Ubuntu维护者提供的最新信息,它列出了使用 --enable-libx264
编辑: 我试图使用mkv容器而不是mp4。关于不支持标签的警告消失了,但是仍无法读取生成的视频。
答案1
小编典典该问题与显示的警告无关。我正在尝试编写单通道图像,而VideoWriter则期望使用3通道彩色图像(VideoWriter的构造函数的第5个参数isColor的默认值为“true”)。解决方案是将isColor设置为false。
2023-03-07:x264的视频编码器,不用ffmpeg,用libx264.dll也行。请用go语言调用libx264.dll,将yuv文件编码成h264文件。
2023-03-07:x264的视频编码器,不用ffmpeg,用libx264.dll也行。请用go语言调用libx264.dll,将yuv文件编码成h264文件。
答案2023-03-07:
使用 github.com/moonfdd/x264-go 库,代码写在了这个库里。
这个库根据头文件编写,不依赖头文件。
执行命令:
go run ./examples/simplest_x264_encoder/main.go
参考了雷霄骅的基于libx264的视频编码器,代码用golang编写。代码如下:
// https://github.com/leixiaohua1020/simplest_encoder/blob/master/simplest_x264_encoder/simplest_x264_encoder.cpp
package main
import (
"fmt"
"os"
"unsafe"
"github.com/moonfdd/ffmpeg-go/ffcommon"
"github.com/moonfdd/x264-go/libx264"
"github.com/moonfdd/x264-go/libx264common"
)
func main0() ffcommon.FInt {
var ret ffcommon.FInt
var y_size ffcommon.FInt
var i, j ffcommon.FInt
//FILE* fp_src = fopen("../cuc_ieschool_640x360_yuv444p.yuv", "rb");
fp_src, _ := os.Open("./resources/cuc_ieschool_640x360_yuv420p.yuv")
fp_dst_file := "./out/cuc_ieschool_640x360_yuv420p.h264"
fp_dst, _ := os.Create(fp_dst_file)
//Encode 50 frame
//if set 0, encode all frame
var frame_num ffcommon.FInt = 0
var csp ffcommon.FInt = libx264.X264_CSP_I420
var width, height ffcommon.FInt = 640, 360
var iNal ffcommon.FInt = 0
var pNals *libx264.X264NalT
var pHandle *libx264.X264T
pPic_in := new(libx264.X264PictureT)
pPic_out := new(libx264.X264PictureT)
pParam := new(libx264.X264ParamT)
//Check
if fp_src == nil || fp_dst == nil {
fmt.Printf("Error open files.\n")
return -1
}
pParam.X264ParamDefault()
pParam.IWidth = width
pParam.IHeight = height
/*
//Param
pParam->i_log_level = X264_LOG_DEBUG;
pParam->i_threads = X264_SYNC_LOOKAHEAD_AUTO;
pParam->i_frame_total = 0;
pParam->i_keyint_max = 10;
pParam->i_bframe = 5;
pParam->b_open_gop = 0;
pParam->i_bframe_pyramid = 0;
pParam->rc.i_qp_constant=0;
pParam->rc.i_qp_max=0;
pParam->rc.i_qp_min=0;
pParam->i_bframe_adaptive = X264_B_ADAPT_TRELLIS;
pParam->i_fps_den = 1;
pParam->i_fps_num = 25;
pParam->i_timebase_den = pParam->i_fps_num;
pParam->i_timebase_num = pParam->i_fps_den;
*/
pParam.ICsp = csp
pParam.X264ParamApplyProfile(libx264.X264ProfileNames[5])
pHandle = pParam.X264EncoderOpen164()
pPic_out.X264PictureInit()
pPic_in.X264PictureAlloc(csp, pParam.IWidth, pParam.IHeight)
//ret = x264_encoder_headers(pHandle, &pNals, &iNal);
y_size = pParam.IWidth * pParam.IHeight
//detect frame number
if frame_num == 0 {
fi, _ := fp_src.Stat()
switch csp {
case libx264.X264_CSP_I444:
frame_num = int32(fi.Size()) / (y_size * 3)
case libx264.X264_CSP_I420:
frame_num = int32(fi.Size()) / (y_size * 3 / 2)
default:
fmt.Printf("Colorspace Not Support.\n")
return -1
}
}
//Loop to Encode
for i = 0; i < frame_num; i++ {
switch csp {
case libx264.X264_CSP_I444:
fp_src.Read(ffcommon.ByteSliceFromByteP(pPic_in.Img.Plane[0], int(y_size))) //Y
fp_src.Read(ffcommon.ByteSliceFromByteP(pPic_in.Img.Plane[1], int(y_size))) //U
fp_src.Read(ffcommon.ByteSliceFromByteP(pPic_in.Img.Plane[2], int(y_size))) //V
case libx264.X264_CSP_I420:
fp_src.Read(ffcommon.ByteSliceFromByteP(pPic_in.Img.Plane[0], int(y_size))) //Y
fp_src.Read(ffcommon.ByteSliceFromByteP(pPic_in.Img.Plane[1], int(y_size/4))) //U
fp_src.Read(ffcommon.ByteSliceFromByteP(pPic_in.Img.Plane[2], int(y_size/4))) //V
default:
fmt.Printf("Colorspace Not Support.\n")
return -1
}
pPic_in.IPts = int64(i)
ret = pHandle.X264EncoderEncode(&pNals, &iNal, pPic_in, pPic_out)
if ret < 0 {
fmt.Printf("Error.\n")
return -1
}
fmt.Printf("Succeed encode frame: %5d\n", i)
for j = 0; j < iNal; j++ {
a := unsafe.Sizeof(libx264.X264NalT{})
pNal := (*libx264.X264NalT)(unsafe.Pointer(uintptr(unsafe.Pointer(pNals)) + uintptr(a*uintptr(j))))
fp_dst.Write(ffcommon.ByteSliceFromByteP(pNal.PPayload, int(pNal.IPayload)))
}
}
i = 0
//flush encoder
for {
ret = pHandle.X264EncoderEncode(&pNals, &iNal, nil, pPic_out)
if ret == 0 {
break
}
fmt.Printf("Flush 1 frame.\n")
for j = 0; j < iNal; j++ {
a := unsafe.Sizeof(libx264.X264NalT{})
pNal := (*libx264.X264NalT)(unsafe.Pointer(uintptr(unsafe.Pointer(pNals)) + uintptr(a*uintptr(j))))
fp_dst.Write(ffcommon.ByteSliceFromByteP(pNal.PPayload, int(pNal.IPayload)))
}
i++
}
pPic_in.X264PictureClean()
pHandle.X264EncoderClose()
pHandle = nil
fp_src.Close()
fp_dst.Close()
fmt.Printf("\nffplay %s\n", fp_dst_file)
return 0
}
func main() {
fmt.Println(libx264.X264_POINTVER)
os.Setenv("Path", os.Getenv("Path")+";./lib")
libx264common.SetLibx264Path("./lib/libx264-164.dll")
main0()
}
Android使用FFmpeg(五)--ffmpeg实现音频播放(使用openSL ES进行播放)
关于
Android使用FFmpeg(一)--编译ffmpeg
Android使用FFmpeg(二)--Android Studio配置ffmpeg
Android使用FFmpeg(三)--ffmpeg实现视频播放
Android使用FFmpeg(四)--ffmpeg实现音频播放(使用AudioTrack进行播放)
Android使用FFmpeg(五)--ffmpeg实现音频播放(使用openSL ES进行播放)
Android使用FFmpeg(六)--ffmpeg实现音视频同步播放
Android使用FFmpeg(七)--ffmpeg实现暂停、快退快进播放
准备工作
openSL ES了解
正文
实现整体思路:使用ffmpeg解封装、解码视频得到pcm数据-->数据添加到opensl es缓冲区中-->播放
实现具体思路:因为在上篇中详细讲解了将视频通过ffmpeg解码成pcm,所以在这篇中将详细讲解如何通过opensl es播放。
我们还是根据流程图来进行代码的编写,注释已经写好,代码不懂之处可以看注释:
1.创建引擎:
//创建引擎
void createEngine(){
slCreateEngine(&engineObject,0,NULL,0,NULL,NULL);//创建引擎
(*engineObject)->Realize(engineObject,SL_BOOLEAN_FALSE);//实现engineObject接口对象
(*engineObject)->GetInterface(engineObject,SL_IID_ENGINE,&engineEngine);//通过引擎调用接口初始化SLEngineItf
}
2.创建混音器:
//创建混音器
void createMixVolume(){
(*engineEngine)->CreateOutputMix(engineEngine,&outputMixObject,0,0,0);//用引擎对象创建混音器接口对象
(*outputMixObject)->Realize(outputMixObject,SL_BOOLEAN_FALSE);//实现混音器接口对象
SLresult sLresult = (*outputMixObject)->GetInterface(outputMixObject,SL_IID_ENVIRONMENTALREVERB,&outputMixEnvironmentalReverb);//利用混音器实例对象接口初始化具体的混音器对象
//设置
if (SL_RESULT_SUCCESS == sLresult) {
(*outputMixEnvironmentalReverb)->
SetEnvironmentalReverbProperties(outputMixEnvironmentalReverb, &settings);
}
}
3.创建播放器并播放:
void createPlayer(){
//初始化ffmpeg
int rate;
int channels;
createFFmpeg(&rate,&channels);
LOGE("RATE %d",rate);
LOGE("channels %d",channels);
/*
* typedef struct SLDataLocator_AndroidBufferQueue_ {
SLuint32 locatorType;//缓冲区队列类型
SLuint32 numBuffers;//buffer位数
} */
SLDataLocator_AndroidBufferQueue android_queue = {SL_DATALOCATOR_ANDROIDSIMPLEBUFFERQUEUE,2};
/**
typedef struct SLDataFormat_PCM_ {
SLuint32 formatType; pcm
SLuint32 numChannels; 通道数
SLuint32 samplesPerSec; 采样率
SLuint32 bitsPerSample; 采样位数
SLuint32 containerSize; 包含位数
SLuint32 channelMask; 立体声
SLuint32 endianness; end标志位
} SLDataFormat_PCM;
*/
SLDataFormat_PCM pcm = {SL_DATAFORMAT_PCM,channels,rate*1000
,SL_PCMSAMPLEFORMAT_FIXED_16
,SL_PCMSAMPLEFORMAT_FIXED_16
,SL_SPEAKER_FRONT_LEFT|SL_SPEAKER_FRONT_RIGHT,SL_BYTEORDER_LITTLEENDIAN};
/*
* typedef struct SLDataSource_ {
void *pLocator;//缓冲区队列
void *pFormat;//数据样式,配置信息
} SLDataSource;
* */
SLDataSource dataSource = {&android_queue,&pcm};
SLDataLocator_OutputMix slDataLocator_outputMix={SL_DATALOCATOR_OUTPUTMIX,outputMixObject};
SLDataSink slDataSink = {&slDataLocator_outputMix,NULL};
const SLInterfaceID ids[3]={SL_IID_BUFFERQUEUE,SL_IID_EFFECTSEND,SL_IID_VOLUME};
const SLboolean req[3]={SL_BOOLEAN_FALSE,SL_BOOLEAN_FALSE,SL_BOOLEAN_FALSE};
/*
* SLresult (*CreateAudioPlayer) (
SLEngineItf self,
SLObjectItf * pPlayer,
SLDataSource *pAudioSrc,//数据设置
SLDataSink *pAudioSnk,//关联混音器
SLuint32 numInterfaces,
const SLInterfaceID * pInterfaceIds,
const SLboolean * pInterfaceRequired
);
* */
LOGE("执行到此处")
(*engineEngine)->CreateAudioPlayer(engineEngine,&audioplayer,&dataSource,&slDataSink,3,ids,req);
(*audioplayer)->Realize(audioplayer,SL_BOOLEAN_FALSE);
LOGE("执行到此处2")
(*audioplayer)->GetInterface(audioplayer,SL_IID_PLAY,&slPlayItf);//初始化播放器
//注册缓冲区,通过缓冲区里面 的数据进行播放
(*audioplayer)->GetInterface(audioplayer,SL_IID_BUFFERQUEUE,&slBufferQueueItf);
//设置回调接口
(*slBufferQueueItf)->RegisterCallback(slBufferQueueItf,getQueueCallBack,NULL);
//播放
(*slPlayItf)->SetPlayState(slPlayItf,SL_PLAYSTATE_PLAYING);
//开始播放
getQueueCallBack(slBufferQueueItf,NULL);
}
//回调的函数
void getQueueCallBack(SLAndroidSimpleBufferQueueItf slBufferQueueItf, void* context){
buffersize=0;
getPcm(&buffer,&buffersize);
if(buffer!=NULL&&buffersize!=0){
//将得到的数据加入到队列中
(*slBufferQueueItf)->Enqueue(slBufferQueueItf,buffer,buffersize);
}
}
4.释放资源,从下往上依次释放:
void realseResource(){
if(audioplayer!=NULL){
(*audioplayer)->Destroy(audioplayer);
audioplayer=NULL;
slBufferQueueItf=NULL;
slPlayItf=NULL;
}
if(outputMixObject!=NULL){
(*outputMixObject)->Destroy(outputMixObject);
outputMixObject=NULL;
outputMixEnvironmentalReverb=NULL;
}
if(engineObject!=NULL){
(*engineObject)->Destroy(engineObject);
engineObject=NULL;
engineEngine=NULL;
}
realseFFmpeg();
}
5.关于使用ffmpeg得到pcm,我们将其单独写入一个cpp文件中,分为三部分:创建,得到pcm,释放资源。方便在openSL ES这边进行一个调用。具体代码的注释和思路在上篇中已经讲解,不懂的请看上篇的内容。这里的代码只是将整体的代码进行了分类和模块化。
//
// Created by david on 2017/9/25.
//
#include "FFmpegMusic.h"
AVFormatContext *pFormatCtx;
AVCodecContext *pCodecCtx;
AVCodec *pCodex;
AVPacket *packet;
AVFrame *frame;
SwrContext *swrContext;
uint8_t *out_buffer;
int out_channer_nb;
int audio_stream_idx=-1;
//opensl es调用 int * rate,int *channel
int createFFmpeg(int *rate,int *channel){
av_register_all();
char *input = "/sdcard/input.mp3";
pFormatCtx = avformat_alloc_context();
LOGE("Lujng %s",input);
LOGE("xxx %p",pFormatCtx);
int error;
char buf[] = "";
//打开视频地址并获取里面的内容(解封装)
if (error = avformat_open_input(&pFormatCtx, input, NULL, NULL) < 0) {
av_strerror(error, buf, 1024);
// LOGE("%s" ,inputPath)
LOGE("Couldn''t open file %s: %d(%s)", input, error, buf);
// LOGE("%d",error)
LOGE("打开视频失败")
}
//3.获取视频信息
if(avformat_find_stream_info(pFormatCtx,NULL) < 0){
LOGE("%s","获取视频信息失败");
return -1;
}
int i=0;
for (int i = 0; i < pFormatCtx->nb_streams; ++i) {
if (pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) {
LOGE(" 找到音频id %d", pFormatCtx->streams[i]->codec->codec_type);
audio_stream_idx=i;
break;
}
}
// mp3的解码的装置
// 获取音频编解码的装置
pCodecCtx=pFormatCtx->streams[audio_stream_idx]->codec;
LOGE("获取视频编码器上下文 %p ",pCodecCtx);
pCodex = avcodec_find_decoder(pCodecCtx->codec_id);
LOGE("获取视频编码 %p",pCodex);
if (avcodec_open2(pCodecCtx, pCodex, NULL)<0) {
}
packet = (AVPacket *)av_malloc(sizeof(AVPacket));
// av_init_packet(packet);
// 音频数据
frame = av_frame_alloc();
// mp3 里面所包含的编码格式 转换成 pcm SwcContext
swrContext = swr_alloc();
int length=0;
int got_frame;
// 44100*2
out_buffer = (uint8_t *) av_malloc(44100 * 2);
uint64_t out_ch_layout=AV_CH_LAYOUT_STEREO;
// 输出采样位数 16位
enum AVSampleFormat out_formart=AV_SAMPLE_FMT_S16;
//输出的采样率必须与输入相同
int out_sample_rate = pCodecCtx->sample_rate;
swr_alloc_set_opts(swrContext, out_ch_layout, out_formart, out_sample_rate,
pCodecCtx->channel_layout, pCodecCtx->sample_fmt, pCodecCtx->sample_rate, 0,
NULL);
swr_init(swrContext);
// 获取通道数 2
out_channer_nb = av_get_channel_layout_nb_channels(AV_CH_LAYOUT_STEREO);
*rate = pCodecCtx->sample_rate;
*channel = pCodecCtx->channels;
return 0;
}
//
int getPcm(void **pcm,size_t *pcm_size){
int frameCount=0;
int got_frame;
while (av_read_frame(pFormatCtx, packet) >= 0) {
if (packet->stream_index == audio_stream_idx) {
// 解码 mp3 编码格式frame----pcm frame
avcodec_decode_audio4(pCodecCtx, frame, &got_frame, packet);
if (got_frame) {
LOGE("解码");
/**
* int swr_convert(struct SwrContext *s, uint8_t **out, int out_count,
const uint8_t **in , int in_count);
*/
swr_convert(swrContext, &out_buffer, 44100 * 2, (const uint8_t **) frame->data, frame->nb_samples);
// 缓冲区的大小
int size = av_samples_get_buffer_size(NULL, out_channer_nb, frame->nb_samples,
AV_SAMPLE_FMT_S16, 1);
*pcm = out_buffer;
*pcm_size = size;
break;
}
}
}
return 0;
}
void realseFFmpeg(){
av_free_packet(packet);
av_free(out_buffer);
av_frame_free(&frame);
swr_free(&swrContext);
avcodec_close(pCodecCtx);
avformat_close_input(&pFormatCtx);
}
小结
按照流程图来编写代码清晰明朗,只是一些细节的地方注意就行。另外注意以下几点:
1.测试时请使用真机测试,因为没有使用x86的cpu的.so;
2.注意添加权限;
3.注意将music.cpp添加到CMakeLists.txt中;
4.测试时请在手机中存入input.xxx的音频文件。
源码地址
Android使用FFmpeg--Shell脚本编写与执行编译FFmpeg库
FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计 算机程序。FFmpeg
是一个多媒体视频处理工具,有非常强大的功能包括视频采集功能、
视频格式转换、视频抓图、给视频加水印等。FFmpeg是由C代码编写而成,功能多,代码量大。
以上呢是百度百科上的,事实上,FFmpeg的视音频编解码功能确实太强大了,几乎囊括了现存所有的视音频编码标准,因此只要做视音频开发,几乎离不开它。市面上主流的播放器(暴风影音)、直播软件、视频转化工具(格式工厂),小视频软件等几乎都是由FFmpeg来做支持的。FFmpeg是由C语言开发的,支持各种平台,我作为一个Android开发,其他的就不提了,也不会我们就来看看Android下是怎么使用FFmpeg的。
在Android平台使用需要先编译,后使用,编译可以通过MakeFile语法来进行编 译。
一、首先下载FFmpeg
下载地址: http://ffmpeg.org/download.html
下载NDK(最好是R17以下)
ffmpeg库下载下来解压缩目录是这样的
我们通过上图configure该命令去编译FFmpeg,这里面有很多参数configure也是一个shell脚本
可以通过如下命令来查看参数
./configure --help
参数详情请查看我们这里就不多说了:https://www.jianshu.com/p/76db41141e53
二、FFmpeg 编写build for Android shell脚本
由于configure命令参数太多,我们这里需要编写一个shell脚本来编译FFmpeg动态库,即.so库,则需要对configure脚本进行修改。
打开configure脚本
找到如下一段:
//修改前
SLIBNAME_WITH_MAJOR='$(SLIBNA ME).$(libmAJOR)’
LIB_INSTALL_EXTRA_CMD='$$(RANL IB) "$(LIBDIR)/$(LIBNAME)“’
SLIB_INSTALL_NAME='$(SLIBNAME_ WITH_VERSION)’
SLIB_INSTALL_LINKS='$(SLIBNAME_ WITH_MAJOR) $(SLIBNAME)'
修改成如下:
//修改后
SLIBNAME_WITH_MAJOR='$(SLIBPR EF)$(FULLNAME)- $(libmAJOR)$(SLIBSUF)’
LIB_INSTALL_EXTRA_CMD='$$(RANL IB) "$(LIBDIR)/$(LIBNAME)“’
SLIB_INSTALL_NAME='$(SLIBNAME_ WITH_MAJOR)’
SLIB_INSTALL_LINKS='$(SLIBNAME) '
然后我们编写一个shell脚本build.sh与configure同目录下来执行configure脚本命令
build.sh代码如下:
#!/bin/bash
NDK_ROOT=/root/ndk/android-ndk-r17c
#TOOLCHAIN 变量指向ndk中的交叉编译gcc所在的目录
TOOLCHAIN=$NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/
#FLAGS与INCLUDES变量 可以从AS ndk工程的.externativeBuild/cmake/debug/armeabi-v7a/build.ninja中拷贝,需要注意的是**地址**
FLAGS="-isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=21 -g -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security -std=c++11 -O0 -fPIC"
INCLUDES="-isystem $NDK_ROOT/sources/cxx-stl/llvm-libc++/include -isystem $NDK_ROOT/sources/android/support/include -isystem $NDK_ROOT/sources/cxx-stl/llvm-libc++abi/include"
#执行configure脚本,用于生成makefile
#--prefix : 安装目录
#--enable-small : 优化大小
#--disable-programs : 不编译ffmpeg程序(命令行工具),我们是需要获得静态(动态)库。
#--disable-avdevice : 关闭avdevice模块,此模块在android中无用
#--disable-encoders : 关闭所有编码器 (播放不需要编码)
#--disable-muxers : 关闭所有复用器(封装器),不需要生成mp4这样的文件,所以关闭
#--disable-filters :关闭视频滤镜
#--enable-cross-compile : 开启交叉编译(ffmpeg比较**跨平台**,并不是所有库都有这么happy的选项 )
#--cross-prefix: 看右边的值应该就知道是干嘛的,gcc的前缀 xxx/xxx/xxx-gcc 则给xxx/xxx/xxx-
#disable-shared enable-static 不写也可以,默认就是这样的。
#--sysroot:
#--extra-cflags: 会传给gcc的参数
#--arch --target-os :
PREFIX=./android/armeabi-v7a2
./configure \
--prefix=$PREFIX \
--prefix=$PREFIX \
--enable-small \
--disable-programs \
--disable-avdevice \
--disable-encoders \
--disable-muxers \
--disable-filters \
--enable-cross-compile \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--disable-shared \
--enable-static \
--sysroot=$NDK_ROOT/platforms/android-21/arch-arm \
--extra-cflags="$FLAGS $INCLUDES" \
--extra-cflags="-isysroot $NDK_ROOT/sysroot" \
--arch=arm \
--target-os=android
make clean
make install
然后执行即可:
./build.sh
下面我们就等编译并生产一个Android的文件夹即可。
arm-linux Opencv+ffmpeg 交叉编译
环境
编译器使用的是arm-none-linux-gnueabi
arm依赖库的安装路径为/usr/arm-none-linux-gnueabi
###安装pkg-config###
sudo apt-get install pkg-config sudo apt-get install libgtk2.0-dev
###安装依赖项###
sudo apt-get install libavcodec-dev libavformat-dev libswscale-dev
这几项与视频解码相关,不安装的话后面opencvmake结果就会出现这样:
FFMPEG:NO
avcodec:NO
avformat:NO
avutil:NO
swscale:NO
avresample:NO
###x264交叉编译###
./configure --host=arm-xilinx-linux --cross-prefix=arm-none-linux-gnueabi- --disable-asm --enable-shared --prefix=/usr/arm-none-linux-gnueabi make make install
###zlib交叉编译###
./configure --prefix=/usr/arm-none-linux-gnueabi -shared
修改makefile
CC=arm-none-linux-gnueabi-gcc AR=arm-none-linux-gnueabi-ar RANLIB=arm-none-linux-gnueabi-ranlib LDSHARED=arm-none-linux-gnueabi-gcc -shared -Wl,-soname,libz.so.1,--version-script,zlib.map
make make install
###xvidcore交叉编译###
xvidcore的配置文件在/build/generic里 ./configure --host=arm-xilinx-linux-gnueabi --disable-assembly --enable-shared --prefix=/usr/arm-none-linux-gnueabi make make install
###ffmpeg交叉编译###
ffmpeg 使用的是2.0.7版本 (GLIBC 2.7)
./configure --prefix=/usr/arm-none-linux-gnueabi --enable-shared --enable-cross-compile --arch=arm --disable-stripping --target-os=linux --cross-prefix=arm-none-linux-gnueabi- make make install
###安装cmake###
sudo apt-get install cmake cmake-qt-gui
###opencv交叉编译###
opencv版本 3.2.0
sudo cmake-gui
使用cmake生成项目
选择选择源代码目录和Build目录
注意
期望的构建目录不要和源码放在一起
初始化
点击Configur或者Generator,弹出CMakeSetup页面
选择UnixMakefiles
接着选择Specify options for cross-compiling
OperatingSystem填写linux
C Compilers 填写交叉编译器arm-none-linux-gnueabi-gcc命令的地址
C++Compilers填写arm-none-linux-gnueabi-g++的地址
CMAKE_FIND_ROOT_PATH 选择依赖路径/usr/arm-none-linux-gnueabi
确定,进入主界面
修改配置参数
CMAKE_INSTALL_PREFIX 设为 /usr/arm-none-linux-gnueabi
CMAKE_C_COMPILER 设为 arm-none-linux-gnueabi-gcc
CMAKE_CXX_COMPILER 设为 arm-none-linux-gnueabi-g++
CMAKE_FIND_ROOT_PATH 设为 /usr/arm-none-linux-gnueabi
CMAKE_C_FLAGS 设为 -Wl,-rpath-link=/usr/arm-none-linux-gnueabi/lib
CMAKE_C_FLAGS 设为 -Wl,-rpath-link=/usr/arm-none-linux-gnueabi/lib
//usr/arm-none-linux-gnueabi/lib 是依赖lib的路径
修改支持项
取消除了WITH_FFMPEG , WITH_PNG , WITH_JPEG , WITH_TIFF , WITH_V4L 以外的支持项
如果要使用OpenCV_Contrib
OPENCV_EXTRA_MODULES 选择OpenCV_Contrib/modules目录
点击Configure确认配置,然后点击Gennerate就会生成Makefile
进入构建目录
make
make install
我们今天的关于在Linux上使用FFmpeg从OpenCV 3编写x264的分享已经告一段落,感谢您的关注,如果您想了解更多关于2023-03-07:x264的视频编码器,不用ffmpeg,用libx264.dll也行。请用go语言调用libx264.dll,将yuv文件编码成h264文件。、Android使用FFmpeg(五)--ffmpeg实现音频播放(使用openSL ES进行播放)、Android使用FFmpeg--Shell脚本编写与执行编译FFmpeg库、arm-linux Opencv+ffmpeg 交叉编译的相关信息,请在本站查询。
本文标签: