[C / C++] cherche un dieu du DirectShow (graphe/filtres)

cherche un dieu du DirectShow (graphe/filtres) [C / C++] - C++ - Programmation

Marsh Posté le 02-04-2002 à 14:08:07    

J'aimerai écrire une app. qui convertit des fichiers AVI en ASF.
Dans tous les SDK il est écrit qu'une méthode simple pour faire ce genre de conversion est d'utiliser la fonc  
'pGraph->RenderFile(L"fichier.avi" , NULL)' qui va construire automatiquement le graphe en y ajoutant tous les filtres nécessaire et en connectant les différents pins. Ensuite il suffit d'enlever les filtres de rendu (vidéo et audio) en déconnetant d'abord les pins correspondant et d'ajouter son filtre (dans mon cas un asfwriter) et de le conneter aux pins de sortie auxquelles étaient connecté les filtres de rendu.
 
La question est:
Comment fait-on pour trouver ces filtres de rendu ? je ne connais par le nom attribué par le graphe donc je ne peut pas utiliser la fonc. FindFilterByName()... quand je fait une énumération de ces filtres, coment puis-je savoir que tel filtre est le filtre de rendu.
 
Je pourrai aussi essayer avec un 'GetClassID()' de réperer les filtres de rendu mais le problème c qu'encore une fois je ne sais pas quels filtres seront utilisé pour le rendu (cela peut dépendre du hardware dans la machine je pense non ?)
 
Merci d'avance !

 

[jfdsdjhfuetppo]--Message édité par ZZZzzz--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 02-04-2002 à 14:08:07   

Reply

Marsh Posté le 03-04-2002 à 12:17:54    

bon finalement j'utilise l'interface CaptureGrapheBuilder pour simplifier les connections des pins et ainsi je peux me permettre de construire mon propre graphe sans avoir à remplacer des filtres.  
Voici mon code:
 
"
HRESULT AviToWMV(const CHAR* InFile, const CHAR* OutFile, DWORD IndexProfile )
{
    HRESULT     rval = S_OK;
 
 IGraphBuilder*   pGraph = NULL;
    IMediaFilter*   pMediaFilter = NULL;
 IMediaControl*   pMediaControl = NULL;
 IMediaEventEx*   pMediaEventEx = NULL;
 ICaptureGraphBuilder2* pCaptureBuilder = NULL;
 IBaseFilter*   pSourceFilter = NULL;
 //IBaseFilter*   pAVISplitter = NULL;
 IBaseFilter*   pASFWriter = NULL;
 IFileSinkFilter*  pFileSinkFilter = NULL;
 IConfigAsfWriter*  pConfigASFWriter = NULL;
 WCHAR*     wFile = NULL;
 
//msg("s5" );
 // on crée le graph
 JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, // à voir ce dernier param
          IID_IGraphBuilder, (LPVOID *)&pGraph));
 
 // on y ajoute un filtre de "lecture" asynchrone de données AVI
 wFile = (WCHAR*)malloc((strlen(InFile)+1)*sizeof(WCHAR));
    wcscpy(wFile, T2W(InFile));  
 LIF(pGraph->AddSourceFilter(wFile, L"Source Filter", &pSourceFilter));
 SAFE_FREE(wFile);
 if(FAILED(rval)) goto start_error;
 
//msg("s6" );
 // on crée le capture builder qui va nous faciliter la vie
 LIF(CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC,  
  IID_ICaptureGraphBuilder2, (void **)&pCaptureBuilder))
 if(FAILED(rval)) goto start_error;
 
 // Associate the graph with the builder.
 LIF(pCaptureBuilder->SetFiltergraph(pGraph))
 if(FAILED(rval)) goto start_error;
 
 
