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

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Inscrit en
    Mai 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 13
    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 : 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
    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
    Membre habitué
    Inscrit en
    Mai 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 13
    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 : 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
    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
    Membre habitué
    Inscrit en
    Mai 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 13
    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 : 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
    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 : 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
    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
    Membre habitué
    Inscrit en
    Mai 2006
    Messages
    13
    Détails du profil
    Informations forums :
    Inscription : Mai 2006
    Messages : 13
    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

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