Mercurial > mplayer.hg
annotate libmpcodecs/ae_twolame.c @ 24590:2c238fa777ff
ao_alsa: Fix get_space() return values larger than buffersize
After a buffer underrun the ALSA get_space() function sometimes returned
values larger than the ao had set in ao_data.buffersize. Fix this by
replacing the old check against MAX_OUTBURST by one against
ao_data.buffersize. There should be no need for the MAX_OUTBURST check;
the current MPlayer side should no longer have any constant limit on the
amount of data an ao can buffer or request at once.
The get_space() values larger than ao_data.buffersize triggered errors
in audio decoding causing the current attempt to fill audio buffers to
be aborted. I'm not sure how often that caused behavior noticeably worse
then an underrun already is.
author | uau |
---|---|
date | Mon, 24 Sep 2007 21:49:58 +0000 |
parents | ed8f90096c65 |
children | 39d9ff988bc0 |
rev | line source |
---|---|
15359 | 1 #include <stdio.h> |
2 #include <stdlib.h> | |
3 #include <inttypes.h> | |
4 #include <unistd.h> | |
5 #include <string.h> | |
6 #include <sys/types.h> | |
7 #include "m_option.h" | |
17012 | 8 #include "mp_msg.h" |
22601
ed8f90096c65
Add explicit location for headers from the libmpdemux/ directory.
diego
parents:
22600
diff
changeset
|
9 #include "libmpdemux/aviheader.h" |
17012 | 10 #include "libaf/af_format.h" |
22601
ed8f90096c65
Add explicit location for headers from the libmpdemux/ directory.
diego
parents:
22600
diff
changeset
|
11 #include "libmpdemux/ms_hdr.h" |
22600
3c2b4a866c6a
Add explicit location for headers from the stream/ directory.
diego
parents:
21660
diff
changeset
|
12 #include "stream/stream.h" |
22601
ed8f90096c65
Add explicit location for headers from the libmpdemux/ directory.
diego
parents:
22600
diff
changeset
|
13 #include "libmpdemux/muxer.h" |
15359 | 14 #include "ae_twolame.h" |
17012 | 15 #include "libmpdemux/mp3_hdr.h" |
15359 | 16 |
17 | |
18 static int | |
19 param_bitrate = 192, | |
20 param_psy = 3, | |
21 param_maxvbr = 0, | |
22 param_errprot = 0, | |
23 param_debug = 0; | |
24 | |
25 static float param_vbr = 0; | |
26 static char *param_mode = "stereo"; | |
27 | |
28 m_option_t twolameopts_conf[] = { | |
29 {"br", ¶m_bitrate, CONF_TYPE_INT, 0, 0, 0, NULL}, | |
30 {"mode", ¶m_mode, CONF_TYPE_STRING, 0, 0, 0, NULL}, | |
15362
4ff00aa141ef
updated psycho model range; made a parameter file-static in ae_toolame.c
nicodvb
parents:
15359
diff
changeset
|
31 {"psy", ¶m_psy, CONF_TYPE_INT, CONF_RANGE, -1, 4, NULL}, |
15359 | 32 {"vbr", ¶m_vbr, CONF_TYPE_FLOAT, CONF_RANGE, -50, 50, NULL}, |
33 {"maxvbr", ¶m_maxvbr, CONF_TYPE_INT, 0, 0, 0, NULL}, | |
34 {"errprot", ¶m_errprot, CONF_TYPE_INT, CONF_RANGE, 0, 1, NULL}, | |
35 {"debug", ¶m_debug, CONF_TYPE_INT, CONF_RANGE, 0, 100000000, NULL}, | |
36 {NULL, NULL, 0, 0, 0, 0, NULL} | |
37 }; | |
38 | |
39 | |
40 static int bind_twolame(audio_encoder_t *encoder, muxer_stream_t *mux_a) | |
41 { | |
42 mpae_twolame_ctx *ctx = (mpae_twolame_ctx *) encoder->priv; | |
43 | |
44 mux_a->wf = malloc(sizeof(WAVEFORMATEX)+256); | |
45 mux_a->wf->wFormatTag = 0x50; | |
46 mux_a->wf->nChannels = encoder->params.channels; | |
47 mux_a->wf->nSamplesPerSec = encoder->params.sample_rate; | |
48 mux_a->wf->nAvgBytesPerSec = encoder->params.bitrate / 8; | |
49 | |
50 if(ctx->vbr || ((mux_a->wf->nAvgBytesPerSec * encoder->params.samples_per_frame) % mux_a->wf->nSamplesPerSec)) | |
51 { | |
52 mux_a->h.dwScale = encoder->params.samples_per_frame; | |
53 mux_a->h.dwRate = encoder->params.sample_rate; | |
54 mux_a->h.dwSampleSize = 0; // Blocksize not constant | |
55 } | |
56 else | |
57 { | |
58 mux_a->h.dwScale = (mux_a->wf->nAvgBytesPerSec * encoder->params.samples_per_frame)/ mux_a->wf->nSamplesPerSec; /* for cbr */ | |
59 mux_a->h.dwRate = mux_a->wf->nAvgBytesPerSec; | |
60 mux_a->h.dwSampleSize = mux_a->h.dwScale; | |
61 } | |
62 mux_a->wf->nBlockAlign = mux_a->h.dwScale; | |
63 mux_a->h.dwSuggestedBufferSize = (encoder->params.audio_preload*mux_a->wf->nAvgBytesPerSec)/1000; | |
64 mux_a->h.dwSuggestedBufferSize -= mux_a->h.dwSuggestedBufferSize % mux_a->wf->nBlockAlign; | |
65 | |
66 mux_a->wf->cbSize = 0; //12; | |
67 mux_a->wf->wBitsPerSample = 0; /* does not apply */ | |
68 ((MPEGLAYER3WAVEFORMAT *) (mux_a->wf))->wID = 1; | |
69 ((MPEGLAYER3WAVEFORMAT *) (mux_a->wf))->fdwFlags = 2; | |
70 ((MPEGLAYER3WAVEFORMAT *) (mux_a->wf))->nBlockSize = mux_a->wf->nBlockAlign; | |
71 ((MPEGLAYER3WAVEFORMAT *) (mux_a->wf))->nFramesPerBlock = 1; | |
72 ((MPEGLAYER3WAVEFORMAT *) (mux_a->wf))->nCodecDelay = 0; | |
73 | |
74 // Fix allocation | |
75 mux_a->wf = realloc(mux_a->wf, sizeof(WAVEFORMATEX)+mux_a->wf->cbSize); | |
76 | |
77 encoder->input_format = AF_FORMAT_S16_NE; | |
78 encoder->min_buffer_size = mux_a->h.dwSuggestedBufferSize; | |
79 encoder->max_buffer_size = mux_a->h.dwSuggestedBufferSize*2; | |
80 | |
81 return 1; | |
82 } | |
83 | |
84 static int encode_twolame(audio_encoder_t *encoder, uint8_t *dest, void *src, int len, int max_size) | |
85 { | |
86 mpae_twolame_ctx *ctx = (mpae_twolame_ctx *)encoder->priv; | |
87 int ret_size = 0, r2; | |
88 | |
89 len /= (2*encoder->params.channels); | |
90 ret_size = twolame_encode_buffer_interleaved(ctx->twolame_ctx, src, len, dest, max_size); | |
91 r2 = mp_decode_mp3_header(dest); | |
16482 | 92 mp_msg(MSGT_MENCODER, MSGL_DBG2, "\nSIZE: %d, max: %d, r2: %d\n", ret_size, max_size, r2); |
15359 | 93 if(r2 > 0) |
94 ret_size = r2; | |
95 return ret_size; | |
96 } | |
97 | |
98 int close_twolame(audio_encoder_t *encoder) | |
99 { | |
100 free(encoder->priv); | |
101 return 1; | |
102 } | |
103 | |
104 static int get_frame_size(audio_encoder_t *encoder) | |
105 { | |
106 int sz; | |
107 if(encoder->stream->buffer_len < 4) | |
108 return 0; | |
109 sz = mp_decode_mp3_header(encoder->stream->buffer); | |
110 if(sz <= 0) | |
111 return 0; | |
112 return sz; | |
113 } | |
114 | |
115 | |
116 int mpae_init_twolame(audio_encoder_t *encoder) | |
117 { | |
118 int mode; | |
119 mpae_twolame_ctx *ctx = NULL; | |
120 | |
121 if(encoder->params.channels == 1) | |
122 { | |
123 mp_msg(MSGT_MENCODER, MSGL_INFO, "ae_twolame, 1 audio channel, forcing mono mode\n"); | |
124 mode = TWOLAME_MONO; | |
125 } | |
126 else if(encoder->params.channels == 2) | |
127 { | |
128 if(! strcasecmp(param_mode, "dual")) | |
129 mode = TWOLAME_DUAL_CHANNEL; | |
130 else if(! strcasecmp(param_mode, "jstereo")) | |
131 mode = TWOLAME_JOINT_STEREO; | |
132 else if(! strcasecmp(param_mode, "stereo")) | |
133 mode = TWOLAME_STEREO; | |
134 else | |
135 { | |
136 mp_msg(MSGT_MENCODER, MSGL_ERR, "ae_twolame, unknown mode %s, exiting\n", param_mode); | |
137 } | |
138 } | |
139 else | |
140 mp_msg(MSGT_MENCODER, MSGL_ERR, "ae_twolame, Twolame can't encode > 2 channels, exiting\n"); | |
141 | |
142 ctx = (mpae_twolame_ctx *) calloc(1, sizeof(mpae_twolame_ctx)); | |
143 if(ctx == NULL) | |
144 { | |
145 mp_msg(MSGT_MENCODER, MSGL_ERR, "ae_twolame, couldn't alloc a %d bytes context, exiting\n", sizeof(mpae_twolame_ctx)); | |
146 return 0; | |
147 } | |
148 | |
149 ctx->twolame_ctx = twolame_init(); | |
150 if(ctx->twolame_ctx == NULL) | |
151 { | |
152 mp_msg(MSGT_MENCODER, MSGL_ERR, "ae_twolame, couldn't initial parameters from libtwolame, exiting\n"); | |
153 free(ctx); | |
154 return 0; | |
155 } | |
156 ctx->vbr = 0; | |
157 | |
158 if(twolame_set_num_channels(ctx->twolame_ctx, encoder->params.channels) != 0) | |
159 return 0; | |
160 if(twolame_set_mode(ctx->twolame_ctx, mode) != 0) | |
161 return 0; | |
162 | |
163 if(twolame_set_in_samplerate(ctx->twolame_ctx, encoder->params.sample_rate) != 0) | |
164 return 0; | |
165 | |
166 if(twolame_set_out_samplerate(ctx->twolame_ctx, encoder->params.sample_rate) != 0) | |
167 return 0; | |
168 | |
169 if(encoder->params.sample_rate < 32000) | |
170 twolame_set_version(ctx->twolame_ctx, TWOLAME_MPEG2); | |
171 else | |
172 twolame_set_version(ctx->twolame_ctx, TWOLAME_MPEG1); | |
173 | |
174 if(twolame_set_psymodel(ctx->twolame_ctx, param_psy) != 0) | |
175 return 0; | |
176 | |
177 if(twolame_set_bitrate(ctx->twolame_ctx, param_bitrate) != 0) | |
178 return 0; | |
179 | |
180 if(param_errprot) | |
181 if(twolame_set_error_protection(ctx->twolame_ctx, TRUE) != 0) | |
182 return 0; | |
183 | |
184 if(param_vbr != 0) | |
185 { | |
186 if(twolame_set_VBR(ctx->twolame_ctx, TRUE) != 0) | |
187 return 0; | |
188 if(twolame_set_VBR_q(ctx->twolame_ctx, param_vbr) != 0) | |
189 return 0; | |
190 if(twolame_set_padding(ctx->twolame_ctx, FALSE) != 0) | |
191 return 0; | |
192 if(param_maxvbr) | |
193 { | |
194 if(twolame_set_VBR_max_bitrate_kbps(ctx->twolame_ctx, param_maxvbr) != 0) | |
195 return 0; | |
196 } | |
197 ctx->vbr = 1; | |
198 } | |
199 | |
200 if(twolame_set_verbosity(ctx->twolame_ctx, param_debug) != 0) | |
201 return 0; | |
202 | |
203 if(twolame_init_params(ctx->twolame_ctx) != 0) | |
204 return 0; | |
205 | |
206 encoder->params.bitrate = param_bitrate * 1000; | |
207 encoder->params.samples_per_frame = 1152; | |
208 encoder->priv = ctx; | |
209 encoder->decode_buffer_size = 1152 * 2 * encoder->params.channels; | |
210 | |
211 encoder->bind = bind_twolame; | |
212 encoder->get_frame_size = get_frame_size; | |
213 encoder->encode = encode_twolame; | |
214 encoder->close = close_twolame; | |
215 | |
216 return 1; | |
217 } | |
218 |