//msg("s7" );
 { // AddKeyProvider()
  prov.AddRef();
  // Give the graph an IObjectWithSite pointer to us for callbacks & QueryService.
  IObjectWithSite* pObjectWithSite = NULL;
  rval = pGraph->QueryInterface(IID_IObjectWithSite, (void**)&pObjectWithSite);
  if (SUCCEEDED(rval))
  {
   rval = pObjectWithSite->SetSite((IUnknown *) (IServiceProvider *) &prov);
   SAFE_RELEASE(pObjectWithSite);
  }
  if(FAILED(rval)) goto start_error;
 }
 
//msg("s8" );
 // on construit l'ASF Writer et le FileSink
 wFile = (WCHAR*)malloc((strlen(OutFile)+1)*sizeof(WCHAR));
    wcscpy(wFile, T2W(OutFile));  
 LIF(pCaptureBuilder->SetOutputFileName(&MEDIASUBTYPE_Asf, wFile, &pASFWriter, &pFileSinkFilter));
 SAFE_FREE(wFile);
 if(FAILED(rval)) goto start_error;
 
 // l'avi spliter
 //LIF(CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC,  
 // IID_ICaptureGraphBuilder2, (void **)&pAVISplitter))
 //if(FAILED(rval)) goto start_error;
 
 // le décompresseur audio
 
 // le vidéo...
 
//msg("s9" );
 // et on connecte les pins:
 LIF(pCaptureBuilder->RenderStream(0, 0, pSourceFilter,  NULL, pASFWriter));
 if(FAILED(rval)) goto start_error;
 
 
    // vitesse max pour la conversion
    // Keep a useless clock from being instantiated....
    LIF(pGraph->QueryInterface(IID_IMediaFilter, (void **) &pMediaFilter));
 if(FAILED(rval)) goto start_error;
    LIF(pMediaFilter->SetSyncSource(NULL));
 if(FAILED(rval)) goto start_error;
 
 
 // on récupère maintenant un control pour lancer la conversion
 LIF(pGraph->QueryInterface(IID_IMediaControl, (void **)&pMediaControl));    
 if(FAILED(rval)) goto start_error;
 
 LIF(pGraph->QueryInterface(IID_IMediaEventEx, (void **)&pMediaEventEx));    
 if(FAILED(rval)) goto start_error;
 
msg("avant Run" );
 LIF(pMediaControl->Run());
 if(FAILED(rval)) goto start_error;
msg("go !" );
 
 // on attends que ça se termine, donc pour l'instant c un processus bloquant
 long evcode;
 LIF(pMediaEventEx->WaitForCompletion(1000 * 120, &evcode));  
 if(FAILED(rval)) goto start_error;
 
 LIF(pMediaControl->Stop());
 if(SUCCEEDED(rval)) msg("finish !" );
 
start_error:
if(FAILED(rval)) msg(Error);
 
 SAFE_RELEASE(pCaptureBuilder);
 SAFE_RELEASE(pGraph);
    SAFE_RELEASE(pMediaFilter);
 SAFE_RELEASE(pMediaControl);
 SAFE_RELEASE(pMediaEventEx);
 SAFE_RELEASE(pSourceFilter);
 SAFE_RELEASE(pASFWriter);
 SAFE_RELEASE(pFileSinkFilter);
 SAFE_RELEASE(pConfigASFWriter);
 
 
    return ( rval );
}
"
 
 
Lors de l'appel à pMediaControl->Run() j'ai une "assertion failed", et la fonction me retourne l'erreur E_FAIL (pas très explicite)... keski ne va pas dans mon code ? les filtres ne sont pas correctes ? ça ne fonctionne même pas pour une vidéo AVI non compressé... est-ce que je dois ajouter moi-même d'éventuel filtre de décompression pour des fichiers AVI compressé ou les connections (dites intelligentes) s'ent ocuuperont toutes seules ?
 
 Merci d'avance !

Reply

Marsh Posté le 03-04-2002 à 13:08:45    

bon j'ai changé le titre du topic ça va ptêt attirer des personnes :sarcastic:

Reply

Marsh Posté le 15-04-2002 à 10:40:10    

