~ubuntu-branches/debian/experimental/libav/experimental

1 by Reinhard Tartler
Import upstream version 0.6.2
1
/*
2
 * Copyright (C) 2003 the ffmpeg project
3
 *
1.1.1 by Reinhard Tartler
Import upstream version 0.7~b1
4
 * This file is part of Libav.
1 by Reinhard Tartler
Import upstream version 0.6.2
5
 *
1.1.1 by Reinhard Tartler
Import upstream version 0.7~b1
6
 * Libav is free software; you can redistribute it and/or
1 by Reinhard Tartler
Import upstream version 0.6.2
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
1.1.1 by Reinhard Tartler
Import upstream version 0.7~b1
11
 * Libav is distributed in the hope that it will be useful,
1 by Reinhard Tartler
Import upstream version 0.6.2
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
1.1.1 by Reinhard Tartler
Import upstream version 0.7~b1
17
 * License along with Libav; if not, write to the Free Software
1 by Reinhard Tartler
Import upstream version 0.6.2
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
/**
22
 * @file
23
 * id RoQ Video Decoder by Dr. Tim Ferguson
24
 * For more information about the id RoQ format, visit:
25
 *   http://www.csse.monash.edu.au/~timf/
26
 */
27
28
#include <stdio.h>
29
#include <stdlib.h>
30
#include <string.h>
31
32
#include "avcodec.h"
33
#include "bytestream.h"
1.1.23 by Reinhard Tartler
Import upstream version 10~alpha1
34
#include "internal.h"
1 by Reinhard Tartler
Import upstream version 0.6.2
35
#include "roqvideo.h"
36
37
static void roqvideo_decode_frame(RoqContext *ri)
38
{
39
    unsigned int chunk_id = 0, chunk_arg = 0;
40
    unsigned long chunk_size = 0;
41
    int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1;
1.1.10 by Reinhard Tartler
Import upstream version 0.8.1
42
    int vqid, xpos, ypos, xp, yp, x, y, mx, my;
1 by Reinhard Tartler
Import upstream version 0.6.2
43
    int frame_stats[2][4] = {{0},{0}};
44
    roq_qcell *qcell;
1.1.10 by Reinhard Tartler
Import upstream version 0.8.1
45
    int64_t chunk_start;
1 by Reinhard Tartler
Import upstream version 0.6.2
46
1.1.17 by Reinhard Tartler
Import upstream version 9.4
47
    while (bytestream2_get_bytes_left(&ri->gb) >= 8) {
1.1.11 by Reinhard Tartler
Import upstream version 0.8.99-1537-gacb2c79
48
        chunk_id   = bytestream2_get_le16(&ri->gb);
1.1.10 by Reinhard Tartler
Import upstream version 0.8.1
49
        chunk_size = bytestream2_get_le32(&ri->gb);
1.1.11 by Reinhard Tartler
Import upstream version 0.8.99-1537-gacb2c79
50
        chunk_arg  = bytestream2_get_le16(&ri->gb);
1 by Reinhard Tartler
Import upstream version 0.6.2
51
52
        if(chunk_id == RoQ_QUAD_VQ)
53
            break;
54
        if(chunk_id == RoQ_QUAD_CODEBOOK) {
55
            if((nv1 = chunk_arg >> 8) == 0)
56
                nv1 = 256;
57
            if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size)
58
                nv2 = 256;
59
            for(i = 0; i < nv1; i++) {
1.1.10 by Reinhard Tartler
Import upstream version 0.8.1
60
                ri->cb2x2[i].y[0] = bytestream2_get_byte(&ri->gb);
61
                ri->cb2x2[i].y[1] = bytestream2_get_byte(&ri->gb);
62
                ri->cb2x2[i].y[2] = bytestream2_get_byte(&ri->gb);
63
                ri->cb2x2[i].y[3] = bytestream2_get_byte(&ri->gb);
1.1.11 by Reinhard Tartler
Import upstream version 0.8.99-1537-gacb2c79
64
                ri->cb2x2[i].u    = bytestream2_get_byte(&ri->gb);
65
                ri->cb2x2[i].v    = bytestream2_get_byte(&ri->gb);
1 by Reinhard Tartler
Import upstream version 0.6.2
66
            }
67
            for(i = 0; i < nv2; i++)
68
                for(j = 0; j < 4; j++)
1.1.10 by Reinhard Tartler
Import upstream version 0.8.1
69
                    ri->cb4x4[i].idx[j] = bytestream2_get_byte(&ri->gb);
1 by Reinhard Tartler
Import upstream version 0.6.2
70
        }
71
    }
