Mercurial > mplayer.hg
annotate libmpcodecs/ad_speex.c @ 33672:e576232a39d5
Prevent balance from hopping.
Only recalculate the balance if the balance has changed, not if just
the volume has changed.
Because (at least with my soundcard) not all volume values can be
stored, but seem to be mapped onto a discrete value set, recalculation
the balance from the volume isn't accurate enough.
author | ib |
---|---|
date | Tue, 28 Jun 2011 18:16:06 +0000 |
parents | 1ff13ad1bc59 |
children | a93891202051 |
rev | line source |
---|---|
30421
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
1 /* |
16916 | 2 * Speex decoder by Reimar Döffinger <Reimar.Doeffinger@stud.uni-karlsruhe.de> |
30421
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
3 * |
16916 | 4 * This code may be be relicensed under the terms of the GNU LGPL when it |
5 * becomes part of the FFmpeg project (ffmpeg.org) | |
30421
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
6 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
7 * This file is part of MPlayer. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
8 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
9 * MPlayer is free software; you can redistribute it and/or modify |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
10 * it under the terms of the GNU General Public License as published by |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
11 * the Free Software Foundation; either version 2 of the License, or |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
12 * (at your option) any later version. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
13 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
14 * MPlayer is distributed in the hope that it will be useful, |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
17 * GNU General Public License for more details. |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
18 * |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
19 * You should have received a copy of the GNU General Public License along |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
20 * with MPlayer; if not, write to the Free Software Foundation, Inc., |
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
16916 | 22 */ |
30421
bbb6ebec87a0
Add missing license headers to all files in the libmpcodecs directory.
diego
parents:
20962
diff
changeset
|
23 |
16916 | 24 #include "config.h" |
18157
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
25 #include <stdlib.h> |
16916 | 26 #include <speex/speex.h> |
27 #include <speex/speex_stereo.h> | |
28 #include <speex/speex_header.h> | |
29 #include "ad_internal.h" | |
30 | |
30504
cc27da5d7286
Mark all ad_info_t/vd_info_t structure declarations as const.
diego
parents:
30421
diff
changeset
|
31 static const ad_info_t info = { |
16916 | 32 "Speex audio decoder", |
33 "speex", | |
34 "Reimar Döffinger", | |
35 "", | |
36 "" | |
37 }; | |
38 | |
39 LIBAD_EXTERN(speex) | |
40 | |
41 typedef struct { | |
42 SpeexBits bits; | |
43 void *dec_context; | |
44 SpeexStereoState stereo; | |
45 SpeexHeader *hdr; | |
46 } context_t; | |
47 | |
18157
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
48 #define MAX_FRAMES_PER_PACKET 100 |
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
49 |
16916 | 50 static int preinit(sh_audio_t *sh) { |
18157
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
51 sh->audio_out_minsize = 2 * 320 * MAX_FRAMES_PER_PACKET * 2 * sizeof(short); |
16916 | 52 return 1; |
53 } | |
54 | |
30842
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
55 static int read_le32(const uint8_t **src) { |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
56 const uint8_t *p = *src; |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
57 *src += 4; |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
58 return p[0] + (p[1] << 8) + (p[2] << 16) + (p[3] << 24); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
59 } |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
60 |
16916 | 61 static int init(sh_audio_t *sh) { |
18879 | 62 context_t *ctx = calloc(1, sizeof(context_t)); |
30842
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
63 const uint8_t *hdr = (const uint8_t *)(sh->wf + 1); |
16916 | 64 const SpeexMode *spx_mode; |
65 const SpeexStereoState st_st = SPEEX_STEREO_STATE_INIT; // hack | |
33240
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
66 if (sh->wf && sh->wf->cbSize >= 80) |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
67 ctx->hdr = speex_packet_to_header((char *)&sh->wf[1], sh->wf->cbSize); |
30842
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
68 if (!ctx->hdr && sh->wf->cbSize == 0x72 && hdr[0] == 1 && hdr[1] == 0) { |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
69 // speex.acm format: raw SpeexHeader dump |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
70 ctx->hdr = calloc(1, sizeof(*ctx->hdr)); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
71 hdr += 2; |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
72 hdr += 8; // identifier string |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
73 hdr += 20; // version string |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
74 ctx->hdr->speex_version_id = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
75 ctx->hdr->header_size = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
76 ctx->hdr->rate = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
77 ctx->hdr->mode = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
78 ctx->hdr->mode_bitstream_version = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
79 ctx->hdr->nb_channels = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
80 ctx->hdr->bitrate = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
81 ctx->hdr->frame_size = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
82 ctx->hdr->vbr = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
83 ctx->hdr->frames_per_packet = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
84 } |
30841 | 85 if (!ctx->hdr) { |
33240
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
86 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Invalid or missing extradata! Assuming defaults.\n"); |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
87 ctx->hdr = calloc(1, sizeof(*ctx->hdr)); |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
88 ctx->hdr->frames_per_packet = 1; |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
89 ctx->hdr->mode = 0; |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
90 if (sh->wf) { |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
91 ctx->hdr->nb_channels = sh->wf->nChannels; |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
92 ctx->hdr->rate = sh->wf->nSamplesPerSec; |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
93 if (ctx->hdr->rate > 16000) |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
94 ctx->hdr->mode = 2; |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
95 else if (ctx->hdr->rate > 8000) |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
96 ctx->hdr->mode = 1; |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
97 } |
30841 | 98 } |
16916 | 99 if (ctx->hdr->nb_channels != 1 && ctx->hdr->nb_channels != 2) { |
100 mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Invalid number of channels (%i), " | |
101 "assuming mono\n", ctx->hdr->nb_channels); | |
102 ctx->hdr->nb_channels = 1; | |
103 } | |
18157
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
104 if (ctx->hdr->frames_per_packet > MAX_FRAMES_PER_PACKET) { |
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
105 mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Invalid number of frames per packet (%i), " |
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
106 "assuming 1\n", ctx->hdr->frames_per_packet); |
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
107 ctx->hdr->frames_per_packet = 1; |
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
108 } |
16916 | 109 switch (ctx->hdr->mode) { |
110 case 0: | |
111 spx_mode = &speex_nb_mode; break; | |
112 case 1: | |
113 spx_mode = &speex_wb_mode; break; | |
114 case 2: | |
115 spx_mode = &speex_uwb_mode; break; | |
116 default: | |
18157
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
117 mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Unknown speex mode (%i)\n", ctx->hdr->mode); |
16916 | 118 spx_mode = &speex_nb_mode; |
119 } | |
120 ctx->dec_context = speex_decoder_init(spx_mode); | |
121 speex_bits_init(&ctx->bits); | |
122 memcpy(&ctx->stereo, &st_st, sizeof(ctx->stereo)); // hack part 2 | |
123 sh->channels = ctx->hdr->nb_channels; | |
124 sh->samplerate = ctx->hdr->rate; | |
125 sh->samplesize = 2; | |
126 sh->sample_format = AF_FORMAT_S16_NE; | |
127 sh->context = ctx; | |
128 return 1; | |
129 } | |
130 | |
131 static void uninit(sh_audio_t *sh) { | |
132 context_t *ctx = sh->context; | |
133 if (ctx) { | |
134 speex_bits_destroy(&ctx->bits); | |
135 speex_decoder_destroy(ctx->dec_context); | |
32537
8fa2f43cb760
Remove most of the NULL pointer check before free all over the code
cboesch
parents:
30842
diff
changeset
|
136 free(ctx->hdr); |
16916 | 137 free(ctx); |
138 } | |
139 ctx = NULL; | |
140 } | |
141 | |
142 static int decode_audio(sh_audio_t *sh, unsigned char *buf, | |
143 int minlen, int maxlen) { | |
32617
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
144 double pts; |
16916 | 145 context_t *ctx = sh->context; |
146 int len, framelen, framesamples; | |
147 char *packet; | |
148 int i, err; | |
149 speex_decoder_ctl(ctx->dec_context, SPEEX_GET_FRAME_SIZE, &framesamples); | |
150 framelen = framesamples * ctx->hdr->nb_channels * sizeof(short); | |
151 if (maxlen < ctx->hdr->frames_per_packet * framelen) { | |
152 mp_msg(MSGT_DECAUDIO, MSGL_V, "maxlen too small in decode_audio\n"); | |
153 return -1; | |
154 } | |
32617
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
155 len = ds_get_packet_pts(sh->ds, (unsigned char **)&packet, &pts); |
16916 | 156 if (len <= 0) return -1; |
32617
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
157 if (sh->pts == MP_NOPTS_VALUE) |
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
158 sh->pts = 0; |
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
159 if (pts != MP_NOPTS_VALUE) { |
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
160 sh->pts = pts; |
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
161 sh->pts_bytes = 0; |
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
162 } |
16916 | 163 speex_bits_read_from(&ctx->bits, packet, len); |
164 i = ctx->hdr->frames_per_packet; | |
165 do { | |
166 err = speex_decode_int(ctx->dec_context, &ctx->bits, (short *)buf); | |
167 if (err == -2) | |
168 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Error decoding file.\n"); | |
169 if (ctx->hdr->nb_channels == 2) | |
170 speex_decode_stereo_int((short *)buf, framesamples, &ctx->stereo); | |
171 buf = &buf[framelen]; | |
172 } while (--i > 0); | |
32617
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
173 sh->pts_bytes += ctx->hdr->frames_per_packet * framelen; |
16916 | 174 return ctx->hdr->frames_per_packet * framelen; |
175 } | |
176 | |
177 static int control(sh_audio_t *sh, int cmd, void *arg, ...) { | |
178 return CONTROL_UNKNOWN; | |
179 } |