j'ai réussi à faire un code qui fonctionne bien... je peux convertir pas mal de format vidéo en ASF maintenant (certains font encore une assertion failed lors du Run si le format de départ ne convient pas, c énervant.. n'y-a-t-il pas un moyen d'éviter cela ????)...
par contre je n'arrive pas à avoir la progression de la compression... j'ai pourtant crée un IMediaEventEx mais celui-ci ne m'envoie jamais rien (sauf si je force un Stop() ou un Pause() )... je ne peux même pas savoir lorsque la conversion est terminée.. comment cela se fait-il ? je peux mettre un bout de mon code si vous le souhaiter ... merci d'avance !

Reply

Marsh Posté le 15-04-2002 à 12:43:17    

ZZZzzz a écrit a écrit :

j'ai réussi à faire un code qui fonctionne bien... je peux convertir pas mal de format vidéo en ASF maintenant (certains font encore une assertion failed lors du Run si le format de départ ne convient pas, c énervant.. n'y-a-t-il pas un moyen d'éviter cela ????)...
par contre je n'arrive pas à avoir la progression de la compression... j'ai pourtant crée un IMediaEventEx mais celui-ci ne m'envoie jamais rien (sauf si je force un Stop() ou un Pause() )... je ne peux même pas savoir lorsque la conversion est terminée.. comment cela se fait-il ? je peux mettre un bout de mon code si vous le souhaiter ... merci d'avance !  




 
Je ne m'y connais pas trop mais pour une appli dvd par ex, il faut faire un dvdcontrol.setoption(nom_de_l'event,true) pour que le IMEDIAEventEX les recoivent.
Ainsi on peut savoir la progression en HH:MM:SS:FF de la lecture du dvd.
 
Il faut peut etre activer une option de ce type pour savoir la progression de la compression.


---------------

Reply

Marsh Posté le 15-04-2002 à 13:18:10    

