C/C++ probleme de fuite memoire

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#1
Bonjour ,
je veux afficher une image jpg qui vien du "net" avec ma PSP en boucle (car c'est une webcam) mais je perd 400 a 800ko de memoire par boucle :
Code:
#include <pspkernel.h>
#include <oslib/oslib.h>

#include <psphttp.h>
#include <psprtc.h> 

PSP_MODULE_INFO("Net Test", 0, 1, 0);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);
PSP_HEAP_SIZE_KB(20*1024);

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Globals:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#define ADDRESS "192.168.10.90"

static int runningFlag = 1;
static OSL_IMAGE *bkg = NULL;
static char message[100] = "";
static char buffer[100] = "";

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Callbacks:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Exit callback */
int exit_callback(int arg1, int arg2, void *common) {
    runningFlag = 0;
    return 0;
}

/* Callback thread */
int CallbackThread(SceSize args, void *argp) {
    int cbid;

    cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
    sceKernelRegisterExitCallback(cbid);
    sceKernelSleepThreadCB();
    return 0;
}

/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void) {
    int thid = 0;
    thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, PSP_THREAD_ATTR_USER, 0);
    if(thid >= 0)
        sceKernelStartThread(thid, 0, 0);
    return thid;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Init OSLib:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int initOSLib(){
    oslInit(0);
    oslInitGfx(OSL_PF_8888, 1);
    oslInitAudio();
    oslSetQuitOnLoadFailure(1);
    oslSetKeyAutorepeatInit(40);
    oslSetKeyAutorepeatInterval(10);
    return 0;
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Connect to Access Point:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int connectAPCallback(int state){
    oslStartDrawing();
    oslDrawImageXY(bkg, 0, 0);
    oslDrawString(30, 200, "Connecting to AP...");
    sprintf(buffer, "State: %i", state);
    oslDrawString(30, 230, buffer);
    oslEndDrawing();
    oslEndFrame();
    oslSyncFrame();

    return 0;
}


int connectToAP(int config){
    oslStartDrawing();
    oslDrawImageXY(bkg, 0, 0);
    oslDrawString(30, 200, "Connecting to AP...");
    oslEndDrawing();
    oslEndFrame();
    oslSyncFrame();

    int result = oslConnectToAP(config, 10, connectAPCallback);
    if (!result){
 		return 1;
    }else{
        oslStartDrawing();
        oslDrawImageXY(bkg, 0, 0);
        sprintf(buffer, "Error connecting to AP!");
        oslDrawString(30, 200, buffer);
        oslEndDrawing();
        oslEndFrame();
        oslSyncFrame();
		sceKernelDelayThread(3*1000000);
    }
    //oslDisconnectFromAP();
    return 0;
}


int Net_IMG_Load(char *url, int save_MS){
   int template, connection, request, ret, status,fd;

   template = sceHttpCreateTemplate("OSL-agent/0.0.1 libhttp/1.0.0", 1, 1);
   if(template < 0) return 0;
   ret = sceHttpSetResolveTimeOut(template, 500000);
   if(ret < 0)   return 0;
   ret = sceHttpSetRecvTimeOut(template, 10000000);
   if(ret < 0)   return 0;
   ret = sceHttpSetSendTimeOut(template, 10000000);
   if(ret < 0)   return 0;
   connection = sceHttpCreateConnectionWithURL(template, url, 0);
   if(connection < 0) return 0L;
   request = sceHttpCreateRequestWithURL(connection, PSP_HTTP_METHOD_GET, (char*)url, 0);
   if(request < 0)   return 0;
   ret = sceHttpSendRequest(request, 0, 0);
   if(ret < 0)   return 0;
   ret = sceHttpGetStatusCode(request, &status);
   if(ret < 0)   return 0;
   if(status != 200) return 0;

//***merci biscottealacrevette
   SceULong64 length;
   sceHttpGetContentLength (request, &length);
   void* target = malloc((SceULong64)length);
   sceHttpReadData(request,target,(SceULong64)length);
//***
   sceHttpDeleteRequest(request); sceHttpDeleteConnection(connection);   sceHttpDeleteTemplate(template);
   free(ret);
      //Set data for the temporary file
   oslSetTempFileData(target, (SceULong64)length, &VF_MEMORY);
   //Load a JPG file using the temporary file (oslGetTempFileName to get its name)
   bkg = NULL;
   bkg = oslLoadImageFileJPG(oslGetTempFileName(), OSL_IN_RAM | OSL_SWIZZLED, OSL_PF_5650);

   if (save_MS>0) {
      char *filepath="";
      pspTime TimePSP;
      sceRtcGetCurrentClockLocalTime(&TimePSP);
      sprintf(filepath,"ms0:/PSP/PHOTO/FOX_%02dH%02dM%02dS%02dms.jpg" , TimePSP.hour , TimePSP.minutes , TimePSP.seconds , (TimePSP.microseconds>>12) & 0xff);
      fd = sceIoOpen(filepath, PSP_O_WRONLY | PSP_O_CREAT, 0777);
      sceIoWrite(fd, target, (SceULong64)length);
      sceIoClose(fd);
   }
	  free(target);
	  //free(oslSetTempFileData);
	  return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Main:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main(){
	int skip = 0;
    int enabled = 1;
    int selectedConfig = 0;
    SetupCallbacks();

    initOSLib();
    oslIntraFontInit(INTRAFONT_CACHE_MED);
    oslNetInit();

    //Loads image:
    bkg = oslLoadImageFilePNG("bkg.png", OSL_IN_RAM | OSL_SWIZZLED, OSL_PF_8888);

    //Load font:
    OSL_FONT *font = oslLoadFontFile("flash0:/font/ltn0.pgf");
    oslSetFont(font);

    if (!oslIsWlanPowerOn())
        sprintf(message, "Please turn on the WLAN.");

    //Get connections list:
    struct oslNetConfig configs[OSL_MAX_NET_CONFIGS];
    int numconfigs = oslGetNetConfigs(configs);
    if (!numconfigs){
        sprintf(message, "No configuration found!");
        enabled = 0;
    }

	int connected = 0;

    while(runningFlag && !osl_quit){
        if (!skip){
			oslStartDrawing();
			oslDrawImageXY(bkg, 0, 0);
            if (enabled){
                sprintf(buffer, "Press X to connect to %s.", configs[selectedConfig].name);
    			oslDrawString(30, 50, buffer);
    			oslDrawString(30, 80, "Press UP and DOWN to change settings.");
            }
            oslDrawString(30, 150, "Press /\\ to quit.");
			oslDrawString(30, 250, "Press () to screen.");

			sprintf(buffer, "Memory Available %iko.", oslGetRamStatus().maxAvailable/1024);
			oslDrawString(30, 100, buffer);
			oslDrawString(30, 200, message);

			oslEndDrawing();
		}
        oslEndFrame();
        skip = oslSyncFrame();

        oslReadKeys();
        if (osl_keys->released.triangle)
            runningFlag = 0;

        if (osl_keys->released.cross){

            connected = connectToAP(selectedConfig + 1);
			while (connected==0) 
			{connected = connectToAP(selectedConfig + 1);}

		}else if (osl_keys->released.circle){
			            Net_IMG_Load("http://192.168.10.90:8888/", 0);

		}else if (osl_keys->released.up){
            if (++selectedConfig >= numconfigs)
                selectedConfig = numconfigs - 1;

		}else if (osl_keys->released.down){
            if (--selectedConfig < 0)
                selectedConfig = 0;
        }
    }
    //Quit OSL:
    oslNetTerm();
    oslEndGfx();
    sceKernelExitGame();
    return 0;

}
donc tout se passe bien (pas de fuite) sauf lorsque j'appuis sur rond (circle) pour prendre un screenshot de la cam (en realité recuperer un jpg sur le serveur) ce qui lance donc ma fonction int Net_IMG_Load(char *url, int save_MS) et me fait perdre 400 a 800ko a chaque fois , avec 18Mo de ram ca va pas tres loin , je pense que la probleme vien de :
Code:
int Net_IMG_Load(char *url, int save_MS){
   int template, connection, request, ret, status,fd;

   template = sceHttpCreateTemplate("OSL-agent/0.0.1 libhttp/1.0.0", 1, 1);
   if(template < 0) return 0;
   ret = sceHttpSetResolveTimeOut(template, 500000);
   if(ret < 0)   return 0;
   ret = sceHttpSetRecvTimeOut(template, 10000000);
   if(ret < 0)   return 0;
   ret = sceHttpSetSendTimeOut(template, 10000000);
   if(ret < 0)   return 0;
   connection = sceHttpCreateConnectionWithURL(template, url, 0);
   if(connection < 0) return 0L;
   request = sceHttpCreateRequestWithURL(connection, PSP_HTTP_METHOD_GET, (char*)url, 0);
   if(request < 0)   return 0;
   ret = sceHttpSendRequest(request, 0, 0);
   if(ret < 0)   return 0;
   ret = sceHttpGetStatusCode(request, &status);
   if(ret < 0)   return 0;
   if(status != 200) return 0;

//***merci biscottealacrevette
   SceULong64 length;
   sceHttpGetContentLength (request, &length);
   void* target = malloc((SceULong64)length);
   sceHttpReadData(request,target,(SceULong64)length);
//***
   sceHttpDeleteRequest(request); sceHttpDeleteConnection(connection);   sceHttpDeleteTemplate(template);
   free(ret);
      //Set data for the temporary file
   oslSetTempFileData(target, (SceULong64)length, &VF_MEMORY);
   //Load a JPG file using the temporary file (oslGetTempFileName to get its name)
   bkg = NULL;
   bkg = oslLoadImageFileJPG(oslGetTempFileName(), OSL_IN_RAM | OSL_SWIZZLED, OSL_PF_5650);

   if (save_MS>0) {
      char *filepath="";
      pspTime TimePSP;
      sceRtcGetCurrentClockLocalTime(&TimePSP);
      sprintf(filepath,"ms0:/PSP/PHOTO/FOX_%02dH%02dM%02dS%02dms.jpg" , TimePSP.hour , TimePSP.minutes , TimePSP.seconds , (TimePSP.microseconds>>12) & 0xff);
      fd = sceIoOpen(filepath, PSP_O_WRONLY | PSP_O_CREAT, 0777);
      sceIoWrite(fd, target, (SceULong64)length);
      sceIoClose(fd);
   }
	  free(target);
	  //free(oslSetTempFileData);
	  return 0;
}
 
A

Anonymous

Invité
#2
C'est pas un truc du genre qu'il faut libérer la case mémoire du pointeur après utilisation sinon y va utiliser de plus en plus de mémoire ?

Avec un Delete tonpointeur;
 

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#3
oui en effet une connerie dans le pointeur avec target (et une autre dans la destruction de l'image) donc plus de fuite :
Code:
#include <pspkernel.h>
#include <oslib/oslib.h>

#include <psphttp.h>
#include <psprtc.h> 

PSP_MODULE_INFO("Net Test", 0, 1, 0);
PSP_MAIN_THREAD_ATTR(THREAD_ATTR_USER | THREAD_ATTR_VFPU);
PSP_HEAP_SIZE_KB(-2048);

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Globals:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

static int runningFlag = 1;
OSL_IMAGE *bkg = NULL;
static char message[100] = "";
static char buffer[100] = "";

SceULong64 length;
void* target;

char *url = "http://192.168.10.90:8888/";

int template, connexion, request, ret, status;

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Callbacks:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/* Exit callback */
int exit_callback(int arg1, int arg2, void *common) {
    runningFlag = 0;
    return 0;
}

/* Callback thread */
int CallbackThread(SceSize args, void *argp) {
    int cbid;

    cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
    sceKernelRegisterExitCallback(cbid);
    sceKernelSleepThreadCB();
    return 0;
}

/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void) {
    int thid = 0;
    thid = sceKernelCreateThread("update_thread", CallbackThread, 0x11, 0xFA0, PSP_THREAD_ATTR_USER, 0);
    if(thid >= 0)
        sceKernelStartThread(thid, 0, 0);
    return thid;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Init OSLib:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int initOSLib(){
    oslInit(0);
    oslInitGfx(OSL_PF_8888, 1);
    oslInitAudio();
    oslSetQuitOnLoadFailure(1);
    oslSetKeyAutorepeatInit(40);
    oslSetKeyAutorepeatInterval(10);
    return 0;
}


///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Connect to Access Point:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int connectAPCallback(int state){
    oslStartDrawing();
    oslDrawImageXY(bkg, 0, 0);
    oslDrawString(30, 200, "Connecting to AP...");
    sprintf(buffer, "State: %i", state);
    oslDrawString(30, 230, buffer);
    oslEndDrawing();
    oslEndFrame();
    oslSyncFrame();

    return 0;
}


int connectToAP(int config){
    oslStartDrawing();
    oslDrawImageXY(bkg, 0, 0);
    oslDrawString(30, 200, "Connecting to AP...");
    oslEndDrawing();
    oslEndFrame();
    oslSyncFrame();

    int result = oslConnectToAP(config, 10, connectAPCallback);
    if (!result){
		template = sceHttpCreateTemplate("OSL-agent/0.0.1 libhttp/1.0.0", 1, 1);if(template < 0) return 0;
		connexion = sceHttpCreateConnectionWithURL(template, url, 0);if(connexion < 0) return 0;
		return 1;
    }else{
        oslStartDrawing();
        oslDrawImageXY(bkg, 0, 0);
        sprintf(buffer, "Error connecting to AP!");
        oslDrawString(30, 200, buffer);
        oslEndDrawing();
        oslEndFrame();
        oslSyncFrame();
		sceKernelDelayThread(3*1000000);
    }
    //oslDisconnectFromAP();
    return 0;
}


int Net_IMG_Load(int save_MS){

   //ret = sceHttpSetResolveTimeOut(template, 500000);if(ret < 0) return 0;
   //ret = sceHttpSetRecvTimeOut(template, 10000000);if(ret < 0) return 0;
   //ret = sceHttpSetSendTimeOut(template, 10000000);if(ret < 0) return 0;
   request = sceHttpCreateRequestWithURL(connexion, PSP_HTTP_METHOD_GET, (char*)url, 0);if(request < 0) return 0;
   ret = sceHttpSendRequest(request, 0, 0);if(ret < 0) return 0;
   ret = sceHttpGetStatusCode(request, &status);if(ret < 0) return 0;if(status != 200) return 0;

//***merci biscottealacrevette
   sceHttpGetContentLength (request, &length);
   target = malloc((SceULong64)length);
   sceHttpReadData(request,target,(SceULong64)length);
//***

   //Set data for the temporary file
   oslSetTempFileData(target, length, &VF_MEMORY);
   //Load a JPG file using the temporary file (oslGetTempFileName to get its name)
   oslDeleteImage(bkg);
   bkg = oslLoadImageFileJPG(oslGetTempFileName(), OSL_IN_RAM | OSL_SWIZZLED, OSL_PF_8888);
   //oslScaleImage  (bkg,bkg,0,0,480,272); 
   
   if (save_MS>0) {
	  int fd;
      char *filepath="";
      pspTime TimePSP;
      sceRtcGetCurrentClockLocalTime(&TimePSP);
      sprintf(filepath,"ms0:/PSP/PHOTO/FOX_%02dH%02dM%02dS%02dms.jpg" , TimePSP.hour , TimePSP.minutes , TimePSP.seconds , (TimePSP.microseconds>>12) & 0xff);
      fd = sceIoOpen(filepath, PSP_O_WRONLY | PSP_O_CREAT, 0777);
      sceIoWrite(fd, target, (SceULong64)length);
      sceIoClose(fd);
   }
	  free(target);
	  return 0;
}

///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Main:
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int main(){
	int skip = 0;
    int enabled = 1;
    int selectedConfig = 0;
    SetupCallbacks();

    initOSLib();
    oslIntraFontInit(INTRAFONT_CACHE_MED);
    oslNetInit();

    //Loads image:
    bkg = oslLoadImageFilePNG("bkg.png", OSL_IN_RAM | OSL_SWIZZLED, OSL_PF_8888);

    //Load font:
    OSL_FONT *font = oslLoadFontFile("flash0:/font/ltn0.pgf");
    oslSetFont(font);

    if (!oslIsWlanPowerOn())
        sprintf(message, "Please turn on the WLAN.");

    //Get connections list:
    struct oslNetConfig configs[OSL_MAX_NET_CONFIGS];
    int numconfigs = oslGetNetConfigs(configs);
    if (!numconfigs){
        sprintf(message, "No configuration found!");
        enabled = 0;
    }

	int connected = 0;

    while(runningFlag && !osl_quit){
        if (!skip){
			oslStartDrawing();
			oslDrawImageXY(bkg, 0, 0);
            if (enabled){
                sprintf(buffer, "Press X to connect to %s.", configs[selectedConfig].name);
    			oslDrawString(30, 5, buffer);
    			oslDrawString(30, 25, "Press UP and DOWN to change settings.");
            }
            oslDrawString(30, 60, "Press /\\ to quit.");

			sprintf(buffer, "Memory Available %iko.", oslGetRamStatus().maxAvailable/1024);
			oslDrawString(30, 95, buffer);
			sprintf(buffer, "Image %iko.", length/1024);
			oslDrawString(30, 115, buffer);
			sprintf(buffer, "Connected %i.template %i,\nconnexion  %i,request %i,\nret %i, status %i", connected, template, connexion, request, ret, status);
			oslDrawString(30, 135, buffer);
			oslDrawString(30, 250, message);

			oslEndDrawing();
		}
        oslEndFrame();
        skip = oslSyncFrame();

        oslReadKeys();
        if (osl_keys->released.triangle)
            runningFlag = 0;

        if (osl_keys->released.cross){

            connected = connectToAP(selectedConfig + 1);
			while (connected==0) 
			{connected = connectToAP(selectedConfig + 1);}

		}else if (osl_keys->released.circle){
            //Net_IMG_Load(0);

		}else if (osl_keys->released.up){
            if (++selectedConfig >= numconfigs)
                selectedConfig = numconfigs - 1;

		}else if (osl_keys->released.down){
            if (--selectedConfig < 0)
                selectedConfig = 0;
        }
		if (connected>0) 
		{
			Net_IMG_Load(0);
		}
    }
    //Quit OSL:
    oslNetTerm();
    oslEndGfx();
    sceKernelExitGame();
    return 0;

}
mais 2 nouveaux problemes :
au bout de quelques sceHttpCreateRequestWithURL j'ai un request negatif (ca je sais pas si ca vien du serveur au pire je vais essayer sur une image google pour voir si sur un autre serveur ca passe) , et probleme avec la lenteur de oslScaleImage qui me fais perdre bcp de "FPS" (l'image recuperée fait 640x480 et je veux reduire en 480x272 pour l'afficher entierement sur l'ecran de 480x272)
 
A

Anonymous

Invité
#4
Sur ce coup là , je pense pas pouvoir t'aider , j'ai commencer le C++ il y a une semaine et demi environ. Doc je ne suis rendu qu'à Qt.(Faudra que je relise un peu le polymorphisme et truc du genre mais plus tard :p)
 

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#5
Pour eviter l'erreure de request negatif avec sceHttpCreateRequestWithURL j'ai decidé de modifier le serveur pour qu'il n'envoie pas une page web mais directement les données en pur sock (en envoyant 2 paquets : 1er de 4 octets avec les 2 derniers octets qui donnent la taille du prochain (pour redimensionner target) et le 2ieme qui est l'image) , donc ca roulait correctement sans erreures mais le probleme c'est que le temps que la console affiche l'image (et oui pas puissant une psp) ca freinait la reception donc j'avais l'image de y'a 15 jours (enfin de y'a 1 ou 2 secondes , donc pour commander un robot c'est pas terrible il fini toujours dans le mur).
Pour eviter de freiner la reception je l'ai mise dans un thread avec une structure :
Code:
typedef struct Image Image;
struct Image
{
  size_t length;
  unsigned char* Data;
};

Image frame; 

void Frames_Thread()
{
	while (SocketCam>0) 
		{
			if (sceNetInetRecv(SocketCam,FrameHeader,4,0)>0)
			{
				length=FrameHeader[2]*256+FrameHeader[3];
				target = malloc((size_t)length);
				if(readDataLarge(SocketCam, target, length)>0)
				{
					frame.length=length;
					frame.Data=target;
					free(target);
					Updated_Frame++;
				}
			}
	}
}
impeccable je recois tres vite mais voila que ca affiche rien dans le thread principale (enfin ca plante la console) :
Code:
if (Updated_Frame>50) //je laisse recevoir 50 images pour les test de receptions
		{
			oslDeleteImage(bkg);
			//Set data for the temporary file
			oslSetTempFileData(frame.Data, frame.length, &VF_MEMORY);
			//Load a JPG file using the temporary file (oslGetTempFileName to get its name)
			bkg = oslLoadImageFileJPG(oslGetTempFileName(), OSL_IN_RAM | OSL_SWIZZLED, OSL_PF_8888);
			bkg->stretchX=480;
			bkg->stretchY=272;
			Updated_Frame=0;
			//oslScaleImage(bkg,bkg,0,0,480,272);
		}
donc je regarde et en fait j'ai frame.Data qui est different de ce que je devrais avoir :


a la place de :

???????????
 
Inscrit
22 Octobre 2011
Messages
34
Reactions
0
#6
Il faut que tu saches que quand tu libères target, frame.Data le sera aussi vu que ces deux variables pointent vers la même case mémoire. Par conséquent, tu utilises une case mémoire invalide par la suite et c'est ça qui fait planter ta console (et en plus y'a risque de [grosse] fuite de mémoire si le programme n'entre pas dans ton if).
De plus, imaginons que tu reçoives deux frames mais que la console n'ait le temps d'en afficher qu'une seule, tu auras là aussi une fuite de mémoire, donc pas cool.

Il faudrait que tu stocke chaque frame reçue dans une queue, et que tu fasses un pop dans ton thread principal pour afficher chaque image. Et c'est à ce moment là que tu dois libérer ta mémoire.
 
Inscrit
19 Octobre 2010
Messages
214
Reactions
0
#7
Petit scarabé a tout à fait raison.

En fait, tu as plusieurs possibilités. En voici deux :
1/ Si tu es certain de passer dans ton code d'affichage à chaque fois, alors tu peux simplement faire un free(frame.Data) à la fin de ta routine d'affichage.

2/ Solution plus propre, et à peine plus compliquée : gérer une file de buffers.
Il faut pour cela que tu estimes le nombre d'image maxi que tu dois pouvoir garder en mémoire entre leur lecture et leur affichage (50 ?).
Cela suppose que tu aies assez de mémoire pour conserver ce nombre d'images.

Voici le principe (j'ai tapé le code directement dans le forum, et comme ça fait 6 mois que je ne code plus en C/C++, il peut y avoir des fautes de syntaxe).
Au lancement de ton programme, tu appelles InitFrames.
A chaque réception, tu utilises le buffer retourné par NextDataBufferToStore pour stocker les données. Au cas où l'affichage ne suit pas la capture, les plus anciennes frames sont perdues.
Pour l'affichage, tu appelles NextDataBufferToStore : si il te renvoie NULL, il n'y a rien a afficher. Sinon, le structure renvoyée correspond décrit ce qui est a afficher.

Code:
#define NB_FRAMES 50
Image frame[NB_FRAMES];
volatile int FramesHead = 0; // Index of the next Frame to be stored
volatile int FramesCurrent = 0; // Index of the next Frame to be displayed

InitFrames()
{
  for (int i=0; i<NB_FRAMES; i++)
  {
    frame[i].Data = NULL;
    frame[i].length = 0;
  }
}

// Returns the buffer to be used for storing incoming data. 
unsigned char *NextDataBufferToStore(int length)
{
  Image *NextStoreFrame = &Frames[(FramesHead++)%NB_FRAMES];
  if (NextStoreFrame->Data != null)
    NextStoreFrame.Data = realloc(NextStoreFrame.Data, length);
  else
    NextStoreFrame.Data = malloc(length);
  NextStoreFrame.length = length;
  if (FramesHead == FramesCurrent) // All "slots" are full and not displayed => oldest frame is lost
     FramesCurrent = (FramesCurrent++)%NB_FRAMES;
  return NextStoreFrame.Data;
}

// Returns the next Frame to be displayed. NULL if nothing to display. 
Image *NextFrameToDisplay()
{
  if (FramesHead == FramesCurrent) return NULL; // All stored frames are allready displayed

  Image *NextDisplayFrame = &Frames[(FramesCurrent++)%NB_FRAMES];
  if (NextDisplayFrame ->Data == NULL) return NULL; 
  return NextDisplayFrame;
}
 

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#8
merci , en fait j'ai a peu pres resolu le probleme en fesant ca : (j'ai juste besoin de la derniere frame)
Code:
int SocketCam = 0;
volatile size_t length;

static unsigned char FrameHeader[4]; // !F (2bytes) + length (2 bytes)
volatile static unsigned char* target;

volatile unsigned char Image_FrameHeader[2]; //length (2 bytes)
volatile static unsigned char* Image_Data;

volatile int Updated_Frame=0;

//------------------------------------------
void Frames_Thread()
{
	while (SocketCam>0) 
	{
		if (sceNetInetRecv(SocketCam,FrameHeader,4,0)>0)
		{
			length=FrameHeader[2]*256+FrameHeader[3];
			target = malloc((size_t)length);
			if(readDataLarge(SocketCam, target, length)>0)
			{
				if (Updated_Frame!=-1)
				{
					memcpy(Image_FrameHeader, FrameHeader+2 , 2);
					free(Image_Data);
					Image_Data = malloc((size_t)length);
					memcpy(Image_Data, target, length);
					Updated_Frame++;
				}
				free(target);
			}
		}
	}
}

//--------------------------------------
//thread principal 
//....
 while(runningFlag && !osl_quit){
        if (!skip){
			oslStartDrawing();
			oslDrawImageXY(bkg, 0, 0);
            if (enabled){
                sprintf(buffer, "Press X to connect to %s.", configs[selectedConfig].name);
    			oslDrawString(30, 5, buffer);
    			oslDrawString(30, 25, "Press UP or DOWN to change settings.");
            }
            oslDrawString(30, 60, "Press /\\ to quit.");

			sprintf(buffer, "Memory Available %iko.", oslGetRamStatus().maxAvailable/1024);
			oslDrawString(30, 95, buffer);
			sprintf(buffer, "Image %iko.", length/1024);
			oslDrawString(30, 115, buffer);
			//sprintf(buffer, "Connected %i.template %i,\nconnexion  %i,request %i,\nret %i, status %i", connected, template, connexion, request, ret, status);

			sprintf(buffer, "SocketCam %i length %i Frame %i", SocketCam, length, Updated_Frame);

			oslDrawString(30, 135, buffer);
			if (Image_FrameHeader[0]*256 + Image_FrameHeader[1]>0)
				//sprintf(message, "length=%i", Image_FrameHeader[0]*256 + Image_FrameHeader[1]);
				sprintf(message, "length=%i\nImage_Data %02X %02X %02X %02X %02X %02X %02X %02X", Image_FrameHeader[0]*256 + Image_FrameHeader[1], Image_Data[0], Image_Data[1], Image_Data[2], Image_Data[3], Image_Data[4], Image_Data[5], Image_Data[6], Image_Data[7]);
			oslDrawString(30, 240, message);

			oslEndDrawing();
		}
        oslEndFrame();
        skip = oslSyncFrame();
...
 if (osl_keys->released.circle){
             SocketCam=ConnectClient("192.168.10.90",8888);
			 if(SocketCam>0)
			{
				SceUID thid;
				thid = sceKernelCreateThread("Frames", (SceKernelThreadEntry)Frames_Thread, 0x18, 0x10000, 0, NULL);
				sceKernelStartThread(thid, 0, 0);
			}
...
if (Updated_Frame>0) 
		{
			Updated_Frame=-1;
			oslDeleteImage(bkg);
			////Set data for the temporary file
			oslSetTempFileData(Image_Data, Image_FrameHeader[0]*256 + Image_FrameHeader[1], &VF_MEMORY);
			////Load a JPG file using the temporary file (oslGetTempFileName to get its name)
			bkg = oslLoadImageFileJPG(oslGetTempFileName(), OSL_IN_RAM | OSL_SWIZZLED, OSL_PF_8888);
			//oslScaleImage(bkg,bkg,0,0,480,272);
			
			Image_FrameHeader[0]=0;Image_FrameHeader[1]=0;
			Updated_Frame=0;
		}
mais j'en revien au meme probleme , pendant que ca affiche je ne recoit plus rien (meme pas target) malgrés que la reception est dans un autre thread , j'ai l'impression que juste afficher une image la sature (et c'est assez long meme sans redimensionner l'image ca met legerement moins d'une seconde a vu d'oeil , si je redimensionne la c'est meme pas la peine d'y penser) du coup j'ai encore l'image d'hier qui saffiche a la place de l'image du moment

une petite video pour vous montrer le decalage , je passe la main devant la cam et ca affiche 2 sec plus tard (a ouvrir avec vlc , je sais pas pourquoi media player en veut pas) http://toonsmil.chez-alice.fr/videos/V2 ... 360001.avi
le serveur c'est la petite carte qui clignote sous l'ecran ;)
 
Inscrit
19 Octobre 2010
Messages
214
Reactions
0
#9
Tu te crois sur un PC Quad-core ou quoi ?

Visiblement, les threads ne s'executent pas de façon concurrente. Chaque thread est bloquant : si tu veux qu'un thread laisse la main à un autre, il faut le lui dire explicitement. Bref, c'est du multi-thread à la Windows 3.1.

http://forums.ps2dev.org/viewtopic.php?t=12035

Donc à mon avis ça t'apportera de la complexité inutilement si tu veux tronçonner la reception et l'affichage afin de laisser la main à l'autre. Et au final, tu ne devrais pas gagner en performances.

Pour ce qui est du temps d'affichage, évite déjà toutes les recopies du buffer. Là tu charge les données réseau dans un buffer, puis tu les recopies dans un second, ensuite tu crées un fichier virtuel en mémoire (c'est donc ni plus ni moins qu'un nouveau buffer)... forcément, tout cela prend du temps. Surtout qu'il faut y ajouter les allocations/désallocations de la mémoire.

Et ton tableau Image_FrameHeader, quelle horreur ! Pourquoi tu ne stockes pas la taille directement (copie de length) ?
 

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#10
Je me crois sur une console qui "serait" capable d'afficher au moins 3 images par seconde mais ca a pas l'aire d'etre le cas, une seule image sans redimensionnement met deja plus de 2 secondes juste pour l'affichage:
ce qui me choque c'est que si je laisse le code du dessus en modifiant juste ca pour ne rien afficher (tout les buffers sont quand meme remplis):
Code:
if (Updated_Frame>0) 
      {
         Updated_Frame=-1;
         //oslDeleteImage(bkg);
         ////Set data for the temporary file
         oslSetTempFileData(Image_Data, Image_FrameHeader[0]*256 + Image_FrameHeader[1], &VF_MEMORY);
         ////Load a JPG file using the temporary file (oslGetTempFileName to get its name)
         //bkg = oslLoadImageFileJPG(oslGetTempFileName(), OSL_IN_RAM | OSL_SWIZZLED, OSL_PF_8888);
         //oslScaleImage(bkg,bkg,0,0,480,272);
         
         Image_FrameHeader[0]=0;Image_FrameHeader[1]=0;
         Updated_Frame=0;
      }
le serveur envoie les packets a une vitesse folle.

Peu etre que ca viendrait de oslLoadImageFileJPG car de toute facon un fond est quand meme affiché a chaque tour (celui que je charge au tout depart du main avec bkg = oslLoadImageFilePNG("bkg.png", OSL_IN_RAM | OSL_SWIZZLED, OSL_PF_8888); qui est une image en 480x272) et tres vite
comme c'est du jpg je ne peu pas faire ca:
bkg->data=Image_Data; //qui fonctionne que avec du bmp , png ... (enfin du pas compressé).

Pour Image_FrameHeader en fait j'avais essayé au depart avec int Image_length=length; mais le probleme c'est que quand length change Image_length change aussi (ca doit juste envoyer sur la meme adresse memoire , ce qu'explique le petit scarabé) , voila pourquoi je passe par un tableau et un memcpy

c'est quand meme bizarre qu'une console de jeu arrive pas a afficher (en realité a charger via la ram) une image en moins de 2 secondes

puis pour les surchages de bufferS tu as raison c'est pas tres propre (meme si ca c'est negligeable pour le moment niveau performance) le pire c'est que je vien de voir que oslLoadImageFileJPG c'est ca : http://code.google.com/p/oslib-mod/sour ... c=svn2&r=2 donc encore des fichiers virtuels en plus et des malloc dans tout les sens
Je vais essayer de faire un court circuit dans tout ca pour voire ce que ca donne (... mais demain , la j'ai pas le courage)
 
Inscrit
19 Octobre 2010
Messages
214
Reactions
0
#11
ToOnS a dit:
c'est quand meme bizarre qu'une console de jeu arrive pas a afficher (en realité a charger via la ram) une image en moins de 2 secondes
Effectivement. Peut-être n'utilises-tu pas la bonne fonction ?
Si le temps d'affichage est nettement plus important que le temps de transfert par le réseau, tu pourrais aussi envisager un autre format, plus rapide à décompresser (PNG et GIF risquent de ne pas compresser des masses, aussi bien faire un essai avec des Bitmap non compressées : RAW ou BMP).


ToOnS a dit:
Pour Image_FrameHeader en fait j'avais essayé au depart avec int Image_length=length; mais le probleme c'est que quand length change Image_length change aussi (ca doit juste envoyer sur la meme adresse memoire , ce qu'explique le petit scarabé) , voila pourquoi je passe par un tableau et un memcpy
Euh non, si tu déclares :
Code:
   int Image_length=length;
Image_length et length sont a des adresses différentes, et un changement sur length n'affectera pas Image_length après l'affectation.

Cela aurait été le cas si tu avais écrit :
Code:
   int *Image_length=&length;
(dans ce cas Image_length est un pointeur, et tu lui donned la même adresse que length. Donc *Image_length vaudra la même chose que length même si length change après.).

Ou encore :
Code:
   int &Image_length = length; // Syntaxe à confirmer, le C++ ça devient de l'histoire ancienne pour moi
Où là tu lui dis que Image_length est une référence sur la variable length. Ce qui est similaire à la notation précédente, sauf que Image_length s'utilise comme une variable int et non un pointeur.
 

ToOnS

Membre Actif
Inscrit
8 Avril 2009
Messages
974
Reactions
0
#12
je vais essayer comme tu me le proposes de transformer le jpg en raw du coté serveur mais pas sur que ca aille plus vite , ca risque meme d'etre encore plus lent car le serveur c'est cette bete la : http://foxlx.acmesystems.it/ (regardes "Hardware Features" c'est pire que la psp avec ses 333Mhz si elle est overclockée) , une toute petite carte pour donner ca : http://www.youtube.com/watch?v=msIqvdVIStk
 
Haut Bas