Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1777 Le 21/11/2011, à 10:06

The Uploader

Re : /* Topic des codeurs [6] */

lol

C'est pas vendredi pourtant. ^^


- Oldies PC : Intel Pentium 3 @ 800 Mhz sur CM ASUS P2B-F, GeForce 4 Ti4800 SE, Disque Dur Hitachi 160 Go, 512 Mo de RAM, 3DFX Voodoo 2, Sound Blaster 16 ISA PnP, Windows 98 SE / XP)
- Desktop : Intel Core i7 6700K @ 4 GHz sur CM ASUS Z170-P, GeForce GTX 1070, SSD Samsung 850 EVO 1 To, 16 Go de RAM, Disque Dur Seagate Barracuda 3 To, Windows 10

Hors ligne

#1778 Le 21/11/2011, à 10:23

tshirtman

Re : /* Topic des codeurs [6] */

En fait c'est plus sur les tutos haskell qui nous mentent "pour notre bien" que sur le langage lui même, qu'il faut taper.

edit: oh, et ça plaira surement à quelques un ici
http://beets.radbox.org/

Dernière modification par tshirtman (Le 21/11/2011, à 10:24)

Hors ligne

#1779 Le 23/11/2011, à 21:18

grim7reaper

Re : /* Topic des codeurs [6] */

Tiens tiens, y’aurait y pas le nom d’un gus qui traîne par ici dans cet évenement ^^

Hors ligne

#1781 Le 23/11/2011, à 22:21

Elzen

Re : /* Topic des codeurs [6] */

Tiens, Python vient de me faire une surprise…

wins = sysapp.get_windows()
print len(wins)
for win in wins: # Nettoyage.
    if (check_unlist(win)):
        wins.remove(win)
        print "suppr"
    else:
        print "garde"
print len(wins)

a produit l'affichage suivant :

seth@fadreils: ~$ touhy/main/launcher 
4
suppr
suppr
2

Pas mal, non ?

En fait, j'ai juste remplacé wins par sysapp.get_windows() dans la déclaration de la boucle, et ça remarche.

Hors ligne

#1782 Le 23/11/2011, à 23:30

tshirtman

Hors ligne

#1783 Le 23/11/2011, à 23:57

kamui57

Re : /* Topic des codeurs [6] */

Moi aussi :

>>> a = 019
  File "<input>", line 1
    a = 019
          ^
SyntaxError: invalid token
>>> a = 19
>>> print (a)
19
>>> 

Dernière modification par kamui57 (Le 23/11/2011, à 23:59)


Quand le dernier arbre aura été abattu, et le dernier animal exterminé, les hommes se rendront compte que l'argent ne se mange pas (proverbe indien)
Toshiba Satellite L655 4 Go RAM, Archlinux Gnome-shell,LXDE / W7
Toshiba Satellite M30 512 Mo RAM, Archlinux Gnome 3 restreint / Crunchbang LXDE
https://help.ubuntu.com/community/Pastebinit pour poster du texte sur internet en console

Hors ligne

#1784 Le 24/11/2011, à 00:01

Pylades

Re : /* Topic des codeurs [6] */

Bah c’est juste que Python est plus civilisé que PHP, lui au moins il lève une exception quand t’essaies d’utiliser le chiffre 9 dans un nombre en octal. tongue


“Any if-statement is a goto. As are all structured loops.
“And sometimes structure is good. When it’s good, you should use it.
“And sometimes structure is _bad_, and gets into the way, and using a goto is just much clearer.”
                Linus Torvalds – 12 janvier 2003

Hors ligne

#1785 Le 24/11/2011, à 00:20

kamui57

Re : /* Topic des codeurs [6] */

Ouais je m'en étais rendu compte du coup, mais ça surprend^^ (j'ai pas l'habitude de mettre des 0 devant non plus)


Quand le dernier arbre aura été abattu, et le dernier animal exterminé, les hommes se rendront compte que l'argent ne se mange pas (proverbe indien)
Toshiba Satellite L655 4 Go RAM, Archlinux Gnome-shell,LXDE / W7
Toshiba Satellite M30 512 Mo RAM, Archlinux Gnome 3 restreint / Crunchbang LXDE
https://help.ubuntu.com/community/Pastebinit pour poster du texte sur internet en console

Hors ligne

#1786 Le 24/11/2011, à 00:47

HP

Re : /* Topic des codeurs [6] */

ArkSeth a écrit :

Pas mal, non ?

Oui, dans la série code crasseux…


cat /dev/urandom >/dev/null 2>&1 #github

Hors ligne

#1787 Le 24/11/2011, à 01:27

tshirtman

Re : /* Topic des codeurs [6] */

            from PIL import Image as PILImage
            from kivy.core.image import ImageLoaderBase, ImageData, ImageLoader
            import io
            from pyPdf import PdfFileWriter, PdfFileReader
            import PythonMagick as pm


            print "load pdf!", self.page
            # first extract the page from the pdf
            pdf = PdfFileReader(open(filename, 'rb'))
            p = pdf.getPage(self.page)
            size = p.mediaBox[2:]

            w = PdfFileWriter()
            w.addPage(p)
            f = io.BytesIO()
            w.write(f)
            f.seek(0)

            # then convert the one page pdf filebuffer to an image
            blob = pm.Blob(f.read())
            blobrgb = pm.Blob()
            pm.Image(blob).write(blobrgb,'rgb')

            im = PILImage.frombuffer(
                    'RGB',
                    (size[0] * 2, size[1]),
                    blobrgb.data).resize(size)
            return (ImageData(size[0], size[1], 'rgb', im.tostring()),)

je n'ai aucune idée de pourquoi j'ai besoin de multiplier la largeur par deux au chargement, et faire un resize après pour lui donner la bonne taille, mais c'est ce qui marche sur les deux pdfs sur lesquels j'ai testé... (pm = PythonMagick)
Si quelqu'un à une autre idée compatible lgpl (ça je pense que c'est bon, meme si pythonmagick semble utiliser ghostscript, qui est gpl, sa licence semble compatible avec la lgpl) vu que c'est pour kivy, qui est en lgpl. La seule solution d'affichage de pdf qui ne soit ni proprio, ni gpl, est pdfview, en java, qui fait 30000 lignes... et java2python ne s'en sort pas (en meme temps, je m'y attendais) je me vois mal réécrire un tel truc à la main.

edit: il y a un soucis de couleur aussi, je testerais d'autres encodages demain, genre "rbg" ou autres.

Dernière modification par tshirtman (Le 24/11/2011, à 01:32)

Hors ligne

#1788 Le 24/11/2011, à 14:08

The Uploader

Re : /* Topic des codeurs [6] */

P'tain les trolls pro-PHP... >_< !


- Oldies PC : Intel Pentium 3 @ 800 Mhz sur CM ASUS P2B-F, GeForce 4 Ti4800 SE, Disque Dur Hitachi 160 Go, 512 Mo de RAM, 3DFX Voodoo 2, Sound Blaster 16 ISA PnP, Windows 98 SE / XP)
- Desktop : Intel Core i7 6700K @ 4 GHz sur CM ASUS Z170-P, GeForce GTX 1070, SSD Samsung 850 EVO 1 To, 16 Go de RAM, Disque Dur Seagate Barracuda 3 To, Windows 10

Hors ligne

#1789 Le 24/11/2011, à 22:14

Elzen

Re : /* Topic des codeurs [6] */

HP a écrit :

Oui, dans la série code crasseux…

Hum.

Sans doute, mais je t'en prie, poste la version proprée, que j'puisse voir en quoi.


@tshirtman : tête en compote, mais le sujet m'intéresse, je tâcherai d'y jeter un œil ce week-end si j'y arrive (et si tu trouves de ton côté, hésite pas à partager ça wink)

Hors ligne

#1790 Le 24/11/2011, à 22:44

Keldath

Re : /* Topic des codeurs [6] */

ArkSeth a écrit :
HP a écrit :

Oui, dans la série code crasseux…

Sans doute, mais je t'en prie, poste la version proprée, que j'puisse voir en quoi.

Tu pourrais utiliser les list comprehension :

wins = [win for win in sysapp.get_windows() if not check_unlist(win)]

Hors ligne

#1791 Le 24/11/2011, à 22:47

Elzen

Re : /* Topic des codeurs [6] */

Ah, ouais, je pourrais. J'y pense jamais, à cette syntaxe-là.

'Faut dire que j'la trouve nettement moins lisible qu'une petite boucle classique.

Autant, le « machin if cond else truc » ou les conditions du genre « if elem in list », j'trouve ça plus clair que dans les autres langages, autant, le for comme ça, ça fait mal aux yeux, je trouve…

Dernière modification par ArkSeth (Le 24/11/2011, à 22:48)

Hors ligne

#1792 Le 24/11/2011, à 22:59

tshirtman

Re : /* Topic des codeurs [6] */

ou

from itertools import ifilterfalse
wins = list(ifilterfalse(check_unlist, sysapp.get_windows()))

si tu préfères.

si ton test était inversé, on pourrait faire

wins = filter(check_unlist, sysapp.get_windows())

mais bon.

Dernière modification par tshirtman (Le 24/11/2011, à 23:00)

Hors ligne

#1793 Le 24/11/2011, à 23:04

valAa

Re : /* Topic des codeurs [6] */

Keldath a écrit :
ArkSeth a écrit :
HP a écrit :

Oui, dans la série code crasseux…

Sans doute, mais je t'en prie, poste la version proprée, que j'puisse voir en quoi.

Tu pourrais utiliser les list comprehension :

wins = [win for win in sysapp.get_windows() if not check_unlist(win)]

Ça risque de ne pas avoir le même effet.
Le code d'ArkSeth avait un effet de bord (le `remove`) sur la liste originale si celle ci était renvoyée par référence.
Il faudrait donc savoir si le but est de filtrer la liste originale ou de construire une autre liste filtrée.

>>> class A:
...     def __init__(self):
...             self.list = [1, 2, 3, 0, 4]
...     def get_list(self):
...             return self.list
... 
>>> a = A()
>>> list = a.get_list()
>>> list
[1, 2, 3, 0, 4]
>>> for l in a.get_list():
...     if not l:
...             list.remove(l)
... 
>>> list
[1, 2, 3, 4] # okay
>>> a.get_list()
[1, 2, 3, 4] # le 0 est parti là aussi
>>> a = A()
>>> a.get_list()
[1, 2, 3, 0, 4]
>>> list = [l for l in a.get_list() if l]
>>> list
[1, 2, 3, 4] # okay
>>> a.get_list()
[1, 2, 3, 0, 4] # le 0 est toujours là
>>>

Dernière modification par valAa (Le 24/11/2011, à 23:06)

Hors ligne

#1794 Le 24/11/2011, à 23:05

Elzen

Re : /* Topic des codeurs [6] */

@tshirtman : Ça a déjà plus de tronche ^^

Sinon, pour répondre à ta remarque de l'autre coup, il me semblait justement que Python clonait les listes à la volée dans les for, pour permettre de modifier la liste en cours d'itération. En tout cas, j'était déjà tombé sur des codes comme ça qui avaient l'air de marcher.


@valAa : le but était de construire une seconde liste filtrée, je n'agis pas directement sur celle renvoyée par la fonction (en gros, c'est pour une barre des tâches, donc je liste les fenêtres d'une appli wnck, et je ne garde que les fenêtres que je suis censé afficher).

Mais j'avais vérifié auparavant qu'il n'y avait pas d'effets de bord sur la liste originale.

Dernière modification par ArkSeth (Le 24/11/2011, à 23:08)

Hors ligne

#1795 Le 24/11/2011, à 23:08

Keldath

Re : /* Topic des codeurs [6] */