en fait ya pas d'évenements pour récupérer le temps pour la lecture d'un fichier autre que du DVD... enfin je crois (on peut pas récuperer l'évenement EC_END_OF_SEGMENT ou EC_END_OF_STEP car c destiné à un autre usage). j'ai crée un timer qui toute les 500 ms récupère la position courante du playback (avec l'interface IMediaPosition et la méthode get_CurrentPosition()) mais là encore ça foire: ça retourne toujours 0, idem pour la méthode get_StopTime() (pourtant la fonction retourne bien S_OK)... je comprends pas car ça fonctionne correctement pour de la lecture de fichier AVI par exemple, pourquoi on ne peut pas récupérer ce même temps pour de la conversion ?? à priori le mécanisme est le même (sauf que la sortie du graphe n'est pas la même)... kk'un sait-il comment faire ?
 
un ptit bout de mon de code:
 
"  case WM_TIMER:
   {
    float pos = (float)Capturer->GetPosition();
    float duree = (float)Capturer->GetDuration();
    CDC* pcdc = GetDC();
    if(!pcdc) {
     strcpy(Capturer->Error, "Conversion: Cannot Get hdc" );
     return E_FAIL;
    }
    RECT r;
    GetClientRect(&r);
    pcdc->SetTextAlign(TA_CENTER | VTA_CENTER);
    pcdc->SetTextColor(RGB(0xFF, 0xFF, 0xFF)); // texte en blanc
    pcdc->SetBkColor(RGB(0x0, 0x0, 0x0));  // sur fond noir
    pcdc->SetBkMode(OPAQUE);  
 
 
    if(duree) {
     DWORD pourcentage = (DWORD)((float)(pos/(float)duree)*100.0f);
     char ch[50];
     Msg(ch, "      Conversion : %d %%      ", pourcentage);
     pcdc->TextOut(r.right/2, r.bottom/2, ch, strlen(ch));
    }
   }
 
   return 0;
   
"
 
Capturer->GetPosition() et Capturer->GetDuration() appelle respectivement pMediaPosition->get_CurrentPosition() et pMediaPosition->get_StopTime()
 
ça retourne toujours 0 .. j'y comprend rien   :cry:  :cry: !!
 
en tout cas merci pour ton aide radeontof !

 

[jfdsdjhfuetppo]--Message édité par ZZZzzz--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 15-04-2002 à 14:11:55    

De rien.
 
Je sais qu'avec certains formats on ne peut pas avoir la  
position en cours : le mp2 par exemple.
Quand tu fais un getposition t'as 0.
Je sais pas si l'asf fait la même chose.


---------------

Reply

Marsh Posté le 15-04-2002 à 14:50:12    

non l'asf tu peux avoir la position... en tout cas lors d'une lecture. moi mon graphe fait une conversion AVI -> ASF, et ça à priori on ne peut pas récupérer la position courante. enfin j'en sais rien mais moi j'y arrive pas (alors que lors d'une lecture je n'ai aucun probs)... cependant ça serait vraiment étonnant qu'on ne puisse pas avoit la position courante, si cété le cas comment fait-on pour afficher la progression de la conversion ??

Reply

Marsh Posté le 15-04-2002 à 15:03:54    

oui ben en fait je viens de me rendre compte que ce type de graphe ne supporte pas le GetDuration ou GetPosition (par l'intermédiaire de la méthode IMediaSeeking::CheckCapabilities() )
Je suis dégoûté ... comment faire pour afficher une progression de la conversion en pourcentage dans ce cas (car c long en général, il faut que l'utilisateur puisse savoir si ce n'est pas planté) :( ?? kk'un a-t-il une idée ??
 
[edit] ah non je dis des conneris, c la fonction GetCapabilities() que je devais faire, et celle-ci me renvoie que le getposition et le getduration est bien supporté... je vais donc essayé avec l'interface IMediaSeeking...

 

[jfdsdjhfuetppo]--Message édité par ZZZzzz--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 15-04-2002 à 15:24:45    

bonne chance...


---------------

Reply

Marsh Posté le 15-04-2002 à 15:24:45   

Reply

Marsh Posté le 15-04-2002 à 15:30:53    

hurra !! ça marche avec le IMediaSeeking !! j'aurai dû y penser avant ... m'enfin :) !!  
dans le sdk ils disent que ce n'est pas très fiable dans le cas d'une écriture de fichier (c mon cas) et qu'il vaut mieux interroger le fitlre de multiplexage mais apparement ça marche pas mal quand même :) (et pis je connais pas la méthode getposition du filtre de multiplexage) !

Reply

Marsh Posté le 15-04-2002 à 15:39:20    

ZZZzzz a écrit a écrit :

hurra !! ça marche avec le IMediaSeeking !! j'aurai dû y penser avant ... m'enfin :) !!  
dans le sdk ils disent que ce n'est pas très fiable dans le cas d'une écriture de fichier (c mon cas) et qu'il vaut mieux interroger le fitlre de multiplexage mais apparement ça marche pas mal quand même :) (et pis je connais pas la méthode getposition du filtre de multiplexage) !  




 :sol:


---------------

Reply

Marsh Posté le 17-04-2002 à 12:14:05    

j'ai un autre problème maintenant:  
pour la progression de la conversion je gère les évenements par une wndproc grâce à l'interface IMediaEventEx qui m'envoie ces évenements. Mais je n'arrive pas à connaitre la signification de certains d'entre eux comme ceux dont la valeur hexa est: 0x46, 0x48 et 0x49... et j'aurai besoin de savoir à quoi ils servent peut-être que cela m'aiderai à comprendre pourquoi la conversion de fichier ne contenant un flux audio vide foire (car dans ce cas j'ai un ev. = 0x46 d'envoyé mais je ne peux pas réagir à celui-ci puisque je ne sais pas ce qu'il indique)...  je n'ai pas trouvé leur signification dans les SDK ni dans le fichier evcodes.h... any ideas ?
 
pour illustrer un des problèmes que cela pose,  voici un bout de mon code:  
 
"CDC* pcdc = GetDC();
 RECT r;
 GetClientRect(&r);
 if(!pcdc) {  
  strcpy(Capturer->Error, "Convert To WMV: Cannot Get hdc" );
  return E_FAIL;
 }
 
//msg("c3" );
 
 // et on peint le rectangle en noir avant d'afficher le texte
 pcdc->SetTextAlign(TA_CENTER | VTA_CENTER);
 pcdc->SetTextColor(RGB(0xFF, 0xFF, 0xFF)); // texte en blanc
 pcdc->SetBkColor(RGB(0x0, 0x0, 0x0));  // sur fond noir
 pcdc->SetBkMode(OPAQUE);  
 pcdc->FillSolidRect(r.left, r.top, r.right, r.bottom, RGB(0x0, 0x0, 0x0));
 x = r.right/2; y = r.bottom/2;
 pcdc->TextOut(x, y, "   Initializing Conversion...   ", strlen("   Initializing Conversion...   " ));
 
 /**/ReleaseDC(pcdc);
 
   
//msg("c4" );
 rval = Capturer->ConvertToASF(hwnd, InputFilename, OutputFilename, Profile);
//msg("c5" );
 
 // ******* on rechoppe un nouveau DC qui aurait pû être perdu entre temps ******** //
 // pas logique !!!!!!
 pcdc = GetDC();
 GetClientRect(&r);
 if(!pcdc) {  
  strcpy(Capturer->Error, "Convert To WMV: Cannot Get hdc" );
  return E_FAIL;
 }
 
 // on remet les params d'affichage
 pcdc->SetTextAlign(TA_CENTER | VTA_CENTER);
 pcdc->SetTextColor(RGB(0xFF, 0xFF, 0xFF)); // texte en blanc
 pcdc->SetBkColor(RGB(0x0, 0x0, 0x0));  // sur fond noir
 pcdc->SetBkMode(OPAQUE);  
 
 if(FAILED(rval)) {
  pcdc->FillSolidRect(r.left, r.top, r.right, r.bottom, RGB(0x0, 0x0, 0x0));
  pcdc->TextOut(x, y, "Failed to initialise Conversion", strlen("Failed to initialise Conversion" ));
  Sleep(1200);  
//msg("c6 failed" );
 }
 else {
  pcdc->FillSolidRect(r.left, r.top, r.right, r.bottom, RGB(0x0, 0x0, 0x0));
  pcdc->TextOut(x, y, "Converting, please wait...", strlen("Converting, please wait..." ));
//msg("c6" );
 
  if(!SetTimer(CONVERT_TIMER, 500, NULL)) {
   pcdc->TextOut(x, y, "Failed to create timer    ", strlen("Failed to create timer    " ));
   rval = E_FAIL;
  }
 }
"
 
ben c du code dégueu bourrin mais ça marche.. le problème est que je suis obligé de faire un ReleaseDC() + GetDC() à nouveau (après l'appel à l'initalisation de la conversion) sinon lors du prochain appel à pcdc->TExtOut() ça plante (et uniquement si la fenêtre ped le focus entre temps) !! j'ai remarqué que juste avant le plantage je reçois un évenement = 0x49... si je ne reçois pas cette évenement ça ne plante pas ! donc il faut que je sache ce qu'il signifie !

 

[jfdsdjhfuetppo]--Message édité par ZZZzzz--[/jfdsdjhfuetppo]

Reply

Marsh Posté le 17-04-2002 à 14:02:16    

:bounce:

Reply

Marsh Posté le 17-04-2002 à 16:56:02    

:bounce:  :bounce:

Reply

Marsh Posté le 18-04-2002 à 09:42:42    

personne ne sait ?? ah et pas moyen de trouver la solution kkpart (group google, site microsoft) :cry:  !!

Reply

Marsh Posté le 18-04-2002 à 11:29:12    

ça ne fera jamais que le 5ème UP ...

Reply

Sujets relatifs:

Leave a Replay

Make sure you enter the(*)required information where indicate.HTML code is not allowed