annotate libmpcodecs/ad_speex.c @ 31824:e26b1c667fd8

Add const to avoid warnings. The const on the return type is not correct compared to the real win32 API functions, but that really does not matter for us, avoiding the warning is more useful.
author reimar
date Mon, 02 Aug 2010 17:32:42 +0000
parents 482aa22c785e
children 8fa2f43cb760
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
30421
bbb6ebec87a0 Add missing license headers to all files in the libmpcodecs directory.
diego
parents: 20962
diff changeset
1 /*
16916
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
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
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
4 * This code may be be relicensed under the terms of the GNU LGPL when it
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
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
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
22 */
30421
bbb6ebec87a0 Add missing license headers to all files in the libmpcodecs directory.
diego
parents: 20962
diff changeset
23
16916
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
24 #include "config.h"
18157
2c7219c38e56 bug fixes: left-over mode variable used uninitialized,
reimar
parents: 17429
diff changeset
25 #include <stdlib.h>
16916
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
26 #include <speex/speex.h>
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
27 #include <speex/speex_stereo.h>
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
28 #include <speex/speex_header.h>
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
29 #include "ad_internal.h"
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
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
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
32 "Speex audio decoder",
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
33 "speex",
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
34 "Reimar Döffinger",
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
35 "",
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
36 ""
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
37 };
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
38
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
39 LIBAD_EXTERN(speex)
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
40
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
41 typedef struct {
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
42 SpeexBits bits;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
43 void *dec_context;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
44 SpeexStereoState stereo;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
45 SpeexHeader *hdr;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
46 } context_t;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
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
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
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
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
52 return 1;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
53 }
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
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
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
61 static int init(sh_audio_t *sh) {
18879
cc65a585fdcc rm unnecesary casts from void* - part 3
reynaldo
parents: 18157
diff changeset
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
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
64 const SpeexMode *spx_mode;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
65 const SpeexStereoState st_st = SPEEX_STEREO_STATE_INIT; // hack
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
66 if (!sh->wf || sh->wf->cbSize < 80) {
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
67 mp_msg(MSGT_DECAUDIO, MSGL_FATAL, "Missing extradata!\n");
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
68 return 0;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
69 }
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
70 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
71 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
72 // speex.acm format: raw SpeexHeader dump
482aa22c785e Support extradata format of the speex.acm windows codec formerly available
reimar
parents: 30841
diff changeset
73 ctx->hdr = calloc(1, sizeof(*ctx->hdr));
482aa22c785e Support extradata format of the speex.acm windows codec formerly available
reimar
parents: 30841
diff changeset
74 hdr += 2;
482aa22c785e Support extradata format of the speex.acm windows codec formerly available
reimar
parents: 30841
diff changeset
75 hdr += 8; // identifier string
482aa22c785e Support extradata format of the speex.acm windows codec formerly available
reimar
parents: 30841
diff changeset
76 hdr += 20; // version string
482aa22c785e Support extradata format of the speex.acm windows codec formerly available
reimar
parents: 30841
diff changeset
77 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
78 ctx->hdr->header_size = read_le32(&hdr);
482aa22c785e Support extradata format of the speex.acm windows codec formerly available
reimar
parents: 30841
diff changeset
79 ctx->hdr->rate = read_le32(&hdr);
482aa22c785e Support extradata format of the speex.acm windows codec formerly available
reimar
parents: 30841
diff changeset
80 ctx->hdr->mode = read_le32(&hdr);
482aa22c785e Support extradata format of the speex.acm windows codec formerly available
reimar
parents: 30841
diff changeset
81 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
82 ctx->hdr->nb_channels = read_le32(&hdr);
482aa22c785e Support extradata format of the speex.acm windows codec formerly available
reimar
parents: 30841
diff changeset
83 ctx->hdr->bitrate = read_le32(&hdr);
482aa22c785e Support extradata format of the speex.acm windows codec formerly available
reimar
parents: 30841
diff changeset
84 ctx->hdr->frame_size = read_le32(&hdr);
482aa22c785e Support extradata format of the speex.acm windows codec formerly available
reimar
parents: 30841
diff changeset
85 ctx->hdr->vbr = read_le32(&hdr);
482aa22c785e Support extradata format of the speex.acm windows codec formerly available
reimar
parents: 30841
diff changeset
86 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
87 }
30841
a1bf34d75484 Fix crash if speex_packet_to_header fails.
reimar
parents: 30633
diff changeset
88 if (!ctx->hdr) {
a1bf34d75484 Fix crash if speex_packet_to_header fails.
reimar
parents: 30633
diff changeset
89 mp_msg(MSGT_DECAUDIO, MSGL_FATAL, "Invalid extradata!\n");
a1bf34d75484 Fix crash if speex_packet_to_header fails.
reimar
parents: 30633
diff changeset
90 return 0;
a1bf34d75484 Fix crash if speex_packet_to_header fails.
reimar
parents: 30633
diff changeset
91 }
16916
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
92 if (ctx->hdr->nb_channels != 1 && ctx->hdr->nb_channels != 2) {
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
93 mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Invalid number of channels (%i), "
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
94 "assuming mono\n", ctx->hdr->nb_channels);
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
95 ctx->hdr->nb_channels = 1;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
96 }
18157
2c7219c38e56 bug fixes: left-over mode variable used uninitialized,
reimar
parents: 17429
diff changeset
97 if (ctx->hdr->frames_per_packet > MAX_FRAMES_PER_PACKET) {
2c7219c38e56 bug fixes: left-over mode variable used uninitialized,
reimar
parents: 17429
diff changeset
98 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
99 "assuming 1\n", ctx->hdr->frames_per_packet);
2c7219c38e56 bug fixes: left-over mode variable used uninitialized,
reimar
parents: 17429
diff changeset
100 ctx->hdr->frames_per_packet = 1;
2c7219c38e56 bug fixes: left-over mode variable used uninitialized,
reimar
parents: 17429
diff changeset
101 }
16916
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
102 switch (ctx->hdr->mode) {
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
103 case 0:
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
104 spx_mode = &speex_nb_mode; break;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
105 case 1:
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
106 spx_mode = &speex_wb_mode; break;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
107 case 2:
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
108 spx_mode = &speex_uwb_mode; break;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
109 default:
18157
2c7219c38e56 bug fixes: left-over mode variable used uninitialized,
reimar
parents: 17429
diff changeset
110 mp_msg(MSGT_DECAUDIO, MSGL_WARN, "Unknown speex mode (%i)\n", ctx->hdr->mode);
16916
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
111 spx_mode = &speex_nb_mode;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
112 }
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
113 ctx->dec_context = speex_decoder_init(spx_mode);
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
114 speex_bits_init(&ctx->bits);
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
115 memcpy(&ctx->stereo, &st_st, sizeof(ctx->stereo)); // hack part 2
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
116 sh->channels = ctx->hdr->nb_channels;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
117 sh->samplerate = ctx->hdr->rate;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
118 sh->samplesize = 2;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
119 sh->sample_format = AF_FORMAT_S16_NE;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
120 sh->context = ctx;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
121 return 1;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
122 }
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
123
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
124 static void uninit(sh_audio_t *sh) {
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
125 context_t *ctx = sh->context;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
126 if (ctx) {
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
127 speex_bits_destroy(&ctx->bits);
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
128 speex_decoder_destroy(ctx->dec_context);
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
129 if (ctx->hdr)
17429
7dac2afa70aa Use free instead of speex_free - since speex_free does not appear in the
reimar
parents: 16916
diff changeset
130 free(ctx->hdr);
16916
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
131 free(ctx);
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
132 }
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
133 ctx = NULL;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
134 }
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
135
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
136 static int decode_audio(sh_audio_t *sh, unsigned char *buf,
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
137 int minlen, int maxlen) {
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
138 context_t *ctx = sh->context;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
139 int len, framelen, framesamples;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
140 char *packet;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
141 int i, err;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
142 speex_decoder_ctl(ctx->dec_context, SPEEX_GET_FRAME_SIZE, &framesamples);
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
143 framelen = framesamples * ctx->hdr->nb_channels * sizeof(short);
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
144 if (maxlen < ctx->hdr->frames_per_packet * framelen) {
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
145 mp_msg(MSGT_DECAUDIO, MSGL_V, "maxlen too small in decode_audio\n");
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
146 return -1;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
147 }
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
148 len = ds_get_packet(sh->ds, (unsigned char **)&packet);
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
149 if (len <= 0) return -1;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
150 speex_bits_read_from(&ctx->bits, packet, len);
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
151 i = ctx->hdr->frames_per_packet;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
152 do {
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
153 err = speex_decode_int(ctx->dec_context, &ctx->bits, (short *)buf);
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
154 if (err == -2)
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
155 mp_msg(MSGT_DECAUDIO, MSGL_ERR, "Error decoding file.\n");
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
156 if (ctx->hdr->nb_channels == 2)
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
157 speex_decode_stereo_int((short *)buf, framesamples, &ctx->stereo);
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
158 buf = &buf[framelen];
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
159 } while (--i > 0);
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
160 return ctx->hdr->frames_per_packet * framelen;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
161 }
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
162
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
163 static int control(sh_audio_t *sh, int cmd, void *arg, ...) {
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
164 return CONTROL_UNKNOWN;
56f3945e2a61 Speex audio decoding
reimar
parents:
diff changeset
165 }