Mercurial > libavcodec.hg
comparison roqvideo.c @ 5080:e72265f4e518 libavcodec
Split RoQ decoder to accommodate future encoder patch
patch by Vitor vitor1001 gmail moc
original thread: [FFmpeg-devel] [PATCH] RoQ video encoder, take 2
date: 05/27/2007 12:21 PM
author | benoit |
---|---|
date | Tue, 29 May 2007 15:01:33 +0000 |
parents | 4f36b52179d1 |
children | 133329117637 |
comparison
equal
deleted
inserted
replaced
5079:4ff805f87391 | 5080:e72265f4e518 |
---|---|
19 * | 19 * |
20 */ | 20 */ |
21 | 21 |
22 /** | 22 /** |
23 * @file roqvideo.c | 23 * @file roqvideo.c |
24 * Id RoQ Video Decoder by Dr. Tim Ferguson | 24 * Id RoQ Video common functions based on work by Dr. Tim Ferguson |
25 * For more information about the Id RoQ format, visit: | |
26 * http://www.csse.monash.edu.au/~timf/ | |
27 */ | 25 */ |
28 | 26 |
29 #include <stdio.h> | |
30 #include <stdlib.h> | |
31 #include <string.h> | |
32 #include <unistd.h> | |
33 | |
34 #include "avcodec.h" | 27 #include "avcodec.h" |
35 #include "bytestream.h" | 28 #include "roqvideo.h" |
36 #include "dsputil.h" | |
37 | |
38 typedef struct { | |
39 unsigned char y[4]; | |
40 unsigned char u, v; | |
41 } roq_cell; | |
42 | |
43 typedef struct { | |
44 int idx[4]; | |
45 } roq_qcell; | |
46 | 29 |
47 #define avg2(a,b) av_clip_uint8(((int)(a)+(int)(b)+1)>>1) | 30 #define avg2(a,b) av_clip_uint8(((int)(a)+(int)(b)+1)>>1) |
48 #define avg4(a,b,c,d) av_clip_uint8(((int)(a)+(int)(b)+(int)(c)+(int)(d)+2)>>2) | 31 #define avg4(a,b,c,d) av_clip_uint8(((int)(a)+(int)(b)+(int)(c)+(int)(d)+2)>>2) |
49 | |
50 typedef struct RoqContext { | |
51 | |
52 AVCodecContext *avctx; | |
53 DSPContext dsp; | |
54 AVFrame frames[2]; | |
55 AVFrame *last_frame; | |
56 AVFrame *current_frame; | |
57 int first_frame; | |
58 int y_stride; | |
59 int c_stride; | |
60 | |
61 roq_cell cells[256]; | |
62 roq_qcell qcells[256]; | |
63 | |
64 unsigned char *buf; | |
65 int size; | |
66 | |
67 } RoqContext; | |
68 | |
69 #define RoQ_INFO 0x1001 | |
70 #define RoQ_QUAD_CODEBOOK 0x1002 | |
71 #define RoQ_QUAD_VQ 0x1011 | |
72 #define RoQ_SOUND_MONO 0x1020 | |
73 #define RoQ_SOUND_STEREO 0x1021 | |
74 | |
75 #define RoQ_ID_MOT 0x00 | |
76 #define RoQ_ID_FCC 0x01 | |
77 #define RoQ_ID_SLD 0x02 | |
78 #define RoQ_ID_CCC 0x03 | |
79 | |
80 #define get_byte(in_buffer) *(in_buffer++) | |
81 | |
82 | 32 |
83 void ff_apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell) | 33 void ff_apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell) |
84 { | 34 { |
85 unsigned char *yptr; | 35 unsigned char *yptr; |
86 | 36 |
275 | 225 |
276 pa = ri->current_frame->data[2] + (y * ri->y_stride)/4 + x/2; | 226 pa = ri->current_frame->data[2] + (y * ri->y_stride)/4 + x/2; |
277 pb = ri->last_frame->data[2] + (my/2) * (ri->y_stride/2) + (mx + 1)/2; | 227 pb = ri->last_frame->data[2] + (my/2) * (ri->y_stride/2) + (mx + 1)/2; |
278 } | 228 } |
279 } | 229 } |
280 | |
281 static void roqvideo_decode_frame(RoqContext *ri) | |
282 { | |
283 unsigned int chunk_id = 0, chunk_arg = 0; | |
284 unsigned long chunk_size = 0; | |
285 int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1; | |
286 int vqid, bpos, xpos, ypos, xp, yp, x, y, mx, my; | |
287 int frame_stats[2][4] = {{0},{0}}; | |
288 roq_qcell *qcell; | |
289 unsigned char *buf = ri->buf; | |
290 unsigned char *buf_end = ri->buf + ri->size; | |
291 | |
292 while (buf < buf_end) { | |
293 chunk_id = bytestream_get_le16(&buf); | |
294 chunk_size = bytestream_get_le32(&buf); | |
295 chunk_arg = bytestream_get_le16(&buf); | |
296 | |
297 if(chunk_id == RoQ_QUAD_VQ) | |
298 break; | |
299 if(chunk_id == RoQ_QUAD_CODEBOOK) { | |
300 if((nv1 = chunk_arg >> 8) == 0) | |
301 nv1 = 256; | |
302 if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size) | |
303 nv2 = 256; | |
304 for(i = 0; i < nv1; i++) { | |
305 ri->cells[i].y[0] = get_byte(buf); | |
306 ri->cells[i].y[1] = get_byte(buf); | |
307 ri->cells[i].y[2] = get_byte(buf); | |
308 ri->cells[i].y[3] = get_byte(buf); | |
309 ri->cells[i].u = get_byte(buf); | |
310 ri->cells[i].v = get_byte(buf); | |
311 } | |
312 for(i = 0; i < nv2; i++) | |
313 for(j = 0; j < 4; j++) | |
314 ri->qcells[i].idx[j] = get_byte(buf); | |
315 } | |
316 } | |
317 | |
318 bpos = xpos = ypos = 0; | |
319 while(bpos < chunk_size) { | |
320 for (yp = ypos; yp < ypos + 16; yp += 8) | |
321 for (xp = xpos; xp < xpos + 16; xp += 8) { | |
322 if (vqflg_pos < 0) { | |
323 vqflg = buf[bpos++]; vqflg |= (buf[bpos++] << 8); | |
324 vqflg_pos = 7; | |
325 } | |
326 vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; | |
327 frame_stats[0][vqid]++; | |
328 vqflg_pos--; | |
329 | |
330 switch(vqid) { | |
331 case RoQ_ID_MOT: | |
332 ff_apply_motion_8x8(ri, xp, yp, 0, 0); | |
333 break; | |
334 case RoQ_ID_FCC: | |
335 mx = 8 - (buf[bpos] >> 4) - ((signed char) (chunk_arg >> 8)); | |
336 my = 8 - (buf[bpos++] & 0xf) - ((signed char) chunk_arg); | |
337 ff_apply_motion_8x8(ri, xp, yp, mx, my); | |
338 break; | |
339 case RoQ_ID_SLD: | |
340 qcell = ri->qcells + buf[bpos++]; | |
341 ff_apply_vector_4x4(ri, xp, yp, ri->cells + qcell->idx[0]); | |
342 ff_apply_vector_4x4(ri, xp+4, yp, ri->cells + qcell->idx[1]); | |
343 ff_apply_vector_4x4(ri, xp, yp+4, ri->cells + qcell->idx[2]); | |
344 ff_apply_vector_4x4(ri, xp+4, yp+4, ri->cells + qcell->idx[3]); | |
345 break; | |
346 case RoQ_ID_CCC: | |
347 for (k = 0; k < 4; k++) { | |
348 x = xp; y = yp; | |
349 if(k & 0x01) x += 4; | |
350 if(k & 0x02) y += 4; | |
351 | |
352 if (vqflg_pos < 0) { | |
353 vqflg = buf[bpos++]; | |
354 vqflg |= (buf[bpos++] << 8); | |
355 vqflg_pos = 7; | |
356 } | |
357 vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; | |
358 frame_stats[1][vqid]++; | |
359 vqflg_pos--; | |
360 switch(vqid) { | |
361 case RoQ_ID_MOT: | |
362 ff_apply_motion_4x4(ri, x, y, 0, 0); | |
363 break; | |
364 case RoQ_ID_FCC: | |
365 mx = 8 - (buf[bpos] >> 4) - ((signed char) (chunk_arg >> 8)); | |
366 my = 8 - (buf[bpos++] & 0xf) - ((signed char) chunk_arg); | |
367 ff_apply_motion_4x4(ri, x, y, mx, my); | |
368 break; | |
369 case RoQ_ID_SLD: | |
370 qcell = ri->qcells + buf[bpos++]; | |
371 ff_apply_vector_2x2(ri, x, y, ri->cells + qcell->idx[0]); | |
372 ff_apply_vector_2x2(ri, x+2, y, ri->cells + qcell->idx[1]); | |
373 ff_apply_vector_2x2(ri, x, y+2, ri->cells + qcell->idx[2]); | |
374 ff_apply_vector_2x2(ri, x+2, y+2, ri->cells + qcell->idx[3]); | |
375 break; | |
376 case RoQ_ID_CCC: | |
377 ff_apply_vector_2x2(ri, x, y, ri->cells + buf[bpos]); | |
378 ff_apply_vector_2x2(ri, x+2, y, ri->cells + buf[bpos+1]); | |
379 ff_apply_vector_2x2(ri, x, y+2, ri->cells + buf[bpos+2]); | |
380 ff_apply_vector_2x2(ri, x+2, y+2, ri->cells + buf[bpos+3]); | |
381 bpos += 4; | |
382 break; | |
383 } | |
384 } | |
385 break; | |
386 default: | |
387 av_log(ri->avctx, AV_LOG_ERROR, "Unknown vq code: %d\n", vqid); | |
388 } | |
389 } | |
390 | |
391 xpos += 16; | |
392 if (xpos >= ri->avctx->width) { | |
393 xpos -= ri->avctx->width; | |
394 ypos += 16; | |
395 } | |
396 if(ypos >= ri->avctx->height) | |
397 break; | |
398 } | |
399 } | |
400 | |
401 | |
402 static int roq_decode_init(AVCodecContext *avctx) | |
403 { | |
404 RoqContext *s = avctx->priv_data; | |
405 | |
406 s->avctx = avctx; | |
407 s->first_frame = 1; | |
408 s->last_frame = &s->frames[0]; | |
409 s->current_frame = &s->frames[1]; | |
410 avctx->pix_fmt = PIX_FMT_YUV420P; | |
411 dsputil_init(&s->dsp, avctx); | |
412 | |
413 return 0; | |
414 } | |
415 | |
416 static int roq_decode_frame(AVCodecContext *avctx, | |
417 void *data, int *data_size, | |
418 uint8_t *buf, int buf_size) | |
419 { | |
420 RoqContext *s = avctx->priv_data; | |
421 | |
422 if (avctx->get_buffer(avctx, s->current_frame)) { | |
423 av_log(avctx, AV_LOG_ERROR, " RoQ: get_buffer() failed\n"); | |
424 return -1; | |
425 } | |
426 s->y_stride = s->current_frame->linesize[0]; | |
427 s->c_stride = s->current_frame->linesize[1]; | |
428 | |
429 s->buf = buf; | |
430 s->size = buf_size; | |
431 roqvideo_decode_frame(s); | |
432 | |
433 /* release the last frame if it is allocated */ | |
434 if (s->first_frame) | |
435 s->first_frame = 0; | |
436 else | |
437 avctx->release_buffer(avctx, s->last_frame); | |
438 | |
439 *data_size = sizeof(AVFrame); | |
440 *(AVFrame*)data = *s->current_frame; | |
441 | |
442 /* shuffle frames */ | |
443 FFSWAP(AVFrame *, s->current_frame, s->last_frame); | |
444 | |
445 return buf_size; | |
446 } | |
447 | |
448 static int roq_decode_end(AVCodecContext *avctx) | |
449 { | |
450 RoqContext *s = avctx->priv_data; | |
451 | |
452 /* release the last frame */ | |
453 if (s->last_frame->data[0]) | |
454 avctx->release_buffer(avctx, s->last_frame); | |
455 | |
456 return 0; | |
457 } | |
458 | |
459 AVCodec roq_decoder = { | |
460 "roqvideo", | |
461 CODEC_TYPE_VIDEO, | |
462 CODEC_ID_ROQ, | |
463 sizeof(RoqContext), | |
464 roq_decode_init, | |
465 NULL, | |
466 roq_decode_end, | |
467 roq_decode_frame, | |
468 CODEC_CAP_DR1, | |
469 }; |