roqvideo.c
上传用户:wstnjxml
上传日期:2014-04-03
资源大小:7248k
文件大小:15k
源码类别:

Windows CE

开发平台:

C/C++

  1. /*
  2.  * Copyright (C) 2003 the ffmpeg project
  3.  *
  4.  * This library is free software; you can redistribute it and/or
  5.  * modify it under the terms of the GNU Lesser General Public
  6.  * License as published by the Free Software Foundation; either
  7.  * version 2 of the License, or (at your option) any later version.
  8.  *
  9.  * This library is distributed in the hope that it will be useful,
  10.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12.  * Lesser General Public License for more details.
  13.  *
  14.  * You should have received a copy of the GNU Lesser General Public
  15.  * License along with this library; if not, write to the Free Software
  16.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  17.  *
  18.  */
  19. /**
  20.  * @file roqvideo.c
  21.  * Id RoQ Video Decoder by Dr. Tim Ferguson
  22.  * For more information about the Id RoQ format, visit:
  23.  *   http://www.csse.monash.edu.au/~timf/
  24.  */
  25. #include <stdio.h>
  26. #include <stdlib.h>
  27. #include <string.h>
  28. #include <unistd.h>
  29. #include "common.h"
  30. #include "avcodec.h"
  31. #include "dsputil.h"
  32. typedef struct {
  33.   unsigned char y0, y1, y2, y3, u, v;
  34. } roq_cell;
  35. typedef struct {
  36.   int idx[4];
  37. } roq_qcell;
  38. static int uiclip[1024], *uiclp;  /* clipping table */
  39. #define avg2(a,b) uiclp[(((int)(a)+(int)(b)+1)>>1)]
  40. #define avg4(a,b,c,d) uiclp[(((int)(a)+(int)(b)+(int)(c)+(int)(d)+2)>>2)]
  41. typedef struct RoqContext {
  42.     AVCodecContext *avctx;
  43.     DSPContext dsp;
  44.     AVFrame last_frame;
  45.     AVFrame current_frame;
  46.     int first_frame;
  47.     int y_stride;
  48.     int c_stride;
  49.     roq_cell cells[256];
  50.     roq_qcell qcells[256];
  51.     unsigned char *buf;
  52.     int size;
  53. } RoqContext;
  54. #define RoQ_INFO              0x1001
  55. #define RoQ_QUAD_CODEBOOK     0x1002
  56. #define RoQ_QUAD_VQ           0x1011
  57. #define RoQ_SOUND_MONO        0x1020
  58. #define RoQ_SOUND_STEREO      0x1021
  59. #define RoQ_ID_MOT              0x00
  60. #define RoQ_ID_FCC              0x01
  61. #define RoQ_ID_SLD              0x02
  62. #define RoQ_ID_CCC              0x03
  63. #define get_byte(in_buffer) *(in_buffer++)
  64. #define get_word(in_buffer) ((unsigned short)(in_buffer += 2, 
  65.   (in_buffer[-1] << 8 | in_buffer[-2])))
  66. #define get_long(in_buffer) ((unsigned long)(in_buffer += 4, 
  67.   (in_buffer[-1] << 24 | in_buffer[-2] << 16 | in_buffer[-3] << 8 | in_buffer[-4])))
  68. static void apply_vector_2x2(RoqContext *ri, int x, int y, roq_cell *cell)
  69. {
  70.     unsigned char *yptr;
  71.     yptr = ri->current_frame.data[0] + (y * ri->y_stride) + x;
  72.     *yptr++ = cell->y0;
  73.     *yptr++ = cell->y1;
  74.     yptr += (ri->y_stride - 2);
  75.     *yptr++ = cell->y2;
  76.     *yptr++ = cell->y3;
  77.     ri->current_frame.data[1][(y/2) * (ri->c_stride) + x/2] = cell->u;
  78.     ri->current_frame.data[2][(y/2) * (ri->c_stride) + x/2] = cell->v;
  79. }
  80. static void apply_vector_4x4(RoqContext *ri, int x, int y, roq_cell *cell)
  81. {
  82.     unsigned long row_inc, c_row_inc;
  83.     register unsigned char y0, y1, u, v;
  84.     unsigned char *yptr, *uptr, *vptr;
  85.     yptr = ri->current_frame.data[0] + (y * ri->y_stride) + x;
  86.     uptr = ri->current_frame.data[1] + (y/2) * (ri->c_stride) + x/2;
  87.     vptr = ri->current_frame.data[2] + (y/2) * (ri->c_stride) + x/2;
  88.     row_inc = ri->y_stride - 4;
  89.     c_row_inc = (ri->c_stride) - 2;
  90.     *yptr++ = y0 = cell->y0; *uptr++ = u = cell->u; *vptr++ = v = cell->v;
  91.     *yptr++ = y0;
  92.     *yptr++ = y1 = cell->y1; *uptr++ = u; *vptr++ = v;
  93.     *yptr++ = y1;
  94.     yptr += row_inc;
  95.     *yptr++ = y0;
  96.     *yptr++ = y0;
  97.     *yptr++ = y1;
  98.     *yptr++ = y1;
  99.     yptr += row_inc; uptr += c_row_inc; vptr += c_row_inc;
  100.     *yptr++ = y0 = cell->y2; *uptr++ = u; *vptr++ = v;
  101.     *yptr++ = y0;
  102.     *yptr++ = y1 = cell->y3; *uptr++ = u; *vptr++ = v;
  103.     *yptr++ = y1;
  104.     yptr += row_inc;
  105.     *yptr++ = y0;
  106.     *yptr++ = y0;
  107.     *yptr++ = y1;
  108.     *yptr++ = y1;
  109. }
  110. static void apply_motion_4x4(RoqContext *ri, int x, int y, unsigned char mv,
  111.     signed char mean_x, signed char mean_y)
  112. {
  113.     int i, hw, mx, my;
  114.     unsigned char *pa, *pb;
  115.     mx = x + 8 - (mv >> 4) - mean_x;
  116.     my = y + 8 - (mv & 0xf) - mean_y;
  117.     /* check MV against frame boundaries */
  118.     if ((mx < 0) || (mx > ri->avctx->width - 4) ||
  119.         (my < 0) || (my > ri->avctx->height - 4)) {
  120.         av_log(ri->avctx, AV_LOG_ERROR, "motion vector out of bounds: MV = (%d, %d), boundaries = (0, 0, %d, %d)n",
  121.             mx, my, ri->avctx->width, ri->avctx->height);
  122.         return;
  123.     }
  124.     pa = ri->current_frame.data[0] + (y * ri->y_stride) + x;
  125.     pb = ri->last_frame.data[0] + (my * ri->y_stride) + mx;
  126.     for(i = 0; i < 4; i++) {
  127.         pa[0] = pb[0];
  128.         pa[1] = pb[1];
  129.         pa[2] = pb[2];
  130.         pa[3] = pb[3];
  131.         pa += ri->y_stride;
  132.         pb += ri->y_stride;
  133.     }
  134.     hw = ri->y_stride/2;
  135.     pa = ri->current_frame.data[1] + (y * ri->y_stride)/4 + x/2;
  136.     pb = ri->last_frame.data[1] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
  137.     for(i = 0; i < 2; i++) {
  138.         switch(((my & 0x01) << 1) | (mx & 0x01)) {
  139.         case 0:
  140.             pa[0] = pb[0];
  141.             pa[1] = pb[1];
  142.             pa[hw] = pb[hw];
  143.             pa[hw+1] = pb[hw+1];
  144.             break;
  145.         case 1:
  146.             pa[0] = avg2(pb[0], pb[1]);
  147.             pa[1] = avg2(pb[1], pb[2]);
  148.             pa[hw] = avg2(pb[hw], pb[hw+1]);
  149.             pa[hw+1] = avg2(pb[hw+1], pb[hw+2]);
  150.             break;
  151.         case 2:
  152.             pa[0] = avg2(pb[0], pb[hw]);
  153.             pa[1] = avg2(pb[1], pb[hw+1]);
  154.             pa[hw] = avg2(pb[hw], pb[hw*2]);
  155.             pa[hw+1] = avg2(pb[hw+1], pb[(hw*2)+1]);
  156.             break;
  157.         case 3:
  158.             pa[0] = avg4(pb[0], pb[1], pb[hw], pb[hw+1]);
  159.             pa[1] = avg4(pb[1], pb[2], pb[hw+1], pb[hw+2]);
  160.             pa[hw] = avg4(pb[hw], pb[hw+1], pb[hw*2], pb[(hw*2)+1]);
  161.             pa[hw+1] = avg4(pb[hw+1], pb[hw+2], pb[(hw*2)+1], pb[(hw*2)+1]);
  162.             break;
  163.         }
  164.         pa = ri->current_frame.data[2] + (y * ri->y_stride)/4 + x/2;
  165.         pb = ri->last_frame.data[2] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
  166.     }
  167. }
  168. static void apply_motion_8x8(RoqContext *ri, int x, int y,
  169.     unsigned char mv, signed char mean_x, signed char mean_y)
  170. {
  171.     int mx, my, i, j, hw;
  172.     unsigned char *pa, *pb;
  173.     mx = x + 8 - (mv >> 4) - mean_x;
  174.     my = y + 8 - (mv & 0xf) - mean_y;
  175.     /* check MV against frame boundaries */
  176.     if ((mx < 0) || (mx > ri->avctx->width - 8) ||
  177.         (my < 0) || (my > ri->avctx->height - 8)) {
  178.         av_log(ri->avctx, AV_LOG_ERROR, "motion vector out of bounds: MV = (%d, %d), boundaries = (0, 0, %d, %d)n",
  179.             mx, my, ri->avctx->width, ri->avctx->height);
  180.         return;
  181.     }
  182.     pa = ri->current_frame.data[0] + (y * ri->y_stride) + x;
  183.     pb = ri->last_frame.data[0] + (my * ri->y_stride) + mx;
  184.     for(i = 0; i < 8; i++) {
  185.         pa[0] = pb[0];
  186.         pa[1] = pb[1];
  187.         pa[2] = pb[2];
  188.         pa[3] = pb[3];
  189.         pa[4] = pb[4];
  190.         pa[5] = pb[5];
  191.         pa[6] = pb[6];
  192.         pa[7] = pb[7];
  193.         pa += ri->y_stride;
  194.         pb += ri->y_stride;
  195.     }
  196.     hw = ri->c_stride;
  197.     pa = ri->current_frame.data[1] + (y * ri->y_stride)/4 + x/2;
  198.     pb = ri->last_frame.data[1] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
  199.     for(j = 0; j < 2; j++) {
  200.         for(i = 0; i < 4; i++) {
  201.             switch(((my & 0x01) << 1) | (mx & 0x01)) {
  202.             case 0:
  203.                 pa[0] = pb[0];
  204.                 pa[1] = pb[1];
  205.                 pa[2] = pb[2];
  206.                 pa[3] = pb[3];
  207.                 break;
  208.             case 1:
  209.                 pa[0] = avg2(pb[0], pb[1]);
  210.                 pa[1] = avg2(pb[1], pb[2]);
  211.                 pa[2] = avg2(pb[2], pb[3]);
  212.                 pa[3] = avg2(pb[3], pb[4]);
  213.                 break;
  214.  
  215.             case 2:
  216.                 pa[0] = avg2(pb[0], pb[hw]);
  217.                 pa[1] = avg2(pb[1], pb[hw+1]);
  218.                 pa[2] = avg2(pb[2], pb[hw+2]);
  219.                 pa[3] = avg2(pb[3], pb[hw+3]);
  220.                 break;
  221.             case 3:
  222.                 pa[0] = avg4(pb[0], pb[1], pb[hw], pb[hw+1]);
  223.                 pa[1] = avg4(pb[1], pb[2], pb[hw+1], pb[hw+2]);
  224.                 pa[2] = avg4(pb[2], pb[3], pb[hw+2], pb[hw+3]);
  225.                 pa[3] = avg4(pb[3], pb[4], pb[hw+3], pb[hw+4]);
  226.                 break;
  227.             }
  228.             pa += ri->c_stride;
  229.             pb += ri->c_stride;
  230.         }
  231.         pa = ri->current_frame.data[2] + (y * ri->y_stride)/4 + x/2;
  232.         pb = ri->last_frame.data[2] + (my/2) * (ri->y_stride/2) + (mx + 1)/2;
  233.     }
  234. }
  235. static void roqvideo_decode_frame(RoqContext *ri)
  236. {
  237.     unsigned int chunk_id = 0, chunk_arg = 0;
  238.     unsigned long chunk_size = 0;
  239.     int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1;
  240.     int vqid, bpos, xpos, ypos, xp, yp, x, y;
  241.     int frame_stats[2][4] = {{0},{0}};
  242.     roq_qcell *qcell;
  243.     unsigned char *buf = ri->buf;
  244.     unsigned char *buf_end = ri->buf + ri->size;
  245.     while (buf < buf_end) {
  246.         chunk_id = get_word(buf);
  247.         chunk_size = get_long(buf);
  248.         chunk_arg = get_word(buf);
  249.         if(chunk_id == RoQ_QUAD_VQ)
  250.             break;
  251.         if(chunk_id == RoQ_QUAD_CODEBOOK) {
  252.             if((nv1 = chunk_arg >> 8) == 0)
  253.                 nv1 = 256;
  254.             if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size)
  255.                 nv2 = 256;
  256.             for(i = 0; i < nv1; i++) {
  257.                 ri->cells[i].y0 = get_byte(buf);
  258.                 ri->cells[i].y1 = get_byte(buf);
  259.                 ri->cells[i].y2 = get_byte(buf);
  260.                 ri->cells[i].y3 = get_byte(buf);
  261.                 ri->cells[i].u = get_byte(buf);
  262.                 ri->cells[i].v = get_byte(buf);
  263.             }
  264.             for(i = 0; i < nv2; i++)
  265.                 for(j = 0; j < 4; j++)
  266.                     ri->qcells[i].idx[j] = get_byte(buf);
  267.         }
  268.     }
  269.     bpos = xpos = ypos = 0;
  270.     while(bpos < chunk_size) {
  271.         for (yp = ypos; yp < ypos + 16; yp += 8)
  272.             for (xp = xpos; xp < xpos + 16; xp += 8) {
  273.                 if (vqflg_pos < 0) {
  274.                     vqflg = buf[bpos++]; vqflg |= (buf[bpos++] << 8);
  275.                     vqflg_pos = 7;
  276.                 }
  277.                 vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
  278.                 frame_stats[0][vqid]++;
  279.                 vqflg_pos--;
  280.                 switch(vqid) {
  281.                 case RoQ_ID_MOT:
  282.                     apply_motion_8x8(ri, xp, yp, 0, 8, 8);
  283.                     break;
  284.                 case RoQ_ID_FCC:
  285.                     apply_motion_8x8(ri, xp, yp, buf[bpos++], chunk_arg >> 8,
  286.                         chunk_arg & 0xff);
  287.                     break;
  288.                 case RoQ_ID_SLD:
  289.                     qcell = ri->qcells + buf[bpos++];
  290.                     apply_vector_4x4(ri, xp, yp, ri->cells + qcell->idx[0]);
  291.                     apply_vector_4x4(ri, xp+4, yp, ri->cells + qcell->idx[1]);
  292.                     apply_vector_4x4(ri, xp, yp+4, ri->cells + qcell->idx[2]);
  293.                     apply_vector_4x4(ri, xp+4, yp+4, ri->cells + qcell->idx[3]);
  294.                     break;
  295.                 case RoQ_ID_CCC:
  296.                     for (k = 0; k < 4; k++) {
  297.                         x = xp; y = yp;
  298.                         if(k & 0x01) x += 4;
  299.                         if(k & 0x02) y += 4;
  300.                         if (vqflg_pos < 0) {
  301.                             vqflg = buf[bpos++];
  302.                             vqflg |= (buf[bpos++] << 8);
  303.                             vqflg_pos = 7;
  304.                         }
  305.                         vqid = (vqflg >> (vqflg_pos * 2)) & 0x3;
  306.                         frame_stats[1][vqid]++;
  307.                         vqflg_pos--;
  308.                         switch(vqid) {
  309.                         case RoQ_ID_MOT:
  310.                             apply_motion_4x4(ri, x, y, 0, 8, 8);
  311.                             break;
  312.                         case RoQ_ID_FCC:
  313.                             apply_motion_4x4(ri, x, y, buf[bpos++], 
  314.                                 chunk_arg >> 8, chunk_arg & 0xff);
  315.                             break;
  316.                         case RoQ_ID_SLD:
  317.                             qcell = ri->qcells + buf[bpos++];
  318.                             apply_vector_2x2(ri, x, y, ri->cells + qcell->idx[0]);
  319.                             apply_vector_2x2(ri, x+2, y, ri->cells + qcell->idx[1]);
  320.                             apply_vector_2x2(ri, x, y+2, ri->cells + qcell->idx[2]);
  321.                             apply_vector_2x2(ri, x+2, y+2, ri->cells + qcell->idx[3]);
  322.                             break;
  323.                         case RoQ_ID_CCC:
  324.                             apply_vector_2x2(ri, x, y, ri->cells + buf[bpos]);
  325.                             apply_vector_2x2(ri, x+2, y, ri->cells + buf[bpos+1]);
  326.                             apply_vector_2x2(ri, x, y+2, ri->cells + buf[bpos+2]);
  327.                             apply_vector_2x2(ri, x+2, y+2, ri->cells + buf[bpos+3]);
  328.                             bpos += 4;
  329.                             break;
  330.                         }
  331.                     }
  332.                     break;
  333.                 default:
  334.                     av_log(ri->avctx, AV_LOG_ERROR, "Unknown vq code: %dn", vqid);
  335.             }
  336.         }
  337.         xpos += 16;
  338.         if (xpos >= ri->avctx->width) {
  339.             xpos -= ri->avctx->width;
  340.             ypos += 16;
  341.         }
  342.         if(ypos >= ri->avctx->height)
  343.             break;
  344.     }
  345. }
  346. static int roq_decode_init(AVCodecContext *avctx)
  347. {
  348.     RoqContext *s = avctx->priv_data;
  349.     int i;
  350.     s->avctx = avctx;
  351.     s->first_frame = 1;
  352.     avctx->pix_fmt = PIX_FMT_YUV420P;
  353.     avctx->has_b_frames = 0;
  354.     dsputil_init(&s->dsp, avctx);
  355.     uiclp = uiclip+512;
  356.     for(i = -512; i < 512; i++)
  357.         uiclp[i] = (i < 0 ? 0 : (i > 255 ? 255 : i));
  358.     return 0;
  359. }
  360. static int roq_decode_frame(AVCodecContext *avctx,
  361.                             void *data, int *data_size,
  362.                             uint8_t *buf, int buf_size)
  363. {
  364.     RoqContext *s = avctx->priv_data;
  365.     if (avctx->get_buffer(avctx, &s->current_frame)) {
  366.         av_log(avctx, AV_LOG_ERROR, "  RoQ: get_buffer() failedn");
  367.         return -1;
  368.     }
  369.     s->y_stride = s->current_frame.linesize[0];
  370.     s->c_stride = s->current_frame.linesize[1];
  371.     s->buf = buf;
  372.     s->size = buf_size;
  373.     roqvideo_decode_frame(s);
  374.     /* release the last frame if it is allocated */
  375.     if (s->first_frame)
  376.         s->first_frame = 0;
  377.     else
  378.         avctx->release_buffer(avctx, &s->last_frame);
  379.     /* shuffle frames */
  380.     s->last_frame = s->current_frame;
  381.     *data_size = sizeof(AVFrame);
  382.     *(AVFrame*)data = s->current_frame;
  383.     return buf_size;
  384. }
  385. static int roq_decode_end(AVCodecContext *avctx)
  386. {
  387.     RoqContext *s = avctx->priv_data;
  388.     /* release the last frame */
  389.     if (s->last_frame.data[0])
  390.         avctx->release_buffer(avctx, &s->last_frame);
  391.     return 0;
  392. }
  393. AVCodec roq_decoder = {
  394.     "roqvideo",
  395.     CODEC_TYPE_VIDEO,
  396.     CODEC_ID_ROQ,
  397.     sizeof(RoqContext),
  398.     roq_decode_init,
  399.     NULL,
  400.     roq_decode_end,
  401.     roq_decode_frame,
  402.     CODEC_CAP_DR1,
  403. };