72
1.1.10 by Reinhard Tartler
Import upstream version 0.8.1
73
    chunk_start = bytestream2_tell(&ri->gb);
74
    xpos = ypos = 0;
75
    while (bytestream2_tell(&ri->gb) < chunk_start + chunk_size) {
1 by Reinhard Tartler
Import upstream version 0.6.2
76
        for (yp = ypos; yp < ypos + 16; yp += 8)
77
            for (xp = xpos; xp < xpos + 16; xp += 8) {
78
                if (vqflg_pos < 0) {
1.1.10 by Reinhard Tartler
Import upstream version 0.8.1
79
                    vqflg = bytestream2_get_le16(&ri->gb);
1 by Reinhard Tartler
Import upstream version 0.6.2
80
                    vqflg_pos = 7;
81
                }
82
                vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
83
                frame_stats[0][vqid]++;
84
                vqflg_pos--;
85
86
                switch(vqid) {
87
                case RoQ_ID_MOT:
88
                    break;
1.1.10 by Reinhard Tartler
Import upstream version 0.8.1
89
                case RoQ_ID_FCC: {
90
                    int byte = bytestream2_get_byte(&ri->gb);
91
                    mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8));
92
                    my = 8 - (byte & 0xf) - ((signed char) chunk_arg);
1 by Reinhard Tartler
Import upstream version 0.6.2
93
                    ff_apply_motion_8x8(ri, xp, yp, mx, my);
94
                    break;
1.1.10 by Reinhard Tartler
Import upstream version 0.8.1
95
                }
1 by Reinhard Tartler
Import upstream version 0.6.2
96
                case RoQ_ID_SLD:
1.1.10 by Reinhard Tartler
Import upstream version 0.8.1
97
                    qcell = ri->cb4x4 + bytestream2_get_byte(&ri->gb);
1.1.11 by Reinhard Tartler
Import upstream version 0.8.99-1537-gacb2c79
98
                    ff_apply_vector_4x4(ri, xp,     yp,     ri->cb2x2 + qcell->idx[0]);
99
                    ff_apply_vector_4x4(ri, xp + 4, yp,     ri->cb2x2 + qcell->idx[1]);
100
                    ff_apply_vector_4x4(ri, xp,     yp + 4, ri->cb2x2 + qcell->idx[2]);
101
                    ff_apply_vector_4x4(ri, xp + 4, yp + 4, ri->cb2x2 + qcell->idx[3]);
1 by Reinhard Tartler
Import upstream version 0.6.2
102
                    break;
103
                case RoQ_ID_CCC:
104
                    for (k = 0; k < 4; k++) {
105
                        x = xp; y = yp;
106
                        if(k & 0x01) x += 4;
107
                        if(k & 0x02) y += 4;
108
109
                        if (vqflg_pos < 0) {
1.1.10 by Reinhard Tartler
Import upstream version 0.8.1
110
                            vqflg = bytestream2_get_le16(&ri->gb);
1 by Reinhard Tartler
Import upstream version 0.6.2
111
                            vqflg_pos = 7;
112
                        }
113
                        vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
114
                        frame_stats[1][vqid]++;
115
                        vqflg_pos--;
116
                        switch(vqid) {
117
                        case RoQ_ID_MOT:
118
                            break;
1.1.10 by Reinhard Tartler
Import upstream version 0.8.1
119
                        case RoQ_ID_FCC: {
120
                            int byte = bytestream2_get_byte(&ri->gb);
121
                            mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8));
122
                            my = 8 - (byte & 0xf) - ((signed char) chunk_arg);
1 by Reinhard Tartler
Import upstream version 0.6.2
123
                            ff_apply_motion_4x4(ri, x, y, mx, my);
124
                            break;
1.1.10 by Reinhard Tartler
Import upstream version 0.8.1
125
                        }
1 by Reinhard Tartler
Import upstream version 0.6.2
126
                        case RoQ_ID_SLD:
1.1.10 by Reinhard Tartler
Import upstream version 0.8.1
127
                            qcell = ri->cb4x4 + bytestream2_get_byte(&ri->gb);
1.1.11 by Reinhard Tartler
Import upstream version 0.8.99-1537-gacb2c79
128
                            ff_apply_vector_2x2(ri, x,     y,     ri->cb2x2 + qcell->idx[0]);
129
                            ff_apply_vector_2x2(ri, x + 2, y,     ri->cb2x2 + qcell->idx[1]);
130
                            ff_apply_vector_2x2(ri, x,     y + 2, ri->cb2x2 + qcell->idx[2]);
131
                            ff_apply_vector_2x2(ri, x + 2, y + 2, ri->cb2x2 + qcell->idx[3]);
1 by Reinhard Tartler
Import upstream version 0.6.2
132
                            break;
133
                        case RoQ_ID_CCC:
1.1.11 by Reinhard Tartler
Import upstream version 0.8.99-1537-gacb2c79
134
                            ff_apply_vector_2x2(ri, x,     y,     ri->cb2x2 + bytestream2_get_byte(&ri->gb));
135
                            ff_apply_vector_2x2(ri, x + 2, y,     ri->cb2x2 + bytestream2_get_byte(&ri->gb));
136
                            ff_apply_vector_2x2(ri, x,     y + 2, ri->cb2x2 + bytestream2_get_byte(&ri->gb));
137
                            ff_apply_vector_2x2(ri, x + 2, y + 2, ri->cb2x2 + bytestream2_get_byte(&ri->gb));
1 by Reinhard Tartler
Import upstream version 0.6.2
138
                            break;
139
                        }
