comparison nuv.c @ 5658:0dc21d071895 libavcodec

Properly handle nuv file with changing resolution
author reimar
date Sun, 09 Sep 2007 10:20:47 +0000
parents ec46684cc8ad
children d540c7d88344
comparison
equal deleted inserted replaced
5657:ec46684cc8ad 5658:0dc21d071895
29 #include "rtjpeg.h" 29 #include "rtjpeg.h"
30 30
31 typedef struct { 31 typedef struct {
32 AVFrame pic; 32 AVFrame pic;
33 int codec_frameheader; 33 int codec_frameheader;
34 int quality;
34 int width, height; 35 int width, height;
35 unsigned int decomp_size; 36 unsigned int decomp_size;
36 unsigned char* decomp_buf; 37 unsigned char* decomp_buf;
37 uint32_t lq[64], cq[64]; 38 uint32_t lq[64], cq[64];
38 RTJpegContext rtj; 39 RTJpegContext rtj;
102 c->lq[i] = (fallback_lquant[i] << 7) / quality; 103 c->lq[i] = (fallback_lquant[i] << 7) / quality;
103 c->cq[i] = (fallback_cquant[i] << 7) / quality; 104 c->cq[i] = (fallback_cquant[i] << 7) / quality;
104 } 105 }
105 } 106 }
106 107
108 static int codec_reinit(AVCodecContext *avctx, int width, int height, int quality) {
109 NuvContext *c = avctx->priv_data;
110 width = (width + 1) & ~1;
111 height = (height + 1) & ~1;
112 if (quality >= 0)
113 get_quant_quality(c, quality);
114 if (width != c->width || height != c->height) {
115 if (avcodec_check_dimensions(avctx, height, width) < 0)
116 return 0;
117 avctx->width = c->width = width;
118 avctx->height = c->height = height;
119 c->decomp_size = c->height * c->width * 3 / 2;
120 c->decomp_buf = av_realloc(c->decomp_buf, c->decomp_size + LZO_OUTPUT_PADDING);
121 if (!c->decomp_buf) {
122 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
123 return 0;
124 }
125 rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq, c->cq);
126 } else if (quality != c->quality)
127 rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq, c->cq);
128 return 1;
129 }
130
107 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, 131 static int decode_frame(AVCodecContext *avctx, void *data, int *data_size,
108 uint8_t *buf, int buf_size) { 132 uint8_t *buf, int buf_size) {
109 NuvContext *c = avctx->priv_data; 133 NuvContext *c = avctx->priv_data;
110 AVFrame *picture = data; 134 AVFrame *picture = data;
111 int orig_size = buf_size; 135 int orig_size = buf_size;
113 NUV_RTJPEG_IN_LZO = '2', NUV_LZO = '3', 137 NUV_RTJPEG_IN_LZO = '2', NUV_LZO = '3',
114 NUV_BLACK = 'N', NUV_COPY_LAST = 'L'} comptype; 138 NUV_BLACK = 'N', NUV_COPY_LAST = 'L'} comptype;
115 139
116 if (buf_size < 12) { 140 if (buf_size < 12) {
117 av_log(avctx, AV_LOG_ERROR, "coded frame too small\n"); 141 av_log(avctx, AV_LOG_ERROR, "coded frame too small\n");
118 return -1;
119 }
120
121 if (c->pic.data[0])
122 avctx->release_buffer(avctx, &c->pic);
123 c->pic.reference = 1;
124 c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_READABLE |
125 FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
126 if (avctx->get_buffer(avctx, &c->pic) < 0) {
127 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
128 return -1; 142 return -1;
129 } 143 }
130 144
131 // codec data (rtjpeg quant tables) 145 // codec data (rtjpeg quant tables)
132 if (buf[0] == 'D' && buf[1] == 'R') { 146 if (buf[0] == 'D' && buf[1] == 'R') {
155 av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n"); 169 av_log(avctx, AV_LOG_ERROR, "error during lzo decompression\n");
156 buf = c->decomp_buf; 170 buf = c->decomp_buf;
157 buf_size = c->decomp_size; 171 buf_size = c->decomp_size;
158 } 172 }
159 if (c->codec_frameheader) { 173 if (c->codec_frameheader) {
174 int w, h, q;
160 if (buf_size < 12) { 175 if (buf_size < 12) {
161 av_log(avctx, AV_LOG_ERROR, "invalid nuv video frame\n"); 176 av_log(avctx, AV_LOG_ERROR, "invalid nuv video frame\n");
162 return -1; 177 return -1;
163 } 178 }
164 get_quant_quality(c, buf[10]); 179 w = AV_RL16(&buf[6]);
165 rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq, c->cq); 180 h = AV_RL16(&buf[8]);
181 q = buf[10];
182 if (!codec_reinit(avctx, w, h, q))
183 return -1;
166 buf = &buf[12]; 184 buf = &buf[12];
167 buf_size -= 12; 185 buf_size -= 12;
186 }
187
188 if (c->pic.data[0])
189 avctx->release_buffer(avctx, &c->pic);
190 c->pic.reference = 1;
191 c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_READABLE |
192 FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE;
193 if (avctx->get_buffer(avctx, &c->pic) < 0) {
194 av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n");
195 return -1;
168 } 196 }
169 197
170 c->pic.pict_type = FF_I_TYPE; 198 c->pic.pict_type = FF_I_TYPE;
171 c->pic.key_frame = 1; 199 c->pic.key_frame = 1;
172 // decompress/copy/whatever data 200 // decompress/copy/whatever data
208 return orig_size; 236 return orig_size;
209 } 237 }
210 238
211 static int decode_init(AVCodecContext *avctx) { 239 static int decode_init(AVCodecContext *avctx) {
212 NuvContext *c = avctx->priv_data; 240 NuvContext *c = avctx->priv_data;
213 avctx->width = (avctx->width + 1) & ~1;
214 avctx->height = (avctx->height + 1) & ~1;
215 if (avcodec_check_dimensions(avctx, avctx->height, avctx->width) < 0) {
216 return 1;
217 }
218 avctx->pix_fmt = PIX_FMT_YUV420P; 241 avctx->pix_fmt = PIX_FMT_YUV420P;
219 c->pic.data[0] = NULL; 242 c->pic.data[0] = NULL;
243 c->decomp_buf = NULL;
244 c->quality = -1;
245 c->width = 0;
246 c->height = 0;
220 c->codec_frameheader = avctx->codec_tag == MKTAG('R', 'J', 'P', 'G'); 247 c->codec_frameheader = avctx->codec_tag == MKTAG('R', 'J', 'P', 'G');
221 c->width = avctx->width;
222 c->height = avctx->height;
223 c->decomp_size = c->height * c->width * 3 / 2;
224 c->decomp_buf = av_malloc(c->decomp_size + LZO_OUTPUT_PADDING);
225 if (!c->decomp_buf) {
226 av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n");
227 return 1;
228 }
229 dsputil_init(&c->dsp, avctx);
230 if (avctx->extradata_size) 248 if (avctx->extradata_size)
231 get_quant(avctx, c, avctx->extradata, avctx->extradata_size); 249 get_quant(avctx, c, avctx->extradata, avctx->extradata_size);
232 rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq, c->cq); 250 if (!codec_reinit(avctx, avctx->width, avctx->height, -1))
251 return 1;
252 dsputil_init(&c->dsp, avctx);
233 return 0; 253 return 0;
234 } 254 }
235 255
236 static int decode_end(AVCodecContext *avctx) { 256 static int decode_end(AVCodecContext *avctx) {
237 NuvContext *c = avctx->priv_data; 257 NuvContext *c = avctx->priv_data;