Statistics
| Branch: | Revision:

ffmpeg / libavcodec / roqvideodec.c @ 35c621e7

History | View | Annotate | Download (7.33 KB)

1 55c970e3 Vitor Sessak
/*
2
 * Copyright (C) 2003 the ffmpeg project
3
 *
4
 * This file is part of FFmpeg.
5
 *
6
 * FFmpeg is free software; you can redistribute it and/or
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
 *
11
 * FFmpeg is distributed in the hope that it will be useful,
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
17
 * License along with FFmpeg; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 *
20
 */
21
22
/**
23
 * @file roqvideodec.c
24
 * Id RoQ Video Decoder by Dr. Tim Ferguson
25
 * For more information about the Id RoQ format, visit:
26
 *   http://www.csse.monash.edu.au/~timf/
27
 */
28
29
#include <stdio.h>
30
#include <stdlib.h>
31
#include <string.h>
32
#include <unistd.h>
33
34
#include "avcodec.h"
35
#include "bytestream.h"
36
#include "dsputil.h"
37
#include "roqvideo.h"
38
39
static void roqvideo_decode_frame(RoqContext *ri)
40
{
41
    unsigned int chunk_id = 0, chunk_arg = 0;
42
    unsigned long chunk_size = 0;
43
    int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1;
44
    int vqid, bpos, xpos, ypos, xp, yp, x, y, mx, my;
45
    int frame_stats[2][4] = {{0},{0}};
46
    roq_qcell *qcell;
47
    unsigned char *buf = ri->buf;
48
    unsigned char *buf_end = ri->buf + ri->size;
49
50
    while (buf < buf_end) {
51
        chunk_id = bytestream_get_le16(&buf);
52
        chunk_size = bytestream_get_le32(&buf);
53
        chunk_arg = bytestream_get_le16(&buf);
54
55
        if(chunk_id == RoQ_QUAD_VQ)
56
            break;
57
        if(chunk_id == RoQ_QUAD_CODEBOOK) {
58
            if((nv1 = chunk_arg >> 8) == 0)
59
                nv1 = 256;
60
            if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size)
61
                nv2 = 256;
62
            for(i = 0; i < nv1; i++) {
63 160228f8 Eric Lasota
                ri->cb2x2[i].y[0] = *buf++;
64
                ri->cb2x2[i].y[1] = *buf++;
65
                ri->cb2x2[i].y[2] = *buf++;
66
                ri->cb2x2[i].y[3] = *buf++;
67
                ri->cb2x2[i].u = *buf++;
68
                ri->cb2x2[i].v = *buf++;
69 55c970e3 Vitor Sessak
            }
70
            for(i = 0; i < nv2; i++)
71
                for(j = 0; j < 4; j++)
72 160228f8 Eric Lasota
                    ri->cb4x4[i].idx[j] = *buf++;
73 55c970e3 Vitor Sessak
        }
74
    }
75
76
    bpos = xpos = ypos = 0;
77
    while(bpos < chunk_size) {
78
        for (yp = ypos; yp < ypos + 16; yp += 8)
79
            for (xp = xpos; xp < xpos + 16; xp += 8) {
80
                if (vqflg_pos < 0) {
81
                    vqflg = buf[bpos++]; vqflg |= (buf[bpos++] << 8);
82
                    vqflg_pos = 7;
83
                }
84
                vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
85
                frame_stats[0][vqid]++;
86
                vqflg_pos--;
87
88
                switch(vqid) {
89
                case RoQ_ID_MOT:
90
                    break;
91
                case RoQ_ID_FCC:
92
                    mx = 8 - (buf[bpos] >> 4) - ((signed char) (chunk_arg >> 8));
93
                    my = 8 - (buf[bpos++] & 0xf) - ((signed char) chunk_arg);
94
                    ff_apply_motion_8x8(ri, xp, yp, mx, my);
95
                    break;
96
                case RoQ_ID_SLD:
97 160228f8 Eric Lasota
                    qcell = ri->cb4x4 + buf[bpos++];
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]);
102 55c970e3 Vitor Sessak
                    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) {
110
                            vqflg = buf[bpos++];
111
                            vqflg |= (buf[bpos++] << 8);
112
                            vqflg_pos = 7;
113
                        }
114
                        vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
115
                        frame_stats[1][vqid]++;
116
                        vqflg_pos--;
117
                        switch(vqid) {
118
                        case RoQ_ID_MOT:
119
                            break;
120
                        case RoQ_ID_FCC:
121
                            mx = 8 - (buf[bpos] >> 4) - ((signed char) (chunk_arg >> 8));
122
                            my = 8 - (buf[bpos++] & 0xf) - ((signed char) chunk_arg);
123
                            ff_apply_motion_4x4(ri, x, y, mx, my);
124
                            break;
125
                        case RoQ_ID_SLD:
126 160228f8 Eric Lasota
                            qcell = ri->cb4x4 + buf[bpos++];
127
                            ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + qcell->idx[0]);
128
                            ff_apply_vector_2x2(ri, x+2, y, ri->cb2x2 + qcell->idx[1]);
129
                            ff_apply_vector_2x2(ri, x, y+2, ri->cb2x2 + qcell->idx[2]);
130
                            ff_apply_vector_2x2(ri, x+2, y+2, ri->cb2x2 + qcell->idx[3]);
131 55c970e3 Vitor Sessak
                            break;
132
                        case RoQ_ID_CCC:
133 160228f8 Eric Lasota
                            ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + buf[bpos]);
134
                            ff_apply_vector_2x2(ri, x+2, y, ri->cb2x2 + buf[bpos+1]);
135
                            ff_apply_vector_2x2(ri, x, y+2, ri->cb2x2 + buf[bpos+2]);
136
                            ff_apply_vector_2x2(ri, x+2, y+2, ri->cb2x2 + buf[bpos+3]);
137 55c970e3 Vitor Sessak
                            bpos += 4;
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 9489d2ef Vitor Sessak
        if (xpos >= ri->width) {
149
            xpos -= ri->width;
150 55c970e3 Vitor Sessak
            ypos += 16;
151
        }
152 9489d2ef Vitor Sessak
        if(ypos >= ri->height)
153 55c970e3 Vitor Sessak
            break;
154
    }
155
}
156
157
158
static int roq_decode_init(AVCodecContext *avctx)
159
{
160
    RoqContext *s = avctx->priv_data;
161
162
    s->avctx = avctx;
163 9489d2ef Vitor Sessak
    s->width = avctx->width;
164
    s->height = avctx->height;
165 55c970e3 Vitor Sessak
    s->last_frame    = &s->frames[0];
166
    s->current_frame = &s->frames[1];
167 3ccda4ca Eric Lasota
    avctx->pix_fmt = PIX_FMT_YUV444P;
168 55c970e3 Vitor Sessak
    dsputil_init(&s->dsp, avctx);
169
170
    return 0;
171
}
172
173
static int roq_decode_frame(AVCodecContext *avctx,
174
                            void *data, int *data_size,
175
                            uint8_t *buf, int buf_size)
176
{
177
    RoqContext *s = avctx->priv_data;
178
179 29b29011 Michael Niedermayer
    if (avctx->reget_buffer(avctx, s->current_frame)) {
180 55c970e3 Vitor Sessak
        av_log(avctx, AV_LOG_ERROR, "  RoQ: get_buffer() failed\n");
181
        return -1;
182
    }
183
184
    s->buf = buf;
185
    s->size = buf_size;
186
    roqvideo_decode_frame(s);
187
188
    *data_size = sizeof(AVFrame);
189
    *(AVFrame*)data = *s->current_frame;
190
191
    /* shuffle frames */
192
    FFSWAP(AVFrame *, s->current_frame, s->last_frame);
193
194
    return buf_size;
195
}
196
197
static int roq_decode_end(AVCodecContext *avctx)
198
{
199
    RoqContext *s = avctx->priv_data;
200
201
    /* release the last frame */
202
    if (s->last_frame->data[0])
203
        avctx->release_buffer(avctx, s->last_frame);
204 29b29011 Michael Niedermayer
    if (s->current_frame->data[0])
205
        avctx->release_buffer(avctx, s->current_frame);
206 55c970e3 Vitor Sessak
207
    return 0;
208
}
209
210
AVCodec roq_decoder = {
211
    "roqvideo",
212
    CODEC_TYPE_VIDEO,
213
    CODEC_ID_ROQ,
214
    sizeof(RoqContext),
215
    roq_decode_init,
216
    NULL,
217
    roq_decode_end,
218
    roq_decode_frame,
219
    CODEC_CAP_DR1,
220
};