Habitude smile À part ça, tu gagnerais beaucoup en performance en initialisant une liste vide à laquelle tu ajouterais tes éléments s'ils répondent à ta condition (c'est plus rapide d'ajouter que de supprimer un élément). Avec ou sans list comprehension, si tu n'aimes pas.

EDIT : devancé.

Dernière modification par Keldath (Le 24/11/2011, à 23:10)

Hors ligne

#1796 Le 24/11/2011, à 23:12

valAa

Re : /* Topic des codeurs [6] */

Yep.
Dans ce cas, si tu n'aime pas les list comprehension, lambda et filter \o/

wins = filter(lambda w: not check_unlist(w), sysapp.get_windows())

ou au pire...

wins = list()
for w in sysapp.get_windows():
    if not check_unlist(w):
        wins.append(w)

Dernière modification par valAa (Le 24/11/2011, à 23:24)

Hors ligne

#1797 Le 24/11/2011, à 23:34

tshirtman

Re : /* Topic des codeurs [6] */

ArkSeth a écrit :

@tshirtman : Ça a déjà plus de tronche ^^

Sinon, pour répondre à ta remarque de l'autre coup, il me semblait justement que Python clonait les listes à la volée dans les for, pour permettre de modifier la liste en cours d'itération. En tout cas, j'était déjà tombé sur des codes comme ça qui avaient l'air de marcher.
Mais j'avais vérifié auparavant qu'il n'y avait pas d'effets de bord sur la liste originale.

Il me semble qu'il le fait malheureusement dans certains cas, mais que la doc dit qu'il faut pas.

http://docs.python.org/tutorial/control … statements

@valAa: je suis allez chercher ifilterfalse par ce que je trouvais moche d'utiliser lambda pour ça ^^.

edit: c'est quand meme cool d'avoir pus garder la PEP 404 pour ça big_smile http://www.python.org/dev/peps/pep-0404/

Dernière modification par tshirtman (Le 25/11/2011, à 00:36)

Hors ligne

#1798 Le 26/11/2011, à 15:19

The Uploader

Re : /* Topic des codeurs [6] */

/!\ Attention code qui pique, mon C est très con. :]

http://vogons.zetafleet.com/viewtopic.p … 207#249207

J'avais toujours "ma" version modifiée du patch pour DOSBox qui fait que l'enregistrement vidéo se fait dans un thread qui crashait au bout de ~7 minutes avec un usage de la mémoire virtuelle totalement dingue (20 Go... : puis crash du système, ou du moins aucune réponse et le disque dur qui est très occupé..).

Mes modifications avaient au départ pour unique but d'avoir 14 images par seconde, au lieu de 70. Pas de patcher le patch pour que DOSBox évite de crasher..  hmm Et ce, deux fois :

Version originel de src/hardware/hardware.cpp :

/*
 *  Copyright (C) 2002-2009  The DOSBox Team
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

/* $Id: hardware.cpp,v 1.23 2009/10/11 18:09:22 qbix79 Exp $ */

#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include "dosbox.h"
#include "hardware.h"
#include "setup.h"
#include "support.h"
#include "mem.h"
#include "mapper.h"
#include "pic.h"
#include "render.h"
#include "cross.h"

#if (C_SSHOT)

#define C_THREADED_CAPTURE 1

#include <png.h>
#include "../libs/zmbv/zmbv.cpp"

#if (C_THREADED_CAPTURE)
#define MAX_QUEUE_SIZE 400
int secframescount=0;

#include "SDL.h"
#include <queue>

SDL_Thread *video_thread=NULL;
#endif

#endif

static std::string capturedir;
extern const char* RunningProgram;
Bitu CaptureState;

#define WAVE_BUF 16*1024
#define MIDI_BUF 4*1024
#define AVI_HEADER_SIZE    500

#if (C_SSHOT)
typedef struct {
    Bit16s        *audiobuf;
    Bitu        audioused;
    Bit8u        *videobuf;
    Bit8u        *pal;
} video_chunk_t;

typedef struct {
    FILE        *handle;
    Bitu        frames;
    Bit16s        audiobuf[WAVE_BUF][2];
    Bitu        audioused;
    Bitu        audiorate;
    Bitu        audiowritten;
    VideoCodec    *codec;
    Bitu        width, height, bpp;
    Bitu        written;
    float        fps;
    int            bufSize;
    void        *buf;
    Bit8u        *index;
    Bitu        indexsize, indexused;
    Bitu        flags;
    Bitu        pitch;
    zmbv_format_t format;
    int        thread_running;

#if (C_THREADED_CAPTURE)
    std::queue<video_chunk_t> q;
#endif

} video_capture_t;
#endif

static struct {
    struct {
        FILE * handle;
        Bit16s buf[WAVE_BUF][2];
        Bitu used;
        Bit32u length;
        Bit32u freq;
    } wave; 
    struct {
        FILE * handle;
        Bit8u buffer[MIDI_BUF];
        Bitu used,done;
        Bit32u last;
    } midi;
    struct {
        Bitu rowlen;
    } image;
#if (C_SSHOT)
    video_capture_t video;
#endif
} capture;

FILE * OpenCaptureFile(const char * type,const char * ext) {
    if(capturedir.empty()) {
        LOG_MSG("Please specify a capture directory");
        return 0;
    }
    Bitu last=0;
    char file_start[16];
    dir_information * dir;
    /* Find a filename to open */
    dir = open_directory(capturedir.c_str());
    if (!dir) {
        //Try creating it first
        Cross::CreateDir(capturedir);
        dir=open_directory(capturedir.c_str());
        if(!dir) {
        
            LOG_MSG("Can't open dir %s for capturing %s",capturedir.c_str(),type);
            return 0;
        }
    }
    strcpy(file_start,RunningProgram);
    lowcase(file_start);
    strcat(file_start,"_");
    bool is_directory;
    char tempname[CROSS_LEN];
    bool testRead = read_directory_first(dir, tempname, is_directory );
    for ( ; testRead; testRead = read_directory_next(dir, tempname, is_directory) ) {
        char * test=strstr(tempname,ext);
        if (!test || strlen(test)!=strlen(ext)) 
            continue;
        *test=0;
        if (strncasecmp(tempname,file_start,strlen(file_start))!=0) continue;
        Bitu num=atoi(&tempname[strlen(file_start)]);
        if (num>=last) last=num+1;
    }
    close_directory( dir );
    char file_name[CROSS_LEN];
    sprintf(file_name,"%s%c%s%03d%s",capturedir.c_str(),CROSS_FILESPLIT,file_start,last,ext);
    /* Open the actual file */
    FILE * handle=fopen(file_name,"wb");
    if (handle) {
        LOG_MSG("Capturing %s to %s",type,file_name);
    } else {
        LOG_MSG("Failed to open %s for capturing %s",file_name,type);
    }
    return handle;
}

#if (C_SSHOT)
static void CAPTURE_AddAviChunk(const char * tag, Bit32u size, void * data, Bit32u flags) {
    Bit8u chunk[8];Bit8u *index;Bit32u pos, writesize;
    chunk[0] = tag[0];chunk[1] = tag[1];chunk[2] = tag[2];chunk[3] = tag[3];
    host_writed(&chunk[4], size);   
    /* Write the actual data */
    fwrite(chunk,1,8,capture.video.handle);
    writesize = (size+1)&~1;
    fwrite(data,1,writesize,capture.video.handle);
    pos = capture.video.written + 4;
    capture.video.written += writesize + 8;
    if (capture.video.indexused + 16 >= capture.video.indexsize ) {
        capture.video.index = (Bit8u*)realloc( capture.video.index, capture.video.indexsize + 16 * 4096);
        if (!capture.video.index)
            E_Exit("Ran out of memory during AVI capturing");
        capture.video.indexsize += 16*4096;
    }
    index = capture.video.index+capture.video.indexused;
    capture.video.indexused += 16;
    index[0] = tag[0];
    index[1] = tag[1];
    index[2] = tag[2];
    index[3] = tag[3];
    host_writed(index+4, flags);
    host_writed(index+8, pos);
    host_writed(index+12, size);
}

static void CAPTURE_VideoHeader() {
        Bit8u avi_header[AVI_HEADER_SIZE];
        Bitu main_list;
        Bitu header_pos=0;
        Bitu save_pos=ftell(capture.video.handle);
#define AVIOUT4(_S_) memcpy(&avi_header[header_pos],_S_,4);header_pos+=4;
#define AVIOUTw(_S_) host_writew(&avi_header[header_pos], _S_);header_pos+=2;
#define AVIOUTd(_S_) host_writed(&avi_header[header_pos], _S_);header_pos+=4;
        /* Try and write an avi header */
        AVIOUT4("RIFF");                    // Riff header 
        AVIOUTd(AVI_HEADER_SIZE + capture.video.written - 8 + capture.video.indexused);
        AVIOUT4("AVI ");
        AVIOUT4("LIST");                    // List header
        main_list = header_pos;
        AVIOUTd(0);                            // TODO size of list
        AVIOUT4("hdrl");
        AVIOUT4("avih");
        AVIOUTd(56);                         /* # of bytes to follow */
        AVIOUTd((Bit32u)(1000000 / capture.video.fps*0.2));       /* Microseconds per frame */
        AVIOUTd(0);
        AVIOUTd(0);                         /* PaddingGranularity (whatever that might be) */
        AVIOUTd(0x110);                     /* Flags,0x10 has index, 0x100 interleaved */
        AVIOUTd(capture.video.frames);      /* TotalFrames */
        AVIOUTd(0);                         /* InitialFrames */
        AVIOUTd(2);                         /* Stream count */
        AVIOUTd(0);                         /* SuggestedBufferSize */
        AVIOUTd(capture.video.width);       /* Width */
        AVIOUTd(capture.video.height);      /* Height */
        AVIOUTd(0);                         /* TimeScale:  Unit used to measure time */
        AVIOUTd(0);                         /* DataRate:   Data rate of playback     */
        AVIOUTd(0);                         /* StartTime:  Starting time of AVI data */
        AVIOUTd(0);                         /* DataLength: Size of AVI data chunk    */
        /* Video stream list */
        AVIOUT4("LIST");
        AVIOUTd(4 + 8 + 56 + 8 + 40);       /* Size of the list */
        AVIOUT4("strl");
        /* video stream header */
                AVIOUT4("strh");
        AVIOUTd(56);                        /* # of bytes to follow */
        AVIOUT4("vids");                    /* Type */
        AVIOUT4(CODEC_4CC);                    /* Handler */
        AVIOUTd(0);                         /* Flags */
        AVIOUTd(0);                         /* Reserved, MS says: wPriority, wLanguage */
        AVIOUTd(0);                         /* InitialFrames */
        AVIOUTd(1000000);                   /* Scale */
        AVIOUTd((Bit32u)(1000000 * capture.video.fps*0.2));              /* Rate: Rate/Scale == samples/second */
        AVIOUTd(0);                         /* Start */
        AVIOUTd(capture.video.frames);      /* Length */
        AVIOUTd(0);                  /* SuggestedBufferSize */
        AVIOUTd(~0);                 /* Quality */
        AVIOUTd(0);                  /* SampleSize */
        AVIOUTd(0);                  /* Frame */
        AVIOUTd(0);                  /* Frame */
        /* The video stream format */
        AVIOUT4("strf");
        AVIOUTd(40);                 /* # of bytes to follow */
        AVIOUTd(40);                 /* Size */
        AVIOUTd(capture.video.width);         /* Width */
        AVIOUTd(capture.video.height);        /* Height */
//        OUTSHRT(1); OUTSHRT(24);     /* Planes, Count */
        AVIOUTd(0);
        AVIOUT4(CODEC_4CC);          /* Compression */
        AVIOUTd(capture.video.width * capture.video.height*4);  /* SizeImage (in bytes?) */
        AVIOUTd(0);                  /* XPelsPerMeter */
        AVIOUTd(0);                  /* YPelsPerMeter */
        AVIOUTd(0);                  /* ClrUsed: Number of colors used */
        AVIOUTd(0);                  /* ClrImportant: Number of colors important */
        /* Audio stream list */
        AVIOUT4("LIST");
        AVIOUTd(4 + 8 + 56 + 8 + 16);  /* Length of list in bytes */
        AVIOUT4("strl");
        /* The audio stream header */
        AVIOUT4("strh");
        AVIOUTd(56);            /* # of bytes to follow */
        AVIOUT4("auds");
        AVIOUTd(0);             /* Format (Optionally) */
        AVIOUTd(0);             /* Flags */
        AVIOUTd(0);             /* Reserved, MS says: wPriority, wLanguage */
        AVIOUTd(0);             /* InitialFrames */
        AVIOUTd(4);    /* Scale */
        AVIOUTd(capture.video.audiorate*4);             /* Rate, actual rate is scale/rate */
        AVIOUTd(0);             /* Start */
        if (!capture.video.audiorate)
            capture.video.audiorate = 1;
        AVIOUTd(capture.video.audiowritten/4);   /* Length */
        AVIOUTd(0);             /* SuggestedBufferSize */
        AVIOUTd(~0);            /* Quality */
        AVIOUTd(4);                /* SampleSize */
        AVIOUTd(0);             /* Frame */
        AVIOUTd(0);             /* Frame */
        /* The audio stream format */
        AVIOUT4("strf");
        AVIOUTd(16);            /* # of bytes to follow */
        AVIOUTw(1);             /* Format, WAVE_ZMBV_FORMAT_PCM */
        AVIOUTw(2);             /* Number of channels */
        AVIOUTd(capture.video.audiorate);          /* SamplesPerSec */
        AVIOUTd(capture.video.audiorate*4);        /* AvgBytesPerSec*/
        AVIOUTw(4);             /* BlockAlign */
        AVIOUTw(16);            /* BitsPerSample */
        int nmain = header_pos - main_list - 4;
        /* Finish stream list, i.e. put number of bytes in the list to proper pos */
        int njunk = AVI_HEADER_SIZE - 8 - 12 - header_pos;
        AVIOUT4("JUNK");
        AVIOUTd(njunk);
        /* Fix the size of the main list */
        header_pos = main_list;
        AVIOUTd(nmain);
        header_pos = AVI_HEADER_SIZE - 12;
        AVIOUT4("LIST");
        AVIOUTd(capture.video.written+4); /* Length of list in bytes */
        AVIOUT4("movi");
        /* First add the index table to the end */
        memcpy(capture.video.index, "idx1", 4);
        host_writed( capture.video.index+4, capture.video.indexused - 8 );
        fwrite( capture.video.index, 1, capture.video.indexused, capture.video.handle);
        fseek(capture.video.handle, 0, SEEK_SET);
        fwrite(&avi_header, 1, AVI_HEADER_SIZE, capture.video.handle);
        fseek(capture.video.handle, save_pos, SEEK_SET);
}


