IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C Discussion :

Créer un fichier virtuel et connaitre sa taille


Sujet :

C

  1. #1
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 4
    Par défaut Créer un fichier virtuel et connaitre sa taille
    Bonjour,

    Tout d'abord, désolé pour le titre peu clair, mais je voyais pas trop comment résumer le problème.

    Donc j'explique vite fait. Je souhaite créer un petit player vidéo, pour ca, j'utilise 2 librairies, libmpeg2 pour le décodage et SDL pour l'affichage.

    libmpeg2 décode la vidéo, et stocke chaque image produite dans un fichier et SDL (en fait SDL_Image) lit l'image et l'affiche. Le problème, c'est que passer par un fichier, c'est un peu moisi, disons ce qui est.

    Le code de base d'écriture de fichier fourni par libmpeg2 ressemble à ca:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
     
    static void save_ppm (int width, int height, uint8_t * buf, int num)
    {
        char filename[100];
        FILE * ppmfile;
     
        sprintf (filename, "%d.ppm", num);
        ppmfile = fopen (filename, "wb");
        if (!ppmfile) {
            fprintf (stderr, "Could not open file \"%s\".\n", filename);
            exit (1);
        }
     
        fprintf (ppmfile, "P6\n%d %d\n255\n", width, height);
        fwrite (buf, 3 * width, height, ppmfile);
        fclose (ppmfile);
    }
    et pour l'afficher j'utilise IMG_load(filename) (enfin pour le charger).

    Donc pour en revenir au problème (oui je prend mon temps ), j'ai vu 2 solutions:
    - soit écrire le fichier dans la RAM (mais la aucune idée de comment faire, surtout que ca doit être du code portable, donc j'ai des doutes sur cette solution)
    - soit éviter de passer par fopen etc, juste faire un malloc/free. Sauf que (bah oui, y'a un sauf forcément) je rencontre un problème pour trouver la taille du fichier (qui est nécessaire pour utiliser SDL_RWFromMem)

    Donc en restant sur la 2eme solution, j'ai testé la fonction fsize donné dans la faq mais ca plante (et comme un boulet que je suis jai oublié de noter l'erreur :/ ).
    La solution testé avant c'était d'utiliser une chaine pour y placer l'entête ("P6\n etc") avec sprintf pour ensuite utiliser sizeof et strlen pour avoir la taille, un autre sizeof pour avoir la taille du buffer mais je n'obtient pas la bonne taille du fichier apparement.

    Je suis sur à 95% que la solution est toute bête mais la je cale :/
    Merci d'avance.

  2. #2
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Par défaut
    Heu... Désolé de ne pas te répondre. J'ai plutôt une question à te poser.

    Tu comptes afficher une vidéo mpeg2 à partir d'image stockée dans un fichier?

  3. #3
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Par défaut
    Sinon je crois que c'est:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    off_t taille_du_fichier = lseek(fd, 0, SEEK_END);

  4. #4
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 4
    Par défaut
    Citation Envoyé par moldavi
    Tu comptes afficher une vidéo mpeg2 à partir d'image stockée dans un fichier?
    En fait c'est la librairie mpeg2 qui fait ca par défaut, créer une image (le gros problème c'est que la lib est pas documentée donc ca aide pas franchement :/ )

    Le truc que je veux donc c'est éviter d'avoir un vrai fichier (pour éviter les accès disque).
    Donc ce que j'apelle "fichier virtuel" c'est en fait une simple variable de type FILE, sans passer par fopen/fclose, juste qu'il reste en mémoire.

    Mais au passage si quelqu'un à mieux qu'un FILE* je lui en serai reconnaissant (j'ai testé char* en remplacant fprintf par sprintf, ca passe, c'est pour remplacer le fwrite que je voit pas trop comment faire, enfin plus précisement transformer mon tableau de uint8_f et char*)

    Je vais tester ta solution

    edit post test (oui je test vite ) j'ai droit à une "Illegal instruction" quand je lance :/ Je vais essayer de me pencher la dessus.

  5. #5
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Tu as deja tout pour laisser ton fichier en RAM, visiblement.
    Si j'ai bien suivi, tu fais:
    video -> libmpeg2 donne buffer -> save_ppm donne fichier -> SDL_Load charge fichier -> SDL_something affiche fichier.

    Il suffit de supprimer les etapes intermediaires :
    video -> libmpeg2 donne buffer -> SDL_something2 affiche buffer.

    Comme tu l'indiques dans save_ppm, ton buffer est de taille 3 * width * height (j'imagine que le 3 correspond aux composantes de couleurs et que uint8_t est un unsigned char defini pour des questions de portabilite [s'assurer qu'il fait bien un octet]).

    Donc, tu as tout pour travailler en RAM uniquement. Pour trouver la fonction SDL_something2, je te rapporte a la doc de la SDL, que je ne connais pas.

  6. #6
    Inactif  

    Homme Profil pro
    Ingénieur test de performance
    Inscrit en
    Décembre 2003
    Messages
    1 986
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 51
    Localisation : France, Bouches du Rhône (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Ingénieur test de performance
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Décembre 2003
    Messages : 1 986
    Par défaut
    Le truc que je veux donc c'est éviter d'avoir un vrai fichier (pour éviter les accès disque).
    Donc ce que j'apelle "fichier virtuel" c'est en fait une simple variable de type FILE, sans passer par fopen/fclose, juste qu'il reste en mémoire.

    Mais au passage si quelqu'un à mieux qu'un FILE* je lui en serai reconnaissant (j'ai testé char* en remplacant fprintf par sprintf, ca passe, c'est pour remplacer le fwrite que je voit pas trop comment faire, enfin plus précisement transformer mon tableau de uint8_f et char*)
    Je ne voudrais pas te faire peur et te couper dans ton élan (loin de là, j'essaie plutôt d'aider les programmeurs lorsque je peux), mais est-ce que tu penses que l'affichage d'une vidéo (surtout au format mpeg2) se passe comme ça.

    Comme tu le sents déjà, tu veux éviter les accès disque. Et bien il n'y a pas que ça (OULALA non).

    Même d'utiliser la mémoire vive (la RAM), c'est encore lent. Pour du mpeg2, la technique actuelle, c'est d'écrire directement les images dans la carte graphique tout en utilisant le potientel de la carte graphique (optimisation et autre).

    Encore si ce n'était que ça, mais bon c'est déjà pas mal.

    Quoi d'autres? Bein, un autre souci, c'est que tu dois utiliser les threads. Bah oui si tu décompresses une image puis tu l'affiches, puis tu décompresses, etc.. C'est lent.

    Pendant que tu affiches les images, c'est-à-dire que la carte graphique travaille, tu dois dèjà être en train de décompresser l'image suivante, voir l'image suivant la suivante, voir plus...

    Bon ton décodeur, il sait faire et il est sûrement optimisé pour, mais ton affichage je doute.

    En plus les threads ça induit un timer (une synchronisation). Ton décodeur il peut pas aller plus vite que ce qui a été prévu. Tu travailles dans un environnement multitâche, tu ne peux donc pas savoir à quel moment les données sont effectivement décompressées. Tu ne peux pas lire les données dans la RAM si tu n'es pas sur que effectivement tout y est.

    Tu risques donc d'afficher des images qui seront incomplètent et incohérentes et sûrement même pire que ça.

    De plus comment est-ce que tu gères le son. Tu utilises une librairies pour les images, mais qu'en est-il du son? Le mpeg2 c'est aussi du son. Et le son il faut qu'il s'exécute en même temps que la vidéo et au bon moment.

    C'est un domaine très compliqué mais très intéressant.

    Tu peux effectivement faire ce que tu envisages. Ca peut-être une bonne façon de comprendre comme on gère le multimédia.

    Mais peut-être que je m'égare et que la SDL a tout prévu...

  7. #7
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 4
    Par défaut
    Citation Envoyé par DaZumba
    Comme tu l'indiques dans save_ppm, ton buffer est de taille 3 * width * height (j'imagine que le 3 correspond aux composantes de couleurs et que uint8_t est un unsigned char defini pour des questions de portabilite [s'assurer qu'il fait bien un octet]).
    En fait le problème c'est de réussir à concatener les entêtes en char* et le contenu en *uint8_t (depuis hier soir je cherche avec uint8_f, ce qui forcément n'aide pas ... )

    Si je lui passe juste le buffer, il me dit que le type n'est pas reconnu comme image valide.

    J'ai essayé avec strcat en castant mon buffer en char* mais ca veut pas, memcpy non plus d'ailleurs en castant aussi. Au pire je ferais bien une boucle mais c'est déjà assez lourd comme ca, autant pas en rajouter.

    Et merci moldavi pour les conseils, c'est vrai que j'avais pas pensé à écrire directement dans la mémoire de la carte graph et que j'avais pas vu la tache si ardue en fait :/
    Ca accelererait bien le traitement c'est sur. Ca sera peut être l'évolution suivante (ou peut être juste dans le rapport de stage )

  8. #8
    Membre Expert
    Inscrit en
    Décembre 2004
    Messages
    1 478
    Détails du profil
    Informations forums :
    Inscription : Décembre 2004
    Messages : 1 478
    Par défaut
    Citation Envoyé par Sarga
    Si je lui passe juste le buffer, il me dit que le type n'est pas reconnu comme image valide.
    Oui, evidemment il attend un certain format. Ceci dit, je suis surpris : nul part dans la SDL il n'existe une fonction qui prenne un buffer de trois composantes * width * height, et qui l'affiche? C'est basique comme fonction, pourtant. Evidemment, elle ne doit pas faire partie de SDL_Image. Mais comme je l'ecris plus haut, je ne connais pas la SDL, il faudrait regarder la documentation.

  9. #9
    Futur Membre du Club
    Profil pro
    Inscrit en
    Mars 2004
    Messages
    4
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Mars 2004
    Messages : 4
    Par défaut
    Tu roxes, c'est bien ça
    Je m'étais mis en tête l'idée du fichier et du coup je cherchait une fonction chargeant une image, mais en fait non.

    La méthode à utiliser était en fait SDL_CreateRGBSurfaceFrom()
    Pour le moment ca boite (je capte pas trop ce qu'est le paramètre pitch, mais ca doit être trouvable)

    J'édite le post dès que j'ai trouvé ce qu'est exactement le pitch.

    Encore merci à tous

    edit, donc voila, ca marche (a part que la vidéo va au taquet mais ca ca viendra plus tard).
    Donc si quelqu'un se retrouve dans mon cas, le code c'est ca:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    #if SDL_BYTEORDER == SDL_BIG_ENDIAN
      rmask = 0xff0000;
      gmask = 0x00ff00;
      bmask = 0x0000ff;
      amask = 0x000000;
    #else
      rmask = 0x0000ff;
      gmask = 0x00ff00;
      bmask = 0xff0000;
      amask = 0x000000;
    #endif
     
      image = SDL_CreateRGBSurfaceFrom(buf, width, height, 24, 3 * width,
                                       rmask, gmask, bmask, amask);
    Et hop

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [C#] Comment connaitre la taille d'un fichier.
    Par PascalCmoa dans le forum Windows Forms
    Réponses: 6
    Dernier message: 09/02/2018, 08h54
  2. Réponses: 2
    Dernier message: 28/10/2008, 12h21
  3. Réponses: 2
    Dernier message: 26/04/2005, 12h18
  4. [JSP] Connaitre la taille d'un fichier
    Par dst dans le forum Servlets/JSP
    Réponses: 2
    Dernier message: 21/06/2004, 17h22
  5. Comment créer un fichier dummy de taille donnée ?
    Par Maitre Kanter dans le forum Langage
    Réponses: 3
    Dernier message: 13/12/2003, 23h46

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo