]> rtime.felk.cvut.cz Git - frescor/ffmpeg.git/blob - libavcodec/roqaudioenc.c
Cosmetics: Re-indent
[frescor/ffmpeg.git] / libavcodec / roqaudioenc.c
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];
37 } ROQDPCMContext;
38
39 static av_cold int roq_dpcm_encode_init(AVCodecContext *avctx)
40 {
41     ROQDPCMContext *context = avctx->priv_data;
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;
80     else {
81         result = ff_sqrt(diff);
82         result += diff > result*result+result;
83     }
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
113     ROQDPCMContext *context = avctx->priv_data;
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
148 static av_cold int roq_dpcm_encode_close(AVCodecContext *avctx)
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,
159     sizeof(ROQDPCMContext),
160     roq_dpcm_encode_init,
161     roq_dpcm_encode_frame,
162     roq_dpcm_encode_close,
163     NULL,
164     .sample_fmts = (const enum SampleFormat[]){SAMPLE_FMT_S16,SAMPLE_FMT_NONE},
165     .long_name = NULL_IF_CONFIG_SMALL("id RoQ DPCM"),
166 };