Mercurial > libavcodec.hg
annotate roqaudioenc.c @ 8553:6ce9f5616a57 libavcodec
Rename bitstreamBuffers* as bitstream_buffers*
author | cehoyos |
---|---|
date | Wed, 07 Jan 2009 23:42:07 +0000 |
parents | d4f9b58f6425 |
children | 043574c5c153 |
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 static unsigned char dpcmValues[MAX_DPCM]; | |
33 | |
34 | |
35 typedef struct | |
36 { | |
37 short lastSample[2]; | |
8295
d4f9b58f6425
Rename ROQDPCMContext_t to ROQDPCMContext to avoid _t reserved prefix.
vitor
parents:
7451
diff
changeset
|
38 } ROQDPCMContext; |
4932 | 39 |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
4932
diff
changeset
|
40 static av_cold void roq_dpcm_table_init(void) |
4932 | 41 { |
42 int i; | |
43 | |
44 /* Create a table of quick DPCM values */ | |
45 for (i=0; i<MAX_DPCM; i++) { | |
46 int s= ff_sqrt(i); | |
47 int mid= s*s + s; | |
48 dpcmValues[i]= s + (i>mid); | |
49 } | |
50 } | |
51 | |
52 static int roq_dpcm_encode_init(AVCodecContext *avctx) | |
53 { | |
8295
d4f9b58f6425
Rename ROQDPCMContext_t to ROQDPCMContext to avoid _t reserved prefix.
vitor
parents:
7451
diff
changeset
|
54 ROQDPCMContext *context = avctx->priv_data; |
4932 | 55 |
56 if (avctx->channels > 2) { | |
57 av_log(avctx, AV_LOG_ERROR, "Audio must be mono or stereo\n"); | |
58 return -1; | |
59 } | |
60 if (avctx->sample_rate != 22050) { | |
61 av_log(avctx, AV_LOG_ERROR, "Audio must be 22050 Hz\n"); | |
62 return -1; | |
63 } | |
64 if (avctx->sample_fmt != SAMPLE_FMT_S16) { | |
65 av_log(avctx, AV_LOG_ERROR, "Audio must be signed 16-bit\n"); | |
66 return -1; | |
67 } | |
68 | |
69 roq_dpcm_table_init(); | |
70 | |
71 avctx->frame_size = ROQ_FIRST_FRAME_SIZE; | |
72 | |
73 context->lastSample[0] = context->lastSample[1] = 0; | |
74 | |
75 avctx->coded_frame= avcodec_alloc_frame(); | |
76 avctx->coded_frame->key_frame= 1; | |
77 | |
78 return 0; | |
79 } | |
80 | |
81 static unsigned char dpcm_predict(short *previous, short current) | |
82 { | |
83 int diff; | |
84 int negative; | |
85 int result; | |
86 int predicted; | |
87 | |
88 diff = current - *previous; | |
89 | |
90 negative = diff<0; | |
91 diff = FFABS(diff); | |
92 | |
93 if (diff >= MAX_DPCM) | |
94 result = 127; | |
95 else | |
96 result = dpcmValues[diff]; | |
97 | |
98 /* See if this overflows */ | |
99 retry: | |
100 diff = result*result; | |
101 if (negative) | |
102 diff = -diff; | |
103 predicted = *previous + diff; | |
104 | |
105 /* If it overflows, back off a step */ | |
106 if (predicted > 32767 || predicted < -32768) { | |
107 result--; | |
108 goto retry; | |
109 } | |
110 | |
111 /* Add the sign bit */ | |
112 result |= negative << 7; //if (negative) result |= 128; | |
113 | |
114 *previous = predicted; | |
115 | |
116 return result; | |
117 } | |
118 | |
119 static int roq_dpcm_encode_frame(AVCodecContext *avctx, | |
120 unsigned char *frame, int buf_size, void *data) | |
121 { | |
122 int i, samples, stereo, ch; | |
123 short *in; | |
124 unsigned char *out; | |
125 | |
8295
d4f9b58f6425
Rename ROQDPCMContext_t to ROQDPCMContext to avoid _t reserved prefix.
vitor
parents:
7451
diff
changeset
|
126 ROQDPCMContext *context = avctx->priv_data; |
4932 | 127 |
128 stereo = (avctx->channels == 2); | |
129 | |
130 if (stereo) { | |
131 context->lastSample[0] &= 0xFF00; | |
132 context->lastSample[1] &= 0xFF00; | |
133 } | |
134 | |
135 out = frame; | |
136 in = data; | |
137 | |
138 bytestream_put_byte(&out, stereo ? 0x21 : 0x20); | |
139 bytestream_put_byte(&out, 0x10); | |
140 bytestream_put_le32(&out, avctx->frame_size*avctx->channels); | |
141 | |
142 if (stereo) { | |
143 bytestream_put_byte(&out, (context->lastSample[1])>>8); | |
144 bytestream_put_byte(&out, (context->lastSample[0])>>8); | |
145 } else | |
146 bytestream_put_le16(&out, context->lastSample[0]); | |
147 | |
148 /* Write the actual samples */ | |
149 samples = avctx->frame_size; | |
150 for (i=0; i<samples; i++) | |
151 for (ch=0; ch<avctx->channels; ch++) | |
152 *out++ = dpcm_predict(&context->lastSample[ch], *in++); | |
153 | |
154 /* Use smaller frames from now on */ | |
155 avctx->frame_size = ROQ_FRAME_SIZE; | |
156 | |
157 /* Return the result size */ | |
158 return out - frame; | |
159 } | |
160 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
4932
diff
changeset
|
161 static av_cold int roq_dpcm_encode_close(AVCodecContext *avctx) |
4932 | 162 { |
163 av_freep(&avctx->coded_frame); | |
164 | |
165 return 0; | |
166 } | |
167 | |
168 AVCodec roq_dpcm_encoder = { | |
169 "roq_dpcm", | |
170 CODEC_TYPE_AUDIO, | |
171 CODEC_ID_ROQ_DPCM, | |
8295
d4f9b58f6425
Rename ROQDPCMContext_t to ROQDPCMContext to avoid _t reserved prefix.
vitor
parents:
7451
diff
changeset
|
172 sizeof(ROQDPCMContext), |
4932 | 173 roq_dpcm_encode_init, |
174 roq_dpcm_encode_frame, | |
175 roq_dpcm_encode_close, | |
176 NULL, | |
7451
85ab7655ad4d
Modify all codecs to report their supported input and output sample format(s).
pross
parents:
7040
diff
changeset
|
177 .sample_fmts = (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
|
178 .long_name = NULL_IF_CONFIG_SMALL("id RoQ DPCM"), |
4932 | 179 }; |