b2c信息网

您现在的位置是:首页 > 明日新闻 > 正文

明日新闻

关于libx264源码分析的信息

hacker2022-09-14 23:10:38明日新闻81
本文目录一览:1、用mingw编译x264出来的libx264.a和libx264.lib是一样的么

本文目录一览:

用mingw编译x264出来的libx264.a和libx264.lib是一样的么

.lib不可以在vc里面调用,它只是一个函数的入口,就像是需要调用某个函数时就到.lib中查,就可以知道函数在与.lib同名的.dll库中。真正用到的是.dll库。

.a可以进一步编译成.dll库。

.lib不可以再编了,所以不能直接改。

windows中能用的库只有.dll,但是需要.lib库作为函数的入口。

如何使用libx264.lib做x264 编码开发?

把x264.h,libx264.lib,libx264.dll,拷贝到你的工程文件夹下然后再编译试试!

FFmpeg是不是比X264快

FFMPEG是目前被应用最广泛的编解码软件库,支持多种流行的编解码器,它是C语言实现的,不仅被集成到各种PC软件,也经常被移植到多种嵌入式设备中。使用面向对象的办法来设想这样一个编解码库,首先让人想到的是构造各种编解码器的类,然后对于它们的抽象基类确定运行数据流的规则,根据算法转换输入输出对象。

在实际的代码,将这些编解码器分成encoder/decoder,muxer/demuxer和device三种对象,分别对应于编解码,输入输出格式和设备。在main函数的开始,就是初始化这三类对象。在avcodec_register_all中,很多编解码器被注册,包括视频的H.264解码器和X264编码器等,

REGISTER_DECODER (H264, h264);

REGISTER_ENCODER (LIBX264, libx264);

找到相关的宏代码如下

#define REGISTER_ENCODER(X,x) { /

extern AVCodec x##_encoder; /

