Mercurial > libavcodec.hg
annotate roqaudioenc.c @ 10680:d569841bd1b7 libavcodec
Clarify comment: although still hacky, it is correct for existing libtheora
author | conrad |
---|---|
date | Sat, 12 Dec 2009 20:18:49 +0000 |
parents | 1a3908177e87 |
children | 421c9441c11e |
rev | line source |
---|---|
4932 | 1 /* |
2 * RoQ audio encoder | |
3 * | |
4 * Copyright (c) 2005 Eric Lasota | |
5 * Based on RoQ specs (c)2001 Tim Ferguson | |
6 * | |
7 * This file is part of FFmpeg. | |
8 * | |
9 * FFmpeg is free software; you can redistribute it and/or | |
10 * modify it under the terms of the GNU Lesser General Public | |
11 * License as published by the Free Software Foundation; either | |
12 * version 2.1 of the License, or (at your option) any later version. | |
13 * | |
14 * FFmpeg is distributed in the hope that it will be useful, | |
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
17 * Lesser General Public License for more details. | |
18 * | |
19 * You should have received a copy of the GNU Lesser General Public | |
20 * License along with FFmpeg; if not, write to the Free Software | |
21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
22 */ | |
23 | |
24 #include "avcodec.h" | |
25 #include "bytestream.h" | |
26 | |
27 #define ROQ_FIRST_FRAME_SIZE (735*8) | |
28 #define ROQ_FRAME_SIZE 735 | |
29 | |
30 | |
31 #define MAX_DPCM (127*127) | |
32 | |
33 | |
34 typedef struct | |
35 { | |
36 short lastSample[2]; | |
8295
d4f9b58f6425
Rename ROQDPCMContext_t to ROQDPCMContext to avoid _t reserved prefix.
vitor
parents:
7451
diff
changeset
|
37 } ROQDPCMContext; |
4932 | 38 |
9007
043574c5c153
Add missing av_cold in static init/close functions.
stefano
parents:
8295
diff
changeset
|
39 static av_cold int roq_dpcm_encode_init(AVCodecContext *avctx) |
4932 | 40 { |
8295
d4f9b58f6425
Rename ROQDPCMContext_t to ROQDPCMContext to avoid _t reserved prefix.
vitor
parents:
7451
diff
changeset
|
41 ROQDPCMContext *context = avctx->priv_data; |
4932 | 42 |
43 if (avctx->channels > 2) { | |
44 av_log(avctx, AV_LOG_ERROR, "Audio must be mono or stereo\n"); | |
45 return -1; | |
46 } | |
47 if (avctx->sample_rate != 22050) { | |
48 av_log(avctx, AV_LOG_ERROR, "Audio must be 22050 Hz\n"); | |
49 return -1; | |
50 } | |
51 if (avctx->sample_fmt != SAMPLE_FMT_S16) { | |
52 av_log(avctx, AV_LOG_ERROR, "Audio must be signed 16-bit\n"); | |
53 return -1; | |
54 } | |
55 | |
56 avctx->frame_size = ROQ_FIRST_FRAME_SIZE; | |
57 | |
58 context->lastSample[0] = context->lastSample[1] = 0; | |
59 | |
60 avctx->coded_frame= avcodec_alloc_frame(); | |
61 avctx->coded_frame->key_frame= 1; | |
62 | |
63 return 0; | |
64 } | |
65 | |
66 static unsigned char dpcm_predict(short *previous, short current) | |
67 { | |
68 int diff; | |
69 int negative; | |
70 int result; | |
71 int predicted; | |
72 | |
73 diff = current - *previous; | |
74 | |
75 negative = diff<0; | |
76 diff = FFABS(diff); | |
77 | |
78 if (diff >= MAX_DPCM) | |
79 result = 127; | |
10427
1a3908177e87
Replace big square-root table by a call to ff_sqrt(). Based on a patch
vitor
parents:
10145
diff
changeset
|
80 else { |
1a3908177e87
Replace big square-root table by a call to ff_sqrt(). Based on a patch
vitor
parents:
10145
diff
changeset
|
81 result = ff_sqrt(diff); |
1a3908177e87
Replace big square-root table by a call to ff_sqrt(). Based on a patch
vitor
parents:
10145
diff
changeset
|
82 result += diff > result*result+result; |
1a3908177e87
Replace big square-root table by a call to ff_sqrt(). Based on a patch
vitor
parents:
10145
diff
changeset
|
83 } |
4932 | 84 |
85 /* See if this overflows */ | |
86 retry: | |
87 diff = result*result; | |
88 if (negative) | |
89 diff = -diff; | |
90 predicted = *previous + diff; | |
91 | |
92 /* If it overflows, back off a step */ | |
93 if (predicted > 32767 || predicted < -32768) { | |
94 result--; | |
95 goto retry; | |
96 } | |
97 | |
98 /* Add the sign bit */ | |
99 result |= negative << 7; //if (negative) result |= 128; | |
100 | |
101 *previous = predicted; | |
102 | |
103 return result; | |
104 } | |
105 | |
106 static int roq_dpcm_encode_frame(AVCodecContext *avctx, | |
107 unsigned char *frame, int buf_size, void *data) | |
108 { | |
109 int i, samples, stereo, ch; | |
110 short *in; | |
111 unsigned char *out; | |
112 | |
8295
d4f9b58f6425
Rename ROQDPCMContext_t to ROQDPCMContext to avoid _t reserved prefix.
vitor
parents:
7451
diff
changeset
|
113 ROQDPCMContext *context = avctx->priv_data; |
4932 | 114 |
115 stereo = (avctx->channels == 2); | |
116 | |
117 if (stereo) { | |
118 context->lastSample[0] &= 0xFF00; | |
119 context->lastSample[1] &= 0xFF00; | |
120 } | |
121 | |
122 out = frame; | |
123 in = data; | |
124 | |
125 bytestream_put_byte(&out, stereo ? 0x21 : 0x20); | |
126 bytestream_put_byte(&out, 0x10); | |
127 bytestream_put_le32(&out, avctx->frame_size*avctx->channels); | |
128 | |
129 if (stereo) { | |
130 bytestream_put_byte(&out, (context->lastSample[1])>>8); | |
131 bytestream_put_byte(&out, (context->lastSample[0])>>8); | |
132 } else | |
133 bytestream_put_le16(&out, context->lastSample[0]); | |
134 | |
135 /* Write the actual samples */ | |
136 samples = avctx->frame_size; | |
137 for (i=0; i<samples; i++) | |
138 for (ch=0; ch<avctx->channels; ch++) | |
139 *out++ = dpcm_predict(&context->lastSample[ch], *in++); | |
140 | |
141 /* Use smaller frames from now on */ | |
142 avctx->frame_size = ROQ_FRAME_SIZE; | |
143 | |
144 /* Return the result size */ | |
145 return out - frame; | |
146 } | |
147 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
4932
diff
changeset
|
148 static av_cold int roq_dpcm_encode_close(AVCodecContext *avctx) |
4932 | 149 { |
150 av_freep(&avctx->coded_frame); | |
151 | |
152 return 0; | |
153 } | |
154 | |
155 AVCodec roq_dpcm_encoder = { | |
156 "roq_dpcm", | |
157 CODEC_TYPE_AUDIO, | |
158 CODEC_ID_ROQ_DPCM, | |
8295
d4f9b58f6425
Rename ROQDPCMContext_t to ROQDPCMContext to avoid _t reserved prefix.
vitor
parents:
7451
diff
changeset
|
159 sizeof(ROQDPCMContext), |
4932 | 160 roq_dpcm_encode_init, |
161 roq_dpcm_encode_frame, | |
162 roq_dpcm_encode_close, | |
163 NULL, | |
10145
7955db355703
Make sample_fmts and channel_layouts compound literals const to reduce size of
reimar
parents:
9007
diff
changeset
|
164 .sample_fmts = (const enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE}, |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6816
diff
changeset
|
165 .long_name = NULL_IF_CONFIG_SMALL("id RoQ DPCM"), |
4932 | 166 }; |