~ubuntu-branches/ubuntu/jaunty/xvidcap/jaunty-proposed

« back to all changes in this revision

Viewing changes to ffmpeg/libavcodec/qpeg.c

  • Committer: Bazaar Package Importer
  • Author(s): John Dong
  • Date: 2008-02-25 15:47:12 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080225154712-qvr11ekcea4c9ry8
Tags: 1.1.6-0.1ubuntu1
* Merge from debian-multimedia (LP: #120003), Ubuntu Changes:
 - For ffmpeg-related build-deps, remove cvs from package names.
 - Standards-Version 3.7.3
 - Maintainer Spec

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * QPEG codec
 
3
 * Copyright (c) 2004 Konstantin Shishkov
 
4
 *
 
5
 * This file is part of FFmpeg.
 
6
 *
 
7
 * FFmpeg is free software; you can redistribute it and/or
 
8
 * modify it under the terms of the GNU Lesser General Public
 
9
 * License as published by the Free Software Foundation; either
 
10
 * version 2.1 of the License, or (at your option) any later version.
 
11
 *
 
12
 * FFmpeg is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
 * Lesser General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU Lesser General Public
 
18
 * License along with FFmpeg; if not, write to the Free Software
 
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
 
20
 *
 
21
 */
 
22
 
 
23
/**
 
24
 * @file qpeg.c
 
25
 * QPEG codec.
 
26
 */
 
27
 
 
28
#include "avcodec.h"
 
29
#include "mpegvideo.h"
 
30
 
 
31
typedef struct QpegContext{
 
32
    AVCodecContext *avctx;
 
33
    AVFrame pic;
 
34
    uint8_t *refdata;
 
35
} QpegContext;
 
36
 
 
37
static void qpeg_decode_intra(uint8_t *src, uint8_t *dst, int size,
 
38
                            int stride, int width, int height)
 
39
{
 
40
    int i;
 
41
    int code;
 
42
    int c0, c1;
 
43
    int run, copy;
 
44
    int filled = 0;
 
45
    int rows_to_go;
 
46
 
 
47
    rows_to_go = height;
 
48
    height--;
 
49
    dst = dst + height * stride;
 
50
 
 
51
    while((size > 0) && (rows_to_go > 0)) {
 
52
        code = *src++;
 
53
        size--;
 
54
        run = copy = 0;
 
55
        if(code == 0xFC) /* end-of-picture code */
 
56
            break;
 
57
        if(code >= 0xF8) { /* very long run */
 
58
            c0 = *src++;
 
59
            c1 = *src++;
 
60
            size -= 2;
 
61
            run = ((code & 0x7) << 16) + (c0 << 8) + c1 + 2;
 
62
        } else if (code >= 0xF0) { /* long run */
 
63
            c0 = *src++;
 
64
            size--;
 
65
            run = ((code & 0xF) << 8) + c0 + 2;
 
66
        } else if (code >= 0xE0) { /* short run */
 
67
            run = (code & 0x1F) + 2;
 
68
        } else if (code >= 0xC0) { /* very long copy */
 
69
            c0 = *src++;
 
70
            c1 = *src++;
 
71
            size -= 2;
 
72
            copy = ((code & 0x3F) << 16) + (c0 << 8) + c1 + 1;
 
73
        } else if (code >= 0x80) { /* long copy */
 
74
            c0 = *src++;
 
75
            size--;
 
76
            copy = ((code & 0x7F) << 8) + c0 + 1;
 
77
        } else { /* short copy */
 
78
            copy = code + 1;
 
79
        }
 
80
 
 
81
        /* perform actual run or copy */
 
82
        if(run) {
 
83
            int p;
 
84
 
 
85
            p = *src++;
 
86
            size--;
 
87
            for(i = 0; i < run; i++) {
 
88
                dst[filled++] = p;
 
89
                if (filled >= width) {
 
90
                    filled = 0;
 
91
                    dst -= stride;
 
92
                    rows_to_go--;
 
93
                    if(rows_to_go <= 0)
 
94
                        break;
 
95
                }
 
96
            }
 
97
        } else {
 
98
            size -= copy;
 
99
            for(i = 0; i < copy; i++) {
 
100
                dst[filled++] = *src++;
 
101
                if (filled >= width) {
 
102
                    filled = 0;
 
103
                    dst -= stride;
 
104
                    rows_to_go--;
 
105
                    if(rows_to_go <= 0)
 
106
                        break;
 
107
                }
 
108
            }
 
109
        }
 
110
    }
 
111
}
 
112
 
 
113
static int qpeg_table_h[16] =
 
114
 { 0x00, 0x20, 0x20, 0x20, 0x18, 0x10, 0x10, 0x20, 0x10, 0x08, 0x18, 0x08, 0x08, 0x18, 0x10, 0x04};
 
115
static int qpeg_table_w[16] =
 
116
 { 0x00, 0x20, 0x18, 0x08, 0x18, 0x10, 0x20, 0x10, 0x08, 0x10, 0x20, 0x20, 0x08, 0x10, 0x18, 0x04};
 
117
 
 
118
/* Decodes delta frames */
 
119
static void qpeg_decode_inter(uint8_t *src, uint8_t *dst, int size,
 
120
                            int stride, int width, int height,
 
121
                            int delta, uint8_t *ctable, uint8_t *refdata)
 
122
{
 
123
    int i, j;
 
124
    int code;
 
125
    int filled = 0;
 
126
    int orig_height;
 
127
    uint8_t *blkdata;
 
128
 
 
129
    /* copy prev frame */
 
130
    for(i = 0; i < height; i++)
 
131
        memcpy(refdata + (i * width), dst + (i * stride), width);
 
132
 
 
133
    orig_height = height;
 
134
    blkdata = src - 0x86;
 
135
    height--;
 
136
    dst = dst + height * stride;
 
137
 
 
138
    while((size > 0) && (height >= 0)) {
 
139
        code = *src++;
 
140
        size--;
 
141
 
 
142
        if(delta) {
 
143
            /* motion compensation */
 
144
            while((code & 0xF0) == 0xF0) {
 
145
                if(delta == 1) {
 
146
                    int me_idx;
 
147
                    int me_w, me_h, me_x, me_y;
 
148
                    uint8_t *me_plane;
 
149
                    int corr, val;
 
150
 
 
151
                    /* get block size by index */
 
152
                    me_idx = code & 0xF;
 
153
                    me_w = qpeg_table_w[me_idx];
 
154
                    me_h = qpeg_table_h[me_idx];
 
155
 
 
156
                    /* extract motion vector */
 
157
                    corr = *src++;
 
158
                    size--;
 
159
 
 
160
                    val = corr >> 4;
 
161
                    if(val > 7)
 
162
                        val -= 16;
 
163
                    me_x = val;
 
164
 
 
165
                    val = corr & 0xF;
 
166
                    if(val > 7)
 
167
                        val -= 16;
 
168
                    me_y = val;
 
169
 
 
170
                    /* check motion vector */
 
171
                    if ((me_x + filled < 0) || (me_x + me_w + filled > width) ||
 
172
                       (height - me_y - me_h < 0) || (height - me_y > orig_height) ||
 
173
                       (filled + me_w > width) || (height - me_h < 0))
 
174
                        av_log(NULL, AV_LOG_ERROR, "Bogus motion vector (%i,%i), block size %ix%i at %i,%i\n",
 
175
                               me_x, me_y, me_w, me_h, filled, height);
 
176
                    else {
 
177
                        /* do motion compensation */
 
178
                        me_plane = refdata + (filled + me_x) + (height - me_y) * width;
 
179
                        for(j = 0; j < me_h; j++) {
 
180
                            for(i = 0; i < me_w; i++)
 
181
                                dst[filled + i - (j * stride)] = me_plane[i - (j * width)];
 
182
                        }
 
183
                    }
 
184
                }
 
185
                code = *src++;
 
186
                size--;
 
187
            }
 
188
        }
 
189
 
 
190
        if(code == 0xE0) /* end-of-picture code */
 
191
            break;
 
192
        if(code > 0xE0) { /* run code: 0xE1..0xFF */
 
193
            int p;
 
194
 
 
195
            code &= 0x1F;
 
196
            p = *src++;
 
197
            size--;
 
198
            for(i = 0; i <= code; i++) {
 
199
                dst[filled++] = p;
 
200
                if(filled >= width) {
 
201
                    filled = 0;
 
202
                    dst -= stride;
 
203
                    height--;
 
204
                }
 
205
            }
 
206
        } else if(code >= 0xC0) { /* copy code: 0xC0..0xDF */
 
207
            code &= 0x1F;
 
208
 
 
209
            for(i = 0; i <= code; i++) {
 
210
                dst[filled++] = *src++;
 
211
                if(filled >= width) {
 
212
                    filled = 0;
 
213
                    dst -= stride;
 
214
                    height--;
 
215
                }
 
216
            }
 
217
            size -= code + 1;
 
218
        } else if(code >= 0x80) { /* skip code: 0x80..0xBF */
 
219
            int skip;
 
220
 
 
221
            code &= 0x3F;
 
222
            /* codes 0x80 and 0x81 are actually escape codes,
 
223
               skip value minus constant is in the next byte */
 
224
            if(!code)
 
225
                skip = (*src++) + 64;
 
226
            else if(code == 1)
 
227
                skip = (*src++) + 320;
 
228
            else
 
229
                skip = code;
 
230
            filled += skip;
 
231
            while( filled >= width) {
 
232
                filled -= width;
 
233
                dst -= stride;
 
234
                height--;
 
235
                if(height < 0)
 
236
                    break;
 
237
            }
 
238
        } else {
 
239
            /* zero code treated as one-pixel skip */
 
240
            if(code)
 
241
                dst[filled++] = ctable[code & 0x7F];
 
242
            else
 
243
                filled++;
 
244
            if(filled >= width) {
 
245
                filled = 0;
 
246
                dst -= stride;
 
247
                height--;
 
248
            }
 
249
        }
 
250
    }
 
251
}
 
252
 
 
253
static int decode_frame(AVCodecContext *avctx,
 
254
                        void *data, int *data_size,
 
255
                        uint8_t *buf, int buf_size)
 
256
{
 
257
    QpegContext * const a = avctx->priv_data;
 
258
    AVFrame * const p= (AVFrame*)&a->pic;
 
259
    uint8_t* outdata;
 
260
    int delta;
 
261
 
 
262
    if(p->data[0])
 
263
        avctx->release_buffer(avctx, p);
 
264
 
 
265
    p->reference= 0;
 
266
    if(avctx->get_buffer(avctx, p) < 0){
 
267
        av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
 
268
        return -1;
 
269
    }
 
270
    outdata = a->pic.data[0];
 
271
    if(buf[0x85] == 0x10) {
 
272
        qpeg_decode_intra(buf+0x86, outdata, buf_size - 0x86, a->pic.linesize[0], avctx->width, avctx->height);
 
273
    } else {
 
274
        delta = buf[0x85];
 
275
        qpeg_decode_inter(buf+0x86, outdata, buf_size - 0x86, a->pic.linesize[0], avctx->width, avctx->height, delta, buf + 4, a->refdata);
 
276
    }
 
277
 
 
278
    /* make the palette available on the way out */
 
279
    memcpy(a->pic.data[1], a->avctx->palctrl->palette, AVPALETTE_SIZE);
 
280
    if (a->avctx->palctrl->palette_changed) {
 
281
        a->pic.palette_has_changed = 1;
 
282
        a->avctx->palctrl->palette_changed = 0;
 
283
    }
 
284
 
 
285
    *data_size = sizeof(AVFrame);
 
286
    *(AVFrame*)data = a->pic;
 
287
 
 
288
    return buf_size;
 
289
}
 
290
 
 
291
static int decode_init(AVCodecContext *avctx){
 
292
    QpegContext * const a = avctx->priv_data;
 
293
 
 
294
    a->avctx = avctx;
 
295
    avctx->pix_fmt= PIX_FMT_PAL8;
 
296
    avctx->has_b_frames = 0;
 
297
    a->pic.data[0] = NULL;
 
298
    a->refdata = av_malloc(avctx->width * avctx->height);
 
299
 
 
300
    return 0;
 
301
}
 
302
 
 
303
static int decode_end(AVCodecContext *avctx){
 
304
    QpegContext * const a = avctx->priv_data;
 
305
    AVFrame * const p= (AVFrame*)&a->pic;
 
306
 
 
307
    if(p->data[0])
 
308
        avctx->release_buffer(avctx, p);
 
309
 
 
310
    av_free(a->refdata);
 
311
    return 0;
 
312
}
 
313
 
 
314
AVCodec qpeg_decoder = {
 
315
    "qpeg",
 
316
    CODEC_TYPE_VIDEO,
 
317
    CODEC_ID_QPEG,
 
318
    sizeof(QpegContext),
 
319
    decode_init,
 
320
    NULL,
 
321
    decode_end,
 
322
    decode_frame,
 
323
    CODEC_CAP_DR1,
 
324
};