Revision f025588b

View differences:

libavcodec/Makefile
125 125
OBJS-$(CONFIG_RA_288_DECODER)          += ra288.o
126 126
OBJS-$(CONFIG_ROQ_DECODER)             += roqvideo.o
127 127
OBJS-$(CONFIG_ROQ_DPCM_DECODER)        += dpcm.o
128
OBJS-$(CONFIG_ROQ_DPCM_ENCODER)        += roqaudioenc.o
128 129
OBJS-$(CONFIG_RPZA_DECODER)            += rpza.o
129 130
OBJS-$(CONFIG_RV10_DECODER)            += rv10.o
130 131
OBJS-$(CONFIG_RV10_ENCODER)            += rv10.o
libavcodec/allcodecs.c
226 226

  
227 227
    /* dpcm codecs */
228 228
    REGISTER_DECODER(INTERPLAY_DPCM, interplay_dpcm);
229
    REGISTER_DECODER(ROQ_DPCM, roq_dpcm);
229
    REGISTER_ENCDEC (ROQ_DPCM, roq_dpcm);
230 230
    REGISTER_DECODER(SOL_DPCM, sol_dpcm);
231 231
    REGISTER_DECODER(XAN_DPCM, xan_dpcm);
232 232

  
libavcodec/avcodec.h
2225 2225
extern AVCodec pgmyuv_encoder;
2226 2226
extern AVCodec png_encoder;
2227 2227
extern AVCodec ppm_encoder;
2228
extern AVCodec roq_dpcm_encoder;
2228 2229
extern AVCodec rv10_encoder;
2229 2230
extern AVCodec rv20_encoder;
2230 2231
extern AVCodec sgi_encoder;
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
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
};

Also available in: Unified diff