📄 vmnc.c
字号:
color = !!(flags & HT_CLR); paint_rect(dst2, 0, 0, bw, bh, bg, bpp, stride); if(src - ssrc > ssize - rects * (color * bpp + 2)) { av_log(c->avctx, AV_LOG_ERROR, "Premature end of data!\n"); return -1; } for(k = 0; k < rects; k++) { if(color) { fg = vmnc_get_pixel(src, bpp, c->bigendian); src += bpp; } xy = *src++; wh = *src++; paint_rect(dst2, xy >> 4, xy & 0xF, (wh>>4)+1, (wh & 0xF)+1, fg, bpp, stride); } } } dst += stride * 16; } return src - ssrc;}static int decode_frame(AVCodecContext *avctx, void *data, int *data_size, const uint8_t *buf, int buf_size){ VmncContext * const c = avctx->priv_data; uint8_t *outptr; const uint8_t *src = buf; int dx, dy, w, h, depth, enc, chunks, res, size_left; c->pic.reference = 1; c->pic.buffer_hints = FF_BUFFER_HINTS_VALID | FF_BUFFER_HINTS_PRESERVE | FF_BUFFER_HINTS_REUSABLE; if(avctx->reget_buffer(avctx, &c->pic) < 0){ av_log(avctx, AV_LOG_ERROR, "reget_buffer() failed\n"); return -1; } c->pic.key_frame = 0; c->pic.pict_type = FF_P_TYPE; //restore screen after cursor if(c->screendta) { int i; w = c->cur_w; if(c->width < c->cur_x + w) w = c->width - c->cur_x; h = c->cur_h; if(c->height < c->cur_y + h) h = c->height - c->cur_y; dx = c->cur_x; if(dx < 0) { w += dx; dx = 0; } dy = c->cur_y; if(dy < 0) { h += dy; dy = 0; } if((w > 0) && (h > 0)) { outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0]; for(i = 0; i < h; i++) { memcpy(outptr, c->screendta + i * c->cur_w * c->bpp2, w * c->bpp2); outptr += c->pic.linesize[0]; } } } src += 2; chunks = AV_RB16(src); src += 2; while(chunks--) { dx = AV_RB16(src); src += 2; dy = AV_RB16(src); src += 2; w = AV_RB16(src); src += 2; h = AV_RB16(src); src += 2; enc = AV_RB32(src); src += 4; outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0]; size_left = buf_size - (src - buf); switch(enc) { case MAGIC_WMVd: // cursor if(size_left < 2 + w * h * c->bpp2 * 2) { av_log(avctx, AV_LOG_ERROR, "Premature end of data! (need %i got %i)\n", 2 + w * h * c->bpp2 * 2, size_left); return -1; } src += 2; c->cur_w = w; c->cur_h = h; c->cur_hx = dx; c->cur_hy = dy; if((c->cur_hx > c->cur_w) || (c->cur_hy > c->cur_h)) { av_log(avctx, AV_LOG_ERROR, "Cursor hot spot is not in image: %ix%i of %ix%i cursor size\n", c->cur_hx, c->cur_hy, c->cur_w, c->cur_h); c->cur_hx = c->cur_hy = 0; } c->curbits = av_realloc(c->curbits, c->cur_w * c->cur_h * c->bpp2); c->curmask = av_realloc(c->curmask, c->cur_w * c->cur_h * c->bpp2); c->screendta = av_realloc(c->screendta, c->cur_w * c->cur_h * c->bpp2); load_cursor(c, src); src += w * h * c->bpp2 * 2; break; case MAGIC_WMVe: // unknown src += 2; break; case MAGIC_WMVf: // update cursor position c->cur_x = dx - c->cur_hx; c->cur_y = dy - c->cur_hy; break; case MAGIC_WMVg: // unknown src += 10; break; case MAGIC_WMVh: // unknown src += 4; break; case MAGIC_WMVi: // ServerInitialization struct c->pic.key_frame = 1; c->pic.pict_type = FF_I_TYPE; depth = *src++; if(depth != c->bpp) { av_log(avctx, AV_LOG_INFO, "Depth mismatch. Container %i bpp, Frame data: %i bpp\n", c->bpp, depth); } src++; c->bigendian = *src++; if(c->bigendian & (~1)) { av_log(avctx, AV_LOG_INFO, "Invalid header: bigendian flag = %i\n", c->bigendian); return -1; } //skip the rest of pixel format data src += 13; break; case MAGIC_WMVj: // unknown src += 2; break; case 0x00000000: // raw rectangle data if((dx + w > c->width) || (dy + h > c->height)) { av_log(avctx, AV_LOG_ERROR, "Incorrect frame size: %ix%i+%ix%i of %ix%i\n", w, h, dx, dy, c->width, c->height); return -1; } if(size_left < w * h * c->bpp2) { av_log(avctx, AV_LOG_ERROR, "Premature end of data! (need %i got %i)\n", w * h * c->bpp2, size_left); return -1; } paint_raw(outptr, w, h, src, c->bpp2, c->bigendian, c->pic.linesize[0]); src += w * h * c->bpp2; break; case 0x00000005: // HexTile encoded rectangle if((dx + w > c->width) || (dy + h > c->height)) { av_log(avctx, AV_LOG_ERROR, "Incorrect frame size: %ix%i+%ix%i of %ix%i\n", w, h, dx, dy, c->width, c->height); return -1; } res = decode_hextile(c, outptr, src, size_left, w, h, c->pic.linesize[0]); if(res < 0) return -1; src += res; break; default: av_log(avctx, AV_LOG_ERROR, "Unsupported block type 0x%08X\n", enc); chunks = 0; // leave chunks decoding loop } } if(c->screendta){ int i; //save screen data before painting cursor w = c->cur_w; if(c->width < c->cur_x + w) w = c->width - c->cur_x; h = c->cur_h; if(c->height < c->cur_y + h) h = c->height - c->cur_y; dx = c->cur_x; if(dx < 0) { w += dx; dx = 0; } dy = c->cur_y; if(dy < 0) { h += dy; dy = 0; } if((w > 0) && (h > 0)) { outptr = c->pic.data[0] + dx * c->bpp2 + dy * c->pic.linesize[0]; for(i = 0; i < h; i++) { memcpy(c->screendta + i * c->cur_w * c->bpp2, outptr, w * c->bpp2); outptr += c->pic.linesize[0]; } outptr = c->pic.data[0]; put_cursor(outptr, c->pic.linesize[0], c, c->cur_x, c->cur_y); } } *data_size = sizeof(AVFrame); *(AVFrame*)data = c->pic; /* always report that the buffer was completely consumed */ return buf_size;}/* * * Init VMnc decoder * */static int decode_init(AVCodecContext *avctx){ VmncContext * const c = avctx->priv_data; c->avctx = avctx; c->pic.data[0] = NULL; c->width = avctx->width; c->height = avctx->height; if (avcodec_check_dimensions(avctx, avctx->width, avctx->height) < 0) { return 1; } c->bpp = avctx->bits_per_sample; c->bpp2 = c->bpp/8; switch(c->bpp){ case 8: avctx->pix_fmt = PIX_FMT_PAL8; break; case 16: avctx->pix_fmt = PIX_FMT_RGB555; break; case 32: avctx->pix_fmt = PIX_FMT_RGB32; break; default: av_log(avctx, AV_LOG_ERROR, "Unsupported bitdepth %i\n", c->bpp); } return 0;}/* * * Uninit VMnc decoder * */static int decode_end(AVCodecContext *avctx){ VmncContext * const c = avctx->priv_data; if (c->pic.data[0]) avctx->release_buffer(avctx, &c->pic); av_free(c->curbits); av_free(c->curmask); av_free(c->screendta); return 0;}AVCodec vmnc_decoder = { "VMware video", CODEC_TYPE_VIDEO, CODEC_ID_VMNC, sizeof(VmncContext), decode_init, NULL, decode_end, decode_frame};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -