x264 linux 编译,x264在Android平台上的编译和使用

x264在Android平台上的移植

gedit ~/.bashrc

将 /opt/android-sdk-linux/tools 添加到 "PATH"环境变量中

将 /opt/android-ndk-r8b 添加到 "PATH"环境变量中

将x264源码包last_x264.tar.bz2下载到~/x264-android目录下,并解压到目录~/x264-android/x264-snapshot-20130808-2245/下

cd ~/x264-android/x264-snapshot-20130808-2245

执行以下配置脚本:

./configure --enable-pic --enable-strip --enable-static --cross-prefix=/opt/android-ndk-r8b/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86/bin/arm-linux-androideabi- --sysroot=/opt/android-ndk-r8b/platforms/android-14/arch-arm --host=arm-linux --prefix=./build --extra-cflags="-march=armv7-a -mtune=cortex-a8 -mfloat-abi=softfp -mfpu=neon -D__ARM_ARCH_7__ -D__ARM_ARCH_7A__"

然后:make

最后:在当前目录下生成libx264.a的静态库

注:最好用android-ndk-r8b之前的ndk版本(包括android-ndk-r8b)编译,android-ndk-r8b之后的版本编译x264,最后会报"cannot scan executable section 1 of libx264.a(dct-a.o) for Cortex-A8 erratum because it has no mapping symbols"的警告

x264在android平台上的使用

1、创建工程x264_android

android list targets

android create project --target 1 --name x264_android --path ~/workspace/x264_android --package com.modukaikai.x264 --activity x264Activity

2、copy x264的库和头文件到jni目录

mkdir ~/workspace/x264_android/jni

mkdir ~/workspace/x264_android/jni/x264

cp ~/x264-android/x264-snapshot-20130808-2245/libx264.a ~/workspace/x264_android/jni/x264

cp ~/x264-android/x264-snapshot-20130808-2245/x264.h ~/workspace/x264_android/jni/x264

cp ~/x264-android/x264-snapshot-20130808-2245/x264_config.h ~/workspace/x264_android/jni/x264

3、创建x264encoder类封装x264的调用接口

以下是x264encoder.h(放在jni目录下)

#ifndef x264encoder_h

#define x264encoder_h

extern "C"

{

#include "stdint.h"

#include "x264.h"

enum bitrate_level

{

HIGH_LEVEL = 0,

STANDARD_LEVEL = 1,

MEDIUM_LEVEL = 2,

LOW_LEVEL = 3,

};

class X264Encoder

{

public:

X264Encoder();

~X264Encoder();

bool openX264Encoder();

//    long x264EncoderProcess(uint8_t *pSrcData, int srcDataSize, x264_nal_t **nals, int& nalsCount);

long x264EncoderProcess(x264_picture_t *pPicture, x264_nal_t **nals, int& nalsCount);

bool closeX264Encoder();

void setSourceFormat(unsigned int sourcformat);

void setResolution(unsigned int w, unsigned int h);

void setBitrate(unsigned int i_bitrate);

void setFps(unsigned int fps);

void setI_KeyInt_Max(unsigned int i_frame_max);

void setQp_Max(unsigned int qp_max);

void setQp_Min(unsigned int qp_min);

void forceIDRFrame();

void upgradeBitrateLevel();

void declineBitrateLevel();

void setLeastBitrateLevel();

private:

x264_param_t *pParameter;

x264_t *x264EncoderHandle;

//    x264_picture_t *pPicture;

x264_picture_t *pOutput;

unsigned int sourceFormat;

//    unsigned int i_bitrate;

unsigned int bitratelevel;

unsigned int i_fps;

unsigned int i_keyint_max;

unsigned int width;

unsigned int height;

unsigned int qp_max;

unsigned int qp_min;

unsigned int current_f_rf_constant;

unsigned int userSetting_f_rf_constant;

int64_t frameNo;

bool isForceIDRFrameEnabled;

};

}

#endif

以下是x264encoder.cpp(放在jni目录下)

#include

#include

#include "x264encoder.h"

// new version for x264 encoder

X264Encoder::X264Encoder()

{

this->bitratelevel = STANDARD_LEVEL;

qp_max = 30;

qp_min = 0;

i_fps = 20;

i_keyint_max = 300;

width = 352;

height = 288;

frameNo = 0;

isForceIDRFrameEnabled = false;

pParameter = NULL;

x264EncoderHandle = NULL;

//    pPicture = NULL;

pOutput = NULL;

}

X264Encoder::~X264Encoder()

{

this->closeX264Encoder();

}

void X264Encoder::setSourceFormat(unsigned int sourcformat)

{

this->sourceFormat = sourcformat;

}

void X264Encoder::setResolution(unsigned int w, unsigned int h)

{

width = w;

height = h;

}

void X264Encoder::setBitrate(unsigned int i_bitrate)

{

if (i_bitrate > 0 && i_bitrate <= 64) {

this->bitratelevel = LOW_LEVEL;

}else if(i_bitrate > 64 && i_bitrate <= 128){

this->bitratelevel = MEDIUM_LEVEL;

}else if (i_bitrate > 128 && i_bitrate <= 256) {

this->bitratelevel = STANDARD_LEVEL;

}else if (i_bitrate > 256 && i_bitrate <= 384) {

this->bitratelevel = HIGH_LEVEL;

}else if (i_bitrate > 384 && i_bitrate <= 512) {

this->bitratelevel = HIGH_LEVEL;

}else {

this->bitratelevel = STANDARD_LEVEL;

}

}

void X264Encoder::setFps(unsigned int fps)

{

i_fps = fps;

}

void X264Encoder::setI_KeyInt_Max(unsigned int i_frame_max)

{

i_keyint_max = i_frame_max;

}

void X264Encoder::setQp_Max(unsigned int qp_max)

{

this->qp_max = qp_max;

}

void X264Encoder::setQp_Min(unsigned int qp_min)

{

this->qp_min = qp_min;

}

bool X264Encoder::openX264Encoder()

{

//    return false;

this->closeX264Encoder();

if(!pParameter)

{

pParameter = (x264_param_t *)malloc(sizeof(x264_param_t));

if (!pParameter) {

this->closeX264Encoder();

return false;

}

memset(pParameter, 0, sizeof(x264_param_t));

}

int ret = x264_param_default_preset(pParameter, "ultrafast", "zerolatency");

if (ret != 0) {

this->closeX264Encoder();

return false;

}

pParameter->i_level_idc = 30;

pParameter->i_width = width;

pParameter->i_height = height;

pParameter->b_deterministic = 1;

//    pParameter->b_sliced_threads = 1;

pParameter->i_threads = 1;

pParameter->i_csp = X264_CSP_I420;//X264_CSP_NV12;//X264_CSP_I420;

pParameter->i_fps_num = i_fps;

pParameter->i_fps_den = 1;

pParameter->i_bframe = 0;

pParameter->i_keyint_max = i_keyint_max;

//    pParameter->b_open_gop = 1;

//    pParameter->rc.i_bitrate = i_bitrate;

pParameter->rc.i_rc_method = X264_RC_CRF;//X264_RC_CQP;

if (this->bitratelevel == LOW_LEVEL) {

pParameter->rc.f_rf_constant = 32;

}else if(this->bitratelevel == MEDIUM_LEVEL){

pParameter->rc.f_rf_constant = 29;

}else if (this->bitratelevel == STANDARD_LEVEL) {

pParameter->rc.f_rf_constant = 26;

}else if (this->bitratelevel == HIGH_LEVEL) {

pParameter->rc.f_rf_constant = 24;

}else {

pParameter->rc.f_rf_constant = 24;

}

current_f_rf_constant = pParameter->rc.f_rf_constant;

userSetting_f_rf_constant = pParameter->rc.f_rf_constant;

// from huxiaopeng

pParameter->analyse.b_transform_8x8 = 1;

pParameter->rc.f_aq_strength = 1.5;

pParameter->rc.i_aq_mode = 0;

pParameter->rc.f_qcompress = 0.0;

pParameter->rc.f_ip_factor = 0.5;

pParameter->rc.f_rate_tolerance = 0.1;

pParameter->analyse.i_direct_mv_pred = X264_DIRECT_PRED_AUTO;

pParameter->analyse.i_me_method = X264_ME_DIA;

pParameter->analyse.i_me_range = 16;

pParameter->analyse.i_subpel_refine = 2;

//    pParameter->analyse.i_noise_reduction = 1;

pParameter->i_slice_max_size = 1200;

//    pParameter->i_nal_hrd = X264_NAL_HRD_NONE;

pParameter->b_deblocking_filter = 1;

pParameter->i_deblocking_filter_alphac0 = 4;

pParameter->i_deblocking_filter_beta = 4;

pParameter->rc.b_mb_tree = 0;

pParameter->i_log_level = X264_LOG_NONE;

if(x264_param_apply_profile(pParameter, "baseline"))

{

this->closeX264Encoder();

return false;

}

if (!x264EncoderHandle) {

x264EncoderHandle = x264_encoder_open(pParameter);

if (!x264EncoderHandle) {

this->closeX264Encoder();

return false;

}

}

/*

if (!pPicture) {

pPicture = (x264_picture_t *)malloc(sizeof(x264_picture_t));

if (!pPicture) {

this->closeX264Encoder();

return false;

}

memset(pPicture, 0, sizeof(x264_picture_t));

}

if (x264_picture_alloc(pPicture, X264_CSP_I420, width, height)) {

this->closeX264Encoder();

return false;

}

*/

if (!pOutput) {

pOutput = (x264_picture_t *)malloc(sizeof(x264_picture_t));

if (!pOutput) {

this->closeX264Encoder();

return false;

}

memset(pOutput, 0, sizeof(x264_picture_t));

}

return true;

}

void X264Encoder::forceIDRFrame()

{

isForceIDRFrameEnabled = true;

}

void X264Encoder::upgradeBitrateLevel()

{

/*

if (this->bitratelevel == HIGH_LEVEL) {

return;

}

this->bitratelevel++;

if (this->bitratelevel == LOW_LEVEL) {

pParameter->rc.f_rf_constant = 30;

}else if(this->bitratelevel == MEDIUM_LEVEL){

pParameter->rc.f_rf_constant = 27;

}else if (this->bitratelevel == STANDARD_LEVEL) {

pParameter->rc.f_rf_constant = 24;

}else if (this->bitratelevel == HIGH_LEVEL) {

pParameter->rc.f_rf_constant = 22;

}else {

pParameter->rc.f_rf_constant = 23;

}

*/

if (userSetting_f_rf_constant >= current_f_rf_constant) {

return;

}

pParameter->rc.f_rf_constant--;

current_f_rf_constant = pParameter->rc.f_rf_constant;

x264_encoder_reconfig(x264EncoderHandle, pParameter);

}

void X264Encoder::setLeastBitrateLevel()

{

pParameter->rc.f_rf_constant = 32;

current_f_rf_constant = pParameter->rc.f_rf_constant;

x264_encoder_reconfig(x264EncoderHandle, pParameter);

}

void X264Encoder::declineBitrateLevel()

{

/*

if (this->bitratelevel == LOW_LEVEL) {

return;

}

this->bitratelevel--;

if (this->bitratelevel == LOW_LEVEL) {

pParameter->rc.f_rf_constant = 30;

}else if(this->bitratelevel == MEDIUM_LEVEL){

pParameter->rc.f_rf_constant = 27;

}else if (this->bitratelevel == STANDARD_LEVEL) {

pParameter->rc.f_rf_constant = 24;

}else if (this->bitratelevel == HIGH_LEVEL) {

pParameter->rc.f_rf_constant = 22;

}else {

pParameter->rc.f_rf_constant = 23;

}

*/

if (32 <= current_f_rf_constant) {

return;

}

pParameter->rc.f_rf_constant++;

current_f_rf_constant = pParameter->rc.f_rf_constant;

x264_encoder_reconfig(x264EncoderHandle, pParameter);

}

