Mercurial > libavcodec.hg
annotate ljpegenc.c @ 7354:456957d86106 libavcodec
My commit at r14340 was not the right solution. For a monochromatic
frame, there will be only one centroid and it will be impossible to
find three distinct ones. It is better to just avoid shifting if
there are not three different centroids.
author | vitor |
---|---|
date | Wed, 23 Jul 2008 05:54:34 +0000 |
parents | e943e1409077 |
children | 7477cbdacb20 |
rev | line source |
---|---|
5020 | 1 /* |
5028 | 2 * lossless JPEG encoder |
5020 | 3 * Copyright (c) 2000, 2001 Fabrice Bellard. |
4 * Copyright (c) 2003 Alex Beregszaszi | |
5 * Copyright (c) 2003-2004 Michael Niedermayer | |
6 * | |
5214 | 7 * Support for external huffman table, various fixes (AVID workaround), |
8 * aspecting, new decode_frame mechanism and apple mjpeg-b support | |
9 * by Alex Beregszaszi | |
10 * | |
5020 | 11 * This file is part of FFmpeg. |
12 * | |
13 * FFmpeg is free software; you can redistribute it and/or | |
14 * modify it under the terms of the GNU Lesser General Public | |
15 * License as published by the Free Software Foundation; either | |
16 * version 2.1 of the License, or (at your option) any later version. | |
17 * | |
18 * FFmpeg is distributed in the hope that it will be useful, | |
19 * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
20 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
21 * Lesser General Public License for more details. | |
22 * | |
23 * You should have received a copy of the GNU Lesser General Public | |
24 * License along with FFmpeg; if not, write to the Free Software | |
25 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA | |
26 */ | |
27 | |
28 /** | |
5028 | 29 * @file ljpegenc.c |
30 * lossless JPEG encoder. | |
5020 | 31 */ |
32 | |
33 #include "avcodec.h" | |
34 #include "dsputil.h" | |
35 #include "mpegvideo.h" | |
36 #include "mjpeg.h" | |
5028 | 37 #include "mjpegenc.h" |
5020 | 38 |
39 | |
40 static int encode_picture_lossless(AVCodecContext *avctx, unsigned char *buf, int buf_size, void *data){ | |
41 MpegEncContext * const s = avctx->priv_data; | |
42 MJpegContext * const m = s->mjpeg_ctx; | |
43 AVFrame *pict = data; | |
44 const int width= s->width; | |
45 const int height= s->height; | |
46 AVFrame * const p= (AVFrame*)&s->current_picture; | |
47 const int predictor= avctx->prediction_method+1; | |
48 | |
49 init_put_bits(&s->pb, buf, buf_size); | |
50 | |
51 *p = *pict; | |
52 p->pict_type= FF_I_TYPE; | |
53 p->key_frame= 1; | |
54 | |
5029
dbaa06366c3c
add a proper prefix to all mjpeg encoder exported functions
aurel
parents:
5028
diff
changeset
|
55 ff_mjpeg_encode_picture_header(s); |
5020 | 56 |
57 s->header_bits= put_bits_count(&s->pb); | |
58 | |
59 if(avctx->pix_fmt == PIX_FMT_RGB32){ | |
60 int x, y, i; | |
61 const int linesize= p->linesize[0]; | |
62 uint16_t (*buffer)[4]= (void *) s->rd_scratchpad; | |
63 int left[3], top[3], topleft[3]; | |
64 | |
65 for(i=0; i<3; i++){ | |
66 buffer[0][i]= 1 << (9 - 1); | |
67 } | |
68 | |
69 for(y = 0; y < height; y++) { | |
70 const int modified_predictor= y ? predictor : 1; | |
71 uint8_t *ptr = p->data[0] + (linesize * y); | |
72 | |
73 if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < width*3*4){ | |
74 av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); | |
75 return -1; | |
76 } | |
77 | |
78 for(i=0; i<3; i++){ | |
79 top[i]= left[i]= topleft[i]= buffer[0][i]; | |
80 } | |
81 for(x = 0; x < width; x++) { | |
82 buffer[x][1] = ptr[4*x+0] - ptr[4*x+1] + 0x100; | |
83 buffer[x][2] = ptr[4*x+2] - ptr[4*x+1] + 0x100; | |
84 buffer[x][0] = (ptr[4*x+0] + 2*ptr[4*x+1] + ptr[4*x+2])>>2; | |
85 | |
86 for(i=0;i<3;i++) { | |
87 int pred, diff; | |
88 | |
89 PREDICT(pred, topleft[i], top[i], left[i], modified_predictor); | |
90 | |
91 topleft[i]= top[i]; | |
92 top[i]= buffer[x+1][i]; | |
93 | |
94 left[i]= buffer[x][i]; | |
95 | |
96 diff= ((left[i] - pred + 0x100)&0x1FF) - 0x100; | |
97 | |
98 if(i==0) | |
5029
dbaa06366c3c
add a proper prefix to all mjpeg encoder exported functions
aurel
parents:
5028
diff
changeset
|
99 ff_mjpeg_encode_dc(s, diff, m->huff_size_dc_luminance, m->huff_code_dc_luminance); //FIXME ugly |
5020 | 100 else |
5029
dbaa06366c3c
add a proper prefix to all mjpeg encoder exported functions
aurel
parents:
5028
diff
changeset
|
101 ff_mjpeg_encode_dc(s, diff, m->huff_size_dc_chrominance, m->huff_code_dc_chrominance); |
5020 | 102 } |
103 } | |
104 } | |
105 }else{ | |
106 int mb_x, mb_y, i; | |
107 const int mb_width = (width + s->mjpeg_hsample[0] - 1) / s->mjpeg_hsample[0]; | |
108 const int mb_height = (height + s->mjpeg_vsample[0] - 1) / s->mjpeg_vsample[0]; | |
109 | |
110 for(mb_y = 0; mb_y < mb_height; mb_y++) { | |
111 if(s->pb.buf_end - s->pb.buf - (put_bits_count(&s->pb)>>3) < mb_width * 4 * 3 * s->mjpeg_hsample[0] * s->mjpeg_vsample[0]){ | |
112 av_log(s->avctx, AV_LOG_ERROR, "encoded frame too large\n"); | |
113 return -1; | |
114 } | |
115 for(mb_x = 0; mb_x < mb_width; mb_x++) { | |
116 if(mb_x==0 || mb_y==0){ | |
117 for(i=0;i<3;i++) { | |
118 uint8_t *ptr; | |
119 int x, y, h, v, linesize; | |
120 h = s->mjpeg_hsample[i]; | |
121 v = s->mjpeg_vsample[i]; | |
122 linesize= p->linesize[i]; | |
123 | |
124 for(y=0; y<v; y++){ | |
125 for(x=0; x<h; x++){ | |
126 int pred; | |
127 | |
128 ptr = p->data[i] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap | |
129 if(y==0 && mb_y==0){ | |
130 if(x==0 && mb_x==0){ | |
131 pred= 128; | |
132 }else{ | |
133 pred= ptr[-1]; | |
134 } | |
135 }else{ | |
136 if(x==0 && mb_x==0){ | |
137 pred= ptr[-linesize]; | |
138 }else{ | |
139 PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor); | |
140 } | |
141 } | |
142 | |
143 if(i==0) | |
5029
dbaa06366c3c
add a proper prefix to all mjpeg encoder exported functions
aurel
parents:
5028
diff
changeset
|
144 ff_mjpeg_encode_dc(s, (int8_t)(*ptr - pred), m->huff_size_dc_luminance, m->huff_code_dc_luminance); //FIXME ugly |
5020 | 145 else |
5029
dbaa06366c3c
add a proper prefix to all mjpeg encoder exported functions
aurel
parents:
5028
diff
changeset
|
146 ff_mjpeg_encode_dc(s, (int8_t)(*ptr - pred), m->huff_size_dc_chrominance, m->huff_code_dc_chrominance); |
5020 | 147 } |
148 } | |
149 } | |
150 }else{ | |
151 for(i=0;i<3;i++) { | |
152 uint8_t *ptr; | |
153 int x, y, h, v, linesize; | |
154 h = s->mjpeg_hsample[i]; | |
155 v = s->mjpeg_vsample[i]; | |
156 linesize= p->linesize[i]; | |
157 | |
158 for(y=0; y<v; y++){ | |
159 for(x=0; x<h; x++){ | |
160 int pred; | |
161 | |
162 ptr = p->data[i] + (linesize * (v * mb_y + y)) + (h * mb_x + x); //FIXME optimize this crap | |
163 //printf("%d %d %d %d %8X\n", mb_x, mb_y, x, y, ptr); | |
164 PREDICT(pred, ptr[-linesize-1], ptr[-linesize], ptr[-1], predictor); | |
165 | |
166 if(i==0) | |
5029
dbaa06366c3c
add a proper prefix to all mjpeg encoder exported functions
aurel
parents:
5028
diff
changeset
|
167 ff_mjpeg_encode_dc(s, (int8_t)(*ptr - pred), m->huff_size_dc_luminance, m->huff_code_dc_luminance); //FIXME ugly |
5020 | 168 else |
5029
dbaa06366c3c
add a proper prefix to all mjpeg encoder exported functions
aurel
parents:
5028
diff
changeset
|
169 ff_mjpeg_encode_dc(s, (int8_t)(*ptr - pred), m->huff_size_dc_chrominance, m->huff_code_dc_chrominance); |
5020 | 170 } |
171 } | |
172 } | |
173 } | |
174 } | |
175 } | |
176 } | |
177 | |
178 emms_c(); | |
179 | |
5029
dbaa06366c3c
add a proper prefix to all mjpeg encoder exported functions
aurel
parents:
5028
diff
changeset
|
180 ff_mjpeg_encode_picture_trailer(s); |
5020 | 181 s->picture_number++; |
182 | |
183 flush_put_bits(&s->pb); | |
184 return pbBufPtr(&s->pb) - s->pb.buf; | |
185 // return (put_bits_count(&f->pb)+7)/8; | |
186 } | |
187 | |
188 | |
5127 | 189 AVCodec ljpeg_encoder = { //FIXME avoid MPV_* lossless JPEG should not need them |
5020 | 190 "ljpeg", |
191 CODEC_TYPE_VIDEO, | |
192 CODEC_ID_LJPEG, | |
193 sizeof(MpegEncContext), | |
194 MPV_encode_init, | |
195 encode_picture_lossless, | |
196 MPV_encode_end, | |
7040
e943e1409077
Make AVCodec long_names definition conditional depending on CONFIG_SMALL.
stefano
parents:
6717
diff
changeset
|
197 .long_name = NULL_IF_CONFIG_SMALL("Lossless JPEG"), |
5020 | 198 }; |