comparison libmpcodecs/ad_libmad.c @ 5479:22b289d7f87f

libmad support, rewritten from scratch using Xine decoder as sample
author arpi
date Wed, 03 Apr 2002 20:14:18 +0000
parents
children 4bae3caef7a9
comparison
equal deleted inserted replaced
5478:1212d2f92a42 5479:22b289d7f87f
1 // SAMPLE audio decoder - you can use this file as template when creating new codec!
2
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6
7 #include "config.h"
8
9 #ifdef USE_LIBMAD
10
11 #include "ad_internal.h"
12
13 static ad_info_t info = {
14 "libmad mpeg audio decoder",
15 "libmad",
16 AFM_MAD,
17 "A'rpi",
18 "libmad...",
19 "based on Xine's libmad/xine_decoder.c"
20 };
21
22 LIBAD_EXTERN(libmad)
23
24 #include <mad.h>
25
26 typedef struct mad_decoder_s {
27
28 struct mad_synth synth;
29 struct mad_stream stream;
30 struct mad_frame frame;
31
32 int have_frame;
33
34 int output_sampling_rate;
35 int output_open;
36 int output_mode;
37
38 } mad_decoder_t;
39
40 static int preinit(sh_audio_t *sh){
41
42 mad_decoder_t *this = (mad_decoder_t *) malloc(sizeof(mad_decoder_t));
43 memset(this,0,sizeof(mad_decoder_t));
44 sh->context = this;
45
46 mad_synth_init (&this->synth);
47 mad_stream_init (&this->stream);
48 mad_frame_init (&this->frame);
49
50 sh->audio_out_minsize=2*4608;
51 sh->audio_in_minsize=4096;
52
53 return 1;
54 }
55
56 static int read_frame(sh_audio_t *sh){
57 mad_decoder_t *this = (mad_decoder_t *) sh->context;
58 int len;
59
60 while((len=demux_read_data(sh->ds,&sh->a_in_buffer[sh->a_in_buffer_len],
61 sh->a_in_buffer_size-sh->a_in_buffer_len))>0){
62 sh->a_in_buffer_len+=len;
63 while(1){
64 int ret;
65 mad_stream_buffer (&this->stream, sh->a_in_buffer, sh->a_in_buffer_len);
66 ret=mad_frame_decode (&this->frame, &this->stream);
67 if (this->stream.next_frame) {
68 int num_bytes =
69 (char*)sh->a_in_buffer+sh->a_in_buffer_len - (char*)this->stream.next_frame;
70 memmove(sh->a_in_buffer, this->stream.next_frame, num_bytes);
71 mp_msg(MSGT_DECAUDIO,MSGL_DBG2,"libmad: %d bytes processed\n",sh->a_in_buffer_len-num_bytes);
72 sh->a_in_buffer_len = num_bytes;
73 }
74 if (ret == 0) return 1; // OK!!!
75 // error! try to resync!
76 if(this->stream.error==MAD_ERROR_BUFLEN) break;
77 }
78 }
79 mp_msg(MSGT_DECAUDIO,MSGL_INFO,"Cannot sync MAD frame\n");
80 return 0;
81 }
82
83 static int init(sh_audio_t *sh){
84 mad_decoder_t *this = (mad_decoder_t *) sh->context;
85
86 this->have_frame=read_frame(sh);
87 if(!this->have_frame) return 0; // failed to sync...
88
89 sh->channels=(this->frame.header.mode == MAD_MODE_SINGLE_CHANNEL) ? 1 : 2;
90 sh->samplerate=this->frame.header.samplerate;
91 sh->i_bps=this->frame.header.bitrate/8;
92
93 return 1;
94 }
95
96 static void uninit(sh_audio_t *sh){
97 mad_decoder_t *this = (mad_decoder_t *) sh->context;
98 mad_synth_finish (&this->synth);
99 mad_frame_finish (&this->frame);
100 mad_stream_finish(&this->stream);
101 free(sh->context);
102 }
103
104 /* utility to scale and round samples to 16 bits */
105 static inline signed int scale(mad_fixed_t sample) {
106 /* round */
107 sample += (1L << (MAD_F_FRACBITS - 16));
108
109 /* clip */
110 if (sample >= MAD_F_ONE)
111 sample = MAD_F_ONE - 1;
112 else if (sample < -MAD_F_ONE)
113 sample = -MAD_F_ONE;
114
115 /* quantize */
116 return sample >> (MAD_F_FRACBITS + 1 - 16);
117 }
118
119 static int decode_audio(sh_audio_t *sh,unsigned char *buf,int minlen,int maxlen){
120 mad_decoder_t *this = (mad_decoder_t *) sh->context;
121 int len=0;
122
123 while(len<minlen && len+4608<=maxlen){
124 if(!this->have_frame) this->have_frame=read_frame(sh);
125 if(!this->have_frame) break; // failed to sync... or EOF
126 this->have_frame=0;
127
128 mad_synth_frame (&this->synth, &this->frame);
129
130 { unsigned int nchannels, nsamples;
131 mad_fixed_t const *left_ch, *right_ch;
132 struct mad_pcm *pcm = &this->synth.pcm;
133 uint16_t *output = (uint16_t*) buf;
134
135 nchannels = pcm->channels;
136 nsamples = pcm->length;
137 left_ch = pcm->samples[0];
138 right_ch = pcm->samples[1];
139
140 len+=2*nchannels*nsamples;
141 buf+=2*nchannels*nsamples;
142
143 while (nsamples--) {
144 /* output sample(s) in 16-bit signed little-endian PCM */
145
146 *output++ = scale(*left_ch++);
147
148 if (nchannels == 2)
149 *output++ = scale(*right_ch++);
150
151 }
152 }
153 }
154
155 return len?len:-1;
156 }
157
158 static int control(sh_audio_t *sh,int cmd,void* arg, ...){
159 mad_decoder_t *this = (mad_decoder_t *) sh->context;
160 // various optional functions you MAY implement:
161 switch(cmd){
162 case ADCTRL_RESYNC_STREAM:
163 sh->a_in_buffer_len=0; // clear audio input buffer
164 this->have_frame=0;
165 mad_synth_init (&this->synth);
166 mad_stream_init (&this->stream);
167 mad_frame_init (&this->frame);
168 return CONTROL_TRUE;
169 case ADCTRL_SKIP_FRAME:
170 this->have_frame=read_frame(sh);
171 return CONTROL_TRUE;
172 }
173 return CONTROL_UNKNOWN;
174 }
175 #endif