Mercurial > mplayer.hg
annotate libmpcodecs/ad_speex.c @ 36782:06344efeded3
configure: improve FFmpeg check.
If internal FFmpeg is not available we should fall back to
external automatically instead of trying to build without
(which is currently broken it seems).
Also we can compile without internal copy as long as the
necessary headers can be found.
Two are required that FFmpeg does not install:
libavformat/internal.h
libavutil/x86/asm.h
author | reimar |
---|---|
date | Mon, 17 Feb 2014 23:25:32 +0000 |
parents | a93891202051 |
children |
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 |
18157
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
24 #include <stdlib.h> |
16916 | 25 #include <speex/speex.h> |
26 #include <speex/speex_stereo.h> | |
27 #include <speex/speex_header.h> | |
34174
a93891202051
Add missing mp_msg.h #includes, remove some unnecessary ones.
diego
parents:
33240
diff
changeset
|
28 |
a93891202051
Add missing mp_msg.h #includes, remove some unnecessary ones.
diego
parents:
33240
diff
changeset
|
29 #include "config.h" |
a93891202051
Add missing mp_msg.h #includes, remove some unnecessary ones.
diego
parents:
33240
diff
changeset
|
30 #include "mp_msg.h" |
16916 | 31 #include "ad_internal.h" |
32 | |
30504
cc27da5d7286
Mark all ad_info_t/vd_info_t structure declarations as const.
diego
parents:
30421
diff
changeset
|
33 static const ad_info_t info = { |
16916 | 34 "Speex audio decoder", |
35 "speex", | |
36 "Reimar Döffinger", | |
37 "", | |
38 "" | |
39 }; | |
40 | |
41 LIBAD_EXTERN(speex) | |
42 | |
43 typedef struct { | |
44 SpeexBits bits; | |
45 void *dec_context; | |
46 SpeexStereoState stereo; | |
47 SpeexHeader *hdr; | |
48 } context_t; | |
49 | |
18157
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
50 #define MAX_FRAMES_PER_PACKET 100 |
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
51 |
16916 | 52 static int preinit(sh_audio_t *sh) { |
18157
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
53 sh->audio_out_minsize = 2 * 320 * MAX_FRAMES_PER_PACKET * 2 * sizeof(short); |
16916 | 54 return 1; |
55 } | |
56 | |
30842
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
57 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
|
58 const uint8_t *p = *src; |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
59 *src += 4; |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
60 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
|
61 } |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
62 |
16916 | 63 static int init(sh_audio_t *sh) { |
18879 | 64 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
|
65 const uint8_t *hdr = (const uint8_t *)(sh->wf + 1); |
16916 | 66 const SpeexMode *spx_mode; |
67 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
|
68 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
|
69 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
|
70 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
|
71 // speex.acm format: raw SpeexHeader dump |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
72 ctx->hdr = calloc(1, sizeof(*ctx->hdr)); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
73 hdr += 2; |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
74 hdr += 8; // identifier string |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
75 hdr += 20; // version string |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
76 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
|
77 ctx->hdr->header_size = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
78 ctx->hdr->rate = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
79 ctx->hdr->mode = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
80 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
|
81 ctx->hdr->nb_channels = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
82 ctx->hdr->bitrate = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
83 ctx->hdr->frame_size = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
84 ctx->hdr->vbr = read_le32(&hdr); |
482aa22c785e
Support extradata format of the speex.acm windows codec formerly available
reimar
parents:
30841
diff
changeset
|
85 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
|
86 } |
30841 | 87 if (!ctx->hdr) { |
33240
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
88 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
|
89 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
|
90 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
|
91 ctx->hdr->mode = 0; |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
92 if (sh->wf) { |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
93 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
|
94 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
|
95 if (ctx->hdr->rate > 16000) |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
96 ctx->hdr->mode = 2; |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
97 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
|
98 ctx->hdr->mode = 1; |
1ff13ad1bc59
Setup default speex modes, allows decoding of speex in flv which does not
reimar
parents:
32617
diff
changeset
|
99 } |
30841 | 100 } |
16916 | 101 if (ctx->hdr->nb_channels != 1 && ctx->hdr->nb_channels != 2) { |
102 mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Invalid number of channels (%i), " | |
103 "assuming mono\n", ctx->hdr->nb_channels); | |
104 ctx->hdr->nb_channels = 1; | |
105 } | |
18157
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
106 if (ctx->hdr->frames_per_packet > MAX_FRAMES_PER_PACKET) { |
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
107 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
|
108 "assuming 1\n", ctx->hdr->frames_per_packet); |
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
109 ctx->hdr->frames_per_packet = 1; |
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
110 } |
16916 | 111 switch (ctx->hdr->mode) { |
112 case 0: | |
113 spx_mode = &speex_nb_mode; break; | |
114 case 1: | |
115 spx_mode = &speex_wb_mode; break; | |
116 case 2: | |
117 spx_mode = &speex_uwb_mode; break; | |
118 default: | |
18157
2c7219c38e56
bug fixes: left-over mode variable used uninitialized,
reimar
parents:
17429
diff
changeset
|
119 mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Unknown speex mode (%i)\n", ctx->hdr->mode); |
16916 | 120 spx_mode = &speex_nb_mode; |
121 } | |
122 ctx->dec_context = speex_decoder_init(spx_mode); | |
123 speex_bits_init(&ctx->bits); | |
124 memcpy(&ctx->stereo, &st_st, sizeof(ctx->stereo)); // hack part 2 | |
125 sh->channels = ctx->hdr->nb_channels; | |
126 sh->samplerate = ctx->hdr->rate; | |
127 sh->samplesize = 2; | |
128 sh->sample_format = AF_FORMAT_S16_NE; | |
129 sh->context = ctx; | |
130 return 1; | |
131 } | |
132 | |
133 static void uninit(sh_audio_t *sh) { | |
134 context_t *ctx = sh->context; | |
135 if (ctx) { | |
136 speex_bits_destroy(&ctx->bits); | |
137 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
|
138 free(ctx->hdr); |
16916 | 139 free(ctx); |
140 } | |
141 ctx = NULL; | |
142 } | |
143 | |
144 static int decode_audio(sh_audio_t *sh, unsigned char *buf, | |
145 int minlen, int maxlen) { | |
32617
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
146 double pts; |
16916 | 147 context_t *ctx = sh->context; |
148 int len, framelen, framesamples; | |
149 char *packet; | |
150 int i, err; | |
151 speex_decoder_ctl(ctx->dec_context, SPEEX_GET_FRAME_SIZE, &framesamples); | |
152 framelen = framesamples * ctx->hdr->nb_channels * sizeof(short); | |
153 if (maxlen < ctx->hdr->frames_per_packet * framelen) { | |
154 mp_msg(MSGT_DECAUDIO, MSGL_V, "maxlen too small in decode_audio\n"); | |
155 return -1; | |
156 } | |
32617
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
157 len = ds_get_packet_pts(sh->ds, (unsigned char **)&packet, &pts); |
16916 | 158 if (len <= 0) return -1; |
32617
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
159 if (sh->pts == MP_NOPTS_VALUE) |
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
160 sh->pts = 0; |
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
161 if (pts != MP_NOPTS_VALUE) { |
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
162 sh->pts = pts; |
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
163 sh->pts_bytes = 0; |
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
164 } |
16916 | 165 speex_bits_read_from(&ctx->bits, packet, len); |
166 i = ctx->hdr->frames_per_packet; | |
167 do { | |
168 err = speex_decode_int(ctx->dec_context, &ctx->bits, (short *)buf); | |
169 if (err == -2) | |
170 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Error decoding file.\n"); | |
171 if (ctx->hdr->nb_channels == 2) | |
172 speex_decode_stereo_int((short *)buf, framesamples, &ctx->stereo); | |
173 buf = &buf[framelen]; | |
174 } while (--i > 0); | |
32617
1baaacf00bbb
Improve speex codec pts handling, make audio timestamps work reasonably
reimar
parents:
32602
diff
changeset
|
175 sh->pts_bytes += ctx->hdr->frames_per_packet * framelen; |
16916 | 176 return ctx->hdr->frames_per_packet * framelen; |
177 } | |
178 | |
179 static int control(sh_audio_t *sh, int cmd, void *arg, ...) { | |
180 return CONTROL_UNKNOWN; | |
181 } |