Mercurial > libavcodec.hg
annotate roqaudioenc.c @ 6920:d02af7474bff libavcodec
Prevent 128*1<<trellis from becoming 0 and creating 0 sized arrays.
fixes CID84 RUN2
CID85 RUN2
CID86 RUN2
CID87 RUN2
CID88 RUN2
CID89 RUN2
CID90 RUN2
CID91 RUN2
CID92 RUN2
CID93 RUN2
CID94 RUN2
CID95 RUN2
CID96 RUN2
CID97 RUN2
CID98 RUN2
CID99 RUN2
CID100 RUN2
CID101 RUN2
CID102 RUN2
CID103 RUN2
CID104 RUN2
CID105 RUN2
CID106 RUN2
author | michael |
---|---|
date | Wed, 28 May 2008 11:59:41 +0000 |
parents | f6c73c9106db |
children | e943e1409077 |
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]; | |
38 } ROQDPCMContext_t; | |
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 { | |
54 ROQDPCMContext_t *context = avctx->priv_data; | |
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 | |
126 ROQDPCMContext_t *context = avctx->priv_data; | |
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, | |
172 sizeof(ROQDPCMContext_t), | |
173 roq_dpcm_encode_init, | |
174 roq_dpcm_encode_frame, | |
175 roq_dpcm_encode_close, | |
176 NULL, | |
6816
f6c73c9106db
consistent codec name by Stefano Sabatini, stefano.sabatini-lala poste it
diego
parents:
6812
diff
changeset
|
177 .long_name = "id RoQ DPCM", |
4932 | 178 }; |