static void CAPTURE_VideoEvent(bool pressed) {
    if (!pressed)
        return;
    if (CaptureState & CAPTURE_VIDEO) {
        /* Close the video */
        CaptureState &= ~CAPTURE_VIDEO;
#if (C_THREADED_CAPTURE)
        /* Waits for thread to finish */
        if (capture.video.thread_running) {
            LOG_MSG("Finalizing video. Please wait...");
            SDL_WaitThread(video_thread,NULL);
        }
#endif
        /* Adds AVI header to the file */
        CAPTURE_VideoHeader();
        /* Close video file and free memory */
        fclose( capture.video.handle );
        free( capture.video.index );
        free( capture.video.buf );
        delete capture.video.codec;
        capture.video.handle = 0;
        LOG_MSG("Stopped capturing video.");
    } else {
        if (!capture.video.thread_running)
            CaptureState |= CAPTURE_VIDEO;
    }
}


int CAPTURE_VideoCompressFrame(video_capture_t *videohandle, video_chunk_t chunk) {
    secframescount++;
    if(secframescount==11)
        secframescount=1;
    if(secframescount==1||secframescount==6){
            Bit8u doubleRow[SCALER_MAXWIDTH*4];
            int codecFlags;
            if (videohandle->frames % 300 == 0)
                    codecFlags = 1;
            else codecFlags = 0;
            if (!videohandle->codec->PrepareCompressFrame( codecFlags, videohandle->format, (char *)chunk.pal, videohandle->buf, videohandle->bufSize))
            {
                    CAPTURE_VideoEvent(true);
                    return 1;
            }
            for (Bit32u i=0;i<videohandle->height;i++) {
                    void * rowPointer;
                    if (videohandle->flags & CAPTURE_FLAG_DBLW) {
                            void *srcLine;
                            Bitu x;
                            Bitu countWidth = videohandle->width >> 1;
                            if (videohandle->flags & CAPTURE_FLAG_DBLH)
                                    srcLine=(chunk.videobuf+(i >> 1)*videohandle->pitch);
                            else
                                    srcLine=(chunk.videobuf+(i >> 0)*videohandle->pitch);
                            switch ( videohandle->bpp) {
                            case 8:
                                    for (x=0;x<countWidth;x++)
                                            ((Bit8u *)doubleRow)[x*2+0] =
                                            ((Bit8u *)doubleRow)[x*2+1] = ((Bit8u *)srcLine)[x];
                                    break;
                            case 15:
                            case 16:
                                    for (x=0;x<countWidth;x++)
                                            ((Bit16u *)doubleRow)[x*2+0] =
                                            ((Bit16u *)doubleRow)[x*2+1] = ((Bit16u *)srcLine)[x];
                                    break;
                            case 32:
                                    for (x=0;x<countWidth;x++)
                                            ((Bit32u *)doubleRow)[x*2+0] =
                                            ((Bit32u *)doubleRow)[x*2+1] = ((Bit32u *)srcLine)[x];
                                    break;
                            }
                rowPointer=doubleRow;
                    } else {
                            if (videohandle->flags & CAPTURE_FLAG_DBLH)
                                    rowPointer=(chunk.videobuf+(i >> 1)*videohandle->pitch);
                            else
                                    rowPointer=(chunk.videobuf+(i >> 0)*videohandle->pitch);
                    }
                    videohandle->codec->CompressLines( 1, &rowPointer );
            }
            int written = videohandle->codec->FinishCompressFrame();
            if (written < 0) {
                    CAPTURE_VideoEvent(true);
                    return 1;
            }
            CAPTURE_AddAviChunk( "00dc", written, videohandle->buf, codecFlags & 1 ? 0x10 : 0x0);
            videohandle->frames++;
            //LOG_MSG("Frame %d video %d audio %d",videohandle->frames, written, videohandle->audioused *4 );
    }
    if ( chunk.audioused ) {
        CAPTURE_AddAviChunk( "01wb", chunk.audioused * 4, chunk.audiobuf, 0);
        videohandle->audiowritten = chunk.audioused*4;
    }
    /* Adds AVI header to the file */
    CAPTURE_VideoHeader();
    return 0;
}

#if (C_THREADED_CAPTURE)

static int CAPTURE_VideoThread(void *videohandleptr) {
        video_capture_t *videohandle=(video_capture_t*)videohandleptr;
    //videohandle->thread_running = true;
    /* Process queue */
    while (!videohandle->q.empty()) {
            //LOG_MSG("queue size %d",videohandle->q.size());
            /* Process a block and write it to disk */
            //LOG_MSG("%d",videohandle->q.size());
            CAPTURE_VideoCompressFrame(videohandle,videohandle->q.front());
            //else CaptureState &= ~CAPTURE_VIDEO;
            free(videohandle->q.front().videobuf);
            free(videohandle->q.front().audiobuf);
            free(videohandle->q.front().pal);
            /* Delete chunk from queue */
            videohandle->q.pop();
    }
    //videohandle->thread_running = false;
    return videohandle->thread_running=0;
}

#endif // C_THREADED_CAPTURE

#endif // C_SSHOT

void CAPTURE_AddImage(Bitu width, Bitu height, Bitu bpp, Bitu pitch, Bitu flags, float fps, Bit8u * data, Bit8u * pal) {
#if (C_SSHOT)
    Bitu i;
    Bit8u doubleRow[SCALER_MAXWIDTH*4];
    Bitu countWidth = width;
    if (flags & CAPTURE_FLAG_DBLH)
        height *= 2;
    if (flags & CAPTURE_FLAG_DBLW)
        width *= 2;

    if (height > SCALER_MAXHEIGHT)
        return;
    if (width > SCALER_MAXWIDTH)
        return;
    if (CaptureState & CAPTURE_IMAGE) {
        png_structp png_ptr;
        png_infop info_ptr;
        png_color palette[256];
        CaptureState &= ~CAPTURE_IMAGE;
        /* Open the actual file */
        FILE * fp=OpenCaptureFile("Screenshot",".png");
        if (!fp) goto skip_shot;
        /* First try to alloacte the png structures */
        png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL,NULL, NULL);
        if (!png_ptr) goto skip_shot;
        info_ptr = png_create_info_struct(png_ptr);
        if (!info_ptr) {
            png_destroy_write_struct(&png_ptr,(png_infopp)NULL);
            goto skip_shot;
        }
        /* Finalize the initing of png library */
        png_init_io(png_ptr, fp);
        png_set_compression_level(png_ptr,Z_BEST_COMPRESSION);
        /* set other zlib parameters */
        png_set_compression_mem_level(png_ptr, 8);
        png_set_compression_strategy(png_ptr,Z_DEFAULT_STRATEGY);
        png_set_compression_window_bits(png_ptr, 15);
        png_set_compression_method(png_ptr, 8);
        png_set_compression_buffer_size(png_ptr, 8192);
        if (bpp==8) {
            png_set_IHDR(png_ptr, info_ptr, width, height,
                8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
                PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
            for (i=0;i<256;i++) {
                palette[i].red=pal[i*4+0];
                palette[i].green=pal[i*4+1];
                palette[i].blue=pal[i*4+2];
            }
            png_set_PLTE(png_ptr, info_ptr, palette,256);
        } else {
            png_set_bgr( png_ptr );
            png_set_IHDR(png_ptr, info_ptr, width, height,
                8, PNG_COLOR_TYPE_RGB, PNG_INTERLACE_NONE,
                PNG_COMPRESSION_TYPE_DEFAULT, PNG_FILTER_TYPE_DEFAULT);
        }
        png_write_info(png_ptr, info_ptr);
        for (i=0;i<height;i++) {
            void *rowPointer;
            void *srcLine;
            if (flags & CAPTURE_FLAG_DBLH)
                srcLine=(data+(i >> 1)*pitch);
            else
                srcLine=(data+(i >> 0)*pitch);
            rowPointer=srcLine;
            switch (bpp) {
            case 8:
                if (flags & CAPTURE_FLAG_DBLW) {
                       for (Bitu x=0;x<countWidth;x++)
                        doubleRow[x*2+0] =
                        doubleRow[x*2+1] = ((Bit8u *)srcLine)[x];
                    rowPointer = doubleRow;
                }
                break;
            case 15:
                if (flags & CAPTURE_FLAG_DBLW) {
                    for (Bitu x=0;x<countWidth;x++) {
                        Bitu pixel = ((Bit16u *)srcLine)[x];
                        doubleRow[x*6+0] = doubleRow[x*6+3] = ((pixel& 0x001f) * 0x21) >>  2;
                        doubleRow[x*6+1] = doubleRow[x*6+4] = ((pixel& 0x03e0) * 0x21) >>  7;
                        doubleRow[x*6+2] = doubleRow[x*6+5] = ((pixel& 0x7c00) * 0x21) >>  12;
                    }
                } else {
                    for (Bitu x=0;x<countWidth;x++) {
                        Bitu pixel = ((Bit16u *)srcLine)[x];
                        doubleRow[x*3+0] = ((pixel& 0x001f) * 0x21) >>  2;
                        doubleRow[x*3+1] = ((pixel& 0x03e0) * 0x21) >>  7;
                        doubleRow[x*3+2] = ((pixel& 0x7c00) * 0x21) >>  12;
                    }
                }
                rowPointer = doubleRow;
                break;
            case 16:
                if (flags & CAPTURE_FLAG_DBLW) {
                    for (Bitu x=0;x<countWidth;x++) {
                        Bitu pixel = ((Bit16u *)srcLine)[x];
                        doubleRow[x*6+0] = doubleRow[x*6+3] = ((pixel& 0x001f) * 0x21) >> 2;
                        doubleRow[x*6+1] = doubleRow[x*6+4] = ((pixel& 0x07e0) * 0x41) >> 9;
                        doubleRow[x*6+2] = doubleRow[x*6+5] = ((pixel& 0xf800) * 0x21) >> 13;
                    }
                } else {
                    for (Bitu x=0;x<countWidth;x++) {
                        Bitu pixel = ((Bit16u *)srcLine)[x];
                        doubleRow[x*3+0] = ((pixel& 0x001f) * 0x21) >>  2;
                        doubleRow[x*3+1] = ((pixel& 0x07e0) * 0x41) >>  9;
                        doubleRow[x*3+2] = ((pixel& 0xf800) * 0x21) >>  13;
                    }
                }
                rowPointer = doubleRow;
                break;
            case 32:
                if (flags & CAPTURE_FLAG_DBLW) {
                    for (Bitu x=0;x<countWidth;x++) {
                        doubleRow[x*6+0] = doubleRow[x*6+3] = ((Bit8u *)srcLine)[x*4+0];
                        doubleRow[x*6+1] = doubleRow[x*6+4] = ((Bit8u *)srcLine)[x*4+1];
                        doubleRow[x*6+2] = doubleRow[x*6+5] = ((Bit8u *)srcLine)[x*4+2];
                    }
                } else {
                    for (Bitu x=0;x<countWidth;x++) {
                        doubleRow[x*3+0] = ((Bit8u *)srcLine)[x*4+0];
                        doubleRow[x*3+1] = ((Bit8u *)srcLine)[x*4+1];
                        doubleRow[x*3+2] = ((Bit8u *)srcLine)[x*4+2];
                    }
                }
                rowPointer = doubleRow;
                break;
            }
            png_write_row(png_ptr, (png_bytep)rowPointer);
        }
        /* Finish writing */
        png_write_end(png_ptr, 0);
        /*Destroy PNG structs*/
        png_destroy_write_struct(&png_ptr, &info_ptr);
        /*close file*/
        fclose(fp);
    }
skip_shot:
    if (CaptureState & CAPTURE_VIDEO) {
        /* Restarts capturing if any of the test fails */
        if (capture.video.handle && (
            capture.video.width != width ||
            capture.video.height != height ||
            capture.video.bpp != bpp ||
            capture.video.fps != fps)) {
            /* Ends current capturing */
            CAPTURE_VideoEvent(true);
            /* Toggle video capture event */
            CaptureState |= CAPTURE_VIDEO;
        }
        /* Choose video format */
        switch (bpp) {
        case 8:capture.video.format = ZMBV_FORMAT_8BPP;break;
        case 15:capture.video.format = ZMBV_FORMAT_15BPP;break;
        case 16:capture.video.format = ZMBV_FORMAT_16BPP;break;
        case 32:capture.video.format = ZMBV_FORMAT_32BPP;break;
        default:
            CAPTURE_VideoEvent(true);
            return;
        }
        /* Initialize video handle */
        if (!capture.video.handle) {
            capture.video.handle = OpenCaptureFile("Video",".avi");
            if (!capture.video.handle) {
                CAPTURE_VideoEvent(true);
                return;
            }
            capture.video.codec = new VideoCodec();
            if (!capture.video.codec) {
                CAPTURE_VideoEvent(true);
                return;
            }
            if (!capture.video.codec->SetupCompress( width, height)) {
                CAPTURE_VideoEvent(true);
                return;
            }
            capture.video.bufSize = capture.video.codec->NeededSize(width, height, capture.video.format);
            capture.video.buf = malloc( capture.video.bufSize );
            if (!capture.video.buf) {
                CAPTURE_VideoEvent(true);
                return;
            }
            capture.video.index = (Bit8u*)malloc( 16*4096 );
            if (!capture.video.index) {
                CAPTURE_VideoEvent(true);
                return;
            }
            capture.video.indexsize = 16*4096;
            capture.video.indexused = 8;

            capture.video.width = width;
            capture.video.height = height;
            capture.video.pitch = pitch;
            capture.video.flags = flags;
            capture.video.bpp = bpp;
            capture.video.fps = fps;
            for (int i=0;i<AVI_HEADER_SIZE;i++)
                fputc(0,capture.video.handle);
            capture.video.frames = 0;
            capture.video.written = 0;
            capture.video.audioused = 0;
            capture.video.audiowritten = 0;
            capture.video.thread_running = 0;

        }
        video_chunk_t chunk;

#if (C_THREADED_CAPTURE)
        /* Create video chunk buffers */
        chunk.videobuf = (Bit8u *)malloc(capture.video.height*capture.video.pitch);
        if (!chunk.videobuf) {
            CAPTURE_VideoEvent(true);
            return;
        }
        chunk.audiobuf = (Bit16s *)malloc(capture.video.audioused*4);
        if (!chunk.audiobuf) {
            CAPTURE_VideoEvent(true);
            return;
        }
        chunk.pal = (Bit8u *)malloc(256*4);
        if (!chunk.pal) {
            CAPTURE_VideoEvent(true);
            return;
        }
        /* Copy data to chunk */
        memcpy(chunk.videobuf,data,capture.video.height*capture.video.pitch);
        memcpy(chunk.audiobuf,&capture.video.audiobuf, capture.video.audioused*4);
        memcpy(chunk.pal,pal,256*4);
        chunk.audioused = capture.video.audioused;
        capture.video.audioused = 0;
        /* Push avi chunk to queue */
        capture.video.q.push(chunk);
                //LOG_MSG("threads %d",thread_count);
        /* If queue exceeds size limit, wait for capture thread to empty queue */
        if (capture.video.q.size()>MAX_QUEUE_SIZE) {
                    //LOG_MSG("queue size %d -> Writing video to disk. Please wait...",capture.video.q.size());
                    SDL_WaitThread(video_thread,NULL);
        }
        /* If thread is not already running, start it */
        if (!capture.video.thread_running){
                    capture.video.thread_running=1;
                    video_thread = SDL_CreateThread(CAPTURE_VideoThread, (void*)&capture.video);}
#else
        /* Compress frame directly (no thread) */
        chunk.videobuf    = data;
        chunk.audiobuf    = (Bit16s*)&capture.video.audiobuf;
        chunk.audioused    = capture.video.audioused;
        chunk.pal        = pal;
        capture.video.audioused = 0;
        CAPTURE_VideoCompressFrame(&capture.video,chunk);
#endif
    }
#endif
    return;
}

#if (C_SSHOT)
static void CAPTURE_ScreenShotEvent(bool pressed) {
    if (!pressed)
        return;
    CaptureState |= CAPTURE_IMAGE;
}
#endif


/* WAV capturing */
static Bit8u wavheader[]={
    'R','I','F','F',    0x0,0x0,0x0,0x0,        /* Bit32u Riff Chunk ID /  Bit32u riff size */
    'W','A','V','E',    'f','m','t',' ',        /* Bit32u Riff Format  / Bit32u fmt chunk id */
    0x10,0x0,0x0,0x0,    0x1,0x0,0x2,0x0,        /* Bit32u fmt size / Bit16u encoding/ Bit16u channels */
    0x0,0x0,0x0,0x0,    0x0,0x0,0x0,0x0,        /* Bit32u freq / Bit32u byterate */
    0x4,0x0,0x10,0x0,    'd','a','t','a',        /* Bit16u byte-block / Bit16u bits / Bit16u data chunk id */
    0x0,0x0,0x0,0x0,                            /* Bit32u data size */
};

void CAPTURE_AddWave(Bit32u freq, Bit32u len, Bit16s * data) {
#if (C_SSHOT)
    if (CaptureState & CAPTURE_VIDEO) {
        Bitu left = WAVE_BUF - capture.video.audioused;
        if (left > len)
            left = len;
        memcpy( &capture.video.audiobuf[capture.video.audioused], data, left*4);
        capture.video.audioused += left;
        capture.video.audiorate = freq;
    }
#endif
    if (CaptureState & CAPTURE_WAVE) {
        if (!capture.wave.handle) {
            capture.wave.handle=OpenCaptureFile("Wave Output",".wav");
            if (!capture.wave.handle) {
                CaptureState &= ~CAPTURE_WAVE;
                return;
            }
            capture.wave.length = 0;
            capture.wave.used = 0;
            capture.wave.freq = freq;
            fwrite(wavheader,1,sizeof(wavheader),capture.wave.handle);
        }
        Bit16s * read = data;
        while (len > 0 ) {
            Bitu left = WAVE_BUF - capture.wave.used;
            if (!left) {
                fwrite(capture.wave.buf,1,4*WAVE_BUF,capture.wave.handle);
                capture.wave.length += 4*WAVE_BUF;
                capture.wave.used = 0;
                left = WAVE_BUF;
            }
            if (left > len)
                left = len;
            memcpy( &capture.wave.buf[capture.wave.used], read, left*4);
            capture.wave.used += left;
            read += left*2;
            len -= left;
        }
    }
}

static void CAPTURE_WaveEvent(bool pressed) {
    if (!pressed)
        return;
    /* Check for previously opened wave file */
    if (capture.wave.handle) {
        LOG_MSG("Stopped capturing wave output.");
        /* Write last piece of audio in buffer */
        fwrite(capture.wave.buf,1,capture.wave.used*4,capture.wave.handle);
        capture.wave.length+=capture.wave.used*4;
        /* Fill in the header with useful information */
        host_writed(&wavheader[0x04],capture.wave.length+sizeof(wavheader)-8);
        host_writed(&wavheader[0x18],capture.wave.freq);
        host_writed(&wavheader[0x1C],capture.wave.freq*4);
        host_writed(&wavheader[0x28],capture.wave.length);
        fseek(capture.wave.handle,0,0);
        fwrite(wavheader,1,sizeof(wavheader),capture.wave.handle);
        fclose(capture.wave.handle);
        capture.wave.handle=0;
        CaptureState |= CAPTURE_WAVE;
    } 
    CaptureState ^= CAPTURE_WAVE;
}

/* MIDI capturing */

static Bit8u midi_header[]={
    'M','T','h','d',            /* Bit32u, Header Chunk */
    0x0,0x0,0x0,0x6,            /* Bit32u, Chunk Length */
    0x0,0x0,                    /* Bit16u, Format, 0=single track */
    0x0,0x1,                    /* Bit16u, Track Count, 1 track */
    0x01,0xf4,                    /* Bit16u, Timing, 2 beats/second with 500 frames */
    'M','T','r','k',            /* Bit32u, Track Chunk */
    0x0,0x0,0x0,0x0,            /* Bit32u, Chunk Length */
    //Track data
};


static void RawMidiAdd(Bit8u data) {
    capture.midi.buffer[capture.midi.used++]=data;
    if (capture.midi.used >= MIDI_BUF ) {
        capture.midi.done += capture.midi.used;
        fwrite(capture.midi.buffer,1,MIDI_BUF,capture.midi.handle);
        capture.midi.used = 0;
    }
}

static void RawMidiAddNumber(Bit32u val) {
    if (val & 0xfe00000) RawMidiAdd((Bit8u)(0x80|((val >> 21) & 0x7f)));
    if (val & 0xfffc000) RawMidiAdd((Bit8u)(0x80|((val >> 14) & 0x7f)));
    if (val & 0xfffff80) RawMidiAdd((Bit8u)(0x80|((val >> 7) & 0x7f)));
    RawMidiAdd((Bit8u)(val & 0x7f));
}

void CAPTURE_AddMidi(bool sysex, Bitu len, Bit8u * data) {
    if (!capture.midi.handle) {
        capture.midi.handle=OpenCaptureFile("Raw Midi",".mid");
        if (!capture.midi.handle) {
            return;
        }
        fwrite(midi_header,1,sizeof(midi_header),capture.midi.handle);
        capture.midi.last=PIC_Ticks;
    }
    Bit32u delta=PIC_Ticks-capture.midi.last;
    capture.midi.last=PIC_Ticks;
    RawMidiAddNumber(delta);
    if (sysex) {
        RawMidiAdd( 0xf0 );
        RawMidiAddNumber( len );
    }
    for (Bitu i=0;i<len;i++) 
        RawMidiAdd(data[i]);
}

static void CAPTURE_MidiEvent(bool pressed) {
    if (!pressed)
        return;
    /* Check for previously opened wave file */
    if (capture.midi.handle) {
        LOG_MSG("Stopping raw midi saving and finalizing file.");
        //Delta time
        RawMidiAdd(0x00);
        //End of track event
        RawMidiAdd(0xff);
        RawMidiAdd(0x2F);
        RawMidiAdd(0x00);
        /* clear out the final data in the buffer if any */
        fwrite(capture.midi.buffer,1,capture.midi.used,capture.midi.handle);
        capture.midi.done+=capture.midi.used;
        fseek(capture.midi.handle,18, SEEK_SET);
        Bit8u size[4];
        size[0]=(Bit8u)(capture.midi.done >> 24);
        size[1]=(Bit8u)(capture.midi.done >> 16);
        size[2]=(Bit8u)(capture.midi.done >> 8);
        size[3]=(Bit8u)(capture.midi.done >> 0);
        fwrite(&size,1,4,capture.midi.handle);
        fclose(capture.midi.handle);
        capture.midi.handle=0;
        CaptureState &= ~CAPTURE_MIDI;
        return;
    } 
    CaptureState ^= CAPTURE_MIDI;
    if (CaptureState & CAPTURE_MIDI) {
        LOG_MSG("Preparing for raw midi capture, will start with first data.");
        capture.midi.used=0;
        capture.midi.done=0;
        capture.midi.handle=0;
    } else {
        LOG_MSG("Stopped capturing raw midi before any data arrived.");
    }
}

class HARDWARE:public Module_base{
public:
    HARDWARE(Section* configuration):Module_base(configuration){
        Section_prop * section = static_cast<Section_prop *>(configuration);
        Prop_path* proppath= section->Get_path("captures");
        capturedir = proppath->realpath;
        CaptureState = 0;
        MAPPER_AddHandler(CAPTURE_WaveEvent,MK_f6,MMOD1,"recwave","Rec Wave");
        MAPPER_AddHandler(CAPTURE_MidiEvent,MK_f8,MMOD1|MMOD2,"caprawmidi","Cap MIDI");
#if (C_SSHOT)
        MAPPER_AddHandler(CAPTURE_ScreenShotEvent,MK_f5,MMOD1,"scrshot","Screenshot");
        MAPPER_AddHandler(CAPTURE_VideoEvent,MK_f5,MMOD1|MMOD2,"video","Video");
#endif
    }
    ~HARDWARE(){
        if (capture.wave.handle) CAPTURE_WaveEvent(true);
        if (capture.midi.handle) CAPTURE_MidiEvent(true);
    }
};

static HARDWARE* test;

void HARDWARE_Destroy(Section * sec) {
    delete test;
}

void HARDWARE_Init(Section * sec) {
    test = new HARDWARE(sec);
    sec->AddDestroyFunction(&HARDWARE_Destroy,true);
}

