| 285 | } |
| 286 | |
| 287 | static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, AVPacket *avpkt) |
| 288 | { |
| 289 | const uint8_t *buf = avpkt->data; |
| 290 | int buf_size = avpkt->size; |
| 291 | VmncContext * const c = avctx->priv_data; |
| 292 | uint8_t *outptr; |
| 293 | const uint8_t *src = buf; |
| 294 | int dx, dy, w, h, depth, enc, chunks, res, size_left; |
| 295 | |
| 296 | c->pic.reference = 1; |
| 297 | c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; |
| 298 | if(avctx->reget_buffer(avctx, &c->pic) < 0){ |
| 299 | av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); |
| 300 | return -1; |
| 301 | } |
| 302 | |
| 303 | c->pic.key_frame = 0; |
| 304 | c->pic.pict_type = FF_P_TYPE; |
| 305 | |
| 306 | //restore screen after cursor |
| 307 | if(c->screendta) { |
| 308 | int i; |
| 309 | w = c->cur_w; |
| 310 | if(c->width < c->cur_x + w) w = c->width - c->cur_x; |
| 311 | h = c->cur_h; |
| 312 | if(c->height < c->cur_y + h) h = c->height - c->cur_y; |
| 313 | dx = c->cur_x; |
| 314 | if(dx < 0) { |
| 315 | w += dx; |
| 316 | dx = 0; |
| 317 | } |
| 318 | dy = c->cur_y; |
| 319 | if(dy < 0) { |
| 320 | h += dy; |
| 321 | dy = 0; |
| 322 | } |
| 323 | if((w > 0) && (h > 0)) { |
| 324 | outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0]; |
| 325 | for(i = 0; i < h; i++) { |
| 326 | memcpy(outptr, c->screendta + i * c->cur_w * c->bpp2, w * c->bpp2); |
| 327 | outptr += c->pic.linesize[0]; |
| 328 | } |
| 329 | } |
| 330 | } |
| 331 | src += 2; |
| 332 | chunks = AV_RB16(src); src += 2; |
| 333 | while(chunks--) { |
| 334 | dx = AV_RB16(src); src += 2; |
| 335 | dy = AV_RB16(src); src += 2; |
| 336 | w = AV_RB16(src); src += 2; |
| 337 | h = AV_RB16(src); src += 2; |
| 338 | enc = AV_RB32(src); src += 4; |
| 339 | outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0]; |
| 340 | size_left = buf_size - (src - buf); |
| 341 | switch(enc) { |
| 342 | case MAGIC_WMVd: // cursor |
| 343 | if(size_left < 2 + w * h * c->bpp2 * 2) { |
| 344 | av_log(avctx, AV_LOG_ERROR, "Premature end of data! (need %i got %i)\n", 2 + w * h * c->bpp2 * 2, size_left); |
nothing calls this directly
no test coverage detected