When being called by the Indian "Microsoft" department I let them join in on my VirtualBox virtual machine, and started a video capture to catch any details on them. Doing so, VirtualBox creates .webm video files.

However, when I now play back that webm file, I see it got mangled right where I changed the VM's resolution. The session lasted an hour (phew...), and at the end I managed to thwart their futile hack attempts at setting a system password on my machine, and instead logged back into the connection they then broke. I think I then saw some full-screen dashboard environment - maybe theirs? Could have some very handy info it this is true!

The mangling seems like it's just a scanline-length issue in the video stream. Tricky thing here is that the video itself is all correctly in 1024x768 resolution, but the payload is just an 800x600 area in the middle (with black borders around it). That inner area is what got messed up further in the video. The black borders remain OK, so it's just VirtualBox's source data stream for the middle part that got misaligned.

Does anyone know of some procedure or software I could use to try to de-mangle this video? I've already seen that webm video files use a Matroska-based standard and use an EBML coding; I've already tried changing some headers values in the EBML structure to fudge the display resolution (making the black borders misaligned but the middle payload OK), but that led nowhere fast (each 5 secs of video or such has it's own header block as well).


To be precise: the video was rendered at 1024x786 pixels, while the virtual machine ran at 800x600. This results in a fat black border surrounding the inner captured content during the entire video. Once I increased the virtual machine's window size (to, say, 1200x650 - really couldn't say exactly), the black border remained the same in size, only the inner content in it gets mangled. With mangled I mean that it looks like it displays the now longer scan lines of 1200 pixels and wraps them in the 800 scanline length, thus each next real scanline gets offset by the horizontal size difference since the previous line is wrapped in it. Or at least, that's what I thought initially, but looking at it again I'm having my doubts on that theory as well.

Well - that's not clear at all :) I've uploaded a frame here: frame of scam video and a short video fragment here: short fragment of scam video (the issue happens halfway through the fragment)

But, to be honest, I think I'd better give up. I start to suspect that the only possible fix is to do pixelgrabbing in the old frames and build a new video out of that, if that's even a fix - i.e. too much effort. Shame, though, since I'd really like to review the content at the end...


Thanks to bukkojot, I've come up with the follow (Windows targetted) app that fits in the middle of the ffmpeg cmdline he gave; maybe someone may find it useful? Note that the "RGB24" in the cmdline must be "rgb24" when using the latest ffmpeg version on Windows, which brings the cmdline I used to:

ffmpeg.exe -i scamvideo_problem.webm -f rawvideo -pix_fmt rgb24 pipe: | restorer.exe | ffmpeg -f rawvideo -pix_fmt rgb24 -s 1103x436 -i pipe: -vcodec libx264 resolvedvideo.avi

The video came out legible (apart from color shifts), and all parties dragged into it have been notified (iTunes, gmail, TeamViewer and VICIdial).

Anyway, this is the C++ code I ended up using:

#include <stdio.h>
#include <io.h>
#include <fcntl.h>
#include <Windows.h>
using namespace std;

int main() {
    const size_t inLineSize = 1024 * 3;
    const size_t inFrameSize = 1024 * 768 * 3;
    const size_t outFrameSize = 1103 * 436 * 3;

    const size_t inPayloadLineSize = 800 * 3;
    const size_t inPayloadNumLines = 600;
    const size_t inPayloadFrameSize = inPayloadLineSize * inPayloadNumLines;
    const size_t inTopBorderNumLines = 84;
    const size_t inLeftBorderNumPixels = 112;
    const size_t inPayloadOffset = inLineSize * inTopBorderNumLines + inLeftBorderNumPixels * 3;

    const size_t outPadSize = outFrameSize - inPayloadFrameSize;

    _setmode(_fileno(stdin), _O_BINARY);
    _setmode(_fileno(stdout), _O_BINARY);

    char* inFrame = new char[inFrameSize];
    char* outPadding = new char[outPadSize];
    memset(outPadding, 0, outPadSize);
    while (!feof(stdin)) {
        size_t sizeLeft = inFrameSize;
        char* nextReadPos = inFrame;
        while (!feof(stdin) && sizeLeft > 0) {
            size_t bytesRead = fread(nextReadPos, 1, sizeLeft, stdin);
            sizeLeft -= bytesRead;
            nextReadPos += bytesRead;
            if (sizeLeft > 0) {
        if (!feof(stdin)) {
            char* inPayloadPos = inFrame;
            inPayloadPos += inPayloadOffset;
            for (size_t inLineNr = 0; inLineNr < inPayloadNumLines; ++inLineNr, inPayloadPos += inLineSize) {
                fwrite(inPayloadPos, 1, inPayloadLineSize, stdout);
            fwrite(outPadding, 1, outPadSize, stdout);
    return 0;
  • By mangled, do you just mean size, or decoding errors?
    – Gyan
    Commented Oct 13, 2017 at 15:40
  • @Mulvya: it's... I'll update the post to give more details :) Commented Oct 13, 2017 at 16:21

1 Answer 1


After a bit manipulation... You see...

enter image description here

Most easiest way for you:

  1. Write very simple app in C, which will read 1024*768*3 bytes and pads by zeros to 1327*768*3 bytes. It easy for you.

  2. Dump raw pixels with ffmpeg, pipe data to your app, pipe data to ffmpeg back

Something like:

ffmpeg -i scamvideo.avi -f rawvideo -pix_fmt RGB24 - | ./a.out | ffmpeg -f rawvideo -pix_fmt RGB24 -s 1327x768 -i - -vcodec libx264 newvideo.avi

All other options to your taste. I think, you got idea.

  • 1
    The luma has been aligned but not the chroma, which will be half-sized.
    – Gyan
    Commented Oct 14, 2017 at 5:12
  • @bukkojot: SO MANY THANKS! You don't know how badly I wanted that video restored! Now for the execution of it :) I'll indeed be able to do it, but I've got to find some time first... got the video anyway, so it won't be going anywhere in the meantime. Commented Oct 14, 2017 at 6:34
  • @Mulvya: * the chroma - if it's legible enough, I'm a happy camper :) Commented Oct 14, 2017 at 6:35
  • 1
    @bukkojot: binary mode was indeed key. And... I've got the video back! Well, only the top 3/4 of the frames since that's the only part that got crammed in the inner 800x600 portion. Anyway, got the e-mail address they tried to use to receive iTunes giftcards on, as well as the desktop they have in front of them (they use VICIdial Web Client). Success! Off to contact fraud@itunes, fraud@teamviewer, fraud@VICIdial and maybe the local police (but I think I won't bother with the last). Couldn't have done it without your answer! Commented Oct 15, 2017 at 19:39
  • 1
    And another comment for anyone trying the same feat: DON'T use Powershell - in it you can use pipes, but it has the nasty habbit of trying to buffer the whole stdout output from one app before piping it to the next... won't work in this case of course. Took me some hair pulling to figure that out... Commented Oct 15, 2017 at 20:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.