a52dec工程ao数据结构和ffmpeg工程codec数据结构比较(2007.9.14)
a52dec工程ao数据结构和ffmpeg工程codec数据结构比较
关键词:
数据结构,算法,分立数据结构,集合数据结构,引用数据结构. 数组集合.
引用注册函数,集合数据结构的注册函数, 分立数据结构的注册函数,
1 a52 工程音频输出数据结构建立过程
1.1 数据结构的建立
typedef struct ao_instance_s ao_instance_t;
//分立数据结构
struct ao_instance_s {
int (* setup) (ao_instance_t * instance, int sample_rate, int * flags,
sample_t * level, sample_t * bias);
int (* play) (ao_instance_t * instance, int flags, sample_t * samples);
void (* close) (ao_instance_t * instance);
};
typedef ao_instance_t * ao_open_t (void);
//引用数据结构
typedef struct ao_driver_s {
char * name;
ao_open_t * open;
} ao_driver_t;
- 定义了基本数据结构ao_instance_s和ao_driver_s. ao_instance_s内部算法包括setup, play和close. ao_driver_s中name表示该输出driver的名字. ao_open_t就是前面定义的ao_instance_s.定义了这个driver的算法的函数指针.以后使用时只要做2部注册就可以了.
1.2 数据结构的例化
extern ao_open_t ao_oss_open;
extern ao_open_t ao_ossdolby_open;
……
extern ao_open_t ao_win_open;
extern ao_open_t ao_windolby_open;
extern ao_open_t ao_wav_open;
extern ao_open_t ao_wavdolby_open;
extern ao_open_t ao_aif_open;
extern ao_open_t ao_aifdolby_open;
……
extern ao_open_t ao_float_open;
//集合数据结构
static ao_driver_t audio_out_drivers[] = {
#ifdef LIBAO_OSS
{"oss", ao_oss_open},
……(略)
{"oss6", ao_oss6_open},
#endif
……(略)
#ifdef LIBAO_AL
……(略)
#endif
#ifdef LIBAO_WIN
{"win", ao_win_open},
{"windolby", ao_windolby_open},
#endif
{"wav", ao_wav_open},
{"wavdolby", ao_wavdolby_open},
{"aif", ao_aif_open},
{"aifdolby", ao_aifdolby_open},
……(略)
{"float", ao_float_open},
{NULL, NULL}
};
1.extern ao_open_t ao_xxx_open实现了对不同driver的注册例化.这些数据结构来自libao文件夹下的C代码.在libao文件夹下定义了audio output的driver实体.
2.static ao_driver_t audio_out_drivers[]实现了使用数组把所有的driver连接到一起.并同时初始化.数组的最后一个数据是{NULL, NULL}表示dirver结束.
1.3 音频输出数据结构的引用.
//集合数据结构的注册函数
ao_driver_t * ao_drivers (void)
{
return audio_out_drivers;
}
算法ao_driver_t * ao_drivers (void)实现数据结构的注册返回.表明可以使用数据结构audio_out_drivers了.
1.4 数据结构的实体
在libao文件下有各个driver的实体文件,以”wav”这个driver举例.在libao文件夹下有audio_out_wav.c整个文件负责定义ao_open_t ao_wav_open数据结构和相应的step,play,close算法.
例如:
//公共算法实体
static int wav_setup (ao_instance_t * _instance, int sample_rate, int * flags,
sample_t * level, sample_t * bias)
{
wav_instance_t * instance = (wav_instance_t *) _instance;
static int init=0;
(略)
return 0;
}
static int wav_play (ao_instance_t * _instance, int flags, sample_t * _samples)
{
wav_instance_t * instance = (wav_instance_t *) _instance;
int16_t int16_samples[256*2];
(略)
return 0;
}
static void wav_close (ao_instance_t * _instance)
{
wav_instance_t * instance = (wav_instance_t *) _instance;
(略)
fclose(outfd);
}
使用wav_open函数注册以上三个算法到相应的数据结构wav_instance_t.
//分立数据结构的注册函数
static ao_instance_t * wav_open (int flags)
{
wav_instance_t * instance;
instance = malloc (sizeof (wav_instance_t));
if (instance == NULL)
return NULL;
instance->ao.setup = wav_setup;
instance->ao.play = wav_play;
instance->ao.close = wav_close;
instance->sample_rate = 0;
instance->set_params = 1;
instance->flags = flags;
instance->size = 0;
return (ao_instance_t *) instance;
}
使用ao_wav_open函数实现对注册函数的引用.
#define A52_STEREO 2
ao_instance_t * ao_wav_open (void)
{
return wav_open (A52_STEREO);
}
1.5 总结
a52dec工程ao模块的特点:使用数组建立driver集.
数据结构特点:
Driver 的分立数据结构ao_instance_s:定义不同driver的公共算法
Driver 的引用数据结构ao_driver_s定义了一个名字用于引用和遍历
Driver 的集合数据结构audio_out_drivers定义了一个数组,把所有的driver连接到一起.
数据结构注册特点:
集合数据结构的注册函数: ao_driver_t * ao_drivers (void),实现audio_out_drivers的引用
分立数据结构的注册函数: ao_instance_t * wav_open (int flags)对分立driver的公共算法注册到相应的ao_instance_s结构体中.
公共算法的实体:
在相应的子目录下建立相应的算法实体.便于管理和修改.外部引用通过注册和extern.
2 ffmpeg工程codec数据结构
略
主要区别:链表建立集合数据结构
//分立数据结构,引用数据结构
//二者合一了
/**
* AVCodec.
*/
typedef struct AVCodec {
const char *name;
enum CodecType type;
enum CodecID id;
int priv_data_size;
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,
uint8_t *buf, int buf_size);
int capabilities;
#if LIBAVCODEC_VERSION_INT < ((50<<16)+(0<<8)+0)
void *dummy; // FIXME remove next time we break binary compatibility
#endif
struct AVCodec *next;
void (*flush)(AVCodecContext *);
const AVRational *supported_framerates; ///array of supported framerates, or NULL if any, array is terminated by {0,0}
const enum PixelFormat *pix_fmts; ///array of supported pixel formats, or NULL if unknown, array is terminanted by -1
} AVCodec;
- ffmpeg还很好的处理了不同cpu平台的问题.通过宏和dsputil_static_init();函数实现.
ffmpeg工程的对指针注册的方式完美应用非常值得学习.