Mercurial > libavcodec.hg
annotate ljpegenc.c @ 12530:63edd10ad4bc libavcodec tip
Try to fix crashes introduced by r25218
r25218 made assumptions about the existence of past reference frames that
weren't necessarily true.
| author | darkshikari |
|---|---|
| date | Tue, 28 Sep 2010 09:06:22 +0000 |
| parents | 7dd2a45249a9 |
| children |
| rev | line source |
|---|---|
| 5020 | 1 /* |
| 5028 | 2 * lossless JPEG encoder |
|
8629
04423b2f6e0b
cosmetics: Remove pointless period after copyright statement non-sentences.
diego
parents:
7744
diff
changeset
|
3 * Copyright (c) 2000, 2001 Fabrice Bellard |
| 5020 | 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 /** | |
|
11644
7dd2a45249a9
Remove explicit filename from Doxygen @file commands.
diego
parents:
11560
diff
changeset
|
29 * @file |
| 5028 | 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 | |
| 10668 | 59 if(avctx->pix_fmt == PIX_FMT_BGRA){ |
| 5020 | 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) | |
|
7744
7477cbdacb20
Fix lossless jpeg encoder to comply to spec and store full redundant
michael
parents:
7040
diff
changeset
|
144 ff_mjpeg_encode_dc(s, *ptr - pred, m->huff_size_dc_luminance, m->huff_code_dc_luminance); //FIXME ugly |
| 5020 | 145 else |
|
7744
7477cbdacb20
Fix lossless jpeg encoder to comply to spec and store full redundant
michael
parents:
7040
diff
changeset
|
146 ff_mjpeg_encode_dc(s, *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) | |
|
7744
7477cbdacb20
Fix lossless jpeg encoder to comply to spec and store full redundant
michael
parents:
7040
diff
changeset
|
167 ff_mjpeg_encode_dc(s, *ptr - pred, m->huff_size_dc_luminance, m->huff_code_dc_luminance); //FIXME ugly |
| 5020 | 168 else |
|
7744
7477cbdacb20
Fix lossless jpeg encoder to comply to spec and store full redundant
michael
parents:
7040
diff
changeset
|
169 ff_mjpeg_encode_dc(s, *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); | |
| 9431 | 184 return put_bits_ptr(&s->pb) - s->pb.buf; |
| 5020 | 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", |
|
11560
8a4984c5cacc
Define AVMediaType enum, and use it instead of enum CodecType, which
stefano
parents:
10668
diff
changeset
|
191 AVMEDIA_TYPE_VIDEO, |
| 5020 | 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 }; |
