Mercurial > libavcodec.hg
annotate dtsdec.c @ 4671:97e3364d267a libavcodec
DXA demuxer and decoder
author | kostya |
---|---|
date | Wed, 14 Mar 2007 14:49:49 +0000 |
parents | ee7422a921cb |
children | 8f47dc8782f9 |
rev | line source |
---|---|
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
1 /* |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
2 * dtsdec.c : free DTS Coherent Acoustics stream decoder. |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
3 * Copyright (C) 2004 Benjamin Zores <ben@geexbox.org> |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
4 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3267
diff
changeset
|
5 * This file is part of FFmpeg. |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
6 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3267
diff
changeset
|
7 * FFmpeg is free software; you can redistribute it and/or modify |
2126 | 8 * it under the terms of the GNU General Public License as published by |
3965 | 9 * the Free Software Foundation; either version 2 of the License, or |
2126 | 10 * (at your option) any later version. |
2967 | 11 * |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3267
diff
changeset
|
12 * FFmpeg is distributed in the hope that it will be useful, |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
2126 | 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
15 * GNU General Public License for more details. | |
2967 | 16 * |
2126 | 17 * You should have received a copy of the GNU General Public License |
3947
c8c591fe26f8
Change license headers to say 'FFmpeg' instead of 'this program/this library'
diego
parents:
3267
diff
changeset
|
18 * along with FFmpeg; if not, write to the Free Software |
4385 | 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
20 */ |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
21 |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
22 #include "avcodec.h" |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
23 #include <dts.h> |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
24 |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
25 #include <stdlib.h> |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
26 #include <string.h> |
2186 | 27 |
3267
8072ed8993f6
dtsdec.c copies one input packet at a time to a (static) buffer of size
rtognimp
parents:
2979
diff
changeset
|
28 #define BUFFER_SIZE 18726 |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
29 #define HEADER_SIZE 14 |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
30 |
4482 | 31 #define CONVERT_LEVEL 1 |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
32 #define CONVERT_BIAS 0 |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
33 |
4481 | 34 typedef struct DTSContext { |
35 dts_state_t *state; | |
36 uint8_t buf[BUFFER_SIZE]; | |
37 uint8_t *bufptr; | |
38 uint8_t *bufpos; | |
39 } DTSContext; | |
40 | |
4478 | 41 static inline int16_t |
4482 | 42 convert(sample_t s) |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
43 { |
4482 | 44 return s * 0x7fff; |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
45 } |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
46 |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
47 static void |
4482 | 48 convert2s16_multi(sample_t *f, int16_t *s16, int flags) |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
49 { |
4478 | 50 int i; |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
51 |
4482 | 52 switch(flags & (DTS_CHANNEL_MASK | DTS_LFE)){ |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
53 case DTS_MONO: |
4482 | 54 for(i = 0; i < 256; i++){ |
55 s16[5*i] = s16[5*i+1] = s16[5*i+2] = s16[5*i+3] = 0; | |
56 s16[5*i+4] = convert(f[i]); | |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
57 } |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
58 case DTS_CHANNEL: |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
59 case DTS_STEREO: |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
60 case DTS_DOLBY: |
4482 | 61 for(i = 0; i < 256; i++){ |
62 s16[2*i] = convert(f[i]); | |
63 s16[2*i+1] = convert(f[i+256]); | |
64 } | |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
65 case DTS_3F: |
4482 | 66 for(i = 0; i < 256; i++){ |
67 s16[5*i] = convert(f[i+256]); | |
68 s16[5*i+1] = convert(f[i+512]); | |
69 s16[5*i+2] = s16[5*i+3] = 0; | |
70 s16[5*i+4] = convert(f[i]); | |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
71 } |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
72 case DTS_2F2R: |
4482 | 73 for(i = 0; i < 256; i++){ |
74 s16[4*i] = convert(f[i]); | |
75 s16[4*i+1] = convert(f[i+256]); | |
76 s16[4*i+2] = convert(f[i+512]); | |
77 s16[4*i+3] = convert(f[i+768]); | |
78 } | |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
79 case DTS_3F2R: |
4482 | 80 for(i = 0; i < 256; i++){ |
81 s16[5*i] = convert(f[i+256]); | |
82 s16[5*i+1] = convert(f[i+512]); | |
83 s16[5*i+2] = convert(f[i+768]); | |
84 s16[5*i+3] = convert(f[i+1024]); | |
85 s16[5*i+4] = convert(f[i]); | |
86 } | |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
87 case DTS_MONO | DTS_LFE: |
4482 | 88 for(i = 0; i < 256; i++){ |
89 s16[6*i] = s16[6*i+1] = s16[6*i+2] = s16[6*i+3] = 0; | |
90 s16[6*i+4] = convert(f[i]); | |
91 s16[6*i+5] = convert(f[i+256]); | |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
92 } |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
93 case DTS_CHANNEL | DTS_LFE: |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
94 case DTS_STEREO | DTS_LFE: |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
95 case DTS_DOLBY | DTS_LFE: |
4482 | 96 for(i = 0; i < 256; i++){ |
97 s16[6*i] = convert(f[i]); | |
98 s16[6*i+1] = convert(f[i+256]); | |
99 s16[6*i+2] = s16[6*i+3] = s16[6*i+4] = 0; | |
100 s16[6*i+5] = convert(f[i+512]); | |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
101 } |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
102 case DTS_3F | DTS_LFE: |
4482 | 103 for(i = 0; i < 256; i++){ |
104 s16[6*i] = convert(f[i+256]); | |
105 s16[6*i+1] = convert(f[i+512]); | |
106 s16[6*i+2] = s16[6*i+3] = 0; | |
107 s16[6*i+4] = convert(f[i]); | |
108 s16[6*i+5] = convert(f[i+768]); | |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
109 } |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
110 case DTS_2F2R | DTS_LFE: |
4482 | 111 for(i = 0; i < 256; i++){ |
112 s16[6*i] = convert(f[i]); | |
113 s16[6*i+1] = convert(f[i+256]); | |
114 s16[6*i+2] = convert(f[i+512]); | |
115 s16[6*i+3] = convert(f[i+768]); | |
116 s16[6*i+4] = 0; | |
117 s16[6*i+5] = convert(f[i+1024]); | |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
118 } |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
119 case DTS_3F2R | DTS_LFE: |
4482 | 120 for(i = 0; i < 256; i++){ |
121 s16[6*i] = convert(f[i+256]); | |
122 s16[6*i+1] = convert(f[i+512]); | |
123 s16[6*i+2] = convert(f[i+768]); | |
124 s16[6*i+3] = convert(f[i+1024]); | |
125 s16[6*i+4] = convert(f[i]); | |
126 s16[6*i+5] = convert(f[i+1280]); | |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
127 } |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
128 } |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
129 } |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
130 |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
131 static int |
4478 | 132 channels_multi(int flags) |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
133 { |
4482 | 134 switch(flags & (DTS_CHANNEL_MASK | DTS_LFE)){ |
135 case DTS_CHANNEL: | |
136 case DTS_STEREO: | |
137 case DTS_DOLBY: | |
138 return 2; | |
139 case DTS_2F2R: | |
140 return 4; | |
141 case DTS_MONO: | |
142 case DTS_3F: | |
143 case DTS_3F2R: | |
4478 | 144 return 5; |
4482 | 145 case DTS_MONO | DTS_LFE: |
146 case DTS_CHANNEL | DTS_LFE: | |
147 case DTS_STEREO | DTS_LFE: | |
148 case DTS_DOLBY | DTS_LFE: | |
149 case DTS_3F | DTS_LFE: | |
150 case DTS_2F2R | DTS_LFE: | |
151 case DTS_3F2R | DTS_LFE: | |
152 return 6; | |
153 } | |
154 | |
155 return -1; | |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
156 } |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
157 |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
158 static int |
4478 | 159 dts_decode_frame(AVCodecContext * avctx, void *data, int *data_size, |
160 uint8_t * buff, int buff_size) | |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
161 { |
4481 | 162 DTSContext *s = avctx->priv_data; |
4478 | 163 uint8_t *start = buff; |
164 uint8_t *end = buff + buff_size; | |
165 int16_t *out_samples = data; | |
4481 | 166 int sample_rate; |
167 int frame_length; | |
168 int flags; | |
4478 | 169 int bit_rate; |
170 int len; | |
4479 | 171 level_t level; |
172 sample_t bias; | |
4482 | 173 int nblocks; |
4479 | 174 int i; |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
175 |
4478 | 176 *data_size = 0; |
2222 | 177 |
4478 | 178 while(1) { |
4479 | 179 int length; |
180 | |
4478 | 181 len = end - start; |
182 if(!len) | |
183 break; | |
4481 | 184 if(len > s->bufpos - s->bufptr) |
185 len = s->bufpos - s->bufptr; | |
186 memcpy(s->bufptr, start, len); | |
187 s->bufptr += len; | |
4478 | 188 start += len; |
4481 | 189 if(s->bufptr != s->bufpos) |
4478 | 190 return start - buff; |
4481 | 191 if(s->bufpos != s->buf + HEADER_SIZE) |
4478 | 192 break; |
3267
8072ed8993f6
dtsdec.c copies one input packet at a time to a (static) buffer of size
rtognimp
parents:
2979
diff
changeset
|
193 |
4481 | 194 length = dts_syncinfo(s->state, s->buf, &flags, &sample_rate, |
195 &bit_rate, &frame_length); | |
4479 | 196 if(!length) { |
197 av_log(NULL, AV_LOG_INFO, "skip\n"); | |
4481 | 198 for(s->bufptr = s->buf; s->bufptr < s->buf + HEADER_SIZE - 1; s->bufptr++) |
199 s->bufptr[0] = s->bufptr[1]; | |
4479 | 200 continue; |
201 } | |
4481 | 202 s->bufpos = s->buf + length; |
4479 | 203 } |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
204 |
4479 | 205 level = CONVERT_LEVEL; |
206 bias = CONVERT_BIAS; | |
207 | |
208 flags |= DTS_ADJUST_LEVEL; | |
4481 | 209 if(dts_frame(s->state, s->buf, &flags, &level, bias)) { |
4479 | 210 av_log(avctx, AV_LOG_ERROR, "dts_frame() failed\n"); |
211 goto end; | |
3267
8072ed8993f6
dtsdec.c copies one input packet at a time to a (static) buffer of size
rtognimp
parents:
2979
diff
changeset
|
212 } |
8072ed8993f6
dtsdec.c copies one input packet at a time to a (static) buffer of size
rtognimp
parents:
2979
diff
changeset
|
213 |
4479 | 214 avctx->sample_rate = sample_rate; |
215 avctx->channels = channels_multi(flags); | |
216 avctx->bit_rate = bit_rate; | |
4478 | 217 |
4482 | 218 nblocks = dts_blocks_num(s->state); |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
219 |
4482 | 220 for(i = 0; i < nblocks; i++) { |
4481 | 221 if(dts_block(s->state)) { |
4479 | 222 av_log(avctx, AV_LOG_ERROR, "dts_block() failed\n"); |
223 goto end; | |
224 } | |
4478 | 225 |
4482 | 226 convert2s16_multi(dts_samples(s->state), out_samples, flags); |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
227 |
4482 | 228 out_samples += 256 * avctx->channels; |
229 *data_size += 256 * sizeof(int16_t) * avctx->channels; | |
4478 | 230 } |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
231 |
4479 | 232 end: |
4481 | 233 s->bufptr = s->buf; |
234 s->bufpos = s->buf + HEADER_SIZE; | |
4478 | 235 return start - buff; |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
236 } |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
237 |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
238 static int |
4478 | 239 dts_decode_init(AVCodecContext * avctx) |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
240 { |
4481 | 241 DTSContext *s = avctx->priv_data; |
242 s->bufptr = s->buf; | |
243 s->bufpos = s->buf + HEADER_SIZE; | |
244 s->state = dts_init(0); | |
245 if(s->state == NULL) | |
4478 | 246 return -1; |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
247 |
4478 | 248 return 0; |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
249 } |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
250 |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
251 static int |
4481 | 252 dts_decode_end(AVCodecContext * avctx) |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
253 { |
4481 | 254 DTSContext *s = avctx->priv_data; |
255 dts_free(s->state); | |
4478 | 256 return 0; |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
257 } |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
258 |
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
259 AVCodec dts_decoder = { |
4478 | 260 "dts", |
261 CODEC_TYPE_AUDIO, | |
262 CODEC_ID_DTS, | |
4481 | 263 sizeof(DTSContext), |
4478 | 264 dts_decode_init, |
265 NULL, | |
266 dts_decode_end, | |
267 dts_decode_frame, | |
2123
ef54decf5624
libdts support by (Benjamin Zores <ben at geexbox dot org>)
michael
parents:
diff
changeset
|
268 }; |