Statistics
| Branch: | Revision:

ffmpeg / libavcodec / roqaudioenc.c @ f025588b

History | View | Annotate | Download (4.21 KB)

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

    
40
static void roq_dpcm_table_init(void)
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

    
161
static int roq_dpcm_encode_close(AVCodecContext *avctx)
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,
177
};