140
                    }
141
                    break;
142
                default:
143
                    av_log(ri->avctx, AV_LOG_ERROR, "Unknown vq code: %d\n", vqid);
144
            }
145
        }
146
147
        xpos += 16;
148
        if (xpos >= ri->width) {
149
            xpos -= ri->width;
150
            ypos += 16;
151
        }
152
        if(ypos >= ri->height)
153
            break;
154
    }
155
}
156
157
158
static av_cold int roq_decode_init(AVCodecContext *avctx)
159
{
160
    RoqContext *s = avctx->priv_data;
161
162
    s->avctx = avctx;
1.1.16 by Reinhard Tartler
Import upstream version 9.3
163
164
    if (avctx->width % 16 || avctx->height % 16) {
165
        av_log(avctx, AV_LOG_ERROR,
166
               "Dimensions must be a multiple of 16\n");
167
        return AVERROR_PATCHWELCOME;
168
    }
169
1 by Reinhard Tartler
Import upstream version 0.6.2
170
    s->width = avctx->width;
171
    s->height = avctx->height;
1.1.23 by Reinhard Tartler
Import upstream version 10~alpha1
172
173
    s->last_frame    = av_frame_alloc();
174
    s->current_frame = av_frame_alloc();
175
    if (!s->current_frame || !s->last_frame) {
176
        av_frame_free(&s->current_frame);
177
        av_frame_free(&s->last_frame);
178
        return AVERROR(ENOMEM);
179
    }
180
1.1.12 by Reinhard Tartler
Import upstream version 9~beta1
181
    avctx->pix_fmt = AV_PIX_FMT_YUV444P;
1 by Reinhard Tartler
Import upstream version 0.6.2
182
183
    return 0;
184
}
185
186
static int roq_decode_frame(AVCodecContext *avctx,
1.1.14 by Reinhard Tartler
Import upstream version 9~beta3
187
                            void *data, int *got_frame,
1 by Reinhard Tartler
Import upstream version 0.6.2
188
                            AVPacket *avpkt)
189
{
190
    const uint8_t *buf = avpkt->data;
191
    int buf_size = avpkt->size;
192
    RoqContext *s = avctx->priv_data;
193
    int copy= !s->current_frame->data[0];
1.1.23 by Reinhard Tartler
Import upstream version 10~alpha1
194
    int ret;
1 by Reinhard Tartler
Import upstream version 0.6.2
195
1.1.23 by Reinhard Tartler
Import upstream version 10~alpha1
196
    if ((ret = ff_reget_buffer(avctx, s->current_frame)) < 0) {
1 by Reinhard Tartler
Import upstream version 0.6.2
197
        av_log(avctx, AV_LOG_ERROR, "  RoQ: get_buffer() failed\n");
1.1.23 by Reinhard Tartler
Import upstream version 10~alpha1
198
        return ret;
1 by Reinhard Tartler
Import upstream version 0.6.2
199
    }
200
201
    if(copy)
202
        av_picture_copy((AVPicture*)s->current_frame, (AVPicture*)s->last_frame,
203
                        avctx->pix_fmt, avctx->width, avctx->height);
204
1.1.10 by Reinhard Tartler
Import upstream version 0.8.1
205
    bytestream2_init(&s->gb, buf, buf_size);
1 by Reinhard Tartler
Import upstream version 0.6.2
206
    roqvideo_decode_frame(s);
207
1.1.23 by Reinhard Tartler
Import upstream version 10~alpha1
208
    if ((ret = av_frame_ref(data, s->current_frame)) < 0)
209
        return ret;
1.1.14 by Reinhard Tartler
Import upstream version 9~beta3
210
    *got_frame      = 1;
1 by Reinhard Tartler
Import upstream version 0.6.2
211
212
    /* shuffle frames */
213
    FFSWAP(AVFrame *, s->current_frame, s->last_frame);
214
215
    return buf_size;
216
}
217
218
static av_cold int roq_decode_end(AVCodecContext *avctx)
219
{
220
    RoqContext *s = avctx->priv_data;
221
1.1.23 by Reinhard Tartler
Import upstream version 10~alpha1
222
    av_frame_free(&s->current_frame);
223
    av_frame_free(&s->last_frame);
1 by Reinhard Tartler
Import upstream version 0.6.2
224
225
    return 0;
226
}
227
1.1.1 by Reinhard Tartler
Import upstream version 0.7~b1
228
AVCodec ff_roq_decoder = {
1.2.1 by Reinhard Tartler
Import upstream version 0.8~beta1
229
    .name           = "roqvideo",
1.1.23 by Reinhard Tartler
Import upstream version 10~alpha1
230
    .long_name      = NULL_IF_CONFIG_SMALL("id RoQ video"),
1.2.1 by Reinhard Tartler
Import upstream version 0.8~beta1
231
    .type           = AVMEDIA_TYPE_VIDEO,
1.1.12 by Reinhard Tartler
Import upstream version 9~beta1
232
    .id             = AV_CODEC_ID_ROQ,
1.2.1 by Reinhard Tartler
Import upstream version 0.8~beta1
233
    .priv_data_size = sizeof(RoqContext),
234
    .init           = roq_decode_init,
235
    .close          = roq_decode_end,
236
    .decode         = roq_decode_frame,
237
    .capabilities   = CODEC_CAP_DR1,
1 by Reinhard Tartler
Import upstream version 0.6.2
238
};