Mercurial > libavcodec.hg
annotate roqaudioenc.c @ 12092:de9e45d04063 libavcodec
DCA: Occasionally a false XCH sync word can turn up after the core DTS data,
to verify the sync word the extension fsize field should be compared to
the core data length field.
Patch by nick.nbrereton@net
author | banan |
---|---|
date | Mon, 05 Jul 2010 08:16:43 +0000 |
parents | 8a4984c5cacc |
children | dde20597f15e |
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 | |
11417 | 24 #include "libavutil/intmath.h" |
4932 | 25 #include "avcodec.h" |
26 #include "bytestream.h" | |
27 | |
28 #define ROQ_FIRST_FRAME_SIZE (735*8) | |
29 #define ROQ_FRAME_SIZE 735 | |
30 | |
31 | |
32 #define MAX_DPCM (127*127) | |
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 |
9007
043574c5c153
Add missing av_cold in static init/close functions.
stefano
parents:
8295
diff
changeset
|
40 static av_cold int roq_dpcm_encode_init(AVCodecContext *avctx) |
4932 | 41 { |
8295
d4f9b58f6425
Rename ROQDPCMContext_t to ROQDPCMContext to avoid _t reserved prefix.
vitor
parents:
7451
diff
changeset
|
42 ROQDPCMContext *context = avctx->priv_data; |
4932 | 43 |
44 if (avctx->channels > 2) { | |
45 av_log(avctx, AV_LOG_ERROR, "Audio must be mono or stereo\n"); | |
46 return -1; | |
47 } | |
48 if (avctx->sample_rate != 22050) { | |
49 av_log(avctx, AV_LOG_ERROR, "Audio must be 22050 Hz\n"); | |
50 return -1; | |
51 } | |
52 if (avctx->sample_fmt != SAMPLE_FMT_S16) { | |
53 av_log(avctx, AV_LOG_ERROR, "Audio must be signed 16-bit\n"); | |
54 return -1; | |
55 } | |
56 | |
57 avctx->frame_size = ROQ_FIRST_FRAME_SIZE; | |
58 | |
59 context->lastSample[0] = context->lastSample[1] = 0; | |
60 | |
61 avctx->coded_frame= avcodec_alloc_frame(); | |
62 avctx->coded_frame->key_frame= 1; | |
63 | |
64 return 0; | |
65 } | |
66 | |
67 static unsigned char dpcm_predict(short *previous, short current) | |
68 { | |
69 int diff; | |
70 int negative; | |
71 int result; | |
72 int predicted; | |
73 | |
74 diff = current - *previous; | |
75 | |
76 negative = diff<0; | |
77 diff = FFABS(diff); | |
78 | |
79 if (diff >= MAX_DPCM) | |
80 result = 127; | |
10427
1a3908177e87
Replace big square-root table by a call to ff_sqrt(). Based on a patch
vitor
parents:
10145
diff
changeset
|
81 else { |
1a3908177e87
Replace big square-root table by a call to ff_sqrt(). Based on a patch
vitor
parents:
10145
diff
changeset
|
82 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
|
83 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
|
84 } |
4932 | 85 |
86 /* See if this overflows */ | |
87 retry: | |
88 diff = result*result; | |
89 if (negative) | |
90 diff = -diff; | |
91 predicted = *previous + diff; | |
92 | |
93 /* If it overflows, back off a step */ | |
94 if (predicted > 32767 || predicted < -32768) { | |
95 result--; | |
96 goto retry; | |
97 } | |
98 | |
99 /* Add the sign bit */ | |
100 result |= negative << 7; //if (negative) result |= 128; | |
101 | |
102 *previous = predicted; | |
103 | |
104 return result; | |
105 } | |
106 | |
107 static int roq_dpcm_encode_frame(AVCodecContext *avctx, | |
108 unsigned char *frame, int buf_size, void *data) | |
109 { | |
110 int i, samples, stereo, ch; | |
111 short *in; | |
112 unsigned char *out; | |
113 | |
8295
d4f9b58f6425
Rename ROQDPCMContext_t to ROQDPCMContext to avoid _t reserved prefix.
vitor
parents:
7451
diff
changeset
|
114 ROQDPCMContext *context = avctx->priv_data; |
4932 | 115 |
116 stereo = (avctx->channels == 2); | |
117 | |
118 if (stereo) { | |
119 context->lastSample[0] &= 0xFF00; | |
120 context->lastSample[1] &= 0xFF00; | |
121 } | |
122 | |
123 out = frame; | |
124 in = data; | |
125 | |
126 bytestream_put_byte(&out, stereo ? 0x21 : 0x20); | |
127 bytestream_put_byte(&out, 0x10); | |
128 bytestream_put_le32(&out, avctx->frame_size*avctx->channels); | |
129 | |
130 if (stereo) { | |
131 bytestream_put_byte(&out, (context->lastSample[1])>>8); | |
132 bytestream_put_byte(&out, (context->lastSample[0])>>8); | |
133 } else | |
134 bytestream_put_le16(&out, context->lastSample[0]); | |
135 | |
136 /* Write the actual samples */ | |
137 samples = avctx->frame_size; | |
138 for (i=0; i<samples; i++) | |
139 for (ch=0; ch<avctx->channels; ch++) | |
140 *out++ = dpcm_predict(&context->lastSample[ch], *in++); | |
141 | |
142 /* Use smaller frames from now on */ | |
143 avctx->frame_size = ROQ_FRAME_SIZE; | |
144 | |
145 /* Return the result size */ | |
146 return out - frame; | |
147 } | |
148 | |
6517
48759bfbd073
Apply 'cold' attribute to init/uninit functions in libavcodec
zuxy
parents:
4932
diff
changeset
|
149 static av_cold int roq_dpcm_encode_close(AVCodecContext *avctx) |
4932 | 150 { |
151 av_freep(&avctx->coded_frame); | |
152 | |
153 return 0; | |
154 } | |
155 | |
156 AVCodec roq_dpcm_encoder = { | |
157 "roq_dpcm", | |
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
11417
diff
changeset
|
158 AVMEDIA_TYPE_AUDIO, |
4932 | 159 CODEC_ID_ROQ_DPCM, |
8295
d4f9b58f6425
Rename ROQDPCMContext_t to ROQDPCMContext to avoid _t reserved prefix.
vitor
parents:
7451
diff
changeset
|
160 sizeof(ROQDPCMContext), |
4932 | 161 roq_dpcm_encode_init, |
162 roq_dpcm_encode_frame, | |
163 roq_dpcm_encode_close, | |
164 NULL, | |
10145
7955db355703
Make sample_fmts and channel_layouts compound literals const to reduce size of
reimar
parents:
9007
diff
changeset
|
165 .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
|
166 .long_name = NULL_IF_CONFIG_SMALL("id RoQ DPCM"), |
4932 | 167 }; |