00001 /* 00002 * Copyright (C) 2003 the ffmpeg project 00003 * 00004 * This file is part of FFmpeg. 00005 * 00006 * FFmpeg is free software; you can redistribute it and/or 00007 * modify it under the terms of the GNU Lesser General Public 00008 * License as published by the Free Software Foundation; either 00009 * version 2.1 of the License, or (at your option) any later version. 00010 * 00011 * FFmpeg is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public 00017 * License along with FFmpeg; if not, write to the Free Software 00018 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00019 */ 00020 00028 #include <stdio.h> 00029 #include <stdlib.h> 00030 #include <string.h> 00031 #include <unistd.h> 00032 00033 #include "avcodec.h" 00034 #include "bytestream.h" 00035 #include "roqvideo.h" 00036 00037 static void roqvideo_decode_frame(RoqContext *ri) 00038 { 00039 unsigned int chunk_id = 0, chunk_arg = 0; 00040 unsigned long chunk_size = 0; 00041 int i, j, k, nv1, nv2, vqflg = 0, vqflg_pos = -1; 00042 int vqid, bpos, xpos, ypos, xp, yp, x, y, mx, my; 00043 int frame_stats[2][4] = {{0},{0}}; 00044 roq_qcell *qcell; 00045 const unsigned char *buf = ri->buf; 00046 const unsigned char *buf_end = ri->buf + ri->size; 00047 00048 while (buf < buf_end) { 00049 chunk_id = bytestream_get_le16(&buf); 00050 chunk_size = bytestream_get_le32(&buf); 00051 chunk_arg = bytestream_get_le16(&buf); 00052 00053 if(chunk_id == RoQ_QUAD_VQ) 00054 break; 00055 if(chunk_id == RoQ_QUAD_CODEBOOK) { 00056 if((nv1 = chunk_arg >> 8) == 0) 00057 nv1 = 256; 00058 if((nv2 = chunk_arg & 0xff) == 0 && nv1 * 6 < chunk_size) 00059 nv2 = 256; 00060 for(i = 0; i < nv1; i++) { 00061 ri->cb2x2[i].y[0] = *buf++; 00062 ri->cb2x2[i].y[1] = *buf++; 00063 ri->cb2x2[i].y[2] = *buf++; 00064 ri->cb2x2[i].y[3] = *buf++; 00065 ri->cb2x2[i].u = *buf++; 00066 ri->cb2x2[i].v = *buf++; 00067 } 00068 for(i = 0; i < nv2; i++) 00069 for(j = 0; j < 4; j++) 00070 ri->cb4x4[i].idx[j] = *buf++; 00071 } 00072 } 00073 00074 bpos = xpos = ypos = 0; 00075 while(bpos < chunk_size) { 00076 for (yp = ypos; yp < ypos + 16; yp += 8) 00077 for (xp = xpos; xp < xpos + 16; xp += 8) { 00078 if (vqflg_pos < 0) { 00079 vqflg = buf[bpos++]; vqflg |= (buf[bpos++] << 8); 00080 vqflg_pos = 7; 00081 } 00082 vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; 00083 frame_stats[0][vqid]++; 00084 vqflg_pos--; 00085 00086 switch(vqid) { 00087 case RoQ_ID_MOT: 00088 break; 00089 case RoQ_ID_FCC: 00090 mx = 8 - (buf[bpos] >> 4) - ((signed char) (chunk_arg >> 8)); 00091 my = 8 - (buf[bpos++] & 0xf) - ((signed char) chunk_arg); 00092 ff_apply_motion_8x8(ri, xp, yp, mx, my); 00093 break; 00094 case RoQ_ID_SLD: 00095 qcell = ri->cb4x4 + buf[bpos++]; 00096 ff_apply_vector_4x4(ri, xp, yp, ri->cb2x2 + qcell->idx[0]); 00097 ff_apply_vector_4x4(ri, xp+4, yp, ri->cb2x2 + qcell->idx[1]); 00098 ff_apply_vector_4x4(ri, xp, yp+4, ri->cb2x2 + qcell->idx[2]); 00099 ff_apply_vector_4x4(ri, xp+4, yp+4, ri->cb2x2 + qcell->idx[3]); 00100 break; 00101 case RoQ_ID_CCC: 00102 for (k = 0; k < 4; k++) { 00103 x = xp; y = yp; 00104 if(k & 0x01) x += 4; 00105 if(k & 0x02) y += 4; 00106 00107 if (vqflg_pos < 0) { 00108 vqflg = buf[bpos++]; 00109 vqflg |= (buf[bpos++] << 8); 00110 vqflg_pos = 7; 00111 } 00112 vqid = (vqflg >> (vqflg_pos * 2)) & 0x3; 00113 frame_stats[1][vqid]++; 00114 vqflg_pos--; 00115 switch(vqid) { 00116 case RoQ_ID_MOT: 00117 break; 00118 case RoQ_ID_FCC: 00119 mx = 8 - (buf[bpos] >> 4) - ((signed char) (chunk_arg >> 8)); 00120 my = 8 - (buf[bpos++] & 0xf) - ((signed char) chunk_arg); 00121 ff_apply_motion_4x4(ri, x, y, mx, my); 00122 break; 00123 case RoQ_ID_SLD: 00124 qcell = ri->cb4x4 + buf[bpos++]; 00125 ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + qcell->idx[0]); 00126 ff_apply_vector_2x2(ri, x+2, y, ri->cb2x2 + qcell->idx[1]); 00127 ff_apply_vector_2x2(ri, x, y+2, ri->cb2x2 + qcell->idx[2]); 00128 ff_apply_vector_2x2(ri, x+2, y+2, ri->cb2x2 + qcell->idx[3]); 00129 break; 00130 case RoQ_ID_CCC: 00131 ff_apply_vector_2x2(ri, x, y, ri->cb2x2 + buf[bpos]); 00132 ff_apply_vector_2x2(ri, x+2, y, ri->cb2x2 + buf[bpos+1]); 00133 ff_apply_vector_2x2(ri, x, y+2, ri->cb2x2 + buf[bpos+2]); 00134 ff_apply_vector_2x2(ri, x+2, y+2, ri->cb2x2 + buf[bpos+3]); 00135 bpos += 4; 00136 break; 00137 } 00138 } 00139 break; 00140 default: 00141 av_log(ri->avctx, AV_LOG_ERROR, "Unknown vq code: %d\n", vqid); 00142 } 00143 } 00144 00145 xpos += 16; 00146 if (xpos >= ri->width) { 00147 xpos -= ri->width; 00148 ypos += 16; 00149 } 00150 if(ypos >= ri->height) 00151 break; 00152 } 00153 } 00154 00155 00156 static av_cold int roq_decode_init(AVCodecContext *avctx) 00157 { 00158 RoqContext *s = avctx->priv_data; 00159 00160 s->avctx = avctx; 00161 s->width = avctx->width; 00162 s->height = avctx->height; 00163 s->last_frame = &s->frames[0]; 00164 s->current_frame = &s->frames[1]; 00165 avctx->pix_fmt = PIX_FMT_YUV444P; 00166 00167 return 0; 00168 } 00169 00170 static int roq_decode_frame(AVCodecContext *avctx, 00171 void *data, int *data_size, 00172 const uint8_t *buf, int buf_size) 00173 { 00174 RoqContext *s = avctx->priv_data; 00175 int copy= !s->current_frame->data[0]; 00176 00177 if (avctx->reget_buffer(avctx, s->current_frame)) { 00178 av_log(avctx, AV_LOG_ERROR, " RoQ: get_buffer() failed\n"); 00179 return -1; 00180 } 00181 00182 if(copy) 00183 av_picture_copy((AVPicture*)s->current_frame, (AVPicture*)s->last_frame, 00184 avctx->pix_fmt, avctx->width, avctx->height); 00185 00186 s->buf = buf; 00187 s->size = buf_size; 00188 roqvideo_decode_frame(s); 00189 00190 *data_size = sizeof(AVFrame); 00191 *(AVFrame*)data = *s->current_frame; 00192 00193 /* shuffle frames */ 00194 FFSWAP(AVFrame *, s->current_frame, s->last_frame); 00195 00196 return buf_size; 00197 } 00198 00199 static av_cold int roq_decode_end(AVCodecContext *avctx) 00200 { 00201 RoqContext *s = avctx->priv_data; 00202 00203 /* release the last frame */ 00204 if (s->last_frame->data[0]) 00205 avctx->release_buffer(avctx, s->last_frame); 00206 if (s->current_frame->data[0]) 00207 avctx->release_buffer(avctx, s->current_frame); 00208 00209 return 0; 00210 } 00211 00212 AVCodec roq_decoder = { 00213 "roqvideo", 00214 CODEC_TYPE_VIDEO, 00215 CODEC_ID_ROQ, 00216 sizeof(RoqContext), 00217 roq_decode_init, 00218 NULL, 00219 roq_decode_end, 00220 roq_decode_frame, 00221 CODEC_CAP_DR1, 00222 .long_name = NULL_IF_CONFIG_SMALL("id RoQ video"), 00223 };