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

DirectX Discussion :

Séparation streaming audio et vidéo directshow


Sujet :

DirectX

  1. #1
    Nouveau Candidat au Club
    Inscrit en
    Mai 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 13
    Points : 1
    Points
    1
    Par défaut Séparation streaming audio et vidéo directshow
    Bonjour,
    Je cherche à séparer les streams audio et vidéo dans l'échantillon AmCap de directShow. Je voudrais sauvegarder le son dans un fichier .wave et la vidéo dans un fichier .avi
    Quelles modifications faut il apporter à la construction du graphe?
    Et à la sauvegarde?
    Merci

  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 : 50
    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
    Points : 2 605
    Points
    2 605
    Par défaut
    Salut.

    Je voudrais sauvegarder le son dans un fichier .wave
    Tu peux utiliser le filtre "wavdest" du SDK (le compiler), et l'associer au filtre "filewriter", pour le fichier de destination.

    et la vidéo dans un fichier .avi
    Il faut un encodeur AVI.

    Quelles modifications faut il apporter à la construction du graphe?
    Je n'ai pas expérimenté ce genre de configuration, mais ce que je ferais:

    tentative de connection intelligente (au cas ou des filtres intermédiaires soient nécessaires), entre la pin d'entrée du wavdest et la pin de sortie audio du filtre de capture.

    Idem pour la vidéo, entre la pin d'entrée de l'encodeur AVI et la pin de sortie vidéo du filtre de capture.

    Si les MEDIA_TYPE correspondent, alors pas de problème.

    Sinon je tenterais de construire un graphe complet (visiblement du mpeg2 pour l'exemple du SDK) et refaire la manipulation ci-dessus à partir du démultiplexeur (enfin juste après le décodage audio et vidéo).

  3. #3
    Nouveau Candidat au Club
    Inscrit en
    Mai 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 13
    Points : 1
    Points
    1
    Par défaut
    Bonjour Moldavi,

    tout d'abord merci de m'avoir répondu.

    Ce que je veux faire précisément?
    Très bien, j'utilise déjà l'échantillon AmCap pour la vidéo
    Le problème est que je dois sauvegarder le son de cette vidéo dans un fichier wav automatiquement et la vidéo dans un fichier avi, je ne veux pas utiliser de convertisseur pour chaque fichier car je vais en avoir des centaines.
    Donc ce que mon programme doit faire:

    Je capture, et je sauve la vidéo dans un fichier .avi et le son correspondant à cette vidéo dans un fichier .wav

    J'ai en effet vu qu'il y avait un filtre wavdest pour le fichier wav mais je n'arrive pas à le compiler, il manque une certaine bibliothèque "largeint.lib"
    j'ai bien compiler les basesclasses mais cela ne m'a crée que les libs strmbasd.lib et strmbase.lib.


    Sinon je suis tout nouveau dans ce domaine.
    Je ne maîtrise pas du tout les graphes et les filtres et ne comprend pas vraiment ce que c'est, en tout cas j'ai compris qu'il me fallait un autre graphe du filtre de capture pour sauver un fichier .wav,
    donc mon idée est d'inclure l'échantillon audioCap dans Amcap pour sauvegarder mon son à part.
    Pour récupérer le son pour le wavedest? il faut connecter la pin d'entrée du wavedest avec la pin de sortie du filtre de capture, ainsi je pourais dériver le son vers le wavedest? c'est ça?
    Dans tous les cas il me faut commencer par compiler ce wavdest en trouvant cette librairie largeint.lib, comment faire?
    Merci encore
    Acadiou

  4. #4
    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 : 50
    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
    Points : 2 605
    Points
    2 605
    Par défaut
    Re.

    J'ai en effet vu qu'il y avait un filtre wavdest pour le fichier wav mais je n'arrive pas à le compiler, il manque une certaine bibliothèque "largeint.lib"
    Dis à ton compilateur d'ignorer cette librairie et la compilation se passera bien.

    j'ai bien compiler les basesclasses mais cela ne m'a crée que les libs strmbasd.lib et strmbase.lib.
    Cela suffira pour compiler les projets AmCap et WavDest.

    Je ne maîtrise pas du tout les graphes et les filtres et ne comprend pas vraiment ce que c'est
    Il va falloir comprendre, parce que sinon tu auras du mal à réaliser ce que tu veux.
    Fais un tour sur la FAQ DirectShow, tu en apprendras un peu plus.

    en tout cas j'ai compris qu'il me fallait un autre graphe du filtre de capture pour sauver un fichier .wav
    Fais un test avec graphedit. Insères le filtre de capture, le filtre wavdest et le filtre filewriter (en donnant un nom de fichier et un répertoire d'enregistrement).

    Relies manuellement la pin de sortie audio avec la pin d'entrée du wavdest, et fais de même avec le wavdest et le filewriter. Si tous se passe bien, tu n'as plus qu'à le faire avec du code.

    Pour la vidéo que tu veux sauvegarder dans un .AVI, il faut savoir si tu veux sauvegarder uniquement les images ou le son et l'image. Dans le deuxième cas ça se complique un peu, parce que je crois que ça risque d'être difficile de sauvegarder le son dans deux fichiers différents à partir du même graphe. En effet cela nécessite que le filtre de capture puisse dupliquer la sortie son ou qu'un filtre intermédiaire distribue le son pour deux autres filtres (wavdest et encodeur AVI).

    Néanmoins il me semble que l'exemple AmCap combine par exemple le preview avec la capture, ce qui signifie que l'image et le son sont distribués entre les filtres de rendu et les filtres de sauvegarde sur disque. Si le filtre de capture n'a pas de pin de preview il utilise un "smart tee filter" qui permet le même résultat. Peut-être que tu pourrais utiliser ce principe pour la sauvegarde en double (dans le cas ou le fichier AVI doit contenir le son).

    Un lien qui explique la recompression AVI:

    http://msdn.microsoft.com/library/de...ganavifile.asp

    Un lien qui explique la compression d'un wave en mp3:
    (Utilises ce principe pour créer ton fichier wave)

    http://www.codeproject.com/audio/dshowencoder.asp

    Tu as tout ce qu'il te faut. Il ne reste plus qu'à te plonger dans ces codes et à expérimenter jusqu'au résultat voulu...

  5. #5
    Nouveau Candidat au Club
    Inscrit en
    Mai 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 13
    Points : 1
    Points
    1
    Par défaut Je veux réaliser un convertisseur avi -> wav
    Bonjour Moldavi

    Je sais ce que je veux et peux faire grace à graphedit

    Je veux joindre la pin audio d'un fichier source avi à la pin d'entrée d'un filtre wavedest et joindre la pin de sortie de ce filtre wavdest à un filewriter .wav
    En gros je veux convertir l'audio d'un fichier avi en fichier wav!

    Je vous montre mon code, peut être ai-je fais une erreur dans le graphe ou dans les différents branchements.
    Dîtes moi ce que vous en pensez s'il vous plaît
    Merci encore


    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    #include<dshow.h>
    #include <d3d9.h>
    #include <vmr9.h>
     
    #define WM_GRAPHNOTIFY  WM_APP + 1
    #define CLASSNAME "EventNotify"
    #define SAFE_RELEASE(i) {if (i) i->Release(); i = NULL;}
     
     
    void Avi2WavConvertor(LPCWSTR file, LPCWSTR waveFile)
    {
    	IBaseFilter *pWavDest;
    	IBaseFilter *pFileWriter;
    	IGraphBuilder *pGraphBuilder;
    	IFileSinkFilter2 *pFileSink;
    	IMediaControl *pMC;
    	IMediaEventEx *pEvent;
    	ICaptureGraphBuilder2 *m_pCapture;
    	HRESULT hr;
     
     
    //creation d'un graph de capture
     
      hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, 
             CLSCTX_INPROC,  IID_ICaptureGraphBuilder2, (void **)&m_pCapture);
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Unable to create capture graph", NULL, NULL);
        }
     
    //creation d'un graph builder
        hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
             IID_IGraphBuilder, (void **)&pGraphBuilder);
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Failed to Create Graph Builder", NULL, NULL);
        }
     
     
    //spécifie le graphe avec lequel on travaille ici le "pGraphBuilder"
    	hr = m_pCapture->SetFiltergraph(pGraphBuilder);  
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Failed", NULL, NULL);
        }
        pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMC);
        pGraphBuilder->QueryInterface(IID_IMediaEventEx, (void **)&pEvent);
     
     
    //creation d'un  wavdest filter
    	  static const GUID CLSID_WavDest = 
               { 0x3c78b8e2, 0x6c4d, 0x11d1, 
               { 0xad, 0xe2, 0x0, 0x0, 0xf8, 0x75, 0x4b, 0x99 } };
        hr = CoCreateInstance(CLSID_WavDest, NULL, 
             CLSCTX_INPROC,  IID_IBaseFilter, (void **)&pWavDest);
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Failed to Create WaveDest Filter", NULL, NULL);
        }
     
     
    //Creation d'un filewriter
        hr = CoCreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC,
                              IID_IFileSinkFilter2, (void **)&pFileSink);
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Failed to Create FileSink2 Filter", NULL, NULL);
        }
     
     
    // Get the file sink interface pointer from the File Writer
        hr = pFileSink->QueryInterface(IID_IBaseFilter, (void **)&pFileWriter);
        if(FAILED(hr))
        {
           MessageBox(NULL, L"Unable to get the File Writer interface pointer from the File Sink", NULL, NULL);
        }
        hr = pFileSink->SetFileName(waveFile, NULL);
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Couldnt create wav file", NULL, NULL);
        }
     
    	//////////////////////////////////////////////////////////
     
    	    //adding wavdest to the graph
        hr = pGraphBuilder->AddFilter(pWavDest, L"WAV DEST");
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Failed to add WavDest To Graph", NULL, NULL);
        }
     
        hr = pGraphBuilder->RenderFile(file, NULL);
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Failed to RenderFile", NULL, NULL);
        }
     
     
    	//////////////////////////////////////////////////////////////
     
    	  //adding writer to the graph
        hr = pGraphBuilder->AddFilter((IBaseFilter *)pFileWriter, L"File Writer");
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Failed to add Writer To Graph", NULL, NULL);
        }
    }
     
    	int main(void)
    	{
     
    		WCHAR *file = L"C:\\Documents and Settings\\alexandre cadiou\\Bureau\\hdfg.avi";
    		WCHAR *wavefile = L"C:\\Documents and Settings\\alexandre cadiou\\Bureau\\hdfg.wav";
     
     
     
    		Avi2WavConvertor( file,  wavefile);
    		return 0;
    	}

  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 : 50
    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
    Points : 2 605
    Points
    2 605
    Par défaut
    Re.

    C'est déjà une bonne chose que tu réussisses la manipulation avec graphedit.

    Pour ton code, il manque des choses. L'exemple simple à partir duquel tu peux te baser pour construire le graphe, c'est "playcap".

    Tu verras que tu dois chercher d'abord un "CLSID_AudioInputDeviceCategory" (dans le sample c'est un "CLSID_VideoInputDeviceCategory", mais c'est le même principe): c'est la fonction "FindCaptureDevice".

    Ensuite tu associes le filtre résultant au graphe:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    g_pGraph->AddFilter(pSrcFilter, L"Audio Capture");
    Après il faut aussi dire au graphe de capture de s'exécuter:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    g_pCapture->RenderStream(...);
    Et enfin dire au graphe de jouer le stream:
    Les étapes que je ne cite pas, tu les as. Mets tout dans le bon ordre comme dans l'exemple "playcap", avec en plus l'ajout des filtres de sauvegarde (tu oublies d'ajouter le filewriter dans le graphe):
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    // Output file filter
    hr = AddFilterByClsid(m_pGraphBuilder, L"File Writer", CLSID_FileWriter, &pDest);
    pDest->QueryInterface(IID_IFileSinkFilter, (void**) &pSink);
    pSink->SetFileName(szDestFileName.AllocSysString(), NULL);
    pSink->Release();
    Il se peut ensuite que tu rencontres des difficultés, mais je t'expliquerai une fois que tu auras déjà mis en place un code correct.

    PS: la fonction "AddGraphToRot" du SDK est très pratique pour visionner le graphe en cours. Tu as aussi "SaveGraphFile" qui te permettra de visualiser le graphe et qui a l'avantage de pouvoir être créé même si le graphe n'est pas complètement opérationnel (avant un FAILED(hr), par exemple). Tu trouves ces fonctions dans le fichier "dshowutil.cpp" avec plein d'autres très pratiques.

  7. #7
    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 : 50
    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
    Points : 2 605
    Points
    2 605
    Par défaut
    Citation Envoyé par acadiou
    Je sais ce que je veux et peux faire grace à graphedit

    Je veux joindre la pin audio d'un fichier source avi à la pin d'entrée d'un filtre wavedest et joindre la pin de sortie de ce filtre wavdest à un filewriter .wav
    En gros je veux convertir l'audio d'un fichier avi en fichier wav!
    Arf je viens juste de m'apercevoir que tu as changé le cahier des charges.

    Pour faire ça tu n'as pas besoin de l'interface "ICaptureGraphBuilder2". Tu fais un rendu de graphe classique avec les filtres adéquates (wavdest et filewriter).

    Comme tu n'as pas besoin des filtres de rendu vidéo, un "renderfile" n'est pas indiqué. Il va falloir se passer de "intelligent connect" et connecter les pins entre elles, manuellement.

    Dans le fichier "dshowutil.cpp", sers-toi des fonctions "GetInPin" et "GetOutPin", ensuite un "connect" avec l'interface IPin récupérée fera l'affaire.

  8. #8
    Nouveau Candidat au Club
    Inscrit en
    Mai 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 13
    Points : 1
    Points
    1
    Par défaut récapitulatif des étaps à coder
    Bonjour Moldavi,

    Si je comprends bien votre dernière réponse annule la précédente?
    Je ne sais plus ce que je dois ajouter!

    Je retire le graphe de capture
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    //creation d'un graph de capture
     
      hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, 
             CLSCTX_INPROC,  IID_ICaptureGraphBuilder2, (void **)&m_pCapture);
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Unable to create capture graph", NULL, NULL);
        }

    Le filtre de capture, je n'en ai plus besoin
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    g_pGraph->AddFilter(pSrcFilter, L"Audio Capture");

    Le renderstream qui dit au graphe de capture de s'executer je n'en ai plus besoi non plus
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    g_pCapture->RenderStream(...);
    Par contre il faut toujours que je dise au graphe de jouer le stream, donc ça j'ajoute
    Ceci ajoute le file writer
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    // Output file filter
    hr = AddFilterByClsid(m_pGraphBuilder, L"File Writer", CLSID_FileWriter, &pDest);
    pDest->QueryInterface(IID_IFileSinkFilter, (void**) &pSink);
    pSink->SetFileName(szDestFileName.AllocSysString(), NULL);
    pSink->Release();
    Vous me dites que j'oublie d'ajouter le file writer dans le graphe mais je pensez que cette fonction s'en chargeait
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      //adding writer to the graph
        hr = pGraphBuilder->AddFilter((IBaseFilter *)pFileWriter, L"File Writer");
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Failed to add Writer To Graph", NULL, NULL);
        }
    Sinon je ne comprends pas comment connecter le filtre wavdest à la source avi qui est présente sur mon bureau, j'aimerais programmer tout ceci sous forme de fonction qui recevrait comme paramètre le nom fichier avi à convertir et le nom du fichier wav à créer.

    Sur le graph edit il n'y a que trois "boites" la source wavdest et le file writer, le connect inteligent gère les connections de pin entres elles et ajoute les filtres intermédiaires si nécessaire ça j'ai bien compris, mais quand on passe au code je ne comprends pas comment les filtres savent où se plaçaient, je vais jetter un coup d'oeil aux fonctions GetInPin et GetOutPin.
    Si vous pouviez mon récapitulatif des étapes à coder en fonction du "nouveau cahier des charges", ça m'aiderait beaucoup.

    Merci encore
    Acadiou

  9. #9
    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 : 50
    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
    Points : 2 605
    Points
    2 605
    Par défaut
    Citation Envoyé par acadiou
    Vous me dites que j'oublie d'ajouter le file writer dans le graphe mais je pensez que cette fonction s'en chargeait
    Autant pour moi, j'avais mal regardé ton code.

    L'ennui quand même, c'est que tu ajoutes le filtre "filewriter" après le "renderfile". Et malheureusement, "connect intelligent" (qui s'effectue lors de l'appel de cette méthode), ne peut pas deviner qu'il faut utiliser ce filtre, puisqu'il n'est pas encore dans le graphe.

    Je te donne les étapes de base, on verra plus tard si l'interface IPin sera nécessaire. En effet, il est possible que "connect intelligent", ajoute les filtres intermédiaires (si nécessaire).

    -> obtenir l'interface IGraphBuilder.
    -> ajouter le filtre wavdest.
    -> ajouter le filtre filewriter, et le paramétrer.
    -> effectuer le rendu du fichier "renderfile"
    -> récupérer les interfaces courantes "IMediaControl", "IMediaEvent".
    -> jouer le fichier.
    -> attendre la fin du stream et procéder au nettoyage courant.

    Si "connect intelligent" connecte bien les filtres entre-eux, alors c'est OK. Sinon utiliser l'interface IPin pour un contrôle plus précis du graphe. Essaies déjà cette méthode, après je t'expliquerai l'utilisation des "pins", si c'est nécessaire.

  10. #10
    Nouveau Candidat au Club
    Inscrit en
    Mai 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 13
    Points : 1
    Points
    1
    Par défaut re: avi2wavconvertor
    Cher Moldavi Bonjour,
    Je suis complètement perdu!

    J'ai pleins de problèmes et il y a pleins de choses que je ne comprends pas.

    Premièrement mon code tel que je vous le montre crée le fichier.wav que je lui demande de créer mas ne met rien dedans, en effet il y a 48o d'info dedans.

    Vous me dîtes:
    "ajouter le filtre filewriter, et le paramétrer"

    Je l'ai ajouté mais je ne sais pas comment le paramétrer.
    C'est peut être ce qui fait qu'il n'y a rien dans mon .wav

    Vous me dîtes:
    "récupérer les interfaces courantes "IMediaControl", "IMediaEvent""

    je récupère l'interface "IMEDIAControl" avec cette fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMC);
    Alors l'interfaces "IMEDIAControl" me permet d'utiliser
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    hr = pMC->Run();
    hr = pMC->Stop();
    J'imagine que c'est ce qui me permet de runer et de stopper le graphe, de le jouer pour reprendre vos termes c'est ça?

    ensuite vous me dîtes:
    attendre la fin du stream et procéder au nettoyage courant


    Comment sait on que le stream est fini? et procéder au nettoyage courant signifie appeler ces fonctions?
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     hr = pGraphBuilder->RemoveFilter(pFileWriter);
         hr = pGraphBuilder->RemoveFilter(pWavDest);
    et si c'est le cas où dois je positionner toutes ces fonctions dans mon code? les unes à la suite des autres?

    Sinon pour ce qui est de l'interface "IMediaEvent" que vous me dîtes de récupérer
    je la récupère en appelant cette fonction
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
     pGraphBuilder->QueryInterface(IID_IMediaEventEx, (void **)&pEvent);
    Mais à quoi sert elle? à gérer des évènements comme les cliques de bouton de souris, celà implique d'avoir une fenêtre? mais je ne veux pas intéragir avec la fonction Avi2WavConvertor que je cherche à coder, je veux juste lui donner en paramètre un fichier source avi et un fichier destination wav pour qu'elle fasse la conversion dès son appel.
    Ensuite je l'ajouterai à l'échantillon AmCap pour pouvoir obtenir une version .wav du son extrait du fichier .avi que cet échantillon crée.


    Vous m'avez parlé des fonctions GetInPin et GetOutPin, je les ai trouvé dans le fichier dshowutil.cpp mais ne les ai pas utilisé car ne sait pas.

    Bref je suis un peu pomé car je n'avance plus et n'arrive pas à trouver d'example concret, je suis en stage en russie et mon maître de stage ne connait pas directx donc le seul interlocuteur qualifié que j'ai c'est vous,

    je vous montre mon code actuel
    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    #include<dshow.h>
    #include <d3d9.h>
    #include <vmr9.h>
    #include <atlbase.h>
    #include <atlcom.h>
    #include <atlwin.h>
    #include <atlctl.h>
    //#include "dshowutil.h"
     
     
     
     
     
    #define WM_GRAPHNOTIFY  WM_APP + 1
    #define CLASSNAME "EventNotify"
    #define SAFE_RELEASE(i) {if (i) i->Release(); i = NULL;}
     
    STDMETHODIMP Avi2WavConvertor(LPCWSTR file, /*HWND g_hwnd,*/ LPCWSTR waveFile)
    {
    	IBaseFilter *pWavDest;
    	IBaseFilter *pFileWriter;
    	IGraphBuilder *pGraphBuilder;
    	IFileSinkFilter2 *pFileSink;
    	IMediaControl *pMC;
    	IMediaEventEx *pEvent;
    	HRESULT hr;
    	HWND hwnd;
     
     
     
     
    //creation d'un graph builder
        hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, 
             IID_IGraphBuilder, (void **)&pGraphBuilder);
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Failed to Create Graph Builder", NULL, NULL);
        }
     
     
     
     
    //add a source filter to the graph
    	CComPtr<IBaseFilter> pSource;
    	hr = pGraphBuilder->AddSourceFilter(L"C:\\Documents and Settings\\alexandre cadiou\\Bureau\\hdfg.avi", L"Source", &pSource);
      if(FAILED(hr))
        {
            MessageBox(NULL, L"Failed to add the source to the graph", NULL, NULL);
        }
     
     
     
    //creation d'un  wavdest filter
    	  static const GUID CLSID_WavDest = 
               { 0x3c78b8e2, 0x6c4d, 0x11d1, 
               { 0xad, 0xe2, 0x0, 0x0, 0xf8, 0x75, 0x4b, 0x99 } };
        hr = CoCreateInstance(CLSID_WavDest, NULL, 
             CLSCTX_INPROC,  IID_IBaseFilter, (void **)&pWavDest);
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Failed to Create WaveDest Filter", NULL, NULL);
        }
     
     
     
    //Creation d'un filewriter
        hr = CoCreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC,
                              IID_IFileSinkFilter2, (void **)&pFileSink);
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Failed to Create FileSink2 Filter", NULL, NULL);
        }
     
     
    // Get the file sink interface pointer from the File Writer
        hr = pFileSink->QueryInterface(IID_IBaseFilter, (void **)&pFileWriter);
        if(FAILED(hr))
        {
           MessageBox(NULL, L"Unable to get the File Writer interface pointer from the File Sink", NULL, NULL);
        }
        hr = pFileSink->SetFileName(waveFile, NULL);
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Couldnt create wav file", NULL, NULL);
        }
     
     
     
    	//////////////////////////////////////////////////////////
     
    	    //adding wavdest to the graph
        hr = pGraphBuilder->AddFilter(pWavDest, L"WAV DEST");
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Failed to add WavDest To Graph", NULL, NULL);
        }
     
     
    	hr = pFileSink->SetMode(AM_FILE_OVERWRITE);
        if(FAILED(hr))
        {
            MessageBox(NULL,L"Failed to OverWrite", NULL, NULL);
        }
     
     
     
     
    	//////////////////////////////////////////////////////////////
     
    	  //adding writer to the graph
        hr = pGraphBuilder->AddFilter((IBaseFilter *)pFileWriter, L"File Writer");
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Failed to add Writer To Graph", NULL, NULL);
        }
     
     
     
     
     
     
    	//récupération des interfaces courantes IMEDIACONTROL et IMEDIAEVENT
     
     
    	  pGraphBuilder->QueryInterface(IID_IMediaControl, (void **)&pMC);
          pGraphBuilder->QueryInterface(IID_IMediaEventEx, (void **)&pEvent);
     
    	  //execute le graph
    	hr = pMC->Run();
        if(FAILED(hr))
        {
            MessageBox(NULL, L"Failed to Run", NULL, NULL);
        }
    	hr = pMC->Stop();
    	   if(FAILED(hr))
        {
            MessageBox(NULL, L"Failed to stop", NULL, NULL);
        }
    	 hr = pGraphBuilder->RemoveFilter(pFileWriter);
         hr = pGraphBuilder->RemoveFilter(pWavDest);
     
        return S_OK;
    }
     
    	int main(void)
    	{
     
     
    		WCHAR *file = L"C:\\Documents and Settings\\alexandre cadiou\\Bureau\\hdfg.avi";
    		WCHAR *wavefile = L"C:\\Documents and Settings\\alexandre cadiou\\Bureau\\hdfg.wav";
     
     
    		Avi2WavConvertor( file, wavefile);
    		return 0;
    	}



    Merci encore

  11. #11
    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 : 50
    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
    Points : 2 605
    Points
    2 605
    Par défaut
    Salut acadiou.

    Quand je disais paramétrer le "filewriter", c'était juste donner un nom de fichier avec l'extension .wav.

    Ton fichier .wav ne fait que 48o parce que tu le "Run", puis tu le "Stop" aussitôt. Tu ne lui laisses pas le temps de se terminer et c'est l'interface "IMediaEventEx" qui va te permettre de savoir quand le fichier est entièrement rendu (Encore que j'ai un doute que le "Run" ait fonctionné, car tu ne fais pas de Render dans ton code donc à priori le graphe n'est pas construit et les 48o correspondent juste à la création du fichier lors du "SetFilName").

    Le nettoyage courant, c'est de Release toutes les interfaces, ce que d'ailleurs tu ne fais à aucun moment (Pourtant tu déclares la macro "SAFE_RELEASE").

    Avec les codes sources des sites que je t'ai donné, tu avais tout ce qu'il faut. Il te manque surtout les notions d'évenements.

    Je te donne un code à ma sauce (compilé avec VC++ 2005 en Unicode). Il est commenté donc je m'arrête ici. Ce code montre l'utilisation de l'interfaces IPin.

    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    90
    91
    92
    93
    94
    95
    96
    97
    98
    99
    100
    101
    102
    103
    104
    105
    106
    107
    108
    109
    110
    111
    112
    113
    114
    115
    116
    117
    118
    119
    120
    121
    122
    123
    124
    125
    126
    127
    128
    129
    130
    131
    132
    133
    134
    135
    136
    137
    138
    139
    140
    141
    142
    143
    144
    145
    146
    147
    148
    149
    150
    151
    152
    153
    154
    155
    156
    157
    158
    159
    160
    161
    162
    163
    164
    165
    166
    167
    168
    169
    170
    171
    172
    173
    174
    175
    176
    177
    178
    179
    180
    181
     
     
    #pragma once
    #define STRICT
    #define _WIN32_WINNT 0x0501
     
    #ifdef _DEBUG
      #pragma comment(lib, "strmbasd")
      #pragma comment(lib, "quartz")
    #else
      #pragma comment(lib, "strmbase")
    #endif
     
    #pragma warning(push)
    #pragma warning(disable : 4996)
    #include <streams.h>
    #pragma warning(pop)
     
    // Une macro qui va éclaicir la fonction "Avi2WavConvertor".
    // Le message d'erreur apparaîtra dans une boîte de dialogue.
    #ifdef _DEBUG
      #define V_RETURN(x) { hr = x; if(FAILED(hr)) { WCHAR wszError[1024]; AMGetErrorText(hr, wszError, 1024); \
                                                     MessageBox(0, wszError, TEXT("Error!"), MB_OK | MB_ICONERROR); \
                                                     return hr; } }
    #else
      #define V_RETURN(x) { hr = x; if(FAILED(hr)) { return hr; } }
    #endif
     
    static const GUID CLSID_WavDest = {0x3c78b8e2, 0x6c4d, 0x11d1, {0xad, 0xe2, 0x0, 0x0, 0xf8, 0x75, 0x4b, 0x99}};
     
    // Ce sont les fonctions des fichiers "dshowutil.cpp" et "dshowutil.h".
    HRESULT GetPin(IBaseFilter* pFilter, PIN_DIRECTION dirrequired, int iNum, IPin** ppPin){
     
      CComPtr< IEnumPins > pEnum;
      *ppPin = NULL;
     
      if(!pFilter)
        return E_POINTER;
     
      HRESULT hr = pFilter->EnumPins(&pEnum);
     
      if(FAILED(hr))
        return hr;
     
      ULONG ulFound;
      IPin* pPin;
      hr = E_FAIL;
     
      while(S_OK == pEnum->Next(1, &pPin, &ulFound)){
     
        PIN_DIRECTION pindir = (PIN_DIRECTION)3;
     
        pPin->QueryDirection(&pindir);
     
        if(pindir == dirrequired){
     
          if(iNum == 0){
            *ppPin = pPin;
            hr = S_OK;
            break;
          }
          iNum--;
        } 
        pPin->Release();
      } 
      return hr;
    }
     
    IPin* GetInPin(IBaseFilter* pFilter, int nPin){
     
      CComPtr<IPin> pComPin;
      GetPin(pFilter, PINDIR_INPUT, nPin, &pComPin);
      return pComPin;
    }
     
    IPin* GetOutPin(IBaseFilter* pFilter, int nPin){
     
      CComPtr<IPin> pComPin;
      GetPin(pFilter, PINDIR_OUTPUT, nPin, &pComPin);
      return pComPin;
    }
     
    HRESULT Avi2WavConvertor(LPCWSTR file, LPCWSTR waveFile){
     
      // J'utilise les CComPtr pour chaque interface.
      // Si une erreur se produit, la fonction retourne et "Release" les pointeurs automatiquement.
      CComPtr<IGraphBuilder>    pGraphBuilder;
     
      // On va contrôler chaque filtre.
      CComPtr<IBaseFilter>      pSourceFilter;
      CComPtr<IBaseFilter>      pWavDest;
      CComPtr<IBaseFilter>      pFileWriter;
     
      // L'interface de paramétrage du pFileWriter.
      CComPtr<IFileSinkFilter2> pFileSink;
     
      // Les interfaces IPin pour gérer chaque filtre.
      CComPtr<IPin>             pPinOutSource;
      CComPtr<IPin>             pPinInWavDest;
      CComPtr<IPin>             pPinOutWavDest;
      CComPtr<IPin>             pPinInFileWriter;
     
      // Les interfaces de contrôle (pour jouer le graphe et pour récupérer les évenements du graphe.
      CComPtr<IMediaControl>    pMC;
      CComPtr<IMediaEventEx>    pEvent;
     
      HRESULT hr = S_OK;
     
      //Creation d'un graph builder avec la méthode des CComPtr.
      V_RETURN(pGraphBuilder.CoCreateInstance(CLSID_FilterGraph));
     
      //Ajout du filtre du fichier à rendre.
      V_RETURN(pGraphBuilder->AddSourceFilter(file, L"SourceFilter", &pSourceFilter));
     
      // Creation d'un filtre wavdest et ajout dans le graphe.
      V_RETURN(pWavDest.CoCreateInstance(CLSID_WavDest, NULL, CLSCTX_INPROC_SERVER));
      V_RETURN(pGraphBuilder->AddFilter(pWavDest, L"WavDestFilter"));
     
      // Creation d'un filtre FileWriterFilter et ajout dans le graphe.
      V_RETURN(pFileWriter.CoCreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC_SERVER));
      V_RETURN(pGraphBuilder->AddFilter(pFileWriter, L"FileWriterFilter"));
     
      // Paramétrage du FileWriterFilter après récupération de l'interface adéquate.
      // Le seul paramétrage est de donner le nom du fichier résultant.
      V_RETURN(pFileWriter->QueryInterface(IID_IFileSinkFilter, reinterpret_cast<void**>(&pFileSink)));
      V_RETURN(pFileSink->SetFileName(waveFile, NULL));
     
      // On récupère la pin de sortie du pSourceFilter et la pin d'entrée du pWavDest.
      pPinOutSource = GetOutPin(pSourceFilter, 0);
      pPinInWavDest = GetInPin(pWavDest, 0);
      // On demande au "graphe manager" de connecter ces deux pins.
      // Cette étape peut être longue, selon le format du fichier source.
      V_RETURN(pGraphBuilder->Connect(pPinOutSource, pPinInWavDest));
     
      // On récupère la pin de sortie du pWavDest et la pin d'entrée du pFileWriter.
      pPinOutWavDest   = GetOutPin(pWavDest, 0);
      pPinInFileWriter = GetInPin(pFileWriter, 0);
      // On demande au "graphe manager" de connecter ces deux pins.
      V_RETURN(pGraphBuilder->Connect(pPinOutWavDest, pPinInFileWriter));
     
      // PS: il est possible aussi de tenter une connection directe entre la Pin de sortie du pSourceFilter
      // et la Pin d'entrée du pFileWriter. En général, plus on gére de filtre et meilleur sera le contrôle
      // de la construction du graphe.
     
      //récupération des interfaces courantes IMediaControl et IMediaEventEx.
      V_RETURN(pGraphBuilder->QueryInterface(IID_IMediaControl, reinterpret_cast<void**>(&pMC)));
      V_RETURN(pGraphBuilder->QueryInterface(IID_IMediaEventEx, reinterpret_cast<void**>(&pEvent)));
     
      // Execution du graphe
      V_RETURN(pMC->Run());
     
      long nCode = 0;
     
      // On attends que le fichier soit entièrement rendu.
      while(nCode != EC_COMPLETE){
     
        V_RETURN(pEvent->WaitForCompletion(1000, &nCode));
      }
     
      // C'est terminé, on stoppe tout.
      V_RETURN(pMC->Stop());
     
      // Le nettoyage classique serait de Release toutes les interfaces obtenues.
      // Dans ce code, les CComPtr vont se charger de ce travail, lorsque cette fonction sera quittée.
     
      return S_OK;
    }
     
    int main(void){
     
       WCHAR* file = L"C:\\Documents and Settings\\alexandre cadiou\\Bureau\\hdfg.avi";
       WCHAR* wavefile = L"C:\\Documents and Settings\\alexandre cadiou\\Bureau\\hdfg.wav";
     
       if(SUCCEEDED(CoInitializeEx(NULL, COINIT_MULTITHREADED))){
     
         Avi2WavConvertor(file, wavefile);
     
         CoUninitialize();
       }
       return 0;
    }

  12. #12
    Nouveau Candidat au Club
    Inscrit en
    Mai 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 13
    Points : 1
    Points
    1
    Par défaut merci
    Merci ça marche nikel!

  13. #13
    Nouveau Candidat au Club
    Inscrit en
    Mai 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 13
    Points : 1
    Points
    1
    Par défaut petite modification
    Bonjour Moldavi,

    J'aimerais savoir si il est possible avec Directx de modifier le fichier wav créer par la fonction Avi2Wavconvertor.

    A savoir, le wav crée est en mode stéréo à 44KHz, j'aimerais le modifier en wav mono à 16 KHz.
    Est ce possible?

    Cordialement,
    Acadiou

  14. #14
    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 : 50
    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
    Points : 2 605
    Points
    2 605
    Par défaut
    Re

    Citation Envoyé par acadiou
    Bonjour Moldavi,

    J'aimerais savoir si il est possible avec Directx de modifier le fichier wav créer par la fonction Avi2Wavconvertor.

    A savoir, le wav crée est en mode stéréo à 44KHz, j'aimerais le modifier en wav mono à 16 KHz.
    Est ce possible?

    Cordialement,
    Acadiou
    C'est possible. Il faut un filtre directshow qui se charge de la transformation stéréo/44KHz ---> mono/16KHz.

    A priori ce filtre fait parti de la catégorie des "compressors". Je crois qu'un tel filtre est fournit en standard (vérifier avec graphedit son CLSID: compressor wav).

    Il faut ensuite l'insérer dans le graphe entre le filtre du fichier source et le "wavdest".

    Il faut le paramétrer puis lancer la lecture du fichier.

    L'exemple du site ou il est montré la transformation d'un fichier wav en mp3 est tout à fait identique dans le principe. Tu peux juste éviter la recherche des compressors en chargeant directement le filtre avec son CLSID.

  15. #15
    Nouveau Candidat au Club
    Inscrit en
    Mai 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 13
    Points : 1
    Points
    1
    Par défaut
    Bonjour,
    Je me suis absenté mais je suis de retour avec une fois de plus beaucoup de questions!

    J'ai essayé de faire ce que vous m'avez dit, ça marche j'ai trouvé un filtre qui me fait passer de 44KHz à 22KHZ mais pour mon maître de stage ce n'est pas satisfaisant, en fait il ne veut pas que j'inclus un filtre compressor car il ne veut pas compresser le fichier wav et veut pouvoir intervenir à plusieurs niveau, changer la fréquence comme bon lui semble. Il pense qu'un filtre en terme de boîte n'est pas satisfaisant.
    J'ai trouver dans l'échantillon AudioCap de direct show la fonction suivante qui m'a l'air très interessante

    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
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    HRESULT CAudioCapDlg::SetAudioProperties()
    {
        HRESULT hr=0;
        IPin *pPin=0;
        IAMBufferNegotiation *pNeg=0;
        IAMStreamConfig *pCfg=0;
        int nFrequency=0;
     
        // Determine audio properties
        int nChannels = m_btnMono.GetCheck() ? 1 : 2;
        int nBytesPerSample = m_btn8BIT.GetCheck() ? 1 : 2;
     
        // Determine requested frequency
        if (IsDlgButtonChecked(IDC_RADIO_11KHZ))      
            nFrequency = 11025;
        else if (IsDlgButtonChecked(IDC_RADIO_22KHZ)) 
            nFrequency = 22050;
        else 
            nFrequency = 44100;
     
        // Find number of bytes in one second
        long lBytesPerSecond = (long) (nBytesPerSample * nFrequency * nChannels);
     
        // Set to 50ms worth of data    
        long lBufferSize = (long) ((float) lBytesPerSecond * DEFAULT_BUFFER_TIME);
     
        // Get the buffer negotiation interface for each pin,
        // since there could be both a Capture and a Preview pin.
        for (int i=0; i<2; i++)
        {
            hr = GetPin(m_pInputDevice, PINDIR_OUTPUT, i, &pPin);
            if (SUCCEEDED(hr))
            {
                // Get buffer negotiation interface
                hr = pPin->QueryInterface(IID_IAMBufferNegotiation, (void **)&pNeg);
                if (FAILED(hr))
                {
                    pPin->Release();
                    break;
                }
     
                // Set the buffer size based on selected settings
                ALLOCATOR_PROPERTIES prop={0};
                prop.cbBuffer = lBufferSize;
                prop.cBuffers = 6;
                prop.cbAlign = nBytesPerSample * nChannels;
                hr = pNeg->SuggestAllocatorProperties(&prop);
                pNeg->Release();
     
                // Now set the actual format of the audio data
                hr = pPin->QueryInterface(IID_IAMStreamConfig, (void **)&pCfg);
                if (FAILED(hr))
                {
                    pPin->Release();
                    break;
                }            
     
                // Read current media type/format
                AM_MEDIA_TYPE *pmt={0};
                hr = pCfg->GetFormat(&pmt);
     
                if (SUCCEEDED(hr))
                {
                    // Fill in values for the new format
                    WAVEFORMATEX *pWF = (WAVEFORMATEX *) pmt->pbFormat;
                    pWF->nChannels = (WORD) nChannels;
                    pWF->nSamplesPerSec = nFrequency;
                    pWF->nAvgBytesPerSec = lBytesPerSecond;
                    pWF->wBitsPerSample = (WORD) (nBytesPerSample * 8);
                    pWF->nBlockAlign = (WORD) (nBytesPerSample * nChannels);
     
                    // Set the new formattype for the output pin
                    hr = pCfg->SetFormat(pmt);
                    UtilDeleteMediaType(pmt);
                }
     
                // Release interfaces
                pCfg->Release();
                pPin->Release();
            }
            // No more output pins on this filter
            else
                break;
        }
     
        return hr;
    }
    Je pense que le "m_pInputDevice" dans mon cas sera le micro de la webcam que j'utilise pour AmCap
    ensuite il faut spécifié les différentes entrées du Buffer ici
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
     // Set the buffer size based on selected settings
                ALLOCATOR_PROPERTIES prop={0};
                prop.cbBuffer = lBufferSize;
                prop.cBuffers = 6;
                prop.cbAlign = nBytesPerSample * nChannels;
                hr = pNeg->SuggestAllocatorProperties(&prop);
                pNeg->Release();
    et les charger dans le format actuel comme ici
    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
    18
    // Read current media type/format
                AM_MEDIA_TYPE *pmt={0};
                hr = pCfg->GetFormat(&pmt);
     
                if (SUCCEEDED(hr))
                {
                    // Fill in values for the new format
                    WAVEFORMATEX *pWF = (WAVEFORMATEX *) pmt->pbFormat;
                    pWF->nChannels = (WORD) nChannels;
                    pWF->nSamplesPerSec = nFrequency;
                    pWF->nAvgBytesPerSec = lBytesPerSecond;
                    pWF->wBitsPerSample = (WORD) (nBytesPerSample * 8);
                    pWF->nBlockAlign = (WORD) (nBytesPerSample * nChannels);
     
                    // Set the new formattype for the output pin
                    hr = pCfg->SetFormat(pmt);
                    UtilDeleteMediaType(pmt);
                }
    Je pense que ça se présente comme un filtre que l'on place juste après le micro dans le graphe.

    J'avais déjà ajouter le graphe avi2wav pour avoir un fichier wav, mais maintenant il faut que j'agisse sur l'entrée du graphe de capture, je pense!
    donc ma question est la suivante, dans l'écantillon AmCap dans la fonction AppCommand il y a
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    case MENU_AUDIOFORMAT:
                ChooseAudioFormat();
                break;
    je pense que c'est ici qu'il faut que j'agisse, qu'en pensez vous?

    Merci encore,

    Acadiou

  16. #16
    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 : 50
    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
    Points : 2 605
    Points
    2 605
    Par défaut
    Re.

    Il faut vérifier que le filtre de capture de ton micro est capable de transmettre les données sons sous plusieurs formats. Si ce n'est pas le cas, tu n'auras pas d'autres choix je pense, que de recompresser le fichier avec un filtre adéquat (à positionner après le filtre de capture). Il doit surement exister des filtres de transformation, plus efficace que des compresseurs, mais bon, pour le format wave natif, je ne pense pas que l'on est vraiment à faire à de la compression (au contraire du mp3).

    Dans l'idée les interfaces que tu proposes ci-dessus permettent ce genre de traitement.

    Une chose à vérifier aussi: lors d'un changement de format, il est parfois nécessaire de stopper le graphe, voir de le reconstruire entièrement, tout dépend de la façon dont sont développés les filtres.


    PS: tu es le deuxième stagiaire que j'aide et qui travaille sur directshow. Je suis étonné d'un tel choix pour un stage. Du moins par rapport à l'utilisation d'une technologie très spécifique comme DShow. Qui a choisit le thème du stage?

  17. #17
    Nouveau Candidat au Club
    Inscrit en
    Mai 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 13
    Points : 1
    Points
    1
    Par défaut :)
    C'est bon! J'ai résolu le problème hier, je peux modifier la fréquence le nombre de canaux ça marche nikel, j'ai juste un peu galérer pour positionner ma fonction, je l'ai mise dans la fonction builgraph juste avant le render stream et ça marche.

    Sinon pour répondre à votre question:

    Je suis en dernière année de l'ISEP (institut supérieur d'éléctronique de paris) www.isep.fr

    J'ai choisi de faire mon stage de dernière année en Russie à Saint petersbourg.

    Le sujet était "développement d'interfaces multimodales" j'ai dans un premier temps améliorer une interface multimode pour utilisateurs handicappés qui ne peuvent utiliser leurs mains"
    j'ai publié un article, je peux vous l'envoyer si vous me donnez votre adresse email.
    Et en ce moment comme vous le savez je modifie l'échantillon Amcap
    Mon maître de stage veut créer une base de données de "speech command"
    Au début nous avions réalisé ce programme de capture avec OpenCv comme lors de ma première tâche, mais OpenCv n'est pas assez rapide et il était indispensable que l'on ait un framerate de 25 FPS, opencv ne nous donnez que 13 fps au mieux
    donc il a fallu tout refaire avec directshow qui est plus rapide.
    Au début lorsque j'ai vu AmCap je ne savais pas par où commencer il a fallu que j'aille sur des forums comme celui ci pour comprendre ce qu'est un graphe.
    Il n'y a pas beaucoup de documentation sur le net, ça a été très difficile au début.
    Donc j'utilise directshow uniquement pour créer un outil de capture qui servira plus tard au développement d'une autre interface multimodale, en fait ce n'est qu'une toute petite étape ais vu qu'il y a des milliers de commande vocales et vidéos à enregistrer, il faut que l'application soit costaud!
    Voilà.
    Sinon la russie c'est sympa, je parle assez bien le russe et je finis mon stage fin août
    Et vous pourquoi connaissez vous aussi bien directshow?

    Acadiou

  18. #18
    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 : 50
    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
    Points : 2 605
    Points
    2 605
    Par défaut
    Re.

    Je suis content de savoir que je parle à un russe

    Pour directshow, ne t'inquiètes pas, c'est la galère pour beaucoup de personnes.

    Je connais bien cette API, parce que dans mon bouleau je développe des logiciels audio/vidéo/3D.

  19. #19
    Nouveau Candidat au Club
    Inscrit en
    Mai 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 13
    Points : 1
    Points
    1
    Par défaut
    Bonjour (Privet! en russe)

    J'ai une nouvelle question!

    Toujours dans l'échantillon AmCap de direct show que je modifie

    Voilà ce que j'aimerais faire, au lieu de runner la capture en cliquant sur "start capture" j'aimerais runner cette capture en enfonçant une touche par exemple la barre espace, tant que je garde cette touche enfoncée la capture a lieu puis dès que je la relache cela a pour effet de stopper la capture et de sauvegarder le fichier dans le .avi et dans le .wav!

    Voici le problème,
    Tout est agencé séparement en fonction des évènements dans la fonction "AppCommand"

    Un case correspond à "capture", un autre à "stopper la capture" un autre à la "sauvegarde des fichiers"

    Bref avec mon event clavier je vais devoir tout mettre dans un seul case

    Premièrement comment récupérer l'event "touche enfoncé" "touche relachée"?
    J'ai déjà trouvé sur le net les fonctions key_event() pour simuler une touche mais ce n'est pas ce que je veux faire
    j'ai aussi trouver la fonction GetAsyncKeyState(int numkey) qui teste l'état d'une touche enfoncée ou relachée!

    Alors j'ai fait un petit test qui ne marche pas!

    Le case "capture" original est celui-ci

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    case MENU_START_CAP:
                if(gcap.fPreviewing)
                    StopPreview();
                if(gcap.fPreviewGraphBuilt)
                    TearDownGraph();
     
     
                BuildCaptureGraph();
                StartCapture();
     
     
                break;
    Je voulais le modifier un peu comme ceci

    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
    18
    19
    20
    21
    22
    23
    24
     
           case MENU_START_CAP:
     
        	if(GetAsyncKeyState(0x08) == 1) //si la barre espace est enfoncé
       {
                    if(gcap.fPreviewing)
                    StopPreview();
                    if(gcap.fPreviewGraphBuilt)
                    TearDownGraph();
    	        BuildCaptureGraph();
                    StartCapture();// on capte
     
                    if(GetAsynckeyState(0x08)==0) // si on a relaché la barre espace ça signifie "stop + sauvegarde!"
                             {
                                  StopCapture();
                                  if(gcap.fWantPreview)
                                          {
                                                  BuildPreviewGraph();
                                                  StartPreview();
                                           }
                                  SaveCaptureFile(hwnd);
    			      Avi2WavConvertor(file , wavefile);
     
                              }
    Et donc ça ne marche pas, alors comment récupérer un évènement clavier proprement?
    A l'avenir il y aura plus d'option et j'aimerais même ne plus passer par le menu de la fenêtre donc ne plus avoir à passer par le case
    mais appuier sur la barre espace directement puis la relacher pour capturer stopper et sauvegarder avec une seule touche!

    J'aimerais par la suite éditer tout un tas de commandes vocales
    je créerai un tableau de string dans lequel j'écrierais des commandes à prononcer
    Il y aura tout une liste, un pointeur se mettra au début du tableau puis dès que j'aurais cliquer sur espace et relaché la capture aura eu lieu, j'aurais le fichier avi et wav de la commande prononcée puis je me décalerai d'un espace dans le tableau jusqu'à la prochaine commande et ainsi de suite, en fait ce programme n'est qu'un créateur de base de données audio et vidéo pour des commander données "ouvrir, fermer, agrandir..." mais tout cela en Russe bien sûr!
    Merci encore!

    Do cvidania!!!
    Acadiou

  20. #20
    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 : 50
    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
    Points : 2 605
    Points
    2 605
    Par défaut
    Re.

    Tu t'embêtes pour rien avec les "GetAsyncKeyState". Dans "AmCap", tu as la fonction:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
     
    LRESULT CALLBACK statusWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
    Lorsqu'une touche est enfoncée, tu reçois le message WM_KEYDOWN. Et lorsqu'une touche est relâchée, c'est le message WM_KEYUP. Ensuite avec un switch, tu peux retrouver la touche concernée (VK_SPACE pour la barre espace).

Discussions similaires

  1. Streaming audio-video: JMF ?
    Par sir_gcc dans le forum Multimédia
    Réponses: 15
    Dernier message: 01/11/2011, 12h54
  2. Streaming Audio
    Par myke38 dans le forum C++Builder
    Réponses: 1
    Dernier message: 27/02/2005, 23h56
  3. Streaming audio, comment faire ?
    Par Pill_S dans le forum Général Conception Web
    Réponses: 3
    Dernier message: 04/02/2005, 10h29
  4. [Stratégie] streaming audio
    Par Slaya dans le forum Développement
    Réponses: 11
    Dernier message: 20/01/2005, 21h23
  5. [Multimédia] Explication sur stream audio
    Par champion dans le forum Développement
    Réponses: 1
    Dernier message: 20/01/2005, 12h14

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