Libav
|
00001 /* 00002 * LOCO codec 00003 * Copyright (c) 2005 Konstantin Shishkov 00004 * 00005 * This file is part of FFmpeg. 00006 * 00007 * FFmpeg is free software; you can redistribute it and/or 00008 * modify it under the terms of the GNU Lesser General Public 00009 * License as published by the Free Software Foundation; either 00010 * version 2.1 of the License, or (at your option) any later version. 00011 * 00012 * FFmpeg is distributed in the hope that it will be useful, 00013 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00015 * Lesser General Public License for more details. 00016 * 00017 * You should have received a copy of the GNU Lesser General Public 00018 * License along with FFmpeg; if not, write to the Free Software 00019 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA 00020 */ 00021 00027 #include "avcodec.h" 00028 #include "get_bits.h" 00029 #include "golomb.h" 00030 #include "mathops.h" 00031 00032 enum LOCO_MODE {LOCO_UNKN=0, LOCO_CYUY2=-1, LOCO_CRGB=-2, LOCO_CRGBA=-3, LOCO_CYV12=-4, 00033 LOCO_YUY2=1, LOCO_UYVY=2, LOCO_RGB=3, LOCO_RGBA=4, LOCO_YV12=5}; 00034 00035 typedef struct LOCOContext{ 00036 AVCodecContext *avctx; 00037 AVFrame pic; 00038 int lossy; 00039 int mode; 00040 } LOCOContext; 00041 00042 typedef struct RICEContext{ 00043 GetBitContext gb; 00044 int save, run, run2; /* internal rice decoder state */ 00045 int sum, count; /* sum and count for getting rice parameter */ 00046 int lossy; 00047 }RICEContext; 00048 00049 static int loco_get_rice_param(RICEContext *r) 00050 { 00051 int cnt = 0; 00052 int val = r->count; 00053 00054 while(r->sum > val && cnt < 9) { 00055 val <<= 1; 00056 cnt++; 00057 } 00058 00059 return cnt; 00060 } 00061 00062 static inline void loco_update_rice_param(RICEContext *r, int val) 00063 { 00064 r->sum += val; 00065 r->count++; 00066 00067 if(r->count == 16) { 00068 r->sum >>= 1; 00069 r->count >>= 1; 00070 } 00071 } 00072 00073 static inline int loco_get_rice(RICEContext *r) 00074 { 00075 int v; 00076 if (r->run > 0) { /* we have zero run */ 00077 r->run--; 00078 loco_update_rice_param(r, 0); 00079 return 0; 00080 } 00081 v = get_ur_golomb_jpegls(&r->gb, loco_get_rice_param(r), INT_MAX, 0); 00082 loco_update_rice_param(r, (v+1)>>1); 00083 if (!v) { 00084 if (r->save >= 0) { 00085 r->run = get_ur_golomb_jpegls(&r->gb, 2, INT_MAX, 0); 00086 if(r->run > 1) 00087 r->save += r->run + 1; 00088 else 00089 r->save -= 3; 00090 } 00091 else 00092 r->run2++; 00093 } else { 00094 v = ((v>>1) + r->lossy) ^ -(v&1); 00095 if (r->run2 > 0) { 00096 if (r->run2 > 2) 00097 r->save += r->run2; 00098 else 00099 r->save -= 3; 00100 r->run2 = 0; 00101 } 00102 } 00103 00104 return v; 00105 } 00106 00107 /* LOCO main predictor - LOCO-I/JPEG-LS predictor */ 00108 static inline int loco_predict(uint8_t* data, int stride, int step) 00109 { 00110 int a, b, c; 00111 00112 a = data[-stride]; 00113 b = data[-step]; 00114 c = data[-stride - step]; 00115 00116 return mid_pred(a, a + b - c, b); 00117 } 00118 00119 static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height, 00120 int stride, const uint8_t *buf, int buf_size, int step) 00121 { 00122 RICEContext rc; 00123 int val; 00124 int i, j; 00125 00126 init_get_bits(&rc.gb, buf, buf_size*8); 00127 rc.save = 0; 00128 rc.run = 0; 00129 rc.run2 = 0; 00130 rc.lossy = l->lossy; 00131 00132 rc.sum = 8; 00133 rc.count = 1; 00134 00135 /* restore top left pixel */ 00136 val = loco_get_rice(&rc); 00137 data[0] = 128 + val; 00138 /* restore top line */ 00139 for (i = 1; i < width; i++) { 00140 val = loco_get_rice(&rc); 00141 data[i * step] = data[i * step - step] + val; 00142 } 00143 data += stride; 00144 for (j = 1; j < height; j++) { 00145 /* restore left column */ 00146 val = loco_get_rice(&rc); 00147 data[0] = data[-stride] + val; 00148 /* restore all other pixels */ 00149 for (i = 1; i < width; i++) { 00150 val = loco_get_rice(&rc); 00151 data[i * step] = loco_predict(&data[i * step], stride, step) + val; 00152 } 00153 data += stride; 00154 } 00155 00156 return (get_bits_count(&rc.gb) + 7) >> 3; 00157 } 00158 00159 static int decode_frame(AVCodecContext *avctx, 00160 void *data, int *data_size, 00161 AVPacket *avpkt) 00162 { 00163 const uint8_t *buf = avpkt->data; 00164 int buf_size = avpkt->size; 00165 LOCOContext * const l = avctx->priv_data; 00166 AVFrame * const p= (AVFrame*)&l->pic; 00167 int decoded; 00168 00169 if(p->data[0]) 00170 avctx->release_buffer(avctx, p); 00171 00172 p->reference = 0; 00173 if(avctx->get_buffer(avctx, p) < 0){ 00174 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); 00175 return -1; 00176 } 00177 p->key_frame = 1; 00178 00179 switch(l->mode) { 00180 case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY: 00181 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, 00182 p->linesize[0], buf, buf_size, 1); 00183 buf += decoded; buf_size -= decoded; 00184 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height, 00185 p->linesize[1], buf, buf_size, 1); 00186 buf += decoded; buf_size -= decoded; 00187 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height, 00188 p->linesize[2], buf, buf_size, 1); 00189 break; 00190 case LOCO_CYV12: case LOCO_YV12: 00191 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, 00192 p->linesize[0], buf, buf_size, 1); 00193 buf += decoded; buf_size -= decoded; 00194 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2, 00195 p->linesize[2], buf, buf_size, 1); 00196 buf += decoded; buf_size -= decoded; 00197 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2, 00198 p->linesize[1], buf, buf_size, 1); 00199 break; 00200 case LOCO_CRGB: case LOCO_RGB: 00201 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height, 00202 -p->linesize[0], buf, buf_size, 3); 00203 buf += decoded; buf_size -= decoded; 00204 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height, 00205 -p->linesize[0], buf, buf_size, 3); 00206 buf += decoded; buf_size -= decoded; 00207 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height, 00208 -p->linesize[0], buf, buf_size, 3); 00209 break; 00210 case LOCO_RGBA: 00211 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height, 00212 p->linesize[0], buf, buf_size, 4); 00213 buf += decoded; buf_size -= decoded; 00214 decoded = loco_decode_plane(l, p->data[0] + 1, avctx->width, avctx->height, 00215 p->linesize[0], buf, buf_size, 4); 00216 buf += decoded; buf_size -= decoded; 00217 decoded = loco_decode_plane(l, p->data[0] + 2, avctx->width, avctx->height, 00218 p->linesize[0], buf, buf_size, 4); 00219 buf += decoded; buf_size -= decoded; 00220 decoded = loco_decode_plane(l, p->data[0] + 3, avctx->width, avctx->height, 00221 p->linesize[0], buf, buf_size, 4); 00222 break; 00223 } 00224 00225 *data_size = sizeof(AVFrame); 00226 *(AVFrame*)data = l->pic; 00227 00228 return buf_size; 00229 } 00230 00231 static av_cold int decode_init(AVCodecContext *avctx){ 00232 LOCOContext * const l = avctx->priv_data; 00233 int version; 00234 00235 l->avctx = avctx; 00236 if (avctx->extradata_size < 12) { 00237 av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n", 00238 avctx->extradata_size); 00239 return -1; 00240 } 00241 version = AV_RL32(avctx->extradata); 00242 switch(version) { 00243 case 1: 00244 l->lossy = 0; 00245 break; 00246 case 2: 00247 l->lossy = AV_RL32(avctx->extradata + 8); 00248 break; 00249 default: 00250 l->lossy = AV_RL32(avctx->extradata + 8); 00251 av_log(avctx, AV_LOG_INFO, "This is LOCO codec version %i, please upload file for study\n", version); 00252 } 00253 00254 l->mode = AV_RL32(avctx->extradata + 4); 00255 switch(l->mode) { 00256 case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY: 00257 avctx->pix_fmt = PIX_FMT_YUV422P; 00258 break; 00259 case LOCO_CRGB: case LOCO_RGB: 00260 avctx->pix_fmt = PIX_FMT_BGR24; 00261 break; 00262 case LOCO_CYV12: case LOCO_YV12: 00263 avctx->pix_fmt = PIX_FMT_YUV420P; 00264 break; 00265 case LOCO_CRGBA: case LOCO_RGBA: 00266 avctx->pix_fmt = PIX_FMT_RGB32; 00267 break; 00268 default: 00269 av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode); 00270 return -1; 00271 } 00272 if(avctx->debug & FF_DEBUG_PICT_INFO) 00273 av_log(avctx, AV_LOG_INFO, "lossy:%i, version:%i, mode: %i\n", l->lossy, version, l->mode); 00274 00275 return 0; 00276 } 00277 00278 static av_cold int decode_end(AVCodecContext *avctx){ 00279 LOCOContext * const l = avctx->priv_data; 00280 AVFrame *pic = &l->pic; 00281 00282 if (pic->data[0]) 00283 avctx->release_buffer(avctx, pic); 00284 00285 return 0; 00286 } 00287 00288 AVCodec loco_decoder = { 00289 "loco", 00290 AVMEDIA_TYPE_VIDEO, 00291 CODEC_ID_LOCO, 00292 sizeof(LOCOContext), 00293 decode_init, 00294 NULL, 00295 decode_end, 00296 decode_frame, 00297 CODEC_CAP_DR1, 00298 .long_name = NULL_IF_CONFIG_SMALL("LOCO"), 00299 };