if(CONFIG_##X##_ENCODER) avcodec_register(x##_encoder); }

#define REGISTER_DECODER(X,x) { /

extern AVCodec x##_decoder; /

if(CONFIG_##X##_DECODER) avcodec_register(x##_decoder); }

这样就实际在代码中根据CONFIG_##X##_ENCODER这样的编译选项来注册libx264_encoder和h264_decoder,注册的过程发生在avcodec_register(AVCodec *codec)函数中,实际上就是向全局链表first_avcodec中加入libx264_encoder、h264_decoder特定的编解码器,输入参数AVCodec是一个结构体,可以理解为编解码器的基类,其中不仅包含了名称,id等属性,而且包含了如下函数指针,让每个具体的编解码器扩展类实现。

int (*init)(AVCodecContext *);

int (*encode)(AVCodecContext *, uint8_t *buf, int buf_size, void *data);

int (*close)(AVCodecContext *);

int (*decode)(AVCodecContext *, void *outdata, int *outdata_size,

const uint8_t *buf, int buf_size);

void (*flush)(AVCodecContext *);

继续追踪libx264,也就是X264的静态编码库,它在FFMPEG编译的时候被引入作为H.264编码器。在libx264.c中有如下代码

AVCodec libx264_encoder = {

.name = "libx264",

.type = CODEC_TYPE_VIDEO,

.id = CODEC_ID_H264,

.priv_data_size = sizeof(X264Context),

.init = X264_init,

.encode = X264_frame,

.close = X264_close,

.capabilities = CODEC_CAP_DELAY,

.pix_fmts = (enum PixelFormat[]) { PIX_FMT_YUV420P, PIX_FMT_NONE },

.long_name = NULL_IF_CONFIG_SMALL("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),

};

这里具体对来自AVCodec得属性和方法赋值。其中

.init = X264_init,

.encode = X264_frame,

.close = X264_close,

将函数指针指向了具体函数,这三个函数将使用libx264静态库中提供的API,也就是X264的主要接口函数进行具体实现。pix_fmts定义了所支持的输入格式,这里4:2:0

PIX_FMT_YUV420P, /// planar YUV 4:2:0, 12bpp, (1 Cr Cb sample per 2x2 Y samples)

上面看到的X264Context封装了X264所需要的上下文管理数据,

typedef struct X264Context {

x264_param_t params;

x264_t *enc;

x264_picture_t pic;

AVFrame out_pic;

} X264Context;

它属于结构体AVCodecContext的void *priv_data变量,定义了每种编解码器私有的上下文属性,AVCodecContext也类似上下文基类一样,还提供其他表示屏幕解析率、量化范围等的上下文属性和rtp_callback等函数指针供编解码使用。

回到main函数,可以看到完成了各类编解码器,输入输出格式和设备注册以后,将进行上下文初始化和编解码参数读入,然后调用av_encode()函数进行具体的编解码工作。根据该函数的注释一路查看其过程:

1. 输入输出流初始化。

2. 根据输入输出流确定需要的编解码器,并初始化。

3. 写输出文件的各部分

重点关注一下step2和3,看看怎么利用前面分析的编解码器基类来实现多态。大概查看一下这段代码的关系,发现在FFMPEG里,可以用类图来表示大概的编解码器组合。

可以参考【3】来了解这些结构的含义(见附录)。在这里会调用一系列来自utils.c的函数,这里的avcodec_open()函数,在打开编解码器都会调用到,它将运行如下代码:

avctx-codec = codec;

avctx-codec_id = codec-id;

avctx-frame_number = 0;

if(avctx-codec-init){

ret = avctx-codec-init(avctx);

进行具体适配的编解码器初始化,而这里的avctx-codec-init(avctx)就是调用AVCodec中函数指针定义的具体初始化函数,例如X264_init。

在avcodec_encode_video()和avcodec_encode_audio()被output_packet()调用进行音视频编码,将同样利用函数指针avctx-codec-encode()调用适配编码器的编码函数,如X264_frame进行具体工作。

从上面的分析,我们可以看到FFMPEG怎么利用面向对象来抽象编解码器行为,通过组合和继承关系具体化每个编解码器实体。设想要在FFMPEG中加入新的解码器H265,要做的事情如下:

1. 在config编译配置中加入CONFIG_H265_DECODER

2. 利用宏注册H265解码器

3. 定义AVCodec 265_decoder变量,初始化属性和函数指针

4. 利用解码器API具体化265_decoder的init等函数指针

完成以上步骤,就可以把新的解码器放入FFMPEG,外部的匹配和运行规则由基类的多态实现了。

4. X264架构分析

X264是一款从2004年有法国大学生发起的开源H.264编码器,对PC进行汇编级代码优化,舍弃了片组和多参考帧等性能效率比不高的功能来提高编码效率,它被FFMPEG作为引入的.264编码库,也被移植到很多DSP嵌入平台。前面第三节已经对FFMPEG中的X264进行举例分析,这里将继续结合X264框架加深相关内容的了解。

查看代码前,还是思考一下对于一款具体的编码器,怎么面向对象分析呢?对熵编码部分对不同算法的抽象,还有帧内或帧间编码各种估计算法的抽象,都可以作为类来构建。

在X264中,我们看到的对外API和上下文变量都声明在X264.h中,API函数中,关于辅助功能的函数在common.c中定义

void x264_picture_alloc( x264_picture_t *pic, int i_csp, int i_width, int i_height );

void x264_picture_clean( x264_picture_t *pic );

int x264_nal_encode( void *, int *, int b_annexeb, x264_nal_t *nal );

而编码功能函数定义在encoder.c

x264_t *x264_encoder_open ( x264_param_t * );

int x264_encoder_reconfig( x264_t *, x264_param_t * );

int x264_encoder_headers( x264_t *, x264_nal_t **, int * );

int x264_encoder_encode ( x264_t *, x264_nal_t **, int *, x264_picture_t *, x264_picture_t * );

void x264_encoder_close ( x264_t * );

在x264.c文件中,有程序的main函数,可以看作做API使用的例子,它也是通过调用X264.h中的API和上下文变量来实现实际功能。

X264最重要的记录上下文数据的结构体x264_t定义在common.h中,它包含了从线程控制变量到具体的SPS、PPS、量化矩阵、cabac上下文等所有的H.264编码相关变量。其中包含如下的结构体

x264_predict_t predict_16x16[4+3];

x264_predict_t predict_8x8c[4+3];

x264_predict8x8_t predict_8x8[9+3];

x264_predict_t predict_4x4[9+3];

x264_predict_8x8_filter_t predict_8x8_filter;

x264_pixel_function_t pixf;

x264_mc_functions_t mc;

x264_dct_function_t dctf;

x264_zigzag_function_t zigzagf;

x264_quant_function_t quantf;

x264_deblock_function_t loopf;

跟踪查看可以看到它们或是一个函数指针,或是由函数指针组成的结构,这样的用法很想面向对象中的interface接口声明。这些函数指针将在x264_encoder_open()函数中被初始化,这里的初始化首先根据CPU的不同提供不同的函数实现代码段,很多与可能是汇编实现,以提高代码运行效率。其次把功能相似的函数集中管理,例如类似intra16的4种和intra4的九种预测函数都被用函数指针数组管理起来。

x264_encoder_encode()是负责编码的主要函数,而其内包含的x264_slice_write()负责片层一下的具体编码,包括了帧内和帧间宏块编码。在这里,cabac和cavlc的行为是根据h-param.b_cabac来区别的,分别运行x264_macroblock_write_cabac()和x264_macroblock_write_cavlc()来写码流,在这一部分,功能函数按文件定义归类,基本按照编码流程图运行,看起来更像面向过程的写法,在已经初始化了具体的函数指针,程序就一直按编码过程的逻辑实现。如果从整体架构来看,x264利用这种类似接口的形式实现了弱耦合和可重用,利用x264_t这个贯穿始终的上下文,实现信息封装和多态。

本文大概分析了FFMPEG/X264的代码架构,重点探讨用C语言来实现面向对象编码,虽不至于强行向C++靠拢,但是也各有实现特色,保证实用性。值得规划C语言软件项目所借鉴。

执行程序报错:can't execute:Permission denied,该怎么解决

执行程序报错:can't execute: Permission denied

1. 编译x264为libx264.a

2. 然后按照所说,使用libx264.a最后编译为x264可执行程序,主要是想验证编译的libx264.a能否在android环境下执行。

3. 接着使用adb把x264程序放置到/data/x264目录下,然后cd 到/data/x264, 运行./x264报错:

sh: ./x264: can't execute: Permission denied

4. 大概过程如下:

shell@android:/ # cd /data/x264

cd /data/x264

shell@android:/data/x264 # ls

ls

x264

yuv_640x480.yuv

shell@android:/data/x264 # ./x264

./x264

sh: ./x264: can't execute: Permission denied

为什么没有权限呀?怎么解决?

没有android开放经验

------解决方案--------------------

修改/data/x264这个目录的权限

ubuntu怎样安装libx264-146

1).安装依赖的包:

code:

sudo apt-get update

sudo apt-get install build-essential git-core checkinstall texi2html libfaac-dev \

libopencore-amrnb-dev libopencore-amrwb-dev libsdl1.2-dev libtheora-dev \

libvorbis-dev libx11-dev libxfixes-dev zlib1g-dev

2.安装Yasm:x264需要使用yasm来针对CPU架构进行优化,提高性能。

code:

cd

wget

tar xzvf yasm-1.2.0.tar.gz

cd yasm-1.2.0

./configure

make

make install

3.安装x264:下载源代码、编译、安装

code:

cd

git clone git://git.videolan.org/x264

cd x264

./configure --enable-shared //动态库

make

make install

4.此时 libx264.so默认安装在/usr/local/lib,直接编译会出现

tmux: error while loading shared libraries: libx264.so.2: cannot open shared object file: No such file or directory

原因就是已经安装了该共享库, 但执行需要调用该共享库的程序的时候, 程序按照默认共享库路径 /usr/lib 找不到该共享库文件.

如果共享库文件安装到了/usr/local/lib(很多开源的共享库都会安装到该目录下)或其它"非/lib或/usr/lib"目录下, 那么在执行ldconfig命令前,

还要把新共享库目录加入到共享库配置文件/etc/ld.so.conf中, 如下:

# cat

/etc/ld.so.conf

include ld.so.conf.d/*.conf

# echo

"/usr/local/lib" /etc/ld.so.conf

# ldconfig

发表评论

评论列表

  • 怎忘好怪(2022-09-15 05:03:32)回复取消回复

    64_picture_t pic; AVFrame out_pic;} X264Context;它属于结构体AVCodecContext的void *priv_data变量,定义了每种编解码器私有的上下文属性,AVCodecContext也类似上下文基类一样,还提供其他表示

  • 酒奴笑惜(2022-09-15 03:14:18)回复取消回复

    析,我们可以看到FFMPEG怎么利用面向对象来抽象编解码器行为,通过组合和继承关系具体化每个编解码器实体。设想要在FFMPEG中加入新的解码器H265,要做的事情如下:1. 在config编译配置中加入CONFIG_H