annotate src/ffmpeg/libavcodec/loco.c @ 854:aac49941ee8f trunk

[svn] statusicon 0.3: alternative right-click menu with simple playback control commands
author giacomo
date Wed, 14 Mar 2007 07:44:00 -0700
parents e8776388b02a
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
808
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
1 /*
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
2 * LOCO codec
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
3 * Copyright (c) 2005 Konstantin Shishkov
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
4 *
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
5 * This file is part of FFmpeg.
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
6 *
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
7 * FFmpeg is free software; you can redistribute it and/or
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
8 * modify it under the terms of the GNU Lesser General Public
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
9 * License as published by the Free Software Foundation; either
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
10 * version 2.1 of the License, or (at your option) any later version.
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
11 *
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
12 * FFmpeg is distributed in the hope that it will be useful,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
15 * Lesser General Public License for more details.
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
16 *
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
17 * You should have received a copy of the GNU Lesser General Public
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
18 * License along with FFmpeg; if not, write to the Free Software
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
20 *
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
21 */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
22
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
23 /**
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
24 * @file loco.c
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
25 * LOCO codec.
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
26 */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
27
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
28 #include "avcodec.h"
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
29 #include "common.h"
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
30 #include "bitstream.h"
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
31 #include "golomb.h"
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
32
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
33 enum LOCO_MODE {LOCO_UNKN=0, LOCO_CYUY2=-1, LOCO_CRGB=-2, LOCO_CRGBA=-3, LOCO_CYV12=-4,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
34 LOCO_YUY2=1, LOCO_UYVY=2, LOCO_RGB=3, LOCO_RGBA=4, LOCO_YV12=5};
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
35
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
36 typedef struct LOCOContext{
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
37 AVCodecContext *avctx;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
38 AVFrame pic;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
39 int lossy;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
40 int mode;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
41 } LOCOContext;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
42
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
43 typedef struct RICEContext{
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
44 GetBitContext gb;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
45 int save, run, run2; /* internal rice decoder state */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
46 int sum, count; /* sum and count for getting rice parameter */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
47 int lossy;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
48 }RICEContext;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
49
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
50 static int loco_get_rice_param(RICEContext *r)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
51 {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
52 int cnt = 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
53 int val = r->count;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
54
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
55 while(r->sum > val && cnt < 9) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
56 val <<= 1;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
57 cnt++;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
58 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
59
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
60 return cnt;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
61 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
62
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
63 static inline void loco_update_rice_param(RICEContext *r, int val)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
64 {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
65 r->sum += val;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
66 r->count++;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
67
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
68 if(r->count == 16) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
69 r->sum >>= 1;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
70 r->count >>= 1;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
71 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
72 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
73
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
74 static inline int loco_get_rice(RICEContext *r)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
75 {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
76 int v;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
77 if (r->run > 0) { /* we have zero run */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
78 r->run--;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
79 loco_update_rice_param(r, 0);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
80 return 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
81 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
82 v = get_ur_golomb_jpegls(&r->gb, loco_get_rice_param(r), INT_MAX, 0);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
83 loco_update_rice_param(r, (v+1)>>1);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
84 if (!v) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
85 if (r->save >= 0) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
86 r->run = get_ur_golomb_jpegls(&r->gb, 2, INT_MAX, 0);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
87 if(r->run > 1)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
88 r->save += r->run + 1;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
89 else
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
90 r->save -= 3;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
91 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
92 else
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
93 r->run2++;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
94 } else {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
95 v = ((v>>1) + r->lossy) ^ -(v&1);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
96 if (r->run2 > 0) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
97 if (r->run2 > 2)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
98 r->save += r->run2;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
99 else
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
100 r->save -= 3;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
101 r->run2 = 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
102 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
103 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
104
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
105 return v;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
106 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
107
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
108 /* LOCO main predictor - LOCO-I/JPEG-LS predictor */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
109 static inline int loco_predict(uint8_t* data, int stride, int step)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
110 {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
111 int a, b, c;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
112
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
113 a = data[-stride];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
114 b = data[-step];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
115 c = data[-stride - step];
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
116
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
117 return mid_pred(a, a + b - c, b);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
118 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
119
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
120 static int loco_decode_plane(LOCOContext *l, uint8_t *data, int width, int height,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
121 int stride, uint8_t *buf, int buf_size, int step)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
122 {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
123 RICEContext rc;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
124 int val;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
125 int i, j;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
126
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
127 init_get_bits(&rc.gb, buf, buf_size*8);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
128 rc.save = 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
129 rc.run = 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
130 rc.run2 = 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
131 rc.lossy = l->lossy;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
132
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
133 rc.sum = 8;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
134 rc.count = 1;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
135
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
136 /* restore top left pixel */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
137 val = loco_get_rice(&rc);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
138 data[0] = 128 + val;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
139 /* restore top line */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
140 for (i = 1; i < width; i++) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
141 val = loco_get_rice(&rc);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
142 data[i * step] = data[i * step - step] + val;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
143 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
144 data += stride;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
145 for (j = 1; j < height; j++) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
146 /* restore left column */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
147 val = loco_get_rice(&rc);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
148 data[0] = data[-stride] + val;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
149 /* restore all other pixels */
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
150 for (i = 1; i < width; i++) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
151 val = loco_get_rice(&rc);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
152 data[i * step] = loco_predict(&data[i * step], stride, step) + val;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
153 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
154 data += stride;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
155 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
156
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
157 return ((get_bits_count(&rc.gb) + 7) >> 3);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
158 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
159
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
160 static int decode_frame(AVCodecContext *avctx,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
161 void *data, int *data_size,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
162 uint8_t *buf, int buf_size)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
163 {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
164 LOCOContext * const l = avctx->priv_data;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
165 AVFrame * const p= (AVFrame*)&l->pic;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
166 int decoded;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
167
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
168 if(p->data[0])
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
169 avctx->release_buffer(avctx, p);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
170
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
171 p->reference = 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
172 if(avctx->get_buffer(avctx, p) < 0){
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
173 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
174 return -1;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
175 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
176 p->key_frame = 1;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
177
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
178 switch(l->mode) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
179 case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY:
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
180 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
181 p->linesize[0], buf, buf_size, 1);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
182 buf += decoded; buf_size -= decoded;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
183 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
184 p->linesize[1], buf, buf_size, 1);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
185 buf += decoded; buf_size -= decoded;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
186 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
187 p->linesize[2], buf, buf_size, 1);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
188 break;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
189 case LOCO_CYV12: case LOCO_YV12:
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
190 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
191 p->linesize[0], buf, buf_size, 1);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
192 buf += decoded; buf_size -= decoded;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
193 decoded = loco_decode_plane(l, p->data[2], avctx->width / 2, avctx->height / 2,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
194 p->linesize[2], buf, buf_size, 1);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
195 buf += decoded; buf_size -= decoded;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
196 decoded = loco_decode_plane(l, p->data[1], avctx->width / 2, avctx->height / 2,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
197 p->linesize[1], buf, buf_size, 1);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
198 break;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
199 case LOCO_CRGB: case LOCO_RGB:
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
200 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1), avctx->width, avctx->height,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
201 -p->linesize[0], buf, buf_size, 3);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
202 buf += decoded; buf_size -= decoded;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
203 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 1, avctx->width, avctx->height,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
204 -p->linesize[0], buf, buf_size, 3);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
205 buf += decoded; buf_size -= decoded;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
206 decoded = loco_decode_plane(l, p->data[0] + p->linesize[0]*(avctx->height-1) + 2, avctx->width, avctx->height,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
207 -p->linesize[0], buf, buf_size, 3);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
208 break;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
209 case LOCO_RGBA:
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
210 decoded = loco_decode_plane(l, p->data[0], avctx->width, avctx->height,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
211 p->linesize[0], buf, buf_size, 4);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
212 buf += decoded; buf_size -= decoded;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
213 decoded = loco_decode_plane(l, p->data[0] + 1, avctx->width, avctx->height,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
214 p->linesize[0], buf, buf_size, 4);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
215 buf += decoded; buf_size -= decoded;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
216 decoded = loco_decode_plane(l, p->data[0] + 2, avctx->width, avctx->height,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
217 p->linesize[0], buf, buf_size, 4);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
218 buf += decoded; buf_size -= decoded;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
219 decoded = loco_decode_plane(l, p->data[0] + 3, avctx->width, avctx->height,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
220 p->linesize[0], buf, buf_size, 4);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
221 break;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
222 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
223
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
224 *data_size = sizeof(AVFrame);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
225 *(AVFrame*)data = l->pic;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
226
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
227 return buf_size;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
228 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
229
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
230 static int decode_init(AVCodecContext *avctx){
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
231 LOCOContext * const l = avctx->priv_data;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
232 int version;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
233
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
234 l->avctx = avctx;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
235 if (avctx->extradata_size < 12) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
236 av_log(avctx, AV_LOG_ERROR, "Extradata size must be >= 12 instead of %i\n",
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
237 avctx->extradata_size);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
238 return -1;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
239 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
240 version = LE_32(avctx->extradata);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
241 switch(version) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
242 case 1:
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
243 l->lossy = 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
244 break;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
245 case 2:
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
246 l->lossy = LE_32(avctx->extradata + 8);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
247 break;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
248 default:
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
249 l->lossy = LE_32(avctx->extradata + 8);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
250 av_log(avctx, AV_LOG_INFO, "This is LOCO codec version %i, please upload file for study\n", version);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
251 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
252
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
253 l->mode = LE_32(avctx->extradata + 4);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
254 switch(l->mode) {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
255 case LOCO_CYUY2: case LOCO_YUY2: case LOCO_UYVY:
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
256 avctx->pix_fmt = PIX_FMT_YUV422P;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
257 break;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
258 case LOCO_CRGB: case LOCO_RGB:
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
259 avctx->pix_fmt = PIX_FMT_BGR24;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
260 break;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
261 case LOCO_CYV12: case LOCO_YV12:
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
262 avctx->pix_fmt = PIX_FMT_YUV420P;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
263 break;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
264 case LOCO_CRGBA: case LOCO_RGBA:
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
265 avctx->pix_fmt = PIX_FMT_RGBA32;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
266 break;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
267 default:
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
268 av_log(avctx, AV_LOG_INFO, "Unknown colorspace, index = %i\n", l->mode);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
269 return -1;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
270 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
271 if(avctx->debug & FF_DEBUG_PICT_INFO)
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
272 av_log(avctx, AV_LOG_INFO, "lossy:%i, version:%i, mode: %i\n", l->lossy, version, l->mode);
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
273
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
274 return 0;
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
275 }
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
276
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
277 AVCodec loco_decoder = {
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
278 "loco",
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
279 CODEC_TYPE_VIDEO,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
280 CODEC_ID_LOCO,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
281 sizeof(LOCOContext),
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
282 decode_init,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
283 NULL,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
284 NULL,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
285 decode_frame,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
286 CODEC_CAP_DR1,
e8776388b02a [svn] - add ffmpeg
nenolod
parents:
diff changeset
287 };