通过重定位标准输入输出文件来实现输入输出。
关键的函数:
static int decode(unsigned char const *start, unsigned long length);
|
注意:这不是libmad的底层函数。
这个函数完成的工作是:
1.初始化decoder:
mad_decoder_init(&decoder, &buffer, input, 0 /* header */, 0 /* filter */, output, error, 0 /* message */);
|
在decoder.c中定义如下:
void mad_decoder_init(struct mad_decoder *decoder, void *data, enum mad_flow (*input_func)(void *, struct mad_stream *), enum mad_flow (*header_func)(void *, struct mad_header const *), enum mad_flow (*filter_func)(void *, struct mad_stream const *, struct mad_frame *), enum mad_flow (*output_func)(void *, struct mad_header const *, struct mad_pcm *), enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame *), enum mad_flow (*message_func)(void *, void *, unsigned int *));
初始化一个mad_decoder的实例。
注意到data时void *,那么程序如何得知处理data的方法呢? |
mad_decoder的结构:
struct mad_decoder { enum mad_decoder_mode mode;
(notes:
enum mad_decoder_mode { MAD_DECODER_MODE_SYNC = 0, MAD_DECODER_MODE_ASYNC }
同步/异步方式
)
int options;
struct { long pid; //异步方式进程号 int in; int out; } async;
struct { struct mad_stream stream; struct mad_frame frame; struct mad_synth synth; } *sync;
void *cb_data;
enum mad_flow (*input_func)(void *, struct mad_stream *); enum mad_flow (*header_func)(void *, struct mad_header const *); enum mad_flow (*filter_func)(void *, struct mad_stream const *, struct mad_frame *); enum mad_flow (*output_func)(void *, struct mad_header const *, struct mad_pcm *); enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame*); enum mad_flow (*message_func)(void *, void *, unsigned int *); };
|
解码器运行:
int mad_decoder_run(struct mad_decoder *decoder, enum mad_decoder_mode mode) { int result; int (*run)(struct mad_decoder *) = 0; //用于指定使用异步还是同步的运行函数
switch (decoder->mode = mode) { case MAD_DECODER_MODE_SYNC: run = run_sync; break;
case MAD_DECODER_MODE_ASYNC: # if defined(USE_ASYNC) run = run_async; # endif break; }
if (run == 0) return -1;
decoder->sync = malloc(sizeof(*decoder->sync)); if (decoder->sync == 0) return -1;
result = run(decoder);
free(decoder->sync); decoder->sync = 0;
return result; }
|
同步运行:
static int run_sync(struct mad_decoder *decoder) { enum mad_flow (*error_func)(void *, struct mad_stream *, struct mad_frame*); void *error_data; int bad_last_frame = 0; struct mad_stream *stream; struct mad_frame *frame; struct mad_synth *synth; int result = 0;
...
if (decoder->error_func) { error_func = decoder->error_func; error_data = decoder->cb_data; } else { error_func = error_default; error_data = &bad_last_frame; } ... mad_stream_init(stream); mad_frame_init(frame); mad_synth_init(synth);
mad_stream_options(stream, decoder->options);
do {
//调用input_func,把cb_data的信息复制到stream中。
switch (decoder->input_func(decoder->cb_data, stream)) {
case MAD_FLOW_STOP: goto done; case MAD_FLOW_BREAK: goto fail; case MAD_FLOW_IGNORE: continue; case MAD_FLOW_CONTINUE: break; }
while (1) { # if defined(USE_ASYNC) ... # endif
if (decoder->header_func) { if (mad_header_decode(&frame->header, stream) == -1) { ... }
switch (decoder->header_func(decoder->cb_data, &frame->header)) { ... } }
if (mad_frame_decode(frame, stream) == -1) {
... } else bad_last_frame = 0;
if (decoder->filter_func) { ... } ... if (decoder->output_func) { switch (decoder->output_func(decoder->cb_data, &frame->header, &synth->pcm)) { case MAD_FLOW_STOP: goto done; case MAD_FLOW_BREAK: goto fail; case MAD_FLOW_IGNORE: case MAD_FLOW_CONTINUE: break; } } } }while (stream->error == MAD_ERROR_BUFLEN);
fail: result = -1;
done: mad_synth_finish(synth); mad_frame_finish(frame); mad_stream_finish(stream);
return result; }
|
input_func在minimad中的实现是非常简单的:
static enum mad_flow input(void *data, struct mad_stream *stream) { struct buffer *buffer = data;
if (!buffer->length) return MAD_FLOW_STOP;
mad_stream_buffer(stream, buffer->start, buffer->length);
buffer->length = 0;
return MAD_FLOW_CONTINUE;
|
output_func在minimad中的实现是:
mad_stream--输入音频数据比特流关联到解码流
mad_frame--解码流关联到解码器
--mad_header--MPEG帧的基本信息
----mad_mode--声道模型
----....
mad_synth--解码器关联到PCM数据合成
--mad_pcm--合成的PCM数据
程序基本流程:
1.初始化stream, synth, frame
2.关联输入流到解码流
3.调用解码器
4.合成PCM数据
5.释放stream, synth, frame
阅读(1969) | 评论(0) | 转发(0) |