Browse code

Properly handle nuv file with changing resolution

Originally committed as revision 10448 to svn://svn.ffmpeg.org/ffmpeg/trunk

Reimar Döffinger authored on 2007/09/09 19:20:47
Showing 1 changed files
... ...
@@ -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