long X264Encoder::x264EncoderProcess(x264_picture_t *pPicture, x264_nal_t **nals, int& nalsCount)

{

pPicture->i_pts = (int64_t)(frameNo * pParameter->i_fps_den);

pPicture->i_type = X264_TYPE_AUTO;

pPicture->i_qpplus1 = 0;//X264_QP_AUTO;

if (isForceIDRFrameEnabled) {

pPicture->i_type = X264_TYPE_IDR;

isForceIDRFrameEnabled = false;

}

int32_t framesize = -1;

framesize = x264_encoder_encode(x264EncoderHandle, nals, &nalsCount, pPicture, pOutput);

if (framesize>0) {

frameNo++;

}

return framesize;

}

/*

long X264Encoder::x264EncoderProcess(uint8_t *pSrcData, int srcDataSize, x264_nal_t **nals, int& nalsCount)

{

pPicture->img.plane[0] = pSrcData;

pPicture->img.plane[1] = pSrcData + srcDataSize*2/3;

pPicture->img.plane[2] = pSrcData + srcDataSize*2/3 + srcDataSize/6;

pPicture->i_pts = (int64_t)(frameNo * pParameter->i_fps_den);

pPicture->i_type = X264_TYPE_AUTO;

pPicture->i_qpplus1 = X264_QP_AUTO;

if (isForceIDRFrameEnabled) {

pPicture->i_type = X264_TYPE_IDR;

isForceIDRFrameEnabled = false;

}

int32_t framesize = -1;

framesize = x264_encoder_encode(x264EncoderHandle, nals, &nalsCount, pPicture, pOutput);

if (framesize>0) {

frameNo++;

}

return framesize;

}

*/

bool X264Encoder::closeX264Encoder()

{

if (pOutput) {

free(pOutput);

pOutput = NULL;

}

/*

if (pPicture) {

free(pPicture);

pPicture = NULL;

}

*/

if (pParameter) {

free(pParameter);

pParameter = NULL;

}

if (x264EncoderHandle) {

x264_encoder_close(x264EncoderHandle);

x264EncoderHandle = NULL;

}

return true;

}

4、在jni目录下创建测试编码的源文件x264_main.cpp

#include

#include "x264encoder.h"

int main( int argc, char **argv )

{

X264Encoder x264Encoder;

x264Encoder.setBitrate(512);

x264Encoder.setResolution(640,480);

x264Encoder.setFps(20);

FILE *inputFile = NULL;

FILE *outputFile = NULL;

inputFile = fopen("yuv_640x480.yuv","rb");

outputFile = fopen("h264_640x480.h264","wb");

x264_picture_t inputPicture;

x264_picture_alloc(&inputPicture, X264_CSP_I420, 640, 480);

x264_nal_t *p_nals = NULL;

int nalsCount = 0;

if(x264Encoder.openX264Encoder())

{

for(int j=0; j<20; j++)

{

fread(inputPicture.img.plane[0],1,640*480, inputFile);

fread(inputPicture.img.plane[1],1,640*480/4, inputFile);

fread(inputPicture.img.plane[2],1,640*480/4, inputFile);

x264Encoder.x264EncoderProcess(&inputPicture,&p_nals,nalsCount);

if(p_nals)

{

for(int i=0; i

{

fwrite(p_nals[i].p_payload, p_nals[i].i_payload, 1, outputFile);

}

}

}

}

fclose(inputFile);

fclose(outputFile);

x264_picture_clean(&inputPicture);

x264Encoder.closeX264Encoder();

return 0;

}

0b1331709591d260c1c78e86d0c51c18.png

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值