00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00027 #include "avcodec.h"
00028 #include "get_bits.h"
00029 #include "golomb.h"
00030 #include "internal.h"
00031 #include "mathops.h"
00032
00033 enum LOCO_MODE {LOCO_UNKN=0, LOCO_CYUY2=-1, LOCO_CRGB=-2, LOCO_CRGBA=-3, LOCO_CYV12=-4,
00034 LOCO_YUY2=1, LOCO_UYVY=2, LOCO_RGB=3, LOCO_RGBA=4, LOCO_YV12=5};
00035
00036 typedef struct LOCOContext{
00037 AVCodecContext *avctx;
00038 AVFrame pic;
00039 int lossy;
00040 int mode;
00041 } LOCOContext;
00042
00043 typedef struct RICEContext{
00044 GetBitContext gb;
00045 int save, run, run2;
00046 int sum, count;
00047 int lossy;
00048 }RICEContext;
00049
00050 static int loco_get_rice_param(RICEContext *r)
00051 {
00052 int cnt = 0;
00053 int val = r->count;
00054
00055 while(r->sum > val && cnt < 9) {
00056 val <<= 1;
00057 cnt++;
00058 }
00059
00060 return cnt;
00061 }
00062
00063 static inline void loco_update_rice_param(RICEContext *r, int val)
00064 {
00065 r->sum += val;
00066 r->count++;
00067
00068 if(r->count == 16) {
00069 r->sum >>= 1;
00070 r->count >>= 1;
00071 }
00072 }
00073
00074 static inline int loco_get_rice(RICEContext *r)
00075 {
00076 int v;
00077 if (r->run > 0) {
00078 r->run--;
00079 loco_update_rice_param(r, 0);
00080 return 0;
00081 }
00082 v = get_ur_golomb_jpegls(&r->gb, loco_get_rice_param(r), INT_MAX, 0);
00083 loco_update_rice_param(r, (v+1)>>1);
00084 if (!v) {
00085 if (r->save >= 0) {
00086 r->run = get_ur_golomb_jpegls(&r->gb, 2, INT_MAX, 0);
00087 if(r->run > 1)
00088 r->save += r->run + 1;
00089 else
00090 r->save -= 3;
00091 }
00092 else
00093 r->run2++;
00094 } else {
00095 v = ((v>>1) + r->lossy) ^ -(v&1);
00096 if (r->run2 > 0) {
00097 if (r->run2 > 2)
00098 r->save += r->run2;
00099 else
00100 r->save -= 3;
00101 r->run2 = 0;
00102 }
00103 }
00104
00105 return v;
00106 }
00107
00108
00109 static inline int loco_predict(uint8_t* data, int stride, int step)
00110 {
00111 int a, b, c;
00112
00113 a = data[-stride];
00114 b = data[-step];
00115 c = data[-stride - step];
00116
00117 return mid_pred(a, a + b - c, b);
00118 }
00119
00120 static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height,
00121 int stride, const uint8_t *buf, int buf_size, int step)
00122 {
00123 RICEContext rc;
00124 int val;
00125 int i, j;
00126
00127 if(buf_size<=0)
00128 return -1;
00129
00130 init_get_bits(&rc.gb, buf, buf_size*8);
00131 rc.save = 0;
00132 rc.run = 0;
00133 rc.run2 = 0;
00134 rc.lossy = l->lossy;
00135
00136 rc.sum = 8;
00137 rc.count = 1;
00138
00139
00140 val = loco_get_rice(&rc);
00141 data[0] = 128 + val;
00142
00143 for (i = 1; i < width; i++) {
00144 val = loco_get_rice(&rc);
00145 data[i * step] = data[i * step - step] + val;
00146 }
00147 data += stride;
00148 for (j = 1; j < height; j++) {
00149
00150 val = loco_get_rice(&rc);
00151 data[0] = data[-stride] + val;
00152
00153 for (i = 1; i < width; i++) {
00154 val = loco_get_rice(&rc);
00155 data[i * step] = loco_predict(&data[i * step], stride, step) + val;
00156 }
00157 data += stride;
00158 }
00159
00160 return (get_bits_count(&rc.gb) + 7) >> 3;
00161 }
00162
00163 static int decode_frame(AVCodecContext *avctx,
00164 void *data, int *got_frame,
00165 AVPacket *avpkt)
00166 {
00167 const uint8_t *buf = avpkt->data;
00168 int buf_size = avpkt->size;
00169 LOCOContext * const l = avctx->priv_data;
00170 AVFrame * const p = &l->pic;
00171 int decoded;
00172
00173 if(p->data[0])
00174 avctx->release_buffer(avctx, p);
00175
00176 p->reference = 0;
00177 if(ff_get_buffer(avctx, p) < 0){
00178 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
00179 return -1;
00180 }
00181 p->key_frame = 1;
00182
00183 #define ADVANCE_BY_DECODED do { \
00184 if (decoded < 0) goto stop; \
00185 buf += decoded; buf_size -= decoded; \
00186 } while(0)
00187 switch(l->mode) {
00188 case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY:
00189 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
00190 p->linesize[0], buf, buf_size, 1);
00191 ADVANCE_BY_DECODED;
00192 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height,
00193 p->linesize[1], buf, buf_size, 1);
00194 ADVANCE_BY_DECODED;
00195 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height,
00196 p->linesize[2], buf, buf_size, 1);
00197 break;
00198 case LOCO_CYV12: case LOCO_YV12:
00199 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
00200 p->linesize[0], buf, buf_size, 1);
00201 ADVANCE_BY_DECODED;
00202 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2,
00203 p->linesize[2], buf, buf_size, 1);
00204 ADVANCE_BY_DECODED;
00205 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2,
00206 p->linesize[1], buf, buf_size, 1);
00207 break;
00208 case LOCO_CRGB: case LOCO_RGB:
00209 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
00210 -p->linesize[0], buf, buf_size, 3);
00211 ADVANCE_BY_DECODED;
00212 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height,
00213 -p->linesize[0], buf, buf_size, 3);
00214 ADVANCE_BY_DECODED;
00215 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height,
00216 -p->linesize[0], buf, buf_size, 3);
00217 break;
00218 case LOCO_CRGBA: case LOCO_RGBA:
00219 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
00220 p->linesize[0], buf, buf_size, 4);
00221 ADVANCE_BY_DECODED;
00222 decoded = loco_decode_plane(l, p->data[0] + 1, avctx->width, avctx->height,
00223 p->linesize[0], buf, buf_size, 4);
00224 ADVANCE_BY_DECODED;
00225 decoded = loco_decode_plane(l, p->data[0] + 2, avctx->width, avctx->height,
00226 p->linesize[0], buf, buf_size, 4);
00227 ADVANCE_BY_DECODED;
00228 decoded = loco_decode_plane(l, p->data[0] + 3, avctx->width, avctx->height,
00229 p->linesize[0], buf, buf_size, 4);
00230 break;
00231 }
00232 stop:
00233
00234 *got_frame = 1;
00235 *(AVFrame*)data = l->pic;
00236
00237 return buf_size < 0 ? -1 : avpkt->size - buf_size;
00238 }
00239
00240 static av_cold int decode_init(AVCodecContext *avctx){
00241 LOCOContext * const l = avctx->priv_data;
00242 int version;
00243
00244 l->avctx = avctx;
00245 if (avctx->extradata_size < 12) {
00246 av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n",
00247 avctx->extradata_size);
00248 return -1;
00249 }
00250 version = AV_RL32(avctx->extradata);
00251 switch(version) {
00252 case 1:
00253 l->lossy = 0;
00254 break;
00255 case 2:
00256 l->lossy = AV_RL32(avctx->extradata + 8);
00257 break;
00258 default:
00259 l->lossy = AV_RL32(avctx->extradata + 8);
00260 av_log_ask_for_sample(avctx, "This is LOCO codec version %i.\n", version);
00261 }
00262
00263 l->mode = AV_RL32(avctx->extradata + 4);
00264 switch(l->mode) {
00265 case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY:
00266 avctx->pix_fmt = AV_PIX_FMT_YUV422P;
00267 break;
00268 case LOCO_CRGB: case LOCO_RGB:
00269 avctx->pix_fmt = AV_PIX_FMT_BGR24;
00270 break;
00271 case LOCO_CYV12: case LOCO_YV12:
00272 avctx->pix_fmt = AV_PIX_FMT_YUV420P;
00273 break;
00274 case LOCO_CRGBA: case LOCO_RGBA:
00275 avctx->pix_fmt = AV_PIX_FMT_RGB32;
00276 break;
00277 default:
00278 av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode);
00279 return -1;
00280 }
00281 if(avctx->debug & FF_DEBUG_PICT_INFO)
00282 av_log(avctx, AV_LOG_INFO, "lossy:%i, version:%i, mode: %i\n", l->lossy, version, l->mode);
00283
00284 avcodec_get_frame_defaults(&l->pic);
00285
00286 return 0;
00287 }
00288
00289 static av_cold int decode_end(AVCodecContext *avctx){
00290 LOCOContext * const l = avctx->priv_data;
00291 AVFrame *pic = &l->pic;
00292
00293 if (pic->data[0])
00294 avctx->release_buffer(avctx, pic);
00295
00296 return 0;
00297 }
00298
00299 AVCodec ff_loco_decoder = {
00300 .name = "loco",
00301 .type = AVMEDIA_TYPE_VIDEO,
00302 .id = AV_CODEC_ID_LOCO,
00303 .priv_data_size = sizeof(LOCOContext),
00304 .init = decode_init,
00305 .close = decode_end,
00306 .decode = decode_frame,
00307 .capabilities = CODEC_CAP_DR1,
00308 .long_name = NULL_IF_CONFIG_SMALL("LOCO"),
00309 };