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

Windows CE

开发平台:

C/C++

  1. /*
  2.  * QPEG codec
  3.  * Copyright (c) 2004 Konstantin Shishkov
  4.  *
  5.  * This library is free software; you can redistribute it and/or
  6.  * modify it under the terms of the GNU Lesser General Public
  7.  * License as published by the Free Software Foundation; either
  8.  * version 2 of the License, or (at your option) any later version.
  9.  *
  10.  * This library is distributed in the hope that it will be useful,
  11.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  13.  * Lesser General Public License for more details.
  14.  *
  15.  * You should have received a copy of the GNU Lesser General Public
  16.  * License along with this library; if not, write to the Free Software
  17.  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  18.  *
  19.  */
  20.  
  21. /**
  22.  * @file qpeg.c
  23.  * QPEG codec.
  24.  */
  25.  
  26. #include "avcodec.h"
  27. #include "mpegvideo.h"
  28. typedef struct QpegContext{
  29.     AVCodecContext *avctx;
  30.     AVFrame pic;
  31.     uint8_t *refdata;
  32. } QpegContext;
  33. static void qpeg_decode_intra(uint8_t *src, uint8_t *dst, int size,
  34.     int stride, int width, int height)
  35. {
  36.     int i;
  37.     int code;
  38.     int c0, c1;
  39.     int run, copy;
  40.     int filled = 0;
  41.     int rows_to_go;
  42.     
  43.     rows_to_go = height;
  44.     height--;
  45.     dst = dst + height * stride;
  46.     
  47.     while((size > 0) && (rows_to_go > 0)) {
  48. code = *src++;
  49. size--;
  50. run = copy = 0;
  51. if(code == 0xFC) /* end-of-picture code */
  52.     break;
  53. if(code >= 0xF8) { /* very long run */
  54.     c0 = *src++;
  55.     c1 = *src++;
  56.     size -= 2;
  57.     run = ((code & 0x7) << 16) + (c0 << 8) + c1 + 2;
  58. } else if (code >= 0xF0) { /* long run */
  59.     c0 = *src++;
  60.     size--;
  61.     run = ((code & 0xF) << 8) + c0 + 2;
  62. } else if (code >= 0xE0) { /* short run */
  63.     run = (code & 0x1F) + 2;
  64. } else if (code >= 0xC0) { /* very long copy */
  65.     c0 = *src++;
  66.     c1 = *src++;
  67.     size -= 2;
  68.     copy = ((code & 0x3F) << 16) + (c0 << 8) + c1 + 1;
  69. } else if (code >= 0x80) { /* long copy */
  70.     c0 = *src++;
  71.     size--;
  72.     copy = ((code & 0x7F) << 8) + c0 + 1;
  73. } else { /* short copy */
  74.     copy = code + 1;
  75. }
  76. /* perform actual run or copy */
  77. if(run) {
  78.     int p;
  79.     
  80.     p = *src++;
  81.     size--;
  82.     for(i = 0; i < run; i++) {
  83. dst[filled++] = p;
  84. if (filled >= width) {
  85.     filled = 0;
  86.     dst -= stride;
  87.                     rows_to_go--;
  88.                     if(rows_to_go <= 0)
  89.                         break;
  90. }
  91.     }
  92. } else {
  93.             size -= copy;
  94.     for(i = 0; i < copy; i++) {
  95. dst[filled++] = *src++;
  96. if (filled >= width) {
  97.     filled = 0;
  98.     dst -= stride;
  99.                     rows_to_go--;
  100.                     if(rows_to_go <= 0)
  101.                         break;
  102. }
  103.     }
  104. }
  105.     }
  106. }
  107. static int qpeg_table_h[16] = 
  108.  { 0x00, 0x20, 0x20, 0x20, 0x18, 0x10, 0x10, 0x20, 0x10, 0x08, 0x18, 0x08, 0x08, 0x18, 0x10, 0x04};
  109. static int qpeg_table_w[16] =
  110.  { 0x00, 0x20, 0x18, 0x08, 0x18, 0x10, 0x20, 0x10, 0x08, 0x10, 0x20, 0x20, 0x08, 0x10, 0x18, 0x04};
  111.  
  112. /* Decodes delta frames */
  113. static void qpeg_decode_inter(uint8_t *src, uint8_t *dst, int size,
  114.     int stride, int width, int height,
  115.     int delta, uint8_t *ctable, uint8_t *refdata)
  116. {
  117.     int i, j;
  118.     int code;
  119.     int filled = 0;
  120.     int orig_height;
  121.     uint8_t *blkdata;
  122.     
  123.     /* copy prev frame */
  124.     for(i = 0; i < height; i++)
  125. memcpy(refdata + (i * width), dst + (i * stride), width);
  126.     
  127.     orig_height = height;
  128.     blkdata = src - 0x86;
  129.     height--;
  130.     dst = dst + height * stride;
  131.     while((size > 0) && (height >= 0)) {
  132. code = *src++;
  133. size--;
  134. if(delta) {
  135.     /* motion compensation */
  136.     while((code & 0xF0) == 0xF0) {
  137. if(delta == 1) {
  138.     int me_idx;
  139.     int me_w, me_h, me_x, me_y;
  140.     uint8_t *me_plane;
  141.     int corr, val;
  142.     
  143.     /* get block size by index */
  144.     me_idx = code & 0xF;
  145.     me_w = qpeg_table_w[me_idx];
  146.     me_h = qpeg_table_h[me_idx];
  147.     
  148.     /* extract motion vector */
  149.     corr = *src++;
  150.     size--;
  151.     val = corr >> 4;
  152.     if(val > 7)
  153. val -= 16;
  154.     me_x = val;
  155.     
  156.     val = corr & 0xF;
  157.     if(val > 7)
  158. val -= 16;
  159.     me_y = val;
  160.     
  161.                     /* check motion vector */
  162.                     if ((me_x + filled < 0) || (me_x + me_w + filled > width) ||
  163.                        (height - me_y - me_h < 0) || (height - me_y > orig_height) ||
  164.                        (filled + me_w > width) || (height - me_h < 0))
  165.                         av_log(NULL, AV_LOG_ERROR, "Bogus motion vector (%i,%i), block size %ix%i at %i,%in",
  166.                                me_x, me_y, me_w, me_h, filled, height);
  167.                     else {
  168.                         /* do motion compensation */
  169.                         me_plane = refdata + (filled + me_x) + (height - me_y) * width;
  170.                         for(j = 0; j < me_h; j++) {
  171.                             for(i = 0; i < me_w; i++)
  172.                                 dst[filled + i - (j * stride)] = me_plane[i - (j * width)];
  173.                         }
  174.     }
  175. }
  176. code = *src++;
  177. size--;
  178.     }
  179. }
  180. if(code == 0xE0) /* end-of-picture code */
  181.     break;
  182. if(code > 0xE0) { /* run code: 0xE1..0xFF */
  183.     int p;
  184.     code &= 0x1F;
  185.     p = *src++;
  186.     size--;
  187.     for(i = 0; i <= code; i++) {
  188. dst[filled++] = p;
  189. if(filled >= width) {
  190.     filled = 0;
  191.     dst -= stride;
  192.     height--;
  193. }
  194.     }
  195. } else if(code >= 0xC0) { /* copy code: 0xC0..0xDF */
  196.     code &= 0x1F;
  197.     
  198.     for(i = 0; i <= code; i++) {
  199. dst[filled++] = *src++;
  200. if(filled >= width) {
  201.     filled = 0;
  202.     dst -= stride;
  203.     height--;
  204. }
  205.     }
  206.     size -= code + 1;
  207. } else if(code >= 0x80) { /* skip code: 0x80..0xBF */
  208.     int skip;
  209.     
  210.     code &= 0x3F;
  211.     /* codes 0x80 and 0x81 are actually escape codes,
  212.        skip value minus constant is in the next byte */
  213.     if(!code)
  214. skip = (*src++) + 64;
  215.     else if(code == 1)
  216. skip = (*src++) + 320;
  217.     else
  218. skip = code;
  219.     filled += skip;
  220.     while( filled >= width) {
  221. filled -= width;
  222. dst -= stride;
  223. height--;
  224.                 if(height < 0)
  225.                     break;
  226.     }
  227. } else {
  228.     /* zero code treated as one-pixel skip */
  229.     if(code)
  230. dst[filled++] = ctable[code & 0x7F];
  231.     else
  232. filled++;
  233.     if(filled >= width) {
  234. filled = 0;
  235. dst -= stride;
  236. height--;
  237.     }
  238. }
  239.     }
  240. }
  241. static int decode_frame(AVCodecContext *avctx, 
  242.                         void *data, int *data_size,
  243.                         uint8_t *buf, int buf_size)
  244. {
  245.     QpegContext * const a = avctx->priv_data;
  246.     AVFrame * const p= (AVFrame*)&a->pic;
  247.     uint8_t* outdata;
  248.     int delta;
  249.     
  250.     if(p->data[0])
  251.         avctx->release_buffer(avctx, p);
  252.     p->reference= 0;
  253.     if(avctx->get_buffer(avctx, p) < 0){
  254.         av_log(avctx, AV_LOG_ERROR, "get_buffer() failedn");
  255.         return -1;
  256.     }
  257.     outdata = a->pic.data[0];
  258.     if(buf[0x85] == 0x10) {
  259. qpeg_decode_intra(buf+0x86, outdata, buf_size - 0x86, a->pic.linesize[0], avctx->width, avctx->height);
  260.     } else {
  261. delta = buf[0x85];
  262. qpeg_decode_inter(buf+0x86, outdata, buf_size - 0x86, a->pic.linesize[0], avctx->width, avctx->height, delta, buf + 4, a->refdata);
  263.     }
  264.     /* make the palette available on the way out */
  265.     memcpy(a->pic.data[1], a->avctx->palctrl->palette, AVPALETTE_SIZE);
  266.     if (a->avctx->palctrl->palette_changed) {
  267.         a->pic.palette_has_changed = 1;
  268.         a->avctx->palctrl->palette_changed = 0;
  269.     }
  270.     *data_size = sizeof(AVFrame);
  271.     *(AVFrame*)data = a->pic;
  272.     
  273.     return buf_size;
  274. }
  275. static int decode_init(AVCodecContext *avctx){
  276.     QpegContext * const a = avctx->priv_data;
  277.     
  278.     a->avctx = avctx;
  279.     avctx->pix_fmt= PIX_FMT_PAL8;
  280.     avctx->has_b_frames = 0;
  281.     a->pic.data[0] = NULL;
  282.     a->refdata = av_malloc(avctx->width * avctx->height);
  283.     return 0;
  284. }
  285. static int decode_end(AVCodecContext *avctx){
  286.     QpegContext * const a = avctx->priv_data;
  287.     AVFrame * const p= (AVFrame*)&a->pic;
  288.     
  289.     if(p->data[0])
  290.         avctx->release_buffer(avctx, p);
  291.     av_free(a->refdata);
  292.     return 0;
  293. }
  294. AVCodec qpeg_decoder = {
  295.     "qpeg",
  296.     CODEC_TYPE_VIDEO,
  297.     CODEC_ID_QPEG,
  298.     sizeof(QpegContext),
  299.     decode_init,
  300.     NULL,
  301.     decode_end,
  302.     decode_frame,
  303.     CODEC_CAP_DR1,
  304. };