patch de kekko (l'enregistrement video se fait dans un SDL_Thread) :

diff --git a/hardware.cpp b/hardware.cpp
index 42570b2..e69b392 100644
--- a/hardware.cpp
+++ b/hardware.cpp
@@ -32,8 +32,21 @@
 #include "cross.h"
 
 #if (C_SSHOT)
+
+#define C_THREADED_CAPTURE 1
+
 #include <png.h>
 #include "../libs/zmbv/zmbv.cpp"
+
+#if (C_THREADED_CAPTURE)
+#define MAX_QUEUE_SIZE 400
+
+#include "SDL.h"
+#include <queue>
+
+SDL_Thread *video_thread;
+#endif
+
 #endif
 
 static std::string capturedir;
@@ -44,6 +57,41 @@ Bitu CaptureState;
 #define MIDI_BUF 4*1024
 #define AVI_HEADER_SIZE    500
 
+#if (C_SSHOT)
+typedef struct {
+    Bit16s        *audiobuf;
+    Bitu        audioused;
+    Bit8u        *videobuf;
+    Bit8u        *pal;
+} video_chunk_t;
+
+typedef struct {
+    FILE        *handle;
+    Bitu        frames;
+    Bit16s        audiobuf[WAVE_BUF][2];
+    Bitu        audioused;
+    Bitu        audiorate;
+    Bitu        audiowritten;
+    VideoCodec    *codec;
+    Bitu        width, height, bpp;
+    Bitu        written;
+    float        fps;
+    int            bufSize;
+    void        *buf;
+    Bit8u        *index;
+    Bitu        indexsize, indexused;
+    Bitu        flags;
+    Bitu        pitch;
+    zmbv_format_t format;
+    bool        thread_running;
+
+#if (C_THREADED_CAPTURE)
+    std::queue<video_chunk_t> q;
+#endif
+
+} video_capture_t;
+#endif
+
 static struct {
     struct {
         FILE * handle;
@@ -62,22 +110,7 @@ static struct {
         Bitu rowlen;
     } image;
 #if (C_SSHOT)
-    struct {
-        FILE        *handle;
-        Bitu        frames;
-        Bit16s        audiobuf[WAVE_BUF][2];
-        Bitu        audioused;
-        Bitu        audiorate;
-        Bitu        audiowritten;
-        VideoCodec    *codec;
-        Bitu        width, height, bpp;
-        Bitu        written;
-        float        fps;
-        int            bufSize;
-        void        *buf;
-        Bit8u        *index;
-        Bitu        indexsize, indexused;
-    } video;
+    video_capture_t video;
 #endif
 } capture;
 
@@ -158,9 +191,6 @@ static void CAPTURE_AddAviChunk(const char * tag, Bit32u size, void * data, Bit3
     host_writed(index+8, pos);
     host_writed(index+12, size);
 }
-#endif
-
-#if (C_SSHOT)
 
 static void CAPTURE_VideoHeader() {
         Bit8u avi_header[AVI_HEADER_SIZE];
@@ -287,27 +317,139 @@ static void CAPTURE_VideoHeader() {
         fseek(capture.video.handle, save_pos, SEEK_SET);
 }
 
+
 static void CAPTURE_VideoEvent(bool pressed) {
     if (!pressed)
         return;
     if (CaptureState & CAPTURE_VIDEO) {
+
         /* Close the video */
         CaptureState &= ~CAPTURE_VIDEO;
-        LOG_MSG("Stopped capturing video.");    
 
+#if (C_THREADED_CAPTURE)
+        /* Waits for thread to finish */
+        if (capture.video.thread_running) {
+            LOG_MSG("Finalizing video. Please wait...");
+            SDL_WaitThread(video_thread,NULL);
+        }
+#endif
         /* Adds AVI header to the file */
         CAPTURE_VideoHeader();
 
+        /* Close video file and free memory */
         fclose( capture.video.handle );
         free( capture.video.index );
         free( capture.video.buf );
         delete capture.video.codec;
         capture.video.handle = 0;
+
+        LOG_MSG("Stopped capturing video.");
+
     } else {
-        CaptureState |= CAPTURE_VIDEO;
+        if (!capture.video.thread_running)
+            CaptureState |= CAPTURE_VIDEO;
     }
 }
-#endif
+
+int CAPTURE_VideoCompressFrame(video_capture_t *videohandle, video_chunk_t chunk) {
+    Bit8u doubleRow[SCALER_MAXWIDTH*4];
+    Bitu countWidth = videohandle->width;
+    int codecFlags;
+
+    if (videohandle->frames % 300 == 0)
+        codecFlags = 1;
+    else codecFlags = 0;
+    if (!videohandle->codec->PrepareCompressFrame( codecFlags, videohandle->format, (char *)chunk.pal, videohandle->buf, videohandle->bufSize))
+    {
+        CAPTURE_VideoEvent(TRUE);
+        return 1;
+    }
+
+    for (Bit32u i=0;i<videohandle->height;i++) {
+        void * rowPointer;
+        if (videohandle->flags & CAPTURE_FLAG_DBLW) {
+            void *srcLine;
+            Bitu x;
+            Bitu countWidth = videohandle->width >> 1;
+            if (videohandle->flags & CAPTURE_FLAG_DBLH)
+                srcLine=(chunk.videobuf+(i >> 1)*videohandle->pitch);
+            else
+                srcLine=(chunk.videobuf+(i >> 0)*videohandle->pitch);
+            switch ( videohandle->bpp) {
+            case 8:
+                for (x=0;x<countWidth;x++)
+                    ((Bit8u *)doubleRow)[x*2+0] =
+                    ((Bit8u *)doubleRow)[x*2+1] = ((Bit8u *)srcLine)[x];
+                break;
+            case 15:
+            case 16:
+                for (x=0;x<countWidth;x++)
+                    ((Bit16u *)doubleRow)[x*2+0] =
+                    ((Bit16u *)doubleRow)[x*2+1] = ((Bit16u *)srcLine)[x];
+                break;
+            case 32:
+                for (x=0;x<countWidth;x++)
+                    ((Bit32u *)doubleRow)[x*2+0] =
+                    ((Bit32u *)doubleRow)[x*2+1] = ((Bit32u *)srcLine)[x];
+                break;
+            }
+            rowPointer=doubleRow;
+        } else {
+            if (videohandle->flags & CAPTURE_FLAG_DBLH)
+                rowPointer=(chunk.videobuf+(i >> 1)*videohandle->pitch);
+            else
+                rowPointer=(chunk.videobuf+(i >> 0)*videohandle->pitch);
+        }
+        videohandle->codec->CompressLines( 1, &rowPointer );
+    }
+    int written = videohandle->codec->FinishCompressFrame();
+    if (written < 0) {
+        CAPTURE_VideoEvent(TRUE);
+        return 1;
+    }
+    CAPTURE_AddAviChunk( "00dc", written, videohandle->buf, codecFlags & 1 ? 0x10 : 0x0);
+    videohandle->frames++;
+//    LOG_MSG("Frame %d video %d audio %d",videohandle->frames, written, videohandle->audioused *4 );
+
+    if ( chunk.audioused ) {
+        CAPTURE_AddAviChunk( "01wb", chunk.audioused * 4, chunk.audiobuf, 0);
+        videohandle->audiowritten = chunk.audioused*4;
+    }
+    
+    /* Adds AVI header to the file */
+    CAPTURE_VideoHeader();
+
+    return 0;
+}
+
+#if (C_THREADED_CAPTURE)
+
+int CAPTURE_VideoThread(void *videohandleptr) {
+    video_capture_t *videohandle=(video_capture_t*)videohandleptr;
+    videohandle->thread_running = true;
+    int rc = 0;
+
+    /* Process queue */
+    while (!videohandle->q.empty()) {
+//        LOG_MSG("queue size %d",videohandle->q.size());
+        /* Process a block and write it to disk */
+        if (!rc) rc = CAPTURE_VideoCompressFrame(videohandle,videohandle->q.front());
+        else CaptureState &= ~CAPTURE_VIDEO;
+        free(videohandle->q.front().videobuf);
+        free(videohandle->q.front().audiobuf);
+        free(videohandle->q.front().pal);
+        /* Delete chunk from queue */
+        videohandle->q.pop();
+    }
+
+    videohandle->thread_running = false;
+    return rc;
+}
+
+#endif // C_THREADED_CAPTURE
+
+#endif // C_SSHOT
+
 
 void CAPTURE_AddImage(Bitu width, Bitu height, Bitu bpp, Bitu pitch, Bitu flags, float fps, Bit8u * data, Bit8u * pal) {
 #if (C_SSHOT)
@@ -452,123 +594,132 @@ void CAPTURE_AddImage(Bitu width, Bitu height, Bitu bpp, Bitu pitch, Bitu flags,
     }
 skip_shot:
     if (CaptureState & CAPTURE_VIDEO) {
-        zmbv_format_t format;
-        /* Disable capturing if any of the test fails */
+
+        /* Restarts capturing if any of the test fails */
         if (capture.video.handle && (
             capture.video.width != width ||
             capture.video.height != height ||
             capture.video.bpp != bpp ||
-            capture.video.fps != fps)) 
-        {
+            capture.video.fps != fps)) {
+        
+            /* Ends current capturing */
             CAPTURE_VideoEvent(true);
+            /* Toggle video capture event */
+            CaptureState |= CAPTURE_VIDEO;
         }
-        CaptureState &= ~CAPTURE_VIDEO;
+
+        /* Choose video format */
         switch (bpp) {
-        case 8:format = ZMBV_FORMAT_8BPP;break;
-        case 15:format = ZMBV_FORMAT_15BPP;break;
-        case 16:format = ZMBV_FORMAT_16BPP;break;
-        case 32:format = ZMBV_FORMAT_32BPP;break;
+        case 8:capture.video.format = ZMBV_FORMAT_8BPP;break;
+        case 15:capture.video.format = ZMBV_FORMAT_15BPP;break;
+        case 16:capture.video.format = ZMBV_FORMAT_16BPP;break;
+        case 32:capture.video.format = ZMBV_FORMAT_32BPP;break;
         default:
-            goto skip_video;
+            CAPTURE_VideoEvent(TRUE);
+            return;
         }
+
+        /* Initialize video handle */
         if (!capture.video.handle) {
             capture.video.handle = OpenCaptureFile("Video",".avi");
-            if (!capture.video.handle)
-                goto skip_video;
+            if (!capture.video.handle) {
+                CAPTURE_VideoEvent(TRUE);
+                return;
+            }
             capture.video.codec = new VideoCodec();
-            if (!capture.video.codec)
-                goto skip_video;
-            if (!capture.video.codec->SetupCompress( width, height)) 
-                goto skip_video;
-            capture.video.bufSize = capture.video.codec->NeededSize(width, height, format);
+            if (!capture.video.codec) {
+                CAPTURE_VideoEvent(TRUE);
+                return;
+            }
+            if (!capture.video.codec->SetupCompress( width, height)) {
+                CAPTURE_VideoEvent(TRUE);
+                return;
+            }
+            capture.video.bufSize = capture.video.codec->NeededSize(width, height, capture.video.format);
             capture.video.buf = malloc( capture.video.bufSize );
-            if (!capture.video.buf)
-                goto skip_video;
+            if (!capture.video.buf) {
+                CAPTURE_VideoEvent(TRUE);
+                return;
+            }
             capture.video.index = (Bit8u*)malloc( 16*4096 );
-            if (!capture.video.buf)
-                goto skip_video;
+            if (!capture.video.index) {
+                CAPTURE_VideoEvent(TRUE);
+                return;
+            }
             capture.video.indexsize = 16*4096;
             capture.video.indexused = 8;
 
             capture.video.width = width;
             capture.video.height = height;
+            capture.video.pitch = pitch;
+            capture.video.flags = flags;
             capture.video.bpp = bpp;
             capture.video.fps = fps;
-            for (i=0;i<AVI_HEADER_SIZE;i++)
+            for (int i=0;i<AVI_HEADER_SIZE;i++)
                 fputc(0,capture.video.handle);
             capture.video.frames = 0;
             capture.video.written = 0;
             capture.video.audioused = 0;
             capture.video.audiowritten = 0;
+            capture.video.thread_running = false;
+
         }
-        int codecFlags;
-        if (capture.video.frames % 300 == 0)
-            codecFlags = 1;
-        else codecFlags = 0;
-        if (!capture.video.codec->PrepareCompressFrame( codecFlags, format, (char *)pal, capture.video.buf, capture.video.bufSize))
-            goto skip_video;
 
-        for (i=0;i<height;i++) {
-            void * rowPointer;
-            if (flags & CAPTURE_FLAG_DBLW) {
-                void *srcLine;
-                Bitu x;
-                Bitu countWidth = width >> 1;
-                if (flags & CAPTURE_FLAG_DBLH)
-                    srcLine=(data+(i >> 1)*pitch);
-                else
-                    srcLine=(data+(i >> 0)*pitch);
-                switch ( bpp) {
-                case 8:
-                    for (x=0;x<countWidth;x++)
-                        ((Bit8u *)doubleRow)[x*2+0] =
-                        ((Bit8u *)doubleRow)[x*2+1] = ((Bit8u *)srcLine)[x];
-                    break;
-                case 15:
-                case 16:
-                    for (x=0;x<countWidth;x++)
-                        ((Bit16u *)doubleRow)[x*2+0] =
-                        ((Bit16u *)doubleRow)[x*2+1] = ((Bit16u *)srcLine)[x];
-                    break;
-                case 32:
-                    for (x=0;x<countWidth;x++)
-                        ((Bit32u *)doubleRow)[x*2+0] =
-                        ((Bit32u *)doubleRow)[x*2+1] = ((Bit32u *)srcLine)[x];
-                    break;
-                }
-                rowPointer=doubleRow;
-            } else {
-                if (flags & CAPTURE_FLAG_DBLH)
-                    rowPointer=(data+(i >> 1)*pitch);
-                else
-                    rowPointer=(data+(i >> 0)*pitch);
-            }
-            capture.video.codec->CompressLines( 1, &rowPointer );
+        video_chunk_t chunk;
+
+#if (C_THREADED_CAPTURE)
+        /* Create video chunk buffers */
+        chunk.videobuf = (Bit8u *)malloc(capture.video.height*capture.video.pitch);
+        if (!chunk.videobuf) {
+            CAPTURE_VideoEvent(true);
+            return;
         }
-        int written = capture.video.codec->FinishCompressFrame();
-        if (written < 0)
-            goto skip_video;
-        CAPTURE_AddAviChunk( "00dc", written, capture.video.buf, codecFlags & 1 ? 0x10 : 0x0);
-        capture.video.frames++;
-//        LOG_MSG("Frame %d video %d audio %d",capture.video.frames, written, capture.video.audioused *4 );
-        if ( capture.video.audioused ) {
-            CAPTURE_AddAviChunk( "01wb", capture.video.audioused * 4, capture.video.audiobuf, 0);
-            capture.video.audiowritten = capture.video.audioused*4;
-            capture.video.audioused = 0;
+        chunk.audiobuf = (Bit16s *)malloc(capture.video.audioused*4);
+        if (!chunk.audiobuf) {
+            CAPTURE_VideoEvent(true);
+            return;
+        }
+        chunk.pal = (Bit8u *)malloc(256*4);
+        if (!chunk.pal) {
+            CAPTURE_VideoEvent(true);
+            return;
+        }
+        /* Copy data to chunk */
+        memcpy(chunk.videobuf,data,capture.video.height*capture.video.pitch);
+        memcpy(chunk.audiobuf,&capture.video.audiobuf, capture.video.audioused*4);
+        memcpy(chunk.pal,pal,256*4);
+        chunk.audioused = capture.video.audioused;
+        capture.video.audioused = 0;
+
+        /* Push avi chunk to queue */
+        capture.video.q.push(chunk);
+
+        /* If queue exceeds size limit, wait for capture thread to empty queue */
+        if (capture.video.q.size()>MAX_QUEUE_SIZE) {
+            LOG_MSG("Writing video to disk. Please wait...");
+            SDL_WaitThread(video_thread,NULL);
         }
 
-        /* Adds AVI header to the file */
-        CAPTURE_VideoHeader();
+        /* If thread is not already running, start it */
+        if (!capture.video.thread_running)
+            video_thread = SDL_CreateThread(CAPTURE_VideoThread, (void*)&capture.video);
+
+#else
+        /* Compress frame directly (no thread) */
+        chunk.videobuf    = data;
+        chunk.audiobuf    = (Bit16s*)&capture.video.audiobuf;
+        chunk.audioused    = capture.video.audioused;
+        chunk.pal        = pal;
+        capture.video.audioused = 0;
+        CAPTURE_VideoCompressFrame(&capture.video,chunk);
+#endif
 
-        /* Everything went okay, set flag again for next frame */
-        CaptureState |= CAPTURE_VIDEO;
     }
-skip_video:
+
 #endif
     return;
 }
 
-
 #if (C_SSHOT)
 static void CAPTURE_ScreenShotEvent(bool pressed) {
     if (!pressed)

[mon code quick & dirty où j'utilise une variable globale..] 14 FPS au lieu de 70 FPS :

diff --git a/hardware.cpp b/hardware.cpp
index e69b392..97c826a 100644
--- a/hardware.cpp
+++ b/hardware.cpp
@@ -40,6 +40,7 @@
 
 #if (C_THREADED_CAPTURE)
 #define MAX_QUEUE_SIZE 400
+int secframescount=0;
 
 #include "SDL.h"
 #include <queue>
@@ -209,10 +210,9 @@ static void CAPTURE_VideoHeader() {
         main_list = header_pos;
         AVIOUTd(0);                            // TODO size of list
         AVIOUT4("hdrl");
-
         AVIOUT4("avih");
         AVIOUTd(56);                         /* # of bytes to follow */
-        AVIOUTd((Bit32u)(1000000 / capture.video.fps));       /* Microseconds per frame */
+        AVIOUTd((Bit32u)(1000000 / capture.video.fps*0.2));       /* Microseconds per frame */
         AVIOUTd(0);
         AVIOUTd(0);                         /* PaddingGranularity (whatever that might be) */
         AVIOUTd(0x110);                     /* Flags,0x10 has index, 0x100 interleaved */
@@ -226,13 +226,12 @@ static void CAPTURE_VideoHeader() {
         AVIOUTd(0);                         /* DataRate:   Data rate of playback     */
         AVIOUTd(0);                         /* StartTime:  Starting time of AVI data */
         AVIOUTd(0);                         /* DataLength: Size of AVI data chunk    */
-
         /* Video stream list */
         AVIOUT4("LIST");
         AVIOUTd(4 + 8 + 56 + 8 + 40);       /* Size of the list */
         AVIOUT4("strl");
         /* video stream header */
-        AVIOUT4("strh");
+                AVIOUT4("strh");
         AVIOUTd(56);                        /* # of bytes to follow */
         AVIOUT4("vids");                    /* Type */
         AVIOUT4(CODEC_4CC);                    /* Handler */
@@ -240,7 +239,7 @@ static void CAPTURE_VideoHeader() {
         AVIOUTd(0);                         /* Reserved, MS says: wPriority, wLanguage */
         AVIOUTd(0);                         /* InitialFrames */
         AVIOUTd(1000000);                   /* Scale */
-        AVIOUTd((Bit32u)(1000000 * capture.video.fps));              /* Rate: Rate/Scale == samples/second */
+        AVIOUTd((Bit32u)(1000000 * capture.video.fps*0.2));              /* Rate: Rate/Scale == samples/second */
         AVIOUTd(0);                         /* Start */
         AVIOUTd(capture.video.frames);      /* Length */
         AVIOUTd(0);                  /* SuggestedBufferSize */
@@ -262,7 +261,6 @@ static void CAPTURE_VideoHeader() {
         AVIOUTd(0);                  /* YPelsPerMeter */
         AVIOUTd(0);                  /* ClrUsed: Number of colors used */
         AVIOUTd(0);                  /* ClrImportant: Number of colors important */
-
         /* Audio stream list */
         AVIOUT4("LIST");
         AVIOUTd(4 + 8 + 56 + 8 + 16);  /* Length of list in bytes */
@@ -297,7 +295,6 @@ static void CAPTURE_VideoHeader() {
         AVIOUTw(16);            /* BitsPerSample */
         int nmain = header_pos - main_list - 4;
         /* Finish stream list, i.e. put number of bytes in the list to proper pos */
-
         int njunk = AVI_HEADER_SIZE - 8 - 12 - header_pos;
         AVIOUT4("JUNK");
         AVIOUTd(njunk);
@@ -335,91 +332,88 @@ static void CAPTURE_VideoEvent(bool pressed) {
 #endif
         /* Adds AVI header to the file */
         CAPTURE_VideoHeader();
-
         /* Close video file and free memory */
         fclose( capture.video.handle );
         free( capture.video.index );
         free( capture.video.buf );
         delete capture.video.codec;
         capture.video.handle = 0;
-
         LOG_MSG("Stopped capturing video.");
-
     } else {
         if (!capture.video.thread_running)
             CaptureState |= CAPTURE_VIDEO;
     }
 }
 
-int CAPTURE_VideoCompressFrame(video_capture_t *videohandle, video_chunk_t chunk) {
-    Bit8u doubleRow[SCALER_MAXWIDTH*4];
-    Bitu countWidth = videohandle->width;
-    int codecFlags;
-
-    if (videohandle->frames % 300 == 0)
-        codecFlags = 1;
-    else codecFlags = 0;
-    if (!videohandle->codec->PrepareCompressFrame( codecFlags, videohandle->format, (char *)chunk.pal, videohandle->buf, videohandle->bufSize))
-    {
-        CAPTURE_VideoEvent(TRUE);
-        return 1;
-    }
-
-    for (Bit32u i=0;i<videohandle->height;i++) {
-        void * rowPointer;
-        if (videohandle->flags & CAPTURE_FLAG_DBLW) {
-            void *srcLine;
-            Bitu x;
-            Bitu countWidth = videohandle->width >> 1;
-            if (videohandle->flags & CAPTURE_FLAG_DBLH)
-                srcLine=(chunk.videobuf+(i >> 1)*videohandle->pitch);
-            else
-                srcLine=(chunk.videobuf+(i >> 0)*videohandle->pitch);
-            switch ( videohandle->bpp) {
-            case 8:
-                for (x=0;x<countWidth;x++)
-                    ((Bit8u *)doubleRow)[x*2+0] =
-                    ((Bit8u *)doubleRow)[x*2+1] = ((Bit8u *)srcLine)[x];
-                break;
-            case 15:
-            case 16:
-                for (x=0;x<countWidth;x++)
-                    ((Bit16u *)doubleRow)[x*2+0] =
-                    ((Bit16u *)doubleRow)[x*2+1] = ((Bit16u *)srcLine)[x];
-                break;
-            case 32:
-                for (x=0;x<countWidth;x++)
-                    ((Bit32u *)doubleRow)[x*2+0] =
-                    ((Bit32u *)doubleRow)[x*2+1] = ((Bit32u *)srcLine)[x];
-                break;
-            }
-            rowPointer=doubleRow;
-        } else {
-            if (videohandle->flags & CAPTURE_FLAG_DBLH)
-                rowPointer=(chunk.videobuf+(i >> 1)*videohandle->pitch);
-            else
-                rowPointer=(chunk.videobuf+(i >> 0)*videohandle->pitch);
-        }
-        videohandle->codec->CompressLines( 1, &rowPointer );
-    }
-    int written = videohandle->codec->FinishCompressFrame();
-    if (written < 0) {
-        CAPTURE_VideoEvent(TRUE);
-        return 1;
-    }
-    CAPTURE_AddAviChunk( "00dc", written, videohandle->buf, codecFlags & 1 ? 0x10 : 0x0);
-    videohandle->frames++;
-//    LOG_MSG("Frame %d video %d audio %d",videohandle->frames, written, videohandle->audioused *4 );
-
-    if ( chunk.audioused ) {
-        CAPTURE_AddAviChunk( "01wb", chunk.audioused * 4, chunk.audiobuf, 0);
-        videohandle->audiowritten = chunk.audioused*4;
-    }
-    
-    /* Adds AVI header to the file */
-    CAPTURE_VideoHeader();
 
-    return 0;
+int CAPTURE_VideoCompressFrame(video_capture_t *videohandle, video_chunk_t chunk) {
+    secframescount++;
+    if(secframescount==11)
+        secframescount=1;
+    if(secframescount==1||secframescount==6){
+            Bit8u doubleRow[SCALER_MAXWIDTH*4];
+            int codecFlags;
+            if (videohandle->frames % 300 == 0)
+                    codecFlags = 1;
+            else codecFlags = 0;
+            if (!videohandle->codec->PrepareCompressFrame( codecFlags, videohandle->format, (char *)chunk.pal, videohandle->buf, videohandle->bufSize))
+            {
+                    CAPTURE_VideoEvent(true);
+                    return 1;
+            }
+            for (Bit32u i=0;i<videohandle->height;i++) {
+                    void * rowPointer;
+                    if (videohandle->flags & CAPTURE_FLAG_DBLW) {
+                            void *srcLine;
+                            Bitu x;
+                            Bitu countWidth = videohandle->width >> 1;
+                            if (videohandle->flags & CAPTURE_FLAG_DBLH)
+                                    srcLine=(chunk.videobuf+(i >> 1)*videohandle->pitch);
+                            else
+                                    srcLine=(chunk.videobuf+(i >> 0)*videohandle->pitch);
+                            switch ( videohandle->bpp) {
+                            case 8:
+                                    for (x=0;x<countWidth;x++)
+                                            ((Bit8u *)doubleRow)[x*2+0] =
+                                            ((Bit8u *)doubleRow)[x*2+1] = ((Bit8u *)srcLine)[x];
+                                    break;
+                            case 15:
+                            case 16:
+                                    for (x=0;x<countWidth;x++)
+                                            ((Bit16u *)doubleRow)[x*2+0] =
+                                            ((Bit16u *)doubleRow)[x*2+1] = ((Bit16u *)srcLine)[x];
+                                    break;
+                            case 32:
+                                    for (x=0;x<countWidth;x++)
+                                            ((Bit32u *)doubleRow)[x*2+0] =
+                                            ((Bit32u *)doubleRow)[x*2+1] = ((Bit32u *)srcLine)[x];
+                                    break;
+                            }
+                rowPointer=doubleRow;
+                    } else {
+                            if (videohandle->flags & CAPTURE_FLAG_DBLH)
+                                    rowPointer=(chunk.videobuf+(i >> 1)*videohandle->pitch);
+                            else
+                                    rowPointer=(chunk.videobuf+(i >> 0)*videohandle->pitch);
+                    }
+                    videohandle->codec->CompressLines( 1, &rowPointer );
+            }
+            int written = videohandle->codec->FinishCompressFrame();
+            if (written < 0) {
+                    CAPTURE_VideoEvent(true);
+                    return 1;
+            }
+            CAPTURE_AddAviChunk( "00dc", written, videohandle->buf, codecFlags & 1 ? 0x10 : 0x0);
+            videohandle->frames++;
+            //LOG_MSG("Frame %d video %d audio %d",videohandle->frames, written, videohandle->audioused *4 );
+    }
+    if ( chunk.audioused ) {
+        CAPTURE_AddAviChunk( "01wb", chunk.audioused * 4, chunk.audiobuf, 0);
+        videohandle->audiowritten = chunk.audioused*4;
+    }
+    /* Adds AVI header to the file */
+    CAPTURE_VideoHeader();
+    return 0;
 }
 
 #if (C_THREADED_CAPTURE)

Premier crash-fix (plein de threads concurrents : DOSBox crash très vite) :

diff --git a/hardware.cpp b/hardware.cpp
index 97c826a..4eed500 100644
--- a/hardware.cpp
+++ b/hardware.cpp
@@ -45,7 +45,7 @@ int secframescount=0;
 #include "SDL.h"
 #include <queue>
 
-SDL_Thread *video_thread;
+SDL_Thread *video_thread=NULL;
 #endif
 
 #endif
@@ -84,7 +84,7 @@ typedef struct {
     Bitu        flags;
     Bitu        pitch;
     zmbv_format_t format;
-    bool        thread_running;
+    int        thread_running;
 
 #if (C_THREADED_CAPTURE)
     std::queue<video_chunk_t> q;
@@ -120,7 +120,6 @@ FILE * OpenCaptureFile(const char * type,const char * ext) {
         LOG_MSG("Please specify a capture directory");
         return 0;
     }
-
     Bitu last=0;
     char file_start[16];
     dir_information * dir;
@@ -167,7 +166,6 @@ FILE * OpenCaptureFile(const char * type,const char * ext) {
 #if (C_SSHOT)
 static void CAPTURE_AddAviChunk(const char * tag, Bit32u size, void * data, Bit32u flags) {
     Bit8u chunk[8];Bit8u *index;Bit32u pos, writesize;
-
     chunk[0] = tag[0];chunk[1] = tag[1];chunk[2] = tag[2];chunk[3] = tag[3];
     host_writed(&chunk[4], size);   
     /* Write the actual data */
@@ -198,7 +196,6 @@ static void CAPTURE_VideoHeader() {
         Bitu main_list;
         Bitu header_pos=0;
         Bitu save_pos=ftell(capture.video.handle);
-
 #define AVIOUT4(_S_) memcpy(&avi_header[header_pos],_S_,4);header_pos+=4;
 #define AVIOUTw(_S_) host_writew(&avi_header[header_pos], _S_);header_pos+=2;
 #define AVIOUTd(_S_) host_writed(&avi_header[header_pos], _S_);header_pos+=4;
@@ -319,10 +316,8 @@ static void CAPTURE_VideoEvent(bool pressed) {
     if (!pressed)
         return;
     if (CaptureState & CAPTURE_VIDEO) {
-
         /* Close the video */
         CaptureState &= ~CAPTURE_VIDEO;
-
 #if (C_THREADED_CAPTURE)
         /* Waits for thread to finish */
         if (capture.video.thread_running) {
@@ -418,39 +413,36 @@ int CAPTURE_VideoCompressFrame(video_capture_t *videohandle, video_chunk_t chunk
 
 #if (C_THREADED_CAPTURE)
 
-int CAPTURE_VideoThread(void *videohandleptr) {
-    video_capture_t *videohandle=(video_capture_t*)videohandleptr;
-    videohandle->thread_running = true;
+static int CAPTURE_VideoThread(void *videohandleptr) {
+        video_capture_t *videohandle=(video_capture_t*)videohandleptr;
+    //videohandle->thread_running = true;
     int rc = 0;
-
     /* Process queue */
     while (!videohandle->q.empty()) {
-//        LOG_MSG("queue size %d",videohandle->q.size());
-        /* Process a block and write it to disk */
-        if (!rc) rc = CAPTURE_VideoCompressFrame(videohandle,videohandle->q.front());
-        else CaptureState &= ~CAPTURE_VIDEO;
-        free(videohandle->q.front().videobuf);
-        free(videohandle->q.front().audiobuf);
-        free(videohandle->q.front().pal);
-        /* Delete chunk from queue */
-        videohandle->q.pop();
+            //LOG_MSG("queue size %d",videohandle->q.size());
+            /* Process a block and write it to disk */
+            //LOG_MSG("%d",videohandle->q.size());
+            if (!rc) rc = CAPTURE_VideoCompressFrame(videohandle,videohandle->q.front());
+            else CaptureState &= ~CAPTURE_VIDEO;
+            free(videohandle->q.front().videobuf);
+            free(videohandle->q.front().audiobuf);
+            free(videohandle->q.front().pal);
+            /* Delete chunk from queue */
+            videohandle->q.pop();
     }
-
-    videohandle->thread_running = false;
-    return rc;
+    //videohandle->thread_running = false;
+    return videohandle->thread_running=0;
 }
 
 #endif // C_THREADED_CAPTURE
 
 #endif // C_SSHOT
 
-
 void CAPTURE_AddImage(Bitu width, Bitu height, Bitu bpp, Bitu pitch, Bitu flags, float fps, Bit8u * data, Bit8u * pal) {
 #if (C_SSHOT)
     Bitu i;
     Bit8u doubleRow[SCALER_MAXWIDTH*4];
     Bitu countWidth = width;
-
     if (flags & CAPTURE_FLAG_DBLH)
         height *= 2;
     if (flags & CAPTURE_FLAG_DBLW)
@@ -460,12 +452,10 @@ void CAPTURE_AddImage(Bitu width, Bitu height, Bitu bpp, Bitu pitch, Bitu flags,
         return;
     if (width > SCALER_MAXWIDTH)
         return;
-    
     if (CaptureState & CAPTURE_IMAGE) {
         png_structp png_ptr;
         png_infop info_ptr;
         png_color palette[256];
-
         CaptureState &= ~CAPTURE_IMAGE;
         /* Open the actual file */
         FILE * fp=OpenCaptureFile("Screenshot",".png");
@@ -478,18 +468,15 @@ void CAPTURE_AddImage(Bitu width, Bitu height, Bitu bpp, Bitu pitch, Bitu flags,
             png_destroy_write_struct(&png_ptr,(png_infopp)NULL);
             goto skip_shot;
         }
-    
         /* Finalize the initing of png library */
         png_init_io(png_ptr, fp);
         png_set_compression_level(png_ptr,Z_BEST_COMPRESSION);
-        
         /* set other zlib parameters */
         png_set_compression_mem_level(png_ptr, 8);
         png_set_compression_strategy(png_ptr,Z_DEFAULT_STRATEGY);
         png_set_compression_window_bits(png_ptr, 15);
         png_set_compression_method(png_ptr, 8);
         png_set_compression_buffer_size(png_ptr, 8192);
-    
         if (bpp==8) {
             png_set_IHDR(png_ptr, info_ptr, width, height,
                 8, PNG_COLOR_TYPE_PALETTE, PNG_INTERLACE_NONE,
@@ -588,20 +575,17 @@ void CAPTURE_AddImage(Bitu width, Bitu height, Bitu bpp, Bitu pitch, Bitu flags,
     }
 skip_shot:
     if (CaptureState & CAPTURE_VIDEO) {
-
         /* Restarts capturing if any of the test fails */
         if (capture.video.handle && (
             capture.video.width != width ||
             capture.video.height != height ||
             capture.video.bpp != bpp ||
             capture.video.fps != fps)) {
-        
             /* Ends current capturing */
             CAPTURE_VideoEvent(true);
             /* Toggle video capture event */
             CaptureState |= CAPTURE_VIDEO;
         }
-
         /* Choose video format */
         switch (bpp) {
         case 8:capture.video.format = ZMBV_FORMAT_8BPP;break;
@@ -609,35 +593,34 @@ skip_shot:
         case 16:capture.video.format = ZMBV_FORMAT_16BPP;break;
         case 32:capture.video.format = ZMBV_FORMAT_32BPP;break;
         default:
-            CAPTURE_VideoEvent(TRUE);
+            CAPTURE_VideoEvent(true);
             return;
         }
-
         /* Initialize video handle */
         if (!capture.video.handle) {
             capture.video.handle = OpenCaptureFile("Video",".avi");
             if (!capture.video.handle) {
-                CAPTURE_VideoEvent(TRUE);
+                CAPTURE_VideoEvent(true);
                 return;
             }
             capture.video.codec = new VideoCodec();
             if (!capture.video.codec) {
-                CAPTURE_VideoEvent(TRUE);
+                CAPTURE_VideoEvent(true);
                 return;
             }
             if (!capture.video.codec->SetupCompress( width, height)) {
-                CAPTURE_VideoEvent(TRUE);
+                CAPTURE_VideoEvent(true);
                 return;
             }
             capture.video.bufSize = capture.video.codec->NeededSize(width, height, capture.video.format);
             capture.video.buf = malloc( capture.video.bufSize );
             if (!capture.video.buf) {
-                CAPTURE_VideoEvent(TRUE);
+                CAPTURE_VideoEvent(true);
                 return;
             }
             capture.video.index = (Bit8u*)malloc( 16*4096 );
             if (!capture.video.index) {
-                CAPTURE_VideoEvent(TRUE);
+                CAPTURE_VideoEvent(true);
                 return;
             }
             capture.video.indexsize = 16*4096;
@@ -655,10 +638,9 @@ skip_shot:
             capture.video.written = 0;
             capture.video.audioused = 0;
             capture.video.audiowritten = 0;
-            capture.video.thread_running = false;
+            capture.video.thread_running = 0;
 
         }
-
         video_chunk_t chunk;
 
 #if (C_THREADED_CAPTURE)
@@ -684,20 +666,18 @@ skip_shot:
         memcpy(chunk.pal,pal,256*4);
         chunk.audioused = capture.video.audioused;
         capture.video.audioused = 0;
-
         /* Push avi chunk to queue */
         capture.video.q.push(chunk);
-
+                //LOG_MSG("threads %d",thread_count);
         /* If queue exceeds size limit, wait for capture thread to empty queue */
         if (capture.video.q.size()>MAX_QUEUE_SIZE) {
-            LOG_MSG("Writing video to disk. Please wait...");
-            SDL_WaitThread(video_thread,NULL);
+                    //LOG_MSG("queue size %d -> Writing video to disk. Please wait...",capture.video.q.size());
+                    SDL_WaitThread(video_thread,NULL);
         }
-
         /* If thread is not already running, start it */
-        if (!capture.video.thread_running)
-            video_thread = SDL_CreateThread(CAPTURE_VideoThread, (void*)&capture.video);
-
+        if (!capture.video.thread_running){
+                    capture.video.thread_running=1;
+                    video_thread = SDL_CreateThread(CAPTURE_VideoThread, (void*)&capture.video);}
 #else
         /* Compress frame directly (no thread) */
         chunk.videobuf    = data;
@@ -707,9 +687,7 @@ skip_shot:
         capture.video.audioused = 0;
         CAPTURE_VideoCompressFrame(&capture.video,chunk);
 #endif
-
     }
-
 #endif
     return;
 }
@@ -774,6 +752,7 @@ void CAPTURE_AddWave(Bit32u freq, Bit32u len, Bit16s * data) {
         }
     }
 }
+
 static void CAPTURE_WaveEvent(bool pressed) {
     if (!pressed)
         return;
@@ -788,7 +767,6 @@ static void CAPTURE_WaveEvent(bool pressed) {
         host_writed(&wavheader[0x18],capture.wave.freq);
         host_writed(&wavheader[0x1C],capture.wave.freq*4);
         host_writed(&wavheader[0x28],capture.wave.length);
-        
         fseek(capture.wave.handle,0,0);
         fwrite(wavheader,1,sizeof(wavheader),capture.wave.handle);
         fclose(capture.wave.handle);

Second crash-fix (plein de threads créés qui restent, utilisation de la mémoire virtuelle qui grimpe jusqu'à des dizaines de Go : crash de DOSBox au bout de ~7 minutes, système qui ne répond plus) :

diff --git a/hardware.cpp b/hardware.cpp
index 4eed500..b057536 100644
--- a/hardware.cpp
+++ b/hardware.cpp
@@ -676,6 +676,7 @@ skip_shot:
         }
         /* If thread is not already running, start it */
         if (!capture.video.thread_running){
+                                        SDL_KillThread(video_thread);
                     capture.video.thread_running=1;
                     video_thread = SDL_CreateThread(CAPTURE_VideoThread, (void*)&capture.video);}
 #else

Bref, ce que je ne comprends pas, c'est que SDL_KillThread est censé être pas propre point de vue mémoire..
Bon, tant que ça fonctionne et que je n'ai pas à y revenir, je vais pas me plaindre. tongue

edit : video test (17 minutes) big_smile
edit  2 : Une vidéo plus longue (32 minutes et 30 secondes) s'est arrêté suite à un crash de DOSBox :

glibc detected : double free or corruption (!prev)

Bon ben m'en fous, je fais pas de vidéos si longues..

Dernière modification par The Uploader (Le 26/11/2011, à 18:28)


- Oldies PC : Intel Pentium 3 @ 800 Mhz sur CM ASUS P2B-F, GeForce 4 Ti4800 SE, Disque Dur Hitachi 160 Go, 512 Mo de RAM, 3DFX Voodoo 2, Sound Blaster 16 ISA PnP, Windows 98 SE / XP)
- Desktop : Intel Core i7 6700K @ 4 GHz sur CM ASUS Z170-P, GeForce GTX 1070, SSD Samsung 850 EVO 1 To, 16 Go de RAM, Disque Dur Seagate Barracuda 3 To, Windows 10

Hors ligne

#1799 Le 26/11/2011, à 22:25

Pylades

Re : /* Topic des codeurs [6] */

tshirtman a écrit :

si ton test était inversé, on pourrait faire

wins = list(filter(check_unlist, sysapp.get_windows()))

mais bon.

Fixed, pour être Python 3 proof.


“Any if-statement is a goto. As are all structured loops.
“And sometimes structure is good. When it’s good, you should use it.
“And sometimes structure is _bad_, and gets into the way, and using a goto is just much clearer.”
                Linus Torvalds – 12 janvier 2003

Hors ligne

#1800 Le 27/11/2011, à 17:16

Elzen

Re : /* Topic des codeurs [6] */

En python 3, que renvoie filter ? Un tuple ?

Sinon, et en python 2 cette fois, existe-t-il un moyen de repérer les arguments d'une commande shell ?
Du genre, je lui passe « echo "liste des fichiers dans '$PWD' :" $(ls -A) » et ça me renvoie un tuple ou une liste contenant « echo », « liste des fichiers dans '$PWD' : » et « $(ls -A) » ?

Si en plus ça pouvait essayer d'interpréter les $, ce serait encore mieux (et donc, dans ce cas, me renvoyer ["echo", "liste des fichiers dans '.'", ".", "..", …]), mais j'n'en demande pas forcément tant ^^

Dernière modification par ArkSeth (Le 27/11/2011, à 17:17)

Hors ligne