roqvideodec.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2003 the ffmpeg project
3  *
4  * This file is part of Libav.
5  *
6  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19  */
20 
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31 
32 #include "avcodec.h"
33 #include "bytestream.h"
34 #include "roqvideo.h"
35 
37 {
38  unsigned int chunk_id = 0, chunk_arg = 0;
39  unsigned long chunk_size = 0;
40  int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1;
41  int vqid, xpos, ypos, xp, yp, x, y, mx, my;
42  int frame_stats[2][4] = {{0},{0}};
43  roq_qcell *qcell;
44  int64_t chunk_start;
45 
46  while (bytestream2_get_bytes_left(&ri->gb) >= 8) {
47  chunk_id = bytestream2_get_le16(&ri->gb);
48  chunk_size = bytestream2_get_le32(&ri->gb);
49  chunk_arg = bytestream2_get_le16(&ri->gb);
50 
51  if(chunk_id == RoQ_QUAD_VQ)
52  break;
53  if(chunk_id == RoQ_QUAD_CODEBOOK) {
54  if((nv1 = chunk_arg >> 8) == 0)
55  nv1 = 256;
56  if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size)
57  nv2 = 256;
58  for(i = 0; i < nv1; i++) {
59  ri->cb2x2[i].y[0] = bytestream2_get_byte(&ri->gb);
60  ri->cb2x2[i].y[1] = bytestream2_get_byte(&ri->gb);
61  ri->cb2x2[i].y[2] = bytestream2_get_byte(&ri->gb);
62  ri->cb2x2[i].y[3] = bytestream2_get_byte(&ri->gb);
63  ri->cb2x2[i].u = bytestream2_get_byte(&ri->gb);
64  ri->cb2x2[i].v = bytestream2_get_byte(&ri->gb);
65  }
66  for(i = 0; i < nv2; i++)
67  for(j = 0; j < 4; j++)
68  ri->cb4x4[i].idx[j] = bytestream2_get_byte(&ri->gb);
69  }
70  }
71 
72  chunk_start = bytestream2_tell(&ri->gb);
73  xpos = ypos = 0;
74  while (bytestream2_tell(&ri->gb) < chunk_start + chunk_size) {
75  for (yp = ypos; yp < ypos + 16; yp += 8)
76  for (xp = xpos; xp < xpos + 16; xp += 8) {
77  if (vqflg_pos < 0) {
78  vqflg = bytestream2_get_le16(&ri->gb);
79  vqflg_pos = 7;
80  }
81  vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
82  frame_stats[0][vqid]++;
83  vqflg_pos--;
84 
85  switch(vqid) {
86  case RoQ_ID_MOT:
87  break;
88  case RoQ_ID_FCC: {
89  int byte = bytestream2_get_byte(&ri->gb);
90  mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8));
91  my = 8 - (byte & 0xf) - ((signed char) chunk_arg);
92  ff_apply_motion_8x8(ri, xp, yp, mx, my);
93  break;
94  }
95  case RoQ_ID_SLD:
96  qcell = ri->cb4x4 + bytestream2_get_byte(&ri->gb);
97  ff_apply_vector_4x4(ri, xp, yp, ri->cb2x2 + qcell->idx[0]);
98  ff_apply_vector_4x4(ri, xp+4, yp, ri->cb2x2 + qcell->idx[1]);
99  ff_apply_vector_4x4(ri, xp, yp+4, ri->cb2x2 + qcell->idx[2]);
100  ff_apply_vector_4x4(ri, xp+4, yp+4, ri->cb2x2 + qcell->idx[3]);
101  break;
102  case RoQ_ID_CCC:
103  for (k = 0; k < 4; k++) {
104  x = xp; y = yp;
105  if(k & 0x01) x += 4;
106  if(k & 0x02) y += 4;
107 
108  if (vqflg_pos < 0) {
109  vqflg = bytestream2_get_le16(&ri->gb);
110  vqflg_pos = 7;
111  }
112  vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
113  frame_stats[1][vqid]++;
114  vqflg_pos--;
115  switch(vqid) {
116  case RoQ_ID_MOT:
117  break;
118  case RoQ_ID_FCC: {
119  int byte = bytestream2_get_byte(&ri->gb);
120  mx = 8 - (byte >> 4) - ((signed char) (chunk_arg >> 8));
121  my = 8 - (byte & 0xf) - ((signed char) chunk_arg);
122  ff_apply_motion_4x4(ri, x, y, mx, my);
123  break;
124  }
125  case RoQ_ID_SLD:
126  qcell = ri->cb4x4 + bytestream2_get_byte(&ri->gb);
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  break;
132  case RoQ_ID_CCC:
133  ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + bytestream2_get_byte(&ri->gb));
134  ff_apply_vector_2x2(ri, x+2, y, ri->cb2x2 + bytestream2_get_byte(&ri->gb));
135  ff_apply_vector_2x2(ri, x, y+2, ri->cb2x2 + bytestream2_get_byte(&ri->gb));
136  ff_apply_vector_2x2(ri, x+2, y+2, ri->cb2x2 + bytestream2_get_byte(&ri->gb));
137  break;
138  }
139  }
140  break;
141  default:
142  av_log(ri->avctx, AV_LOG_ERROR, "Unknown vq code: %d\n", vqid);
143  }
144  }
145 
146  xpos += 16;
147  if (xpos >= ri->width) {
148  xpos -= ri->width;
149  ypos += 16;
150  }
151  if(ypos >= ri->height)
152  break;
153  }
154 }
155 
156 
158 {
159  RoqContext *s = avctx->priv_data;
160 
161  s->avctx = avctx;
162 
163  if (avctx->width % 16 || avctx->height % 16) {
164  av_log(avctx, AV_LOG_ERROR,
165  "Dimensions must be a multiple of 16\n");
166  return AVERROR_PATCHWELCOME;
167  }
168 
169  s->width = avctx->width;
170  s->height = avctx->height;
171  s->last_frame = &s->frames[0];
172  s->current_frame = &s->frames[1];
173  avctx->pix_fmt = PIX_FMT_YUV444P;
174 
175  return 0;
176 }
177 
179  void *data, int *data_size,
180  AVPacket *avpkt)
181 {
182  const uint8_t *buf = avpkt->data;
183  int buf_size = avpkt->size;
184  RoqContext *s = avctx->priv_data;
185  int copy= !s->current_frame->data[0];
186 
187  s->current_frame->reference = 3;
188  if (avctx->reget_buffer(avctx, s->current_frame)) {
189  av_log(avctx, AV_LOG_ERROR, " RoQ: get_buffer() failed\n");
190  return -1;
191  }
192 
193  if(copy)
195  avctx->pix_fmt, avctx->width, avctx->height);
196 
197  bytestream2_init(&s->gb, buf, buf_size);
199 
200  *data_size = sizeof(AVFrame);
201  *(AVFrame*)data = *s->current_frame;
202 
203  /* shuffle frames */
205 
206  return buf_size;
207 }
208 
210 {
211  RoqContext *s = avctx->priv_data;
212 
213  /* release the last frame */
214  if (s->last_frame->data[0])
215  avctx->release_buffer(avctx, s->last_frame);
216  if (s->current_frame->data[0])
217  avctx->release_buffer(avctx, s->current_frame);
218 
219  return 0;
220 }
221 
223  .name = "roqvideo",
224  .type = AVMEDIA_TYPE_VIDEO,
225  .id = CODEC_ID_ROQ,
226  .priv_data_size = sizeof(RoqContext),
230  .capabilities = CODEC_CAP_DR1,
231  .long_name = NULL_IF_CONFIG_SMALL("id RoQ video"),
232 };