Originally committed as revision 10448 to svn://svn.ffmpeg.org/ffmpeg/trunk
Reimar Döffinger authored on 2007/09/09 19:20:47... | ... |
@@ -31,6 +31,7 @@ |
31 | 31 |
typedef struct { |
32 | 32 |
AVFrame pic; |
33 | 33 |
int codec_frameheader; |
34 |
+ int quality; |
|
34 | 35 |
int width, height; |
35 | 36 |
unsigned int decomp_size; |
36 | 37 |
unsigned char* decomp_buf; |
... | ... |
@@ -104,6 +105,29 @@ static void get_quant_quality(NuvContext *c, int quality) { |
104 | 104 |
} |
105 | 105 |
} |
106 | 106 |
|
107 |
+static int codec_reinit(AVCodecContext *avctx, int width, int height, int quality) { |
|
108 |
+ NuvContext *c = avctx->priv_data; |
|
109 |
+ width = (width + 1) & ~1; |
|
110 |
+ height = (height + 1) & ~1; |
|
111 |
+ if (quality >= 0) |
|
112 |
+ get_quant_quality(c, quality); |
|
113 |
+ if (width != c->width || height != c->height) { |
|
114 |
+ if (avcodec_check_dimensions(avctx, height, width) < 0) |
|
115 |
+ return 0; |
|
116 |
+ avctx->width = c->width = width; |
|
117 |
+ avctx->height = c->height = height; |
|
118 |
+ c->decomp_size = c->height * c->width * 3 / 2; |
|
119 |
+ c->decomp_buf = av_realloc(c->decomp_buf, c->decomp_size + LZO_OUTPUT_PADDING); |
|
120 |
+ if (!c->decomp_buf) { |
|
121 |
+ av_log(avctx, AV_LOG_ERROR, "Can't allocate decompression buffer.\n"); |
|
122 |
+ return 0; |
|
123 |
+ } |
|
124 |
+ rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq, c->cq); |
|
125 |
+ } else if (quality != c->quality) |
|
126 |
+ rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq, c->cq); |
|
127 |
+ return 1; |
|
128 |
+} |
|
129 |
+ |
|
107 | 130 |
static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
108 | 131 |
uint8_t *buf, int buf_size) { |
109 | 132 |
NuvContext *c = avctx->priv_data; |
... | ... |
@@ -118,16 +142,6 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
118 | 118 |
return -1; |
119 | 119 |
} |
120 | 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; |
|
129 |
- } |
|
130 |
- |
|
131 | 121 |
// codec data (rtjpeg quant tables) |
132 | 122 |
if (buf[0] == 'D' && buf[1] == 'R') { |
133 | 123 |
int ret; |
... | ... |
@@ -157,16 +171,30 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
157 | 157 |
buf_size = c->decomp_size; |
158 | 158 |
} |
159 | 159 |
if (c->codec_frameheader) { |
160 |
+ int w, h, q; |
|
160 | 161 |
if (buf_size < 12) { |
161 | 162 |
av_log(avctx, AV_LOG_ERROR, "invalid nuv video frame\n"); |
162 | 163 |
return -1; |
163 | 164 |
} |
164 |
- get_quant_quality(c, buf[10]); |
|
165 |
- rtjpeg_decode_init(&c->rtj, &c->dsp, c->width, c->height, c->lq, c->cq); |
|
165 |
+ w = AV_RL16(&buf[6]); |
|
166 |
+ h = AV_RL16(&buf[8]); |
|
167 |
+ q = buf[10]; |
|
168 |
+ if (!codec_reinit(avctx, w, h, q)) |
|
169 |
+ return -1; |
|
166 | 170 |
buf = &buf[12]; |
167 | 171 |
buf_size -= 12; |
168 | 172 |
} |
169 | 173 |
|
174 |
+ if (c->pic.data[0]) |
|
175 |
+ avctx->release_buffer(avctx, &c->pic); |
|
176 |
+ c->pic.reference = 1; |
|
177 |
+ c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_READABLE | |
|
178 |
+ FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; |
|
179 |
+ if (avctx->get_buffer(avctx, &c->pic) < 0) { |
|
180 |
+ av_log(avctx, AV_LOG_ERROR, "get_buffer() failed\n"); |
|
181 |
+ return -1; |
|
182 |
+ } |
|
183 |
+ |
|
170 | 184 |
c->pic.pict_type = FF_I_TYPE; |
171 | 185 |
c->pic.key_frame = 1; |
172 | 186 |
// decompress/copy/whatever data |
... | ... |
@@ -210,26 +238,18 @@ static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, |
210 | 210 |
|
211 | 211 |
static int decode_init(AVCodecContext *avctx) { |
212 | 212 |
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 | 213 |
avctx->pix_fmt = PIX_FMT_YUV420P; |
219 | 214 |
c->pic.data[0] = NULL; |
215 |
+ c->decomp_buf = NULL; |
|
216 |
+ c->quality = -1; |
|
217 |
+ c->width = 0; |
|
218 |
+ c->height = 0; |
|
220 | 219 |
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 | 220 |
if (avctx->extradata_size) |
231 | 221 |
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); |
|
222 |
+ if (!codec_reinit(avctx, avctx->width, avctx->height, -1)) |
|
223 |
+ return 1; |
|
224 |
+ dsputil_init(&c->dsp, avctx); |
|
233 | 225 |
return 0; |
234 | 226 |
} |
235 | 227 |
|