Programmation Multimédia Cours de programmation DirectShow

Transcription

Programmation Multimédia Cours de programmation DirectShow
Programmation Multimédia
Master d'Informatique 2004-2005
Programmation Multimédia
Cours de programmation DirectShow
Pascal Mignot / Pascal Gardeur
Partie 2:
1. Typologie et principes généraux sur les filtres
2. Installation de nouveaux filtres
3. Compression
4. Filtres de sortie
5. Périphériques matériels et interactions avec DirectShow
6. Enumération des filtres disponibles sur un système
7. Gestion des périphériques d'acquisition
8. Contrôle du rendu
9. Debug de DirectShow
Annexes
A : Montage Vidéo
B : Contrôle d'un caméscope numérique
C : Contrôle d'une carte Tuner TV
D : Contrôle d'un DVD
Reproduction et diffusion interdites.
Page 1/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Typologie et principes généraux sur les filtres
Nous présentons dans cette section une partie des filtres DirectShow les plus directement
utilisables.
L'installation de codecs et de filtres particuliers (cf le SDK) permet d'accroître le nombre
de filtres disponibles.
1) Filtres génériques
a) filtres sources
File Source (Async) (CLSID_AsyncReader)
Lecture de fichier asynchrone (bref classique)
File Source (URL) (CLSID_URLReader)
Lecture d'un flux depuis une URL.
b) filtres passants
Smart Tee (CLSID_SmartTee)
Duplication de l'entrée (une entrée, 2 sorties : capture et preview)
Infinite Pin Tee (CLSID_InfTee)
Duplication multiple de l'entrée (une entrée, n sorties)
Sample Grabber (CLSID_SampleGrabber)
Capture des échantillons (passant)
c) filtres de rendu
File Writer (CLSID_FileWriter)
Si le flux n'a pas été converti dans un format reconnaissable, il ne pourra pas être
relu (pour l'audio, utiliser wavDest; pour la vidéo, utiliser l'avi Muxer).
Null Renderer (CLSID_NullRenderer)
Equivalent de /dev/null dans un graphe.
2) Filtres de gestion audio
a) Parser/decoder
Page 2/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
WAVE Parser (CLSID_WAVEParser)
ACM Wrapper (CLSID_ACMWrapper)
Le type de ce filtre est instancié à sa création (quel codec, codage/décodage)
Wave Dest (cf le SDK)
Permet de transformer un flux PCM/audio en flux .wav
b) Filtres transformants
DMO Wrapper (CLSID_DMOWrapperFilter)
Permet d'utiliser des Direct Media Objects dans un graphe
Remarques:
• les effets DirectSound (en rendu ou en capture) sont utilisables avec DirectShow
sous forme de DMO.
• lors de l'installation de certains produits (par exemple Sound Forge), les filtres
audio de l'application sont disponibles sous forme de filtre DirectShow.
c) Filtres de rendu
Default Audio Renderer (WaveOut) (CLSID_AudioRender)
DirectSound Renderer (CLSID_DSoundRender)
d) Manipulation de flux au format Midi
MIDI Parser (cf doc)
Midi Renderer (CLSID_AVIMIDIRender)
e) Filtre de capture
Audio Capture (analogique micro/cd/midi)
CLSID_AudioInputMixerProperties
f) Utilisations classiques
•
•
•
•
Lecture d'un fichier audio au format WAV
File Source Wave Parser Audio Renderer
Lecture d'un fichier audio au format mp3
File Source MPeG1 Splitter ACM Wrapper
Wave Parser Audio Renderer
Remarque: l'ACM Wrapper filter s'instancie comme un décodeur mp3.
Rappel: mp3 = MPeG1 audio layer 3
Lecture d'un fichier audio au format midi
File Source Midi Parser Midi Renderer
Capture audio
Page 3/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
•
Master d'Informatique 2004-2005
Conversion d'un fichier wav en fichier mp3
File Source Wave Parser ACM Wrapper Wave Dest File Writer
Remarque: l'ACM Wrapper filter s'instancie comme un encodeur mp3.
3) Filtres de gestion vidéo
a) Gestions internes
Video Renderer (Video Mixing Renderer 7)
Video Mixing Renderer 9
Color Space Converter
Change le format de couleur (entre RGB8, RGB555, RGB565, RGB24, RGB32)
b) Format AVI
Lecture:
Avi Splitter (CLSID_AviSplitter)
AVI Decompressor (CLSID_AVIDec)
Instance d'un décodeur VCM
Ecriture:
AVI Compressor
Instance d'un encodeur VCM
AVI Mux (CLSID_AviDest)
Utilisations classiques:
• Lecture d'un fichier AVI (audio au format PCM)
Page 4/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
•
Master d'Informatique 2004-2005
Changement du format d'un fichier AVI (l'audio restant au format PCM)
c) Format MPeG1 (svcd et super VideoCD)
MPEG-1 Stream Splitter
Sépare l'audio et la vidéo d'un flux mpeg1
MPEG-1 Video Decoder
MPEG-1 Audio Decoder
Remarque: le muxer et les encoder MPeG1 ne font par partie de DirectShow (installer les
codecs adéquats dans ce but).
Utilisation classique:
File
Source
MPeG1
Stream
Splitter
video
audio
MPeG1
Video Decoder
MPeG1
Audio Decoder
d) Format MPeG2 et DVD
MPEG-2 Demultiplexer (CLSID_MPEG2Demultiplexer)
Séparation d'un flux mpeg2
MPEG-2 Sections and Tables (CLSID_Mpeg2Data)
Données mpeg2 (caractéristique des services, droit d'abonnements, …)
MPEG-2 Splitter (CLSID_MMSPLITTER)
DVD Navigator
Remarque: le muxer et les encoder MPeG2 ne font par partie de DirectShow (installer les
codecs adéquats dans ce but).
Page 5/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Utilisation classique:
Voir en annexe pour plus de précision.
e) Format ASF
WM ASF Writer (CLSID_WMAsfWriter)
Ecriture dans un fichier au format ASF
WM ASF Reader (CLSID_WMAsfReader)
Lecture dans un fichier au format ASF
Utilisation classique:
f) Incrustation / Télétext / Sous-titres
Page 6/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Overlay Mixer (CLSID_OverlayMixer)
Overlay Mixer 2 (CLSID_OverlayMixer2)
World Standard Teletext Decoder (CLSID_WSTDecoder)
Synchronized Accessible Media Interchange (CC) Parser
Line 21 Decoder (DVD video/CC decoder)
4) Capture vidéo
a) Capture vidéo (caméra & webcam)
WDM Video Capture (CLSID_VideoInputDeviceCategory)
VFW Capture Filter (CLSID_VfwCapture)
Remarque: les périphériques de capture vidéo expose généralement une borne de
Capture et une borne de Preview. La borne de Preview peut dégrader ses performances de
façon à conserver la qualité de la borne de Capture.
Dans le cas où la borne de Preview n'est pas disponible, on utilise le filtre suivant. Ce
filtre peut être utilisé dans n'importe quel autre cadre similaire.
Smart Tee filter (CLSID_SmartTee)
Duplique l'entrée vidéo (une entree, deux sorties: capture + renderer)
b) Capture vidéo analogique
Deux filtres permettent de récupérer les données en provenance d'un tuner TV:
Page 7/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
•
•
Master d'Informatique 2004-2005
TV Audio (CLSID_TVAudioFilter) audio analogique
TV Tuner (CLSID_TVTunerFilter) vidéo analogique
WDM Analog Video Crossbar (TV tuner) (CLSID_CrossbarFilterPropertyPage)
A noter que des connections internes doivent être faites de façon à relier les entrées vidéo
et audio disponibles vers la sortie vidéo et audio du Crossbar.
Voir en annexe pour plus de précision.
c) Caméscope numérique
Les caméscopes numériques stockent les informations sous forme de flux (dvsd) qui
inclus l'audio et la vidéo sous forme interlacée. Le passage sous forme interlacée
(muxer/splitter) se fait avec les deux filtres suivants:
DV Splitter (CLSID_DVSplitter)
DV Muxer (CLSID_DVMux)
AVI type I et II:
Type II : fichier avi classique.
Type I : fichier DV.
Type I
AVI
splitter
Type II
AVI
splitter
Page 8/71
DV
splitter
video
audio
DV
Muxer
video
audio
AVI
Mux
AVI
Mux
Type II
Type I
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Accès aux périphériques:
Instance
d'un
filtre
WDM
Video
Capture
de
catégorie
"CLSID_VideoInputDeviceCategory" ou "AM_KSCATEGORY_RENDER".
Filtres de codage/décodage DV
DV Video Encoder (CLSID_DVVideoEnc)
DV Video Decoder (CLSID_DVVideoCodec)
Utilisations classiques:
• DV out (lecture d'une cassette numérique)
•
DV in (enregistrement sur une cassette numérique)
Voir en annexe pour plus de précision.
d) Broadcast Driver Architecture (BDA)
Page 9/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
4. Propriétés
Les propriétés d'une grande partie des périphériques peuvent afficher une boite de
dialogue permettant de configurer le filtre.
La fonction suivante permet d'afficher l'interface de configuration du filtre (certaines
n'ont de sens qu'en mode debug).
HRESULT ShowPropertyDialog(IBaseFilter *Filter, HWND hwnd) {
ISpecifyPropertyPages *Prop;
HRESULT h = Filter->QueryInterface(IID_ISpecifyPropertyPages,
(void **)&Prop);
if FAILED(h) return h;
FILTER_INFO FilterInfo;
h = Filter->QueryFilterInfo(&FilterInfo);
IUnknown *FilterUnk = NULL;
Filter->QueryInterface(IID_IUnknown, (void **)&FilterUnk);
// Show the page.
CAUUID caGUID;
Prop->GetPages(&caGUID);
SAFE_RELEASE(Prop);
OleCreatePropertyFrame(
hwnd,
0, 0,
FilterInfo.achName,
1,
&FilterUnk,
caGUID.cElems,
caGUID.pElems,
0,
0, NULL
//
//
//
//
//
//
//
//
//
Parent window
Reserved
Caption for the dialog box
Number of objects (just the filter)
Array of object pointers.
Number of property pages
Array of property page CLSIDs
Locale identifier
Reserved
);
Page 10/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
// Clean up.
SAFE_RELEASE(FilterUnk);
SAFE_RELEASE(FilterInfo.pGraph);
CoTaskMemFree(caGUID.pElems);
return S_OK;
}
Voir la documentation pour l'explication des fonctions/méthodes ci-dessous.
Exemple: résultat de l'appel de la fonction précédente sur un filter ACM Wrapper de type
compression mp3 permet de choisir interactivement les taux de compression utilisés.
Page 11/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Installation de nouveaux filtres
Pour de nombreuses applications, il devient nécessaire de développer de nouveaux filtres
et/ou d'utiliser des filtres qui ne sont pas installés par défaut sur le système.
1. Installation d'un filtre à partir de son code source
Exemple: le filtre wavdest contenu dans le SDK dans le répertoire:
SDK\Samples\C++\DirectShow\Filters\WavDest\
Cette procédure peut être appliquée pour tout filtre similaire (soit du SDK, soit écrit par
l'utilisateur).
Ce filtre permet d'écrire un fichier au format wav (non compressé).
Installation de ce filtre comme un codec:
1. compiler le filtre (en version release)
2. copier wavdest.ax dans \windows\system32.
3. enregistrer le filtre comme un composant windows avec:
regserv32.exe wavdest.ax
(à effectuer depuis \windows\system32)
Installation du filtre pour l'utiliser dans un programme DirectShow:
1. compiler le filtre (en version release)
2. copier wavdest.lib dans SDKDX9\Lib.
3. créer un fichier wavdest.h contenant la définition du CLSID du filtre (voir au
début du fichier wavdest.cpp); autrement dit contenant:
#include <initguid.h>
#define INITGUID
DEFINE_GUID( CLSID_WavDest , 0x3c78b8e2, 0x6c4d, 0x11d1,
0xad, 0xe2, 0x0, 0x0, 0xf8, 0x75, 0x4b, 0x99 );
4. copier ce fichier wavdest.h dans SDKDX9\include.
Utilisation de ce filtre dans un programme DirectShow:
1. ajouter: #include <wavdest.h>
2. ajouter: #pragma comment(lib,"wavdest.lib")
3. créer le filtre avec comme interface IID_BaseFilter et comme classe
CLSID_WavDest.
Page 12/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
2. Installation d'un filtre à partir d'une source externe
Exemple: le filtre de compression mp3 de Elecard basé sur Lame.
http://www.elecard.com/ftp/pub/directshow/lame_dshow.zip
Cette procédure peut être appliquée pour tout filtre .ax.
Installation de ce filtre comme un codec:
1. copier wavdest.ax dans \windows\system32.
2. enregistrer le filtre comme un composant windows avec:
regserv32.exe wavdest.ax
(à effectuer depuis \windows\system32)
Utilisation de ce filtre dans un code DirectShow:
1. Récupérer le GUID associé à ce filtre dans GraphEdit
Par défaut, les filtres insérés de cette façon se trouvent dans les DirectShow
filters:
On trouve deux GUIDs associés à ce filtre (bas de la fenêtre):
•
Page 13/71
083863F1-70DE-11D0-BD40-00A0C911CE86 : qui correspond à la CLSID
d'un filtre DirectShow (CLSID_LegacyAmFilterCategory)
Université de Reims Champagne-Ardennes
Programmation Multimédia
•
Master d'Informatique 2004-2005
B8D27088-DF5F-4B7C-98DC-0E91A1696286 : qui correspond à la CLSID
de ce filtre.
2. Dans le code C++, il faut définir le GUID de la façon suivante:
#include <initguid.h>
#define INITGUID
DEFINE_GUID(CLSID_CompMP3, 0xb8d27088, 0xdf5f, 0x4b7c,
0x98, 0xdc, 0x0e, 0x91, 0xa1, 0x69, 0x62, 0x86 );
Remarque: le nom CLSID_CompMP3 est au choix de l'utilisateur.
4. créer le filtre avec comme interface IID_BaseFilter et comme classe
CLSID_CompMP3.
3. Filtres disponibles
Il est également possible de rechercher un filtre particulier sur le système par
énumération, et l'utiliser sans connaître au préalable son GUID.
Il sera ainsi possible:
• de récupérer les codecs (filtre de codage/décodage audio/vidéo) installés sur le
système.
Exemple: mp3, divX, …
• de récupérer les filtres d'entrée associés aux périphériques (PnP ou non).
Pour les périphériques PnP, les filtres deviennent disponibles dès que le
périphérique est connecté.
• de récupérer les filtres de sortie (renderer) pour le rendu sur des périphériques
particuliers.
Page 14/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Compression
1. Codecs
codec = COmpressor-DECompressor (audio ou vidéo)
Sous DirectShow, les codecs sont implémentés de différentes façons:
• sous forme d'ACM ou de VCM utilisable avec les filtres "AVI Decompressor"
& "AVI Compressor".
ACM = Audio Compression Manager (gestion des codecs audio)
VCM = Video Compression Manager (gestion des codesc vidéo)
Cette façon d'implémenter les codes est considérée comme obsolète.
• sous forme de filtre DirectShow directement.
La majorité des codecs sont actuellement implémentés sous cette forme, car ils
sont le plus simplement et directement utilisable dans DirectShow.
On peut récupérer la liste de ces codes avec le Device Enumerator
(ICreateDevEnum).
Installation sous forme de .ax.
• sous forme de DirectX Media Object (DMO)
Façon recommandé d'implémenter les Codecs car ils peuvent être utilisé dans à la
fois dans DirectShow (filtre "DMO Wrapper") et dans les autres applications.
Installation sous forme de .dll.
2. Parenthèse sur la compression vidéo
Les compresseurs vidéo utilisent souvent trois types de frames différentes:
o Intraframe : une image décrite entièrement par elle-même. Son taux de
compression (rapport de taille entre l'image naturelle et l'image traitée) est
relativement faible.
Egalement connue sous le nom de keyframe (frame de référence)
o Predicted frame : une image décrite en utilisant les différences entre cette image
et l'image suivante. Le taux de compression est plus élevé que celui des
Intraframes.
o Bidirectionnal frame: une image décrite en utilisant à la fois les différences entre
l'image précédente et l'image suivante. Le taux de compression est supérieur à
l'image prédite.
Page 15/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Dans un flux MPEG, le débit exprime le nombre de bit utilisé pendant une seconde par le
décodeur.
On exprime la portée de la compression par le débit. Plus le débit est élevé, plus la qualité
de la séquence obtenue est bonne. Le corolaire est que la taille fichier obtenue est de plus
en plus importante.
Si le débit est constant dans le temps, on parlera alors de codage CBR (Constant Bit
Rate), sinon on parlera de VBR (Variable Bit Rate). Dans ce dernier cas, le débit varie en
fonction de la complexité des informations à traiter.
3. Configuration de la compression
a. Interface IAMVfwCompressDialogs
Les filtres de type VCM (CLSID_VideoCompressorCategory) peuvent exposer l'interface
IAMVfwCompressDialogs. Attention, si le retour de QueryInterface n'est pas S_OK,
l'interface n'est pas disponible.
Deux fenêtres peuvent être définie: Config, About.
Une fois l'interface obtenue, on appelle la méthode ShowDialog pour afficher la fenêtre
souhaitée:
IAMVfwCompressDialogs::ShowDialog
Syntaxe: HRESULT ShowDialog(int iDialog, HWND hwnd);
Paramètres
VfwCompressDialog_Config
iDialog :
[in]
VfwCompressDialog_About pour le "à propos".
hwnd
: [in] Handle de la fenêtre propriétaire.
pour
configurer,
Retour: S_OK
Remarque: Tant que la boite de dialogue est affichée, vous ne pouvez pas traiter les
données (pause ou run). Les membres VfwCompressDialog_QueryConfig et
VfwCompressDialog_QueryAbout précise si les boites de dialogues sont
disponible ou non pour ce filtre.
Il est possible de configurer plus précisément le filtre sous réserve de connaître la
structure de données qu'il utilise avec les méthodes SetState/GetState.
Page 16/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
b. Interface IAMVideoCompression
Les filtres suivants exposent l'interface IAMVideoCompression:
o DV Video Encoder (CLSID_DVVideoEnc) sur le filtre
o MJPEG Compressor (CLSID_MJPGEnc) sur la borne de sortie.
o WDM Video Capture (CLSID_VideoInputDeviceCategory) sur le filtre.
o AVI Compressor (CLSID_VideoCompressorCategory) sur la borne de
sortie (et IAMVfwCompressDialogs sur le filtre lui-même).
o VFW Capture (CLSID_VideoInputDeviceCategory) sur la borne de
sortie.
o DMO Wrapper (CLSID_DMOWrapperFilter) sur la borne de sortie.
Cette interface permet de configurer de manière assez générale un filtre vidéo en fixant:
o le taux de keyframe: put/get_KeyFrameRate
n = une frame de référence est utilisée toutes les n frames.
o le taux de frame prédite par keyframe : put/get_PFramesPerKeyFrame
p = nombre de frame prédite sur les n (compression MPEG)
o la qualité de la compression : put/get_Quality.
o la largeur de la fenêtre : put/get_WindowSize, (en nombre de frames) sur lequel le
taux est calculé.
La méthode GetInfo permet de connaître les paramètres supportés.
Les méthodes OverrideKeyFrame/OverrideFrameSize permettent de modifier pour
certaines frames le comportement moyen.
Aucune boite de dialogue graphique n'est exposée par cette interface.
Page 17/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Filtres de sortie
1. Filtres de rendu vidéo
a. Filtres de base
•
Video Renderer
Filtre par défaut de rendu vidéo: ce filtre est supporté par toutes les plateformes.
Classe: CLSID_VideoRenderer
•
Video Mixing Renderer 7 (VMR7)
Sous XP seulement: utilise DirectDraw7.
Classe: CLSID_VideoMixingRenderer ou CLSID_VideoRendererDefault
A préférer pour les applications n'effectuant que du rendu vidéo.
•
Video Mixing Renderer 9 (VMR9)
Sur toute plateforme supportant DirectX9.
Classe: CLSID_VideoMixingRenderer9
A préférer pour les applications mélangeant vidéo et 3D.
•
Overlay Mixer
Ancien rendu avec sous-titre (overlay = écriture directe dans la mémoire vidéo).
Remarque: le rendu des sous-titres peut être effectué avec d'autres filtres.
Classe: CLSID_OverlayMixer
Ces filtres de rendu vidéo peuvent opérer dans deux modes différents:
•
mode fenêtré (windowed) : le renderer crée sa propre fenêtre. Cette fenêtre peut
être attachée à l'application.
•
mode non-fenêtré (windowless) : supporté par VMR7 et VMR9. L'affichage doit
être géré par l'application.
b. Contrôles de base
Les interfaces suivantes sont disponibles sur les renderers ci-dessus:
Interface IBasicVideo: propriété générale de la vidéo
•
•
•
•
Page 18/71
récupère la taille de la source vidéo (VideoHeight/VideoWidth/VideoSize),
les statistiques du rendu (AvgTimePerFrame/BitErrorRate/BitRate)
capture d'écran de l'image courante.
fixe/récupère les rectangles source et destination du flux.
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Interface IBasicVideo2:
IBasicVideo + récupère l'aspect ratio.
Interface IVideoWindow: gestion des propriétés de la fenêtre:
•
•
•
•
focus, état (maximisation, minimisation, iconifié, …),
position et taille.
mode fenêtré/plein écran
récupération du handle associé à la fenêtre (pour l'intégrer dans une
application).
c. Gestion du rendu et multistream
Les interfaces suivantes sont pour le VMR (des interfaces similaires existent aussi en
général pour le VMR9).
IVMRFilterConfig: configure comment est effectué le rendu:
o nombres de stream à mixer à l'entrée du renderer.
o mode de rendu (windowed/windowless/renderless)
o le compositeur (mixer personnalisable)
IVMRDeinterlaceControl: fixe la méthode de dé-entrelacement (par stream).
IVMRMixerControl: contrôle de la façon dont sont mixés l'ensemble des streams:
o pour chaque stream, la portion de fenêtre occupée, sa profondeur (calques),
l'ajustement de l'intensité et des couleurs (VMR9 seulement + driver).
o en fixant la couleur de fond.
IVMRMonitorConfig : choix du moniteur utilisé pour le rendu.
d. Exemple: duplication d'une vidéo dans un fenêtre
Page 19/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
CoInitialize (NULL);
IGraphBuilder *pGraph;
CoCreateInstance (CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void **) &pGraph);
// Ajout des filtres dans le graphe
IBaseFilter *FileFilter, *RenderFilter, *TeeFilter;
pGraph->AddSourceFilter(fname, fname, &FileFilter);
CoCreateInstance (CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC,
IID_IBaseFilter, (void **) &RenderFilter);
pGraph->AddFilter(RenderFilter,L"VideoRender");
// Configuration du nombre de stream du video render
// (A faire avant toute connexion)
IVMRFilterConfig9
*FilterConfig;
RenderFilter->QueryInterface(IID_IVMRFilterConfig9,
(void**)&FilterConfig);
FilterConfig->SetNumberOfStreams(2);
// Récupération de bornes a connecter et déconnection
IPin
*Pout,*Pin,*Ptee;
Pout = GetPin(FileFilter,PINDIR_OUTPUT);
Pin = GetPin(RenderFilter,PINDIR_INPUT);
pGraph->Connect(Pout,Pin);
Pin->ConnectedTo(&Pout);
pGraph->Disconnect(Pin);
pGraph->Disconnect(Pout);
// Insertion d'un TEE
CoCreateInstance (CLSID_SmartTee, NULL, CLSCTX_INPROC,
IID_IBaseFilter, (void **) &TeeFilter);
pGraph->AddFilter(TeeFilter,L"Tee");
// Connexion a l'entrée du tee
Ptee = GetPin(TeeFilter,PINDIR_INPUT);
pGraph->Connect(Pout,Ptee);
SAFE_RELEASE(Ptee);
// Connexion en sortie du tee
Ptee = GetPin(TeeFilter,PINDIR_OUTPUT);
pGraph->Connect(Ptee,Pin);
SAFE_RELEASE(Ptee);
// Deuxième connexion en sortie du tee
SAFE_RELEASE(Pin);
Pin = GetIthPin(RenderFilter,PINDIR_INPUT,2);
Ptee = GetIthPin(TeeFilter,PINDIR_OUTPUT,2);
pGraph->Connect(Ptee,Pin);
SAFE_RELEASE(Ptee);
SAFE_RELEASE(Pin);
SAFE_RELEASE(Pout);
// Récupération du contrôleur de mixage
IVMRMixerControl9
*Mixer = NULL;
IBasicVideo
*Base = NULL;
IVideoWindow
*Window = NULL;
RenderFilter->QueryInterface(IID_IVMRMixerControl9,(void**)&Mixer);
RenderFilter->QueryInterface(IID_IBasicVideo,(void**)&Base);
RenderFilter->QueryInterface(IID_IVideoWindow,(void**)&Window);
Page 20/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
long
W,H;
Base->GetVideoSize(&W,&H);
Window->put_Width(2*W);
VMR9NormalizedRect
R0 = { 0.f, 0.f, 0.5f, 1.f},
R1 = {0.5f, 0.f, 1.f, 1.f};
Mixer->SetOutputRect(0,&R0);
Mixer->SetOutputRect(1,&R1);
// Ajouter ici les commandes de contrôles du graphe
Voir aussi les exemples blender du SDK en VMR et en VMR9.
d. VMR9 et 3D
L'intérêt de VMR9 est qu'il permet de faire des liens direct avec DX9, et en particulier le
3D. Inclure d3d9.h et vmr9.h de directX 9.
2. Filtres de rendu audio
a. Filtres de base
•
Audio Renderer (WaveOut) : CLSID_AudioRender
Rendu du son en utilisant WaveOut (pas de mixage)
•
DirectSound Renderer Filter (Défaut) : CLSID_DSoundRender
Rendu du son avec DirectSound
•
Midi Renderer : CLSID_AVIMIDIRender
Pour le rendu de fichier au format midi (doit être précédé du Midi Parser).
b. Contrôles de base
Interface IBasicAudio : fixe ou récupère la balance et le volume (interface triviale).
Interface IAMAudioRendererStats : lecture des statistiques de l'audio-renderer.
Voir la documentation pour les autres interfaces permettant de contrôler le rendu audio.
c. Contrôles DirectSound
Interface IAMDirectSound : fixe le focus.
Interface IDirectSound3DBuffer : cf le cours Direct Sound 3D.
Interface IDirectSound3dListener: cf le cours Direct Sound 3D.
Page 21/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
3. Rendu dans un fichier
a. Filtres de base
•
File Writer : CLSID_FileWriter
Ce filtre doit être précédé d'un filtre qui transforme le flux audio/vidéo en flux de
données. Ceci est effectué par:
Audio : wavdest (Samples\C++\DirectShow\Filters\WavDest)
Vidéo : Avi Mux (classe CLSID_AviDest)
•
ASF Writer : CLSID_WMAsfWriter. Le Windows Media SDK doit être installé.
b. Contrôles de base sur le FileWriter
Interface IFileSinkFilter : Permet de préciser le nom du fichier en sortie.
Création s’il n’existe pas, écrasement s’il existe.
c. Exemple d'écriture dans un fichier
L'exemple suivant prend un fichier avi (compressé ou non) et réécrit le même en
supprimant la bande son.
Principe:
1. connecter un filtre de lecture à un AviMux.
2. connecter l'AviMux au FileWriter.
On ne peut pas connecter directement le filtre de lecture au FileWriter car ce dernier
n’accepte pas n'importe quel type de flux de données. L'AviMux prend en entrée un flux
avi (vidéo+audio) et renvoie en sortie le fichier correspondant sous forme d'un flux de
données.
WCHAR
*fname = L"a.avi";
CoInitialize (NULL);
IGraphBuilder *pGraph;
CoCreateInstance (CLSID_FilterGraph, NULL, CLSCTX_INPROC,
IID_IGraphBuilder, (void **) &pGraph);
// Ajout des filtres dans le graphe
IBaseFilter
*FileRead = NULL, *AviMux = NULL, *FileWriter = NULL;
pGraph->AddSourceFilter(fname, fname, &FileRead);
CoCreateInstance(CLSID_AviDest, NULL, CLSCTX_INPROC,
IID_IBaseFilter, (void **) &AviMux);
pGraph->AddFilter(AviMux,L"AviMux");
Page 22/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
CoCreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC,
IID_IBaseFilter, (void **) &FileWriter);
pGraph->AddFilter(FileWriter,L"FileWriter");
IFileSinkFilter *FileSink;
FileWriter->QueryInterface(IID_IFileSinkFilter, (void**)&FileSink);
FileSink->SetFileName(L"hummer.avi",NULL);
// Récupération des bornes a connecter
IPin
*Pout,*Pin;
Pout = GetPin(FileRead,PINDIR_OUTPUT);
Pin = GetPin(AviMux,PINDIR_INPUT);
pGraph->Connect(Pout,Pin);
SAFE_RELEASE(Pin);
SAFE_RELEASE(Pout);
// Deuxième connexion en sortie du tee
Pout = GetPin(AviMux,PINDIR_OUTPUT);
Pin = GetPin(FileWriter,PINDIR_INPUT);
pGraph->Connect(Pout,Pin);
SAFE_RELEASE(Pin);
SAFE_RELEASE(Pout);
// Ajouter ici le contrôle du graphe
4. Rendu Null
Les flux à l'entrée de ce filtre sont perdus. A utiliser lorsque l'on ne souhaite pas effectuer
de rendu, mais qu'un filtre utilisé dans le graphe a besoin de voir sa borne de sortie
connecté pour fonctionner correctement.
Prendre comme habitude de terminer les graphes par un filtre de rendu.
Ce filtre n'expose aucune interface spécifique pour le configurer.
Classe: CLSID_NullRenderer
Page 23/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Périphériques matériels et interactions
avec DirectShow
Sous DirectShow, on accède aux différents périphériques matériels grâce à des filtres.
Nous donnons ici une idée de la façon dont DirectShow interagit avec les différents
matériels audio et vidéo en expliquant les différentes associations entre les périphériques
et les filtres qui leurs sont associés.
1. Le matériel de capture et de mixage audio (les cartes son)
Les cartes son possèdent généralement un ensemble de connecteurs pour connecter des
enceintes, des microphones, etc … Ces cartes ont la possibilité matérielle de pouvoir
contrôler, sur chacun de ces ports, différentes caractéristiques, telles que le volume, la
balance ou encore le niveau des basses. Sous DirectShow, les entrées de la carte son et les
éléments permettant d’effectuer ces modifications dessus, sont encapsulés dans le filtre
de Capture Audio. Toute carte son peut être reconnue et « récupérée » par l’énumérateur
de périphériques systèmes.
2. Les périphériques VfW (Video for Windows)
Le filtre VFW Capture supporte les anciennes cartes de capture vidéo dites Video for
Windows. Lorsqu’une telle carte est présente (et bien sûr, reconnue par le système
d’exploitation), elle peut, tout comme les périphériques de capture audio, être ajoutés au
graphe de filtres par l’intermédiaire de l’énumérateur de périphériques systèmes.
3. Les périphériques WDM Streaming
Les plus récents décodeurs et cartes de capture sont conformes à la spécification du
Windows Driver Model. De tels dispositifs possèdent plus de fonctionnalités que les
périphériques VfW. Les cartes d’acquisition vidéo WDM peuvent être dotées de
nouvelles possibilités de réglages comme le fait de pouvoir énumérer les différents
formats de capture, de sélectionner une entrée à utiliser, d’obtenir le contrôle sur des
paramètres vidéo (tels que la luminosité ou le contraste).
Afin de pouvoir intégrer ce types de matériel, DirectShow fournit un filtre nommé
KsProxy (surnommé le filtre « couteau suisse » du fait qu’il réalise plusieurs choses
différentes). KsProxy n’apparaît pas dans un graphe sous ce nom mais prend toujours le
nom du périphérique tel qu’il est définit dans la base de registres. Même si seule une
carte est installée sur le système, il se peut que celle-ci contienne « plusieurs
périphériques » (associés à plusieurs fonctionnalités différentes de ce périphérique). Dans
Page 24/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
ce cas, chaque périphérique sera représenté par un filtre différent (ces filtres seront tous
des instances différentes de KsProxy).
Une application utilise l’énumérateur de périphériques systèmes pour trouver les
monikers sur les périphériques WDM. KsProxy est instancié lors de l’appel à
BindToObject sur le moniker. Comme KsProxy peut représenter tous types de
périphériques WDM, il doit interroger le pilote afin de déterminer quel « ensemble de
propriétés » est supporté. Un « ensemble de propriétés » étant une liste de structures de
données utilisées par les pilotes WDM et par quelques filtres en mode utilisateur tels que
certains décodeurs logiciels MPEG-2. KsProxy se configure automatiquement pour
exposer les interfaces correspondantes aux « ensembles de propriétés ». KsProxy traduit
les appels aux méthodes COM en « ensemble de propriétés » et les envois au pilote. Les
fabricants de tels matériels peuvent étendre KsProxy en fournissant des plug-ins (objets
COM), lesquels étant des interfaces adaptées aux fonctionnalités spécifiques du
périphérique. Tous ces détails son cachés à l’application qui contrôle KsProxy de la
même façon que tout autre filtre DirectShow.
4. Kernel Streaming
Les périphériques WDM supportent le « kernel streaming ». Dans ce mode, les données
sont entièrement « canalisées » en mode noyau sans avoir à basculer en mode utilisateur
(rappel: basculer d’un mode à l’autre coûte cher au niveau de la gestion des ressources).
Le kernel streaming permet d’obtenir un meilleur débit sans utiliser trop de ressource
processeur. Les filtres basés sur WDM peuvent utiliser cela pour transporter des données
multimédia directement d’un périphérique matériel à un autre (éventuellement sur des
périphériques différents), sans avoir à copier les données en mémoire principale du
système.
Du point de vue de l’application, tout se passe comme si les données passent d’un filtre à
un autre en mode utilisateur. En réalité, lorsque le graphe et les traitements le permettent,
les données sont canalisées de filtre à filtre (i.e. périphérique à périphérique) en mode
noyau et ceci jusqu’à la carte graphique. Dans certains cas, comme la capture dans un
fichier, le passage des données en mode utilisateur est nécessaire en certains points, mais
les basculements générés ne sont pas forcément synonymes de recopie complète des
données dans la mémoire système.
Page 25/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Enumération des filtres disponibles sur
un système
La recherche des filtres disponibles sur le système s’effectue avec les étapes suivantes:
1. Accès à l’interface ICreateDevEnum d’énumération.
2. Création d’un énumérateur de classe (IEnumMoniker) en spécifiant la catégorie
d’objet à énumérer.
3. Pour chaque objet énuméré dans la classe (IMoniker), récupération de l’ensemble
des propriétés de l’objet (IPropertyBag) à partir d’une version inactive de l’objet.
4. Pour l’objet recherché, instanciation de l’objet (version active).
Moniker : objet COM qui fait référence à une instance spécifique d’un autre objet par
son nom. Un moniker va permettre de localiser, activer et obtenir l’accès à un objet
identifié sans connaître les informations spécifiques relatifs à celui-ci.
Property Bag: ensemble des propriétés d’un objet. On accède aux propriétés par leurs
noms (WCHAR). Les propriétés toujours présentes pour les devices sont:
FriendlyName
Description
DevicePath
: son nom
: sa description (camcorder)
: son « chemin » système (unique même pour plusieurs
devices de même type branché).
1. Enumérateur de classe
Choix du type d’énumération et récupération de l’interface d’énumération des Monikers.
Type : ICreateDevEnum
CLSID = SystemDeviceEnum, IID = ICreateDevEnum :
Page 26/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Exemple:
ICreateDevEnum *pSysDevEnum = NULL;
CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void **)&pSysDevEnum);
Cette objet n’a accès qu’à une seule méthode: CreateClassEnumerator
Syntaxe
HRESULT CreateClassEnumerator(
EFCLSID clsidDeviceClass,
EnumMoniker **ppEnumMoniker,
WORD dwFlags
);
Paramètres
clsidDeviceClass
ppEnumMoniker
dwFlags
: [in] CLSID de la catégorie.
: [out] Adresse du pointeur sur IEnumMoniker.
: [in] Si 0, énumération de tous les filtres dans la catégorie.
Description
Flag
CDEF_DEVMON_CMGR_DEVICE
CDEF_DEVMON_DMO
CDEF_DEVMON_FILTER
CDEF_DEVMON_PNP_DEVICE
Codecs audio et vidéo, compatible avec ACM et VCM.
DirectX Media Objects (DMOs).
Filtres DirectShow par défaut.
Matériel Plug and Play branché.
Retour : Valeur HRESULT (voir la doc).
Remarque : Tester le retour avec S_OK et pas la macro SUCCEEDED.
2. Catégories de filtres
Ces catégories apparaissent dans GraphEdit lors de l’insertion de nouveau filtres.
Elles sont définies dans « Uuids.h », inclure « Dshow.h ».
Nom
Audio Capture Sources
Audio Compressors
Audio Renderers
Device Control Filters
DirectShow Filters
External Renderers
Midi Renderers
Video Capture Sources
Video Compressors
Video Effects (1 input)
Video Effects (2 inputs)
WDM Streaming Capture Devices
WDM Streaming Crossbar Devices
WDM Streaming Rendering Devices
WDM Streaming Tee/Splitter Devices
WDM Streaming TV Audio Devices
WDM Streaming TV Tuner Devices
WDM Streaming VBI Codecs
ActiveMovie Filter Categories
Page 27/71
CLSID
CLSID_AudioInputDeviceCategory
CLSID_AudioCompressorCategory
CLSID_AudioRendererCategory
CLSID_DeviceControlCategory
CLSID_LegacyAmFilterCategory
CLSID_TransmitCategory
CLSID_MidiRendererCategory
CLSID_VideoInputDeviceCategory
CLSID_VideoCompressorCategory
CLSID_VideoEffects1Category
CLSID_VideoEffects2Category
AM_KSCATEGORY_CAPTURE
AM_KSCATEGORY_CROSSBAR
AM_KSCATEGORY_RENDER
AM_KSCATEGORY_SPLITTER
AM_KSCATEGORY_TVAUDIO
AM_KSCATEGORY_TVTUNER
AM_KSCATEGORY_VBICODEC
CLSID_ActiveMovieCategories
Merit
MERIT_DO_NOT_USE
MERIT_DO_NOT_USE
MERIT_NORMAL
MERIT_DO_NOT_USE
MERIT_NORMAL
MERIT_DO_NOT_USE
MERIT_NORMAL
MERIT_DO_NOT_USE
MERIT_DO_NOT_USE
MERIT_DO_NOT_USE
MERIT_DO_NOT_USE
MERIT_DO_NOT_USE
MERIT_DO_NOT_USE
MERIT_DO_NOT_USE
MERIT_DO_NOT_USE
MERIT_DO_NOT_USE
MERIT_DO_NOT_USE
MERIT_DO_NOT_USE
Not applicable
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Les catégories suivantes sont définies dans « Ks.h ».
Nom
WDM Streaming
Communication Transforms
WDM Streaming Data
Transforms
WDM Streaming Interface
Transforms
WDM Streaming Mixer
Devices
CLSID
Merit
KSCATEGORY_COMMUNICATIONSTRANSFORM MERIT_DO_NOT_USE
KSCATEGORY_DATATRANSFORM
MERIT_DO_NOT_USE
KSCATEGORY_INTERFACETRANSFORM
MERIT_DO_NOT_USE
KSCATEGORY_MIXER
MERIT_DO_NOT_USE
La catégorie suivante est définie dans « Ksmedia.h ».
Nom
WDM Streaming System
Audio Devices
CLSID
Merit
KSCATEGORY_AUDIO_DEVICE
MERIT_DO_NOT_USE
Les catégories suivantes sont définies dans « Bdamedia.h ».
Nom
BDA CP/CA Filters Category
BDA Network Providers
BDA Receiver Components
BDA Rendering Filters
BDA Source Filters
BDA Transport Information
Renderers
CLSID
Merit
CLSID_CPCAFiltersCategory
MERIT_NORMAL
KSCATEGORY_BDA_NETWORK_PROVIDER
MERIT_NORMAL
KSCATEGORY_BDA_RECEIVER_COMPONENT
MERIT_NORMAL
KSCATEGORY_IP_SINK
MERIT_DO_NOT_USE
KSCATEGORY_BDA_NETWORK_TUNER
MERIT_DO_NOT_USE
KSCATEGORY_BDA_TRANSPORT_
MERIT_NORMAL
INFORMATION
L’ordre d’inclusion est le suivant :
#include <ks.h>
#include <ksmedia.h>
#include <bdamedia.h>
Acronymes:
WDM = Windows Driver Model.
BDA = Broadcast Driver Architecture (video broadcasting: satellite, cable)
MERIT:
Lorsque le GraphManager effectue des connections (intelligent connect) entre deux
filtres, le MERIT indique si ce filtre peut être utilisé comme filtre intermédiaire:
MERIT_PREFERRED
MERIT_NORMAL
MERIT_UNLIKELY
MERIT_DO_NOT_USE
Page 28/71
: préférer ce filtre
: filtre utilisable
: essayer de ne pas l'utiliser
: ne pas utiliser
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
3. Enumération de Monikers (IEnumMoniker)
Remarque: on est encore dans le cas d'une classe de type IEnumXXX.
On utilise principalement les 2 méthodes suivantes :
•
IEnumMoniker::Next
•
IEnumMoniker::Reset
Utilisation: on fait une boucle while effectuant un Next sur l’IEnumMoniker.
• Chaque Next permet de récupérer le Moniker suivant (ou plusieurs).
• Ce Moniker peut être utilisé pour récupérer l’objet auquel il faut référence.
• Si on ne conserve pas le Moniker, faire un Release avec le Next suivant.
• On arrête l’énumération des Monikers dès que Next renvoit S_FALSE :
On est arrivé sur le dernier Moniker,
S’il s’agissait du premier Next, il n’y a pas d’objet de ce type.
Utilisation: lorsque l’on demande à l’utilisateur de choisir l’objet qu’il désire, Reset
permet de reparcourir la liste des objets. Attention, la liste des objets est susceptible de
changer entre la première et deuxième lecture, ne pas se référer seulement au numéro
d’index du choix (utiliser plutôt le DevicePath).
4. Utilisation d’un Moniker
Il y a deux modes d'utilisation d'un Moniker:
1. IMoniker::BindToStorage : accès aux propriétés de l'objet.
2. IMoniker::BindToObject : accès à l'objet et activation de l'objet.
Une fois le Moniker associé à l’objet récupéré.
a. Accès aux propriétés de l'objet
Pour nous l’objectif sera de récupérer les propriétés de l’objet associé au Moniker sans
l’initialiser.
i. Instanciation mémoire de l'objet
Syntaxe : HRESULT BindToStorage(IBindCtx *pbc, IMoniker *pmkToLeft,
REFIID riid, void **ppvObj);
Paramètres
pbc
pmkToLeft
riid
Page 29/71
: [in] On utilisera NULL.
: [in] On utilisera NULL.
: [in] On utilisera toujours IID_IPropertyBag pour
récupérer l’ensemble de propriétés associé au Moniker.
Université de Reims Champagne-Ardennes
Programmation Multimédia
ppvObj
Master d'Informatique 2004-2005
: [out] Pour nous, il s’agira de l’adresse d’un IPropertyBag
(prendre soin de l’initialiser à NULL avant l’appel, mais il devrait
être aussi NULL après l’appel en cas d’erreur). Rappel: faire appel
à Release pour libérer le PropertyBag (avant tout nouveau
BindToStorage ou en fin d’utilisation).
Retour: E_OUTOFMEMORY, S_OK. Il y a d’autres messages de retour, mais leurs
interprétations dépassent l’objectif du cours.
ii. Lecture des propriétés contenues dans un IPropertyBag
On utilise la méthode Read pour lire le « FriendlyName » contenu dans le PropertyBag.
Syntaxe: HRESULT Read(LPCOLESTR pszPropName,
VARIANT *pVar, IErrorLog *pErrorLog);
Paramètres
pszPropName
pVar
pErrorLog
: [in] Adresse du nom de la propriété à lire. Ne peut être NULL.
: [in, out] VARIANT recevant la valeur.
: [in, out] Code d’erreur en retour. Peut être NULL.
Retour : S_OK ou autre (voir la doc).
Variable de type VARIANT :
VARIANT : type défini essentiellement par les champs suivants:
vt
: type de l’objet stocké dans la structure.
v
: union de variable de presque tous les types.
Après une lecture de données avec une variable de type VARIANT, le champs vt est
rempli avec une valeur indiquant le type de données lu.
Exemple: si v est de type VARIANT,
si
v.vt == VT_BSTR,
alors la variable a lu une chaîne de caractères
le champs v.bstrVal contient cette chaîne de caractères
Principales fonctions utilisées sur un type Variant:
VariantInit(&v);
initialisation d’un variant.
VariantClear(&v); libère les ressources allouées par l’utilisation d’un variant.
Page 30/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
b. Instanciation et initialisation de l'objet
Pour nous l’objectif sera de récupérer les propriétés de l’objet associé au Moniker en
l’initialisant.
Syntaxe : HRESULT BindToObject( IBindCtx * pbc, IMoniker * pmkToLeft,
REFIID riidResult, void ** ppvResult );
Paramètres
pbc
pmkToLeft
riidResult
ppvResult
: [in] On utilisera NULL.
: [in] On utilisera NULL.
: [in] On utilisera toujours un IID_IBaseFilter pour récupérer le
filtre DirectShow dans la classe de filtre dans laquelle on effectue
l’énumération.
: [out] Pour nous, il s’agira d’un IBaseFilter qui correspondra au
filtre choisi parmi ceux énuméré par le Moniker dans la classe.
Prendre soin de l’initialiser à NULL avant l’appel, mais il devrait
être aussi NULL après l’appel en cas d’erreur. Rappel: faire appel
à Release pour libérer l’objet créé en fin d’utilisation.
Retour : E_UNEXPECTED, E_OUTOFMEMORY, S_OK. Il y a d’autres messages de
retour, mais leurs interprétations dépassent l’objectif du cours.
Exemple 1: affichage dans le terminal de l’ensemble des Devices d’un type donné:
HRESULT ShowFilters(REFCLSID clsidDeviceClass, DWORD flag) {
HRESULT
h;
int
i=0;
ICreateDevEnum
*pSysDevEnum = NULL;
IEnumMoniker
*pEnumCat = NULL;
IMoniker
*pMoniker = NULL;
IPropertyBag
*pPropBag = NULL;
// création de l’énumérateur de devices
h = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
(void **)&pSysDevEnum);
if ( h != S_OK ) goto ShowFilterExit;
// création de l’énumérateur de Moniker
h = pSysDevEnum->CreateClassEnumerator(clsidDeviceClass,
&pEnumCat, flag);
if ( h != S_OK ) goto ShowFilterExit;
// énumération des Monikers
while (pEnumCat->Next(1, &pMoniker, NULL) == S_OK) {
h = pMoniker->BindToStorage(NULL,NULL,
IID_IPropertyBag,(void **)&pPropBag);
if ( h != S_OK ) goto ShowFilterExit;
VARIANT var;
VariantInit(&var);
h = pPropBag->Read( L"FriendlyName", &var, NULL );
if ( h == S_OK ) wprintf(L"%02d : %s\n",++i,var.bstrVal);
VariantClear(&var);
Page 31/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
SAFE_RELEASE(pPropBag);
pMoniker->Release();
}
ShowFilterExit:
SAFE_RELEASE(pMoniker);
SAFE_RELEASE(pEnumCat);
SAFE_RELEASE(pSysDevEnum);
return h;
}
Exemple d’utilisation: ShowFilters(CLSID_VideoInputDeviceCategory, 0);
Exemple 2: choix d’un Device
IBaseFilter *GetIthFilterInClass(UINT i,REFCLSID devclass,DWORD flag){
HRESULT s;
IBaseFilter
*Found = NULL;
ICreateDevEnum *CreateDevEnum = NULL;
s = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,CLSCTX_INPROC_SERVER,
IID_ICreateDevEnum, (void**)&CreateDevEnum);
if FAILED(s) goto End;
UINT n = CountClassEnumerator(CreateDevEnum,devclass,flag);
if ((n==0) || (i>=n)) goto End;
IEnumMoniker *EnumMoniker = NULL;
s=CreateDevEnum->CreateClassEnumerator(devclass, &EnumMoniker, flag);
if (s != S_OK) goto End;
if (i>0) {
s=EnumMoniker->Skip(i);
if (s != S_OK) goto EndEnum;
}
IMoniker *Moniker = NULL;
s = EnumMoniker->Next(1, &Moniker, NULL);
if (s != S_OK) goto EndEnum;
s = Moniker->BindToObject(NULL, NULL, IID_IBaseFilter, (void**)&Found);
SAFE_RELEASE(Moniker);
EndEnum:
SAFE_RELEASE(EnumMoniker);
End:
SAFE_RELEASE(CreateDevEnum);
return Found;
}
Page 32/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Gestion des périphériques d'acquisition
1. Filtre de capture
Lorsque l'on dispose d'un filtre de capture, il y a potentiellement plusieurs bornes de
sortie. Un périphérique multifonction peut ainsi exposer de nombreuses bornes.
Le problème qui se produit dans ce cas, est qu'il ne suffit plus, comme pour les filtres
classiques, de connaître le type de flux accepté par la borne et sa direction.
Afin de résoudre ce problème, il est possible d'interroger directement le Driver afin de
connaître la sémantique de chacune des bornes. Ceci se fait, comme nous l'avons déjà
étudié avec DirectSound, grâce aux IKsPropertySet.
La démarche est la suivante:
• pour le filtre de capture considéré, énumérer ses bornes.
• pour chaque borne,
o récupérer l'interface IKsPropertySet. Si cette interface n'est pas disponible,
il ne sera pas possible de récupérer la sémantique de la borne.
o effectuer un Get pour lire la propriété correspondant à:
GUID
= AMPROPSETID_Pin
PropertyID
= AMPROPERTY_PIN_CATEGORY
Exemple:
HRESULT GetPinCategory(IPin *pPin, GUID *pPinCategory){
HRESULT hr;
IKsPropertySet *pKs;
hr = pPin->QueryInterface(IID_IKsPropertySet, (void **)&pKs);
if (FAILED(hr)) {
// The pin does not support IKsPropertySet.
return hr;
}
// Try to retrieve the pin category.
DWORD cbReturned;
hr = pKs->Get(AMPROPSETID_Pin, AMPROPERTY_PIN_CATEGORY, NULL, 0,
pPinCategory, sizeof(GUID), &cbReturned);
// If this succeeded, pPinCategory now contains the category GUID.
pKs->Release();
return hr;
}
Page 33/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Les catégories des bornes sont définies dans la liste suivante (définies dans uuids.h):
GUID
PIN_CATEGORY_ANALOGVIDEOIN
PIN_CATEGORY_CAPTURE
PIN_CATEGORY_CC
PIN_CATEGORY_EDS
PIN_CATEGORY_NABTS
PIN_CATEGORY_PREVIEW
PIN_CATEGORY_STILL
PIN_CATEGORY_TELETEXT
PIN_CATEGORY_TIMECODE
PIN_CATEGORY_VBI
PIN_CATEGORY_VIDEOPORT
PIN_CATEGORY_VIDEOPORT_VBI
PINNAME_VIDEO_CC_CAPTURE
Description
Input pin of the capture filter that takes analog and digitizes it.
Capture pin.
Pin providing closed captioning data from Line 21.
Pin providing Extended Data Services (Line 21, even fields).
Pin providing North American Videotext Standard data.
Preview pin.
Pin that provides a still image. The filter's capture pin must be
connected before the still-image pin is connected.
Pin providing teletext (a closed captioning variant).
Pin providing timecode data.
Pin providing vertical blanking interval data.
Output pin to be connected to input pin zero on the Overlay Mixer.
Pin to be connected to the VBI Surface Allocator, the VBI surface
allocator filter that is needed to allocate the correct video memory for
things like closed captioning overlays in scenarios where a video port
is being used. PCI, IEEE 1394, and USB scenarios do not use this
filter. For more information, see Microsoft TV Technologies.
Hardware slicing closed-captioning pin
2. Graphe de capture
Classe:
CLSID_CaptureGraphBuilder2
Interface:
IID_ICaptureGraphBuilder2
Cette classe de graphe expose des méthodes spécifiques destinées à faciliter la
construction des graphes de capture.
a. Utilisation de base
En utilisation basique, le CaptureGraphBuilder s'utilise en quatre phases:
1. Créer l'objet CaptureGraphBuilder (CoCreateInstance).
2. Fixer le nom du fichier de sortie (ICaptureGraphBuilder2::SetOutputFileName)
cela permet de créer automatiquement le Muxer et le FileSinker nécessaire à la
sauvegarde du flux.
3. Insérer ce filtre dans le graphe contrôlé par le CaptureGraphBuilder (après avec
récupéré un pointeur sur ce dernier dans le CaptureGraphBuilder).
4. Avec le CaptureGraphBuilder, pour chaque type de flux (audio et/ou vidéo),
effectuer un rendu du flux vers le Muxer. Il est possible d'ajouter un codec
intermédiaire de compression.
ICaptureGraphBuilder2::SetOutputFileName
Remarques:
• LPCOLESTR est pareil qu'un LPWSTR.
Page 34/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
•
•
•
Master d'Informatique 2004-2005
cette méthode associe un graphe au ICaptureGraphBuilder2 (i.e. la graphe n'est
pas associé à la création du CaptureGraphBuilder).
le Mux permet de mélanger les flux audio et vidéo. Il faudra effectuer les
connections pour chacun de ces flux.
le FileSinker est connecté sur le Mux, et permet de sauvegarder le flux en sortie
du Mux.
ICaptureGraphBuilder2::GetFiltergraph
ICaptureGraphBuilder2::RenderStream
Examples
// Vidéo:
pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
pCaptureFilter, NULL, NULL);
// Audio:
pBuilder->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio,
pCaptureFilter, NULL, NULL);
pBuilder->SetOutputFileName(&MEDIASUBTYPE_Avi, L"C:\\Example.avi",
&ppf, &pSink);
pBuilder->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
pCaptureFilter, NULL, ppf);
pBuilder->RenderStream(NULL, NULL, pSrc, pCompressor, pMux);
pBuilder->RenderStream(NULL, NULL, pSrc, NULL, pMux);
c. Utilisation avancée
•
AllocCapFile et CopyCaptureFile pour créer des caches
•
FindInterface et FindPin pour retrouver une interface ou une borne dans le graphe
de capture.
ICaptureGraphBuilder2::FindPin
Syntaxe : HRESULT FindPin(IUnknown *pSource, PIN_DIRECTION pindir,
const GUID *pCategory, const GUID *pType, BOOL fUnconnected,
int num, IPin **ppPin);
Cette méthode peut remplacer avantageusement la fonction GetIthPin donnée dans la
partie sur la construction d'un graphe.
Exemple: liste de toutes les bornes d'entrée audio disponible sur un dispositif de capture.
UINT i=0;
do {
IPin *Pin = NULL;
h = Capture->FindPin(Stream,PINDIR_INPUT,
NULL,&MEDIATYPE_AnalogAudio,TRUE,i,&Pin);
Page 35/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
if (h == S_OK) {
ViewPinInfo(Pin,i+1);
SAFE_RELEASE(Pin);
} else printf("FindPin %s\n",DXGetErrorString9(h));
i++;
} while(h == S_OK);
2. Capture audio
a. Exemple: enregistrement à partir d'un micro dans un fichier
Dans ce cas, une construction manuelle est obligatoire car le filtre WavDest n'est pas
considéré comme le muxer approprié par défaut (fait pour l'enregistrement vidéo).
IGraphBuilder
ICaptureGraphBuilder2
IBaseFilter
IFileSinkFilter
CoInitialize (NULL);
*Graph = NULL;
*Capture = NULL;
*Stream, *WavDest, *FileWriter;
*Sink;
// GraphBuilder et Graph
CoCreateInstance (CLSID_CaptureGraphBuilder2, NULL,
CLSCTX_INPROC,IID_ICaptureGraphBuilder2,(void **)&Capture);
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&Graph);
Capture->SetFiltergraph(Graph);
// Récupération du filtre de capture
FiltersEnumerator(CLSID_AudioInputDeviceCategory,0);
Stream = GetIthFilterInClass(0,CLSID_AudioInputDeviceCategory,0);
Graph->AddFilter(Stream,L"Micro");
// Création du filtre muxer pour l'audio
CoCreateInstance(CLSID_WavDest, NULL, CLSCTX_INPROC,
IID_IBaseFilter, (void **) &WavDest);
Graph->AddFilter(WavDest,L"WaveDest");
// Connexion du filtre de capture et de muxer audio
Capture->RenderStream(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Audio,
Stream,NULL,WavDest);
// Création du filewriter pour l'audio
CoCreateInstance(CLSID_FileWriter, NULL, CLSCTX_INPROC,
IID_IBaseFilter, (void **) &FileWriter);
Graph->AddFilter(FileWriter,L"FileWriter");
FileWriter->QueryInterface(IID_IFileSinkFilter, (void**)&Sink);
Sink->SetFileName(L"test.wav",NULL);
// Connexion du muxer audio et du filewriter
IPin *Pout,*Pin;
Pout = GetPin(WavDest,PINDIR_OUTPUT);
Pin = GetPin(FileWriter,PINDIR_INPUT);
Graph->Connect(Pout,Pin);
SAFE_RELEASE(Pin);
SAFE_RELEASE(Pout);
Page 36/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
b. Configuration d'une entrée audio
Un filtre d'entrée associé à un périphérique matériel qui permet une capture audio expose:
•
une borne d'entrée nommée généralement "Microphone", "Line In", …
On ne peut pas connecter de filtre à cette borne. Elle représente l'entrée physique
sur le périphérique. C'est cette borne qui est configurable avec l'interface
IAMAudioInputMixer.
•
une borne de sortie "Capture". C'est sur cette borne que l'on récupère le flux en
provenance du dispositif de capture audio.
Le choix et la configuration des entrées audio s’effectuent avec l'interface
IAMAudioInputMixer. Elle permet de fixer les propriétés suivantes d'une borne d'entrée
audio.
•
•
•
•
•
•
•
Enable : activation/désactivation.
Mono : mode mono ou multicanal.
Mixlevel : niveau de d'enregistrement pour cette borne (ou gain automatique).
Pan : balance (dans le cas d'une entrée multicanal).
Treble : aiguë
Bass : basse
Loudness : boost des basses
Attention: toutes ces propriétés ne peuvent pas nécessairement être réglées pour le
périphérique en question. Les méthodes peuvent alors retourner E_NOTIMPL pour
indiquer que la fonction n'est pas implémentée, E_FAIL si elle n'est pas disponible, …
Page 37/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Exemple : active la troisième entrée
IPin *Pin = NULL;
h = Capture->FindPin(Stream,PINDIR_INPUT,NULL,&MEDIATYPE_AnalogAudio,
TRUE,2,&Pin);
if (h == S_OK) {
IAMAudioInputMixer *InputMixer = NULL;
Pin->QueryInterface(IID_IAMAudioInputMixer,(void**)&InputMixer);
InputMixer->put_Enable(TRUE);
InputMixer->put_Mono(TRUE);
InputMixer->put_MixLevel(1.0);
SAFE_RELEASE(InputMixer);
SAFE_RELEASE(Pin);
}
c. Configuration du format de la sortie
IAMStreamConfig permet de connaître les formats de capture disponibles ainsi que de
configurer le périphérique. Cela s'effectue en plusieurs étapes:
1. Récupérer la borne de sortie audio du dispositif de capture.
Utiliser ICaptureGraphBuilder2::FindPin
2. Récupérer l'interface IAMStreamConfig de la borne (avant de la connecter).
3. Choisir l'un des modes disponibles GetNumberOfCapabilities pour
récupérer le nombre de mode disponible, GetStreamCaps pour lire le ième
mode.
4. Fixer le mode choisi avec SetFormat.
Notons que de manière plus générique, IAMStreamConfig peut être exposé par toutes les
bornes de sortie d'un graphe, permettant ainsi de changer le format en cours de traitement.
Exemple de code lisant les modes d'enregistrement disponibles:
IAMStreamConfig
*Config = NULL;
h = Capture->FindPin(Stream,PINDIR_OUTPUT,NULL,&MEDIATYPE_Audio,
TRUE,0,&Pin);
h = Pin->QueryInterface(IID_IAMStreamConfig,(void**)&Config);
if (h != S_OK) return E_FAIL;
int ncaps = 0, capsz = 0;
Config->GetNumberOfCapabilities(&ncaps,&capsz);
printf("%d availables modes\n",ncaps);
// Comme il s'agit d'audio: capsz = sizeof(AUDIO_STREAM_CONFIG_CAPS)
for(int i=0;i<ncaps;i++) {
AM_MEDIA_TYPE *am;
AUDIO_STREAM_CONFIG_CAPS cf;
Config->GetStreamCaps(i,&am,(BYTE*)&cf);
if (i==0) ViewSoundFormat(cf);
ViewMediaType(*am);
DeleteMediaType(am);
}
SAFE_RELEASE(Config);
Page 38/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Les fonctions ViewSoundFormat(…) et ViewMediaType(…) sont écrites par l'utilisateur et
permettent respectivement d'afficher le contenu de:
•
la structure AUDIO_STREAM_CONFIG_CAPS qui contient les plages de variation:
o du nombre de canaux disponibles
o du nombre de bits par échantillon
o de la fréquence d'échantillonnage
•
la structure AM_MEDIA_TYPE qui contient une description du format utilisé (déjà
vu), et qui dans le cas des médias de type son, contient une structure
WAVEFORMATEX.
Exemple de sortie avec ce code:
Audio: (AUDIO_STREAM_CONFIG_CAPS)
Channels = 1:1:2
BitsPerSample
= 8:8:16
SampleFrequency= 11025:11025:44100
Mode
FixSz Comp Sz Format (AM_MEDIA_TYPE + WAVEFORMATEX)
PCM audio true false 4 2 x 16 bits @ 44100 Hz (Format=PCM)
PCM audio true false 2 1 x 16 bits @ 44100 Hz (Format=PCM)
PCM audio true false 4 2 x 16 bits @ 32000 Hz (Format=PCM)
PCM audio true false 2 1 x 16 bits @ 32000 Hz (Format=PCM)
PCM audio true false 4 2 x 16 bits @ 22050 Hz (Format=PCM)
PCM audio true false 2 1 x 16 bits @ 22050 Hz (Format=PCM)
PCM audio true false 4 2 x 16 bits @ 11025 Hz (Format=PCM)
PCM audio true false 2 1 x 16 bits @ 11025 Hz (Format=PCM)
PCM audio true false 4 2 x 16 bits @ 8000 Hz (Format=PCM)
PCM audio true false 2 1 x 16 bits @ 8000 Hz (Format=PCM)
PCM audio true false 2 2 x 8 bits @ 44100 Hz (Format=PCM)
PCM audio true false 1 1 x 8 bits @ 44100 Hz (Format=PCM)
PCM audio true false 2 2 x 8 bits @ 32000 Hz (Format=PCM)
PCM audio true false 1 1 x 8 bits @ 32000 Hz (Format=PCM)
PCM audio true false 2 2 x 8 bits @ 22050 Hz (Format=PCM)
PCM audio true false 1 1 x 8 bits @ 22050 Hz (Format=PCM)
PCM audio true false 2 2 x 8 bits @ 11025 Hz (Format=PCM)
PCM audio true false 1 1 x 8 bits @ 11025 Hz (Format=PCM)
PCM audio true false 2 2 x 8 bits @ 8000 Hz (Format=PCM)
PCM audio true false 1 1 x 8 bits @ 8000 Hz (Format=PCM)
PCM audio true false 4 2 x 16 bits @ 48000 Hz (Format=PCM)
PCM audio true false 2 1 x 16 bits @ 48000 Hz (Format=PCM)
PCM audio true false 4 2 x 16 bits @ 96000 Hz (Format=PCM)
PCM audio true false 2 1 x 16 bits @ 96000 Hz (Format=PCM)
On remarque que l'énumération complète fournit plus de modes (indiqués en bleu) que
ceux prévus par AUDIO_STREAM_CONFIG_CAPS.
Voir la documentation pour plus d'information.
3. Capture vidéo
A noter qu'un filtre de capture vidéo peut avoir une borne de capture et une borne de
preview. Afin d'éviter de perdre des frames lors de la capture, la perte de frame sur la
borne de preview est autorisée si elle est nécessaire afin de garantir une bonne qualité sur
la borne de capture. Il est donc conseillé de l'utiliser dans le cas d'une preview.
Page 39/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
a. Configuration d'un dispositif de capture vidéo
IAMVideoProcAmp permet de régler les caractéristiques de l'image capturée à savoir
Brightness (luminosité), Contrast (contraste), Hue (teinte), Saturation (saturation),
Sharpness (finesse), Gamma (gamma), ColorEnable (couleur), WhiteBalance (balance
des blancs), BacklightCompensation (compensation du contre-jour), Gain.
En 3 étapes:
1. Récupérer l'interface IAMVideoProcAmp sur le filtre de capture. Si l'interface
n'est pas disponible, aucun réglage n'est possible.
2. Utiliser la méthode IAMVideoProcAmp::GetRange pour récupérer les plages de
variations, le pas, … pour la propriétés souhaitées (en premier paramètre). Cette
méthode renvoie E_PROP_ID_UNSUPPORTED si la propriété ne peut pas être
réglé sur le périphérique considéré.
3. Utiliser IAMVideoProcAmp::Set/Get pour fixer ou lire le paramètre souhaité
(toujours en premier paramètre).
Exemple: affiche les propriétés disponibles et leurs échelles de variation
const int nProp = 10;
IAMVideoProcAmp *ProcAmp = NULL;
VideoProcAmpProperty Prop[nProp]={
VideoProcAmp_Brightness, VideoProcAmp_Contrast,
VideoProcAmp_Hue, VideoProcAmp_Saturation,
VideoProcAmp_Sharpness, VideoProcAmp_Gamma,
VideoProcAmp_ColorEnable,
VideoProcAmp_WhiteBalance,
VideoProcAmp_BacklightCompensation, VideoProcAmp_Gain };
const char StrProcAmp[nProp][30] = {
"Brightness","Contrast","Hue","Saturation","Sharpness","Gamma",
"ColorEnable","WhiteBalance","BacklightCompensation","Gain" };
h = Pin->QueryInterface(IID_IAMVideoProcAmp, (void **)&Stream);
if (h==S_OK) {
for(int i=0;i<nProp;i++) {
long min,max,delta,defaut,flag;
h = ProcAmp->GetRange(Prop[i],&min,&max,&delta,&defaut,&flag);
if (h!=S_OK) continue;
printf("%s : %d:%d:%d def=%d %s%s%s\n",
StrProcAmp[i],min,delta,max,defaut,
(VideoProcAmp_Flags_Auto & flag ? "auto" : ""),
(VideoProcAmp_Flags_Manual & flag ? "manual" : ""));
}
SAFE_RELEASE(ProcAmp);
b. Configuration du format de la sortie
Pareil que pour l'audio: utiliser l'interface de IAMStreamConfig (permet aussi de lire les
modes disponibles et de fixer les modes de sortie).
Page 40/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
A noter l'interface IAMVfwCaptureDialogs pour les périphériques à la norme VfW qui
permet de choisir à travers une interface: la source de la vidéo, la format de la vidéo, et
l'affichage de la vidéo (son apparence).
c. Autre dispositif de configuration
Les filtres de capture CLSID_VfwCapture exposent l'interface IAMVfwCaptureDialogs
qui permettent d'accéder à l'interface utilisateur ShowDialog (3 boîtes de dialogue
éventuellement possibles si elles sont implémentées: Source, Format, Display).
5. Autres dispositifs de capture
Voir les annexes pour voir comment traiter:
•
•
Page 41/71
un caméscope.
un tuner TV.
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Contrôle du rendu
•
NULL Renderer
Rendu rapide: pour faire en sorte que le flux traverse le graphe le plus rapidement
possible.
•
Horloge du graphe
Lorsque vous construisez un graphe, le manager choisi automatiquement une
horloge de référence. Tous les filtres du graphe sont synchronisés sur celle-ci. En
particulier, les filtres de rendus l’utilisent pour connaître le temps d’affichage d’un
sample.
Il n’y a généralement aucune raison pour modifier l’horloge choisie par le
manager. Cependant, vous pouvez le faire avec la méthode SetSyncSource de
l’interface IMediaFilter, lorsque le graphe est arrêté.
Exemple :
IGraphBuilder *pGraph = 0;
IReferenceClock *pClock = 0;
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
// Build the graph.
pGraph->RenderFile(L"C:\\Example.avi", 0);
// Create your clock.
hr = CreateMyPrivateClock(&pClock);
if (SUCCEEDED(hr))
{
// Set the graph clock.
IMediaFilter *pMediaFilter = 0;
pGraph->QueryInterface(IID_IMediaFilter, (void**)&pMediaFilter);
pMediaFilter->SetSyncSource(pClock);
pClock->Release();
pMediaFilter->Release();
}
Cet exemple suppose que la fonction CreateMyPrivateClock crée une horloge et
renvoie un pointeur sur IReferenceClock. Vous pouvez également la supprimer en
mettant la valeur NULL à SetSyncSource. Ceci permet de traiter les données aussi vite
qu’elles arrivent.
Page 42/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Debug de DirectShow
Utilisation d’un fichier de trace
La méthode IGraphBuilder::SetLogFile permet de spécifier un fichier qui contiendra
les traces relatives à la construction et à l'utilisation du graphe spécifié.
// Initialisation du fichier de trace
LPCTSTR
LogFile = TEXT("trace.log");
HANDLE
hRenderLog=INVALID_HANDLE_VALUE;
hRenderLog = CreateFile(LogFile,
GENERIC_WRITE,
FILE_SHARE_READ, NULL, OPEN_ALWAYS, 0, NULL);
SetFilePointer(hRenderLog, 0, NULL, FILE_END);
if (hRenderLog != INVALID_HANDLE_VALUE)
pGRAPH->SetLogFile((DWORD_PTR) hRenderLog);
// Ici les opérations sur lesquelles ont souhaite des traces
...
// Fin des traces
pGRAPH-> SetLogFile(NULL);
CloseHandle(hRenderLog);
hRenderLog = INVALID_HANDLE_VALUE;
Attention: le fichier résultat contient les traces au format Unicode.
Page 43/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Annexe A: Montage Vidéo
1) Introduction
DirectShow Editing Services (DES) est une API (Application Programming
Interface) qui simplifie grandement les tâches nécessaires à l’édition vidéo. DES est
construite sur le cœur de l’architecture DirectShow, et fournit un ensemble d’interfaces
conçues spécifiquement pour développer des projets d’édition vidéo.
Voici quelques caractéristiques de DES :
Un ordonnancement temporel (modèle de la Timeline) qui organise les
pistes audio et vidéo en couches
La possibilité de voir le résultat du montage en temps réel
L’enregistrement et le chargement de projets sous forme de fichiers XML
La gestion d’effets audio et vidéo, ainsi que de transitions entre clips vidéo
Plus de 100 transitions standard disponibles, définis par la SMPTE (Society
of Motion Picture and Television Engineers)
La conversion automatique du nombre d’images par seconde, et de
l’échantillonnage audio, cela permet d’utiliser des sources hétérogènes
Le redimensionnement ou le recadrage de la vidéo
Voici l’architecture de DirectShow Editing Services :
-
Page 44/71
Timeline : Organise le montage vidéo sous formes de pistes audio et vidéo
où sont insérés des extraits (ayant comme origine un fichier), des transitions,
des effets.
XML Parser : Génère un fichier à partir d’une Timeline, ou bien construit
une Timeline à partir d’un fichier.
Render Engine : Moteur de rendu : produit un graphe des filtres complet à
partir d’une Timeline. Pour visionner le résultat du montage, il n’y a plus
qu’à lancer le graphe.
Université de Reims Champagne-Ardennes
Programmation Multimédia
-
Master d'Informatique 2004-2005
Media Locator : Gère une mémoire cache des répertoires où se trouvent les
éléments média insérés. Quand une tentative de lecture d’un élément
échoue, DES utilise le cache pour trouver l’élément, basé sur un historique
des tentatives réussies.
La Timeline est une description abstraite d’un projet de montage vidéo. Elle
permet de spécifier les extrait vidéo ou audio utilisés dans le projet, les instants de début
et de fin, les effets et les transitions, et bien d’autres choses. La Timeline n’effectue pas
de rendu des flux audio et vidéo. A la place, le moteur de rendu (Render Engine)
construit un graphe des filtres à partir d’une Timeline, pour le rendu ou l’enregistrement
du résultat dans un fichier. Une application de montage vidéo manipule une Timeline
plutôt que directement le graphe des filtres, ce qui serait lourd et source d’erreurs.
Voici les principales tâches que l’on aurait envie de faire avec DES, ainsi que les
interfaces qui nous permettent d’y arriver :
Construire ou modifier une Timeline : IAMTimeline et toutes les interfaces
de la forme IAMTimelineXXXX
Charger ou sauvegarder des projets : IXml2Dex
Voir le résultat d’un projet ou le sauvegarder : IRenderEngine,
ISmartRenderEngine
Connaître les information d’un fichier média : IMediaDet
Définir les propriétés d’un effet ou d’une transition : IPropertySetter
Nous allons maintenant entrer dans le vif du sujet en nous intéressant au modèle
de la Timeline.
2) Architecture d’une composition vidéo : modèle de la Timeline
Une Timeline est l’objet de base pour un projet de montage vidéo. Elle est
destinée à contenir tous les objets utilisés dans le montage (échantillons vidéo, sonores,
effets, transitions), et définit une échelle de temps, ou chronologie, pour le placement de
tous ces objets.
DES utilise une structure en arbre pour la construction d’une Timeline :
Les échantillons audio et vidéo forment les feuilles (extrémités de l’arbre).
On les appelle les objets sources.
Un ensemble de sources d’un même type forme une piste (track).
Un ensemble de pistes forme une composition.
Un groupe contient une composition mère qui peut contenir plusieurs
compositions filles. Il y a un groupe par types de média.
Un ensemble de plusieurs groupes forme une Timeline. Généralement, une
Timeline contient deux groupes : l’un pour le son, l’autre pour la vidéo.
Page 45/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Une Timeline contient au moins un groupe. Chaque groupe constitue un flux à
part entière dans la composition finale. Voici une illustration de la structure d’une
Timeline afin de bien comprendre le principe :
La figure suivante montre qu’une Timeline a aussi le rôle d’ordonner les éléments
par rapport à l’axe du temps :
L’intérêt de disposer de plusieurs pistes (tracks) est visible ici : chacune a une
priorité différente des autres. Ici, la piste 1 a une priorité plus grande que la piste 0. A
chaque niveau de priorité, l’échantillon source dans une piste masque les échantillons
dans les pistes de priorités moindres, sauf dans le cas particulier des transitions. Ainsi,
dans cet exemple, pour ce qui est du groupe audio, DES va sélectionner le début de la
source D, puis la source E, puis la fin de la source D. Lorsqu’il n’y a pas d’éléments sur
la piste de priorité la plus élevée, elle ne masquera pas la piste de priorité moindre et ainsi
de suite.
3) Gestion du temps
Page 46/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Dans DES, on doit à de nombreuses reprises travailler avec des informations
temporelles. Mais leur sens n’est pas toujours le même. Il faut à chaque fois réfléchir au
référentiel dans lequel on travaille. Les trois référentiels différents sont :
-
-
La Timeline : Le temps est exprimé par rapport au début de la Timeline
(qui est l’instant t = 0). Ce référentiel est utilisé lorsque l’on insère un objet
dans la Timeline, pour définir à quel instant de la Timeline on l’insère.
L’échantillon source : Le temps est exprimé par rapport au début du
fichier. Par exemple t = 5s correspond à la moitié d’une vidéo d’une durée
de 10 secondes. On l’utilise pour définir quelle portion du média, contenue
dans un fichier, on veut insérer dans la Timeline (par exemple les 5
premières secondes).
L’objet parent : Le temps est exprimé pour une source par rapport à une
autre source. Par exemple, si un objet démarre à t = 8s sur la Timeline et
contient un autre objet qui démarre à t = 10s sur la Timeline, l’objet fils
démarre à t = 2s dans le référentiel de l’objet parent.
Lorsque l’on veut changer le nombre d’images par seconde d’une vidéo
(« framerate ») c’est-à-dire augmenter la vitesse de lecture ou la diminuer, il faut choisir
de spécifier des instants appropriés. Par exemple, pour jouer une vidéo de 10 secondes en
seulement 5 secondes entre les instants t1 = 20 et t2 = 25 de la Timeline, il suffit de
prendre la totalité de la vidéo (de t = 0 à t = 10 dans le référentiel de la source) puis de
l’insérer entre les instants t = 20 et t = 25 de la Timeline. La conversion de « framerate »
se fera automatiquement.
4) Application d’effets et de transitions
Un effet s’applique sur une seule source, tandis qu’une transition s’effectue entre
deux sources, donc entre deux pistes différentes.
Pour appliquer un effet, il suffit d’ajouter un objet de type effet à une piste en
spécifiant à quel moment débute l’effet et à quel moment il se termine. Si aucune source
n’est placée dans cet intervalle, l’effet n’aura aucun résultat visible.
Voici un exemple de composition qui montre comment on doit placer une
transition :
Page 47/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Le premier cadre bleu montre comment ont été insérés les éléments sur la
Timeline, et le deuxième montre le résultat que l’on obtiendra.
Puisque deux sources ne peuvent se chevaucher sur une même piste, deux pistes
sont nécessaires. La transition, pour s’appliquer, doit chevaucher la fin de la source A et
le début de la source C. La source C doit chevaucher une partie de la source A et
inversement. Le placement des sources sur les pistes associées est très important puisque
la piste 1 a une priorité plus grande que la piste 0. De même, le sens de la transition est
important. Le comportement par défaut est le passage de la piste de priorité moins
importante à la plus importante (de la piste 0 à la piste 1). Par exemple, si l’on avait voulu
placer une transition pour passer progressivement de la source C à la source B, il aurait
fallu modifier une propriété de l’objet transition pour changer le sens de transition (de la
piste 1 à la piste 0).
5) Architectures des interfaces de DES
Les diverses interfaces qui permettent de construire une Timeline et d’y ajouter
des éléments sont liées entre elles à la manière du système de hiérarchie de classes en
C++. Les interfaces mères présentent des méthodes assez générales, tandis que les filles
fournissent des méthodes appropriées dans le cas d’objets précis. Voici la hiérarchie de
ces interfaces :
Page 48/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
IUnknown
IAMTimelineObj
IAMTimelineGroup
IAMTimelineComp
IAMTimelineTrack
IAMTimelineTransable
IAMTimelineEffectable
IAMTimelineSrc
IAMTimelineTrans
IAMTimelineEffect
6) Ordre dans la création d’un projet
Lorsque l’on crée une Timeline, il faut respecter un certain ordre. Ainsi on crée
d’abord un objet Timeline, puis un objet Groupe, puis un objet Composition, puis un
objet Piste, et enfin un objet Source, un objet Transition, ou un objet Effet. Cela se
comprend aisément au vu de l’architecture de la Timeline vu plus haut.
De plus, il est préférable, pour une question de lisibilité du code de créer et de
manipuler une seule piste à la fois (il serait bien sûr possible d’en manipuler plusieurs, en
créant plusieurs instances de l’interface IAMTimelineTrack).
7) Comment s’utilise chaque élément
Je ne décrirai pas ici chaque interface car elles ont chacune de nombreuses
fonctions et toutes ne sont pas utiles pour la majorité de ce que l’on veut faire. Nous
verrons les fonctions incontournables et leur intérêt.
1. Timeline
Page 49/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Pour créer une Timeline, on affecte l’interface IAMTimeline grâce à
CoCreateInstance() comme nous l’avons vu pour les interfaces de base du rendu vidéo.
D’une manière générale, les interfaces d’objets « de base » s’affectent de cette manière,
pour les interfaces plus précises, c’est en effectuant un QueryInterface() sur l’interface
« mère ».
2. Objets d’une Timeline
Pour chaque objet d’une Timeline (groupe, composition, piste, source, transition,
effet), il faut utiliser l’interface IAMTimelineObj. On l’affecte grâce à la fonction
CreateEmptyNode() de l’interface IAMTimeline définie précédemment. On fournit en
paramètre de cette fonction, outre le pointeur sur l’interface IAMTimelineObj à affecter,
le type d’objet (groupe, piste, …) que l’on veut créer.
3. Groupe
Après avoir créé un objet avec l’interface générique IAMTimelineObj, on affecte
l’interface particulière pour l’objet créé. Pour un objet groupe, il s’agit de l’interface
IAMTimelineGroup. On l’affecte en appelant QueryInterface() sur l’interface
IAMTimelineObj. IAMTimelineGroup contient des méthodes spécialement utiles pour les
groupes. On utilise SetMediaType() afin de définir un type de média pour le groupe.
Généralement, on ne remplit que le champ majortype de la structure AM_MEDIA_TYPE
passé en paramètre. Ce champ indique seulement si le groupe contiendra des flux audio
ou vidéo. En modifiant les autres champs, il est possible de définir un format très précis
pour le groupe. Si l’on cherche par la suite à insérer une source de type différent, cela
produira une erreur. Une fois que l’on a défini tout ce que l’on voulait sur l’objet groupe,
on l’insère dans la Timeline en appelant IAMTimeline::AddGroup().
4. Composition
L’interface pour les compositions, IAMTimelineComp, s’affecte en effectuant
un QueryInterface() sur l’interface IAMTimelineGroup (voire plus haut dans la partie
architecture des interfaces de DES).
5. Piste
Une fois l’objet générique de type piste (IAMTimelineObj) créé, on l’insère dans
la composition grâce à la fonction IAMTimelineComp::VTrackInsBefore() en lui
spécifiant l’ordre de priorité de cette piste par rapport aux autres. Après cela, on affecte
l’interface particulière IAMTimelineTrack avec la fonction QueryInterface() de
l’interface IAMTimelineObj.
6. Sources
L’interface
IAMTimelineSrc
est
affectée
avec
IAMTimelineObj::QueryInterface(). Cette interface va particulièrement nous servir à
Page 50/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
définir le fichier source que l’on insère (chemin) avec la fonction
IAMTimelineSrc::SetMediaName(). Ensuite, on définit la portion de média que l’on
insère : IAMTimelineSrc::SetMediaTimes(), en passant en paramètre l’instant de début et
l’instant de fin par rapport au fichier. Puis, on définit à quel endroit de la Timeline on
insère le clip : IAMTimelineObj::SetStartStop(). Les instants début et fin passés en
paramètres sont exprimés par rapport à la Timeline. Finalement, on insère la source dans
la piste : IAMTimelineTrack::SrcAdd().
7. Transitions et effets
Après la création de l’objet générique, on appelle la fonction
SetSubObjectGUID() où l’on spécifie le GUID de la transition choisie. Le GUID du lot
de transitions standard est CLSID_DxtJpeg. Ensuite, on définit à quel endroit de la
Timeline on insère la transition : IAMTimelineObj::SetStartStop(). Pour insérer la
transition dans la piste, on a besoin de l’interface IAMTimelineTransable. On l’obtient
grâce à IAMTimelineTrack::QueryInterface(). On appelle ensuite la fonction
IAMTimelineTransable::TransAdd(). Si l’on veut modifier le sens par défaut de la
transition (piste n à piste n-1), il faut appeler l’interface IAMTimelineTrans et sa
fonction SetSwapInputs().
Les effets fonctionnent à peu de choses près de la même manière que les
transitions, nous n’allons donc pas en parler ici. Pour plus de détails, vous pouvez aller
voir le code source de l’exemple qui utilise les effets : DESCompo3.
8) Rendu du projet
Comme nous l’avons vu précédemment, l’interface IRenderEngine est dédiée à
la construction d’un graphe à partir d’un projet de montage vidéo.
Pour ce faire, on commence par indiquer à l’interface quelle Timeline on utilise :
SetTimelineObject(). Puis on lui demande de construire le graphe avec les deux
fonctions : ConnectFrontEnd() et RenderOutputPins(). La première insère tous les filtres
sauf les filtres de rendu. Cela permet, si on le souhaite, d’insérer d’autres filtres de rendu
que ceux qui sont utilisés par défaut, cela permet aussi d’insérer un filtre
d’enregistrement dans un fichier… RenderOutputPins() insère les filtres de rendu et les
connecte au reste du graphe. Le graphe étant complètement construit, on lui affecte une
interface avec GetFilterGraph(). Ensuite il n’y a plus qu’à lancer le graphe avec
l’interface IMediaControl comme déjà vu dans la partie sur le rendu vidéo.
Je vous invite à examiner les programmes qui ont été fait avec DES :
DESCompo1, 2 et 3. DES se révèle vraiment être un environnement simple et agréable
pour le montage vidéo, une fois que l’on a assimilé les concepts. Ceux-ci sont
relativement bien expliqués dans la documentation de DirectShow.
Page 51/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Annexe B: Contrôle d'un caméscope
1) Vidéo numérique et fichiers AVI
Jusqu’à présent, nous n’avions pas besoin de nous préoccuper du type du fichier
AVI que nous créions lors de la capture avec une webcam. Et de toute façon, je ne
connaissait pas moi-même l’existence de plusieurs types de fichier.
Or, je me suis aperçu, grâce à la recherche effectuée sur les flux qui transitent à
travers un caméscope numérique, qu’il existe deux types de fichier. Dans les sections
précédentes qui traitaient de la webcam, nous utilisions, sans le savoir, le type 2 (voir
plus loin). A partir de maintenant, il est important de distinguer les deux types. En effet, il
est obligatoire d’utiliser le type 1 (voir plus loin) lorsque l’on veut travailler avec un
caméscope numérique.
La vidéo numérique (type 1), « Digital video » (DV) en anglais, peut provenir de
plusieurs types. Elle peut être capturée à partir d’un caméscope numérique, stockée dans
un fichier sur le disque dur, ou stockée sur une cassette en utilisant un caméscope
numérique. A partir de là, plusieurs types d’opérations peuvent s’effectuer sur un flux
numérique, à savoir:
•
•
•
•
•
•
•
Capturer la vidéo à partir d’une caméra.
Transmettre le contenu d’une cassette dans un fichier sur l’ordinateur.
Transmettre un fichier de l’ordinateur sur une cassette.
Lire des données numériques à partir d’un fichier.
Ecrire des données numériques dans un fichier.
Visionner et écouter les flux vidéo et audio d’un flux numérique.
Convertir un fichier d’un type vers l’autre.
DirectShow fourni ces quelques filtres qui nous permettent de réaliser l’ensemble
de ses tâches:
•
•
•
•
•
Le filtre « MSDV Driver ». Ce filtre contrôle un périphérique numérique, comme
un caméscope. En général, le caméscope comporte deux parties ; la caméra et la
cassette. Ce filtre permet de contrôler les deux.
Le filtre « DV Splitter ». Un flux numérique contient à la fois un (ou deux) flux
audio et un flux vidéo. Ce filtre permet de séparer les flux.
Le filtre « DV Muxer ». Il est le contraire du filtre « DV Splitter ».
Le filtre « DV Video Decoder ». Il permet de convertir un flux numérique en un
flux vidéo non compressé.
Le filtre « DV Video Encoder ». Il est le filtre contraire du « DV Video
Decoder ».
Les filtres « DV Splitter » et « DV Video Decoder » fonctionnent ensemble.
Page 52/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Bien entendu, pour le processus inverse, il faut utiliser les filtres « DV Video
Encoder » et « DV Muxer ».
2) Les types de fichiers AVI
Les caméscopes numériques produisent des flux numériques entrelacés. Si vous
voulez enregistrer un tel flux sur le disque, vous avez le choix:
•
•
Stocker les données telles quelles avec un seul flux. Ceci est le type 1.
Stocker les données dans deux flux audio et vidéo séparés. Ceci est le type 2.
Pour la capture vidéo, où la rapidité est importante, il est préférable d’utiliser le
type de fichier 1. En effet, les fichiers de type 2 comportent un flux audio redondant. (Le
flux vidéo contient toujours les données audio mais elles sont simplement cachées en
nommant le flux vidéo.) De plus, écrire un fichier de type 2 requière du temps processeur
supplémentaire pour séparer les flux.
D’un autre côté, les fichiers de type 1 sont moins adaptés aux applications
effectuant de l’édition en temps réel. L’application doit d’abord extraire le flux audio,
effectuer les opérations d’édition puis ré-entrelacer les flux. De plus, le format type 1
n’est pas compatible avec le modèle VfW.
Un fichier de type 2 peut être convertit un type 1 grâce au filtre « DV Muxer ». A
l’inverse, le filtre « DV Splitter » convertit un fichier de type 1 en type 2. (Voir les codes
« Sources\2 - Caméscope Numérique\AVI1_to_AVI2 » et « Sources\2 - Caméscope
Numérique\ AVI2_to_AVI1 ».)
Page 53/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
2.a) Capturer du caméscope à un fichier AVI
Maintenant, nous voulons effectuer la même chose qu’avec une webcam mais en
utilisant un caméscope numérique.
Cette section décrit comment faire pour capturer une vidéo numérique à partir
d’un caméscope ou d’une casette (insérée dans le caméscope.) Voici les étapes à suivre :
1. Créer une instance du filtre « MSDV Driver ». (Voir section « Sélectionner un
périphérique de capture ».)
2. Initialiser le constructeur de graphe de capture. (Voir section « A propos du
constructeur de graphe de capture ».)
3. Construire le graphe de capture dépendant du type de fichier voulu:
• Capturer un fichier de type 1.
• Capturer un fichier de type 2.
4. Lancer le graphe.
•
Capturer un fichier de type 1
Un fichier type 1 ne contient qu’un seul flux entrelacé. Pour capturer un fichier de
type 1 et le prévisualiser en même temps, voici le graphe à construire :
Les filtres contenus dans se graphe sont :
Page 54/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
•
•
•
•
Master d'Informatique 2004-2005
Le filtre « Smart Tee » divise le flux en deux flux pour la capture et la
prévisualisation. Les deux flux contiennent le même flux entrelacé.
Les filtres « AVI Mux » et « File Writer » écrivent le flux entrelacé sur le disque
dur.
Le filtre « DV Splitter » sépare le flux entrelacé en deux flux vidéo et audio. Les
deux servent à la prévisualisation.
Le filtre « DV Video Decoder » décode le flux numérique pour la
prévisualisation.
Voir le code « Sources\2 - Caméscope Numérique\camera_to_AVI1 ».
•
Capturer un fichier de type 2
Un fichier type 2 comporte deux flux, un qui contient la vidéo numérique et
l’autre qui contient l’audio. Pour capturer un fichier de type 2 et le prévisualiser en même
temps, voici le graphe à construire:
Ce graphe est sensiblement identique au précédent pour capturer un fichier de
type 1. La seule différence, c’est que le flux de capture passe à travers le filtre « DV
Splitter » avant de passer dans le filtre « AVI Mux ». De ce fait, le filtre « AVI Mux »
reçoit deux flux : un audio et un vidéo encodé.
Voir le code « Sources\2 - Caméscope Numérique\camera_to_AVI2 ».
•
Capturer à partir d’une cassette
Ce qui précède dans cette section explique comment capturer un flux à partir d’un
caméscope numérique. (On l’utilisait donc comme un webcam.) Maintenant, nous allons
nous intéresser à créer un fichier AVI à partir d’un film qui se trouve sur une cassette.
Avant de commencer, il est important de spécifier que le caméscope doit être en
mode cassette et non pas en mode caméra. De toute façon, pendant l’initialisation de
Page 55/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
l’application, il existe un moyen de faire cette vérification et d’informer l’utilisateur si
besoin est.
Cette vérification ce fait avec la fonction « IAMExtDevice::GetCapability » avec
a valeur « ED_DEVCAP_DEVICE_TYPE. Si la fonction renvoi la valeur
« ED_DEVTYPE_VCR », le périphérique est dans le bon mode et toutes les fonctions
spécifiques au contrôle de la cassette sont disponible (play, stop, pause, …). Sinon, il est
toujours possible d’utiliser le mode caméra uniquement.
Capturer un film à partir d’une cassette fonctionne de la même manière que
capturer à partir du caméscope. Donc, les graphes à construirent sont exactement
identiques suivant le type de fichier désiré. La seule différence réside dans le fait, qu’il
faut mettre la cassette en lecture. (Voir la section « Contrôler un caméscope
numérique ».) Afin d’éviter de perdre quelques secondes au début ou/et à la fin du film,
l’ordre des étapes est important : Il faut d’abord lancer le graphe puis jouer la casette.
Après la transmission complète, il faut d’abord arrêter la casette puis le graphe.
Voir les codes « Sources\2 - Caméscope Numérique\K7_to_AVI1 » et
« Sources\2 - Caméscope Numérique\K7_to_AVI2 ».
2.b) Transmettre un fichier AVI sur une cassette
Après avoir transformé un film d’un cassette en un fichier AVI, il est intéressant
de pouvoir faire le contraire: transmettre un fichier AVI sur une cassette. Ceci ne peut se
faire sans rencontrer une petite difficulté, en effet le fichier AVI en question peut être soit
de type 1, soit de type 2… Voici les étapes à suivre:
1. Créer une instance du filtre « MSDV Driver ».
2. Initialiser le constructeur de graphe de capture.
3. Créer le graphe dépendant du type de fichier:
• Transmettre à partir d’un fichier type 1.
• Transmettre à partir d’un fichier type 2.
4. Mettre le caméscope en mode Enregistrement-Pause. (Voir section « Contrôler un
caméscope numérique ».)
5. Mettre en pause le graphe. Dans ce mode, il graphe envoi en continu la première
image du film.
6. Pour commencer à transmettre, mettre le caméscope en mode Enregistrement puis
lancer le graphe. Le caméscope a besoin d’un certain temps pour ce être disposé à
enregistrer, donc, il est préférable d’attendre deux ou trois secondes avant de
lancer le graphe. Ceci peut aboutir à une duplication de quelques images au début
du film mais assure qu’il n’en manquera pas.
Page 56/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
•
Master d'Informatique 2004-2005
Transmettre à partir d’un fichier type 1
Pour transmettre un fichier de type 1 sur une casette en prévisualisant le film, il
faut utiliser le graphe montré ci-dessous:
Les filtres qui composent ce graphe sont:
•
•
•
Le filtre « AVI Splitter ». Pour un fichier de type 1, la sortie délivre un flux
entrelacé.
Le filtre « Infinite Pin Tee » divise le flux en deux flux pour la capture et la
prévisualisation. Les deux flux sont entrelacés. (Ce graphe utilise le filtre
« Infinite Pin Tee » à la place du filtre « Smart Tee », parce qu’il n’y a pas de
danger de supprimer des images lorsque la source est un fichier, contrairement à
une capture en live.)
Le filtre « DV Splitter » sépare le flux entrelacé en un flux audio et un flux vidéo
décodé par le filtre « DV Video Decoder ».
Voir le code « Sources\2 - Caméscope Numérique\AVI1_to_K7 ».
•
Transmettre à partir d’un fichier type 2
Pour transmettre un fichier de type 1 sur une casette en prévisualisant le film, il
faut utiliser le graphe montré ci-dessous:
Page 57/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Un fichier type 2 à deux flux, d’où l’utilité d’utiliser le filtre « DV Mux » pour le
convertir un fichier de type 1. On peut remarquer que dans tous les cas, le caméscope ne
peut recevoir et envoyer que des flux entrelacé, alors que pour la prévisualisation, il faut
re-séparer les flux. Voir le code « Sources\2 - Caméscope Numérique\AVI2_to_K7 ».
3) Contrôler un caméscope numérique
On a vu qu’il était possible d’utiliser le caméscope numérique comme une
webcam “de luxe”. On a également vu qu’il était possible de lire ou d’enregistrer un film
sur une cassette. Mais à proprement parler des paramètres du caméscope, nous n’avons
encore rien vu.
Le filtre de capture vidéo WDM propose cinq interfaces pour contrôler en
globalité le caméscope numérique:
•
•
•
•
•
IAMExtDevice : une basique interface qui gère quelques fonctions.
IAMCameraControl : permet de régler les paramètres du caméscope (zoom,
focus, …)
IAMExtTransport : cette interface contrôle le mode cassette (lecture, stop, …).
IAMTimecodeReader : permet de savoir à quel endroit nous sommes sur la
cassette.
IAMTimecodeDisplay : permet de modifier l’affichage du caméscope.
Afin de pouvoir utiliser l’ensemble des fonctionnalités de ces interfaces (si
toutefois elles sont disponible sur la caméscope), il ne faut pas oublier d’inclure le fichier
« XPrtDefs.h » dans le projet sous peine d’avoir des erreur de compilation.
Après avoir sélectionner le filtre de capture, il faut utiliser la fonction
« QueryInterface » pour récupérer un pointeur sur l’une de ces interfaces.
3.a) IAMExtDevice
Page 58/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Cette interface gère des fonctions basiques du caméscope et n’est pas très utile.
Elle permet de connaître le port sur lequel le périphérique est connecté (en général sur le
port IEEE de la carte FireWire), et de pouvoir allumer et éteindre le caméscope.
3.b) IAMCameraControl
Cette interface est utile si l’on veut paramétrer à distance les fonctions comme le
zoom, le degré d’exposition, … du caméscope. Comme pour régler la luminosité d’une
webcam, cette interface dispose de trois fonctions, une pour récupérer la plage de valeur
possible et la valeur par défaut, une autre pour récupérer la valeur courante et enfin une
dernière pour modifier cette valeur. Cette interface requière tout de même un matériel très
perfectionné, en effet, le caméscope numérique mis à ma disposition ne supportait pas
cette
fonctionnalité.
(Voir
le
code
« Sources\2
Caméscope
Numérique\IAMCameraControl ».)
3.c) IAMExtTransport
Lorsque que l’on regarde la documentation de cette interface, on peut avoir peur ;
elle est très complexe… mais lorsque que l’on lit les dernières lignes de chaque fonction,
on s’aperçoit que la plupart des fonctions ne sont pas encore implémenter dans cette
version de DirectShow. Pour l’instant, le seul moyen de pouvoir les utiliser est de créer
soi-même sont propre filtre de capture.
De ce fait, cette interface, nettoyée de tout ce qui est inutile, se résume à trois
fonctionnalités :
•
•
•
Détecter le format du support d’enregistrement (cassette).
Modifier des paramètres basiques comme le format de l’heure, …
Contrôler la cassette du caméscope (lecture, stop, retour rapide, …)
Les modes disponibles sont assez nombreux. Pour les utiliser, il suffit d’employer
la méthode « put_Mode ». En voici la liste :
Valeur
Description
ED_MODE_PLAY
Lecture
ED_MODE_STOP
Stop
ED_MODE_FREEZE
Pause
ED_MODE_THAW
Reprendre
ED_MODE_FF
Avance rapide
ED_MODE_REW
Rembobiner
ED_MODE_RECORD
Enregistrer
Page 59/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
ED_MODE_RECORD_FREEZE
Enregistrer-Pause
ED_MODE_RECORD_STROBE
Enregistrer une seule image
ED_MODE_STEP_FWD
Avance d’une seule étape
ED_MODE_STEP_REV
Recule d’une seule étape
ED_MODE_SHUTTLE
Avance rapide mais la vidéo reste visible
ED_MODE_EDIT_CUE
Positionner la
d’évènement
ED_MODE_LINK_ON
Utilise le même mode que le graphe
ED_MODE_LINK_OFF
Mode indépendant du graphe
cassette
à
un
point
Voir le code « Sources\2 - Caméscope Numérique\IAMExtTransport ».
3.d) IAMTimecodeReader
Cette interface sert à connaître l’endroit où nous en sommes sur la cassette ainsi
que le numéro de la piste. Elle peut être utile pour savoir s’il faut ou non changer de
cassette afin d’avertir l’utilisateur.
3.e) IAMTimecodeDisplay
Elle gèrent les paramètres d’affichage du caméscope, comme la couleur, la taille
des caractères, le centrage, la transparence… Voir le code « Sources\2 - Caméscope
Numérique\IAMTimecodeDisplay ».
Page 60/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Annexe C: Contrôle d'une carte Tuner
TV
Nous présentons dans cette partie un autre exemple de capture de flux vidéo
analogique: la carte Tuner-Télévision. Elle diffère des autres scénarios de captures vidéo
en plusieurs points. Tout d’abord, la carte tuner se cale sur un signal analogique qui sera
ensuite numérisé. Ensuite, la partie audio est véhiculée par le signal analogique et la
façon dont elle peut atteindre la carte son peut varier d’un matériel à un autre
(généralement cette liaison externe est réalisée par un câble joignant la carte tuner à la
carte son). Et enfin le signal peut contenir des données supplémentaires dans le "Vertical
Blanking Interval" (VBI, partie contenant un signal non visible), telles que les "Closed
Captions" (CC), le "World Standard Teletext" (WST) et les services de données étendues
(XDS) ; tous ces termes seront repris et développés par la suite.
Sur la figure ci-dessous nous pouvons retrouver la représentation d’un graphe de
prévisualisation de la télévision. Elle servira de base aux explications des filtres utilisés
ainsi qu’à la compréhension du modèle.
Représentation d’un graphe de prévisualisation de la télévision
Voici donc les filtres nécessaires. Tout d’abord le premier filtre à insérer est le
filtre de capture vidéo WDM. C’est le filtre qui pourra délivrer le flux vidéo numérisé
mais pour cela d’autres filtres lui sont nécessaires à savoir:
• le filtre Tuner TV : qui contrôle le tuning pour les tuners TV analogiques.
• le filtre Audio TV : qui contrôle les réglages audio pour les tuners TV
analogiques.
• le filtre "Analog Video Crossbar" : qui se charge de router les signaux vidéo et
audio à travers le composant matériel. Par exemple, un périphérique peut avoir
plusieurs entrées (telles que l’entrée S-Vidéo et l’entrée composite). Le filtre
crossbar permet à l’application de sélectionner l’entrée.
Bien qu’ils soient des filtres séparés dans DirectShow, ils représentent pourtant le
même composant matériel. Chaque filtre contrôle une fonction différente du composant.
Les filtres sont connectés par l’intermédiaire des bornes, mais aucune donnée média ne
circule dans les connexions entre les bornes. Par conséquent, les bornes de ces filtres ne
négocient pas de type de média avant de se connecter. Mais à la place, ils utilisent des
valeurs GUID appelées mediums. Un medium étant une structure qui identifie un chemin
matériel de données entre deux périphériques sur une machine. Par exemple, le filtre
Tuner TV et le filtre de capture vidéo pour une même carte TV supportent le même
Page 61/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
medium, qui permet à l’application de construire le graphe correctement. En pratique,
l’utilisation de ICaptureGraphBuilder2 pour la construction d’un graphe de capture à
pour avantage que ces filtres soient ajoutés automatiquement au graphe.
Sachant quel est le rôle "primaire" que joue chacun des filtres présents dans la
graphe de capture. Nous pouvons maintenant aborder les fonctionnalités que nous offrent
chacun de ces filtres.
Dans le cadre ou nous sommes placés (capture de télévision), le filtre Tuner TV
est énormément important puisque c’est par lui que la sélection d’un canal pourra être
effectuée. De façon interne, le filtre Tuner TV conserve une liste de tables de fréquences.
Chaque table de fréquences correspond aux fréquences de diffusion ou du câble pour un
pays ou une région donné(e). Il existe aussi une table de fréquence "Unicable" générique
qui est utilisée lorsqu’un pays ou une région ne s’est pas vu assigner de fréquences.
Chaque table de fréquences contient une liste de fréquences de tuning. Pour un certain
nombre de pays ou de régions, les indices dans la table correspondent directement aux
numéros de canaux. Mais pour d’autres pays ou régions, cela n’est pas le cas. Alors, dans
cette situation, l’application doit conserver une table de correspondance entre le numéro
des canaux (sélectionner par l’utilisateur) et les entrées dans la table des fréquences.
Grâce à l’interface IAMTVTuner (qui hérite de l’interface IAMTuner) exposée par
ce filtre, nous pouvons obtenir son contrôle sur la sélection de canaux, des fréquences et
récupérer des informations sur les différents standards vidéo analogiques que le Tuner
TV ou encore de spécifier si le signal provient d’une antenne ou du câble. Ayant vu avant
qu’il existe une liste de tables de fréquences, il existe une méthode prenant en paramètre
un entier qui permet de sélectionner la table associée à un pays ou une région ; l’entier
utilisé afin de correspondre avec un pays ou une région est le même que l’indicatif
téléphonique d‘entrée dans ce même pays (par exemple 33 pour la France, 44 pour le
Royaume-Uni ou encore 351 pour le Portugal). La méthode put_Channel nous permet
de sélectionner un canal, mais l’entier qu’elle prend en paramètre correspond à l’indice
de la table de fréquence en cours d’utilisation. Une autre méthode, ChannelMinMax
nous permet de récupérer les canaux minimaux et maximaux utilisables dans la table de
fréquence utilisée, ce qui peut être utile pour tester la validité d’un indice en vue de
l’utiliser pour la méthode précédente par exemple. Il est possible que des entrées dans la
table de fréquences puissent être incorrectes ou obsolètes. Par conséquent, un mécanisme
est fourni pour remplacer chaque entrée par le biais de clés dans la base de registre.
Chaque clé définie un espace de tuning une ou plusieurs sous-clés, et chaque sous-clé
remplace une entrée dans la table des fréquences. La méthode put_TuningSpace permet
de fixer l’espace de tuning courant. C’est donc à l’application de maintenir une
correspondance entre ceux-ci et les pays ou régions. La meilleure approche est d’utiliser
l’identifiant de région ou de pays comme nom pour l’espace de tuning. Bien que les
fréquences sur le câble soient généralement supposées exactes, les fréquences de
diffusion peuvent avoir été réajustées de quelques kHz par la station de diffusion afin de
réduire les interférences potentielles avec des canaux voisins. Lorsque le filtre Tuner TV
se positionne sur un canal, il scanne plus précisément le signal. Le filtre Tuner TV
possède un mécanisme pour sauvegarder les fréquences ajustées dans la base de registres.
La technique consiste à récupérer les canaux minimaux et maximaux, de parcourir les
canaux compris entre ces bornes en le sélectionnant à chaque fois, et lorsque cela est
terminé, de faire appel à StoreAutoTune qui se chargera d’écrire ces nouvelles valeurs
Page 62/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
dans l’entrée de l’espace de tuning courant dans la base de registres. Une autre méthode
permet de récupérer les différents types de standards de télévision vidéo analogique
supportés par la carte. Ces différents standards sont des versions déclinées des 3 grands
standards que sont :
• NTSC (pour National Television Standards Committee) : qui est le
standard le plus utilise aux Etats-Unis et au Japon. Il délivre 30 images
entrelacées par seconde avec une résolution de 525 lignes.
• PAL (pour Phase Alternating Line) : plus largement utilise en Europe et en
Chine. Il délivre 25 images entrelacées par seconde avec une résolution de
625 lignes.
• SECAM (pour Sequentielle Couleur Avec Mémoire) : le plus utilisé en
France (où il a été développé), en Afrique et en Europe de l’Est. Tout
comme PAL, il délivre 25 images entrelacées par seconde avec une
résolution de 625 lignes.
Le filtre TV Audio, par l’intermédiaire de l’interface IAMTVAudio permet à
l’application de récupérer les modes Tv Audio supportés par le matériel physique, de
récupérer le mode courant ou d’en spécifier un. Ces types étant contenus dans un
énumérateur de type enum TVAudioMode, les valeurs pouvant être prises sont :
AMTVAUDIO_MODE_MONO,
AMTVAUDIO_MODE_STEREO,
AMTVAUDIO_MODE_LANG_A,
AMTVAUDIO_MODE_LANG_B
ou
AMTVAUDIO_MODE_LANG_C. Concernant les deux premières possibilités, comme
on peut facilement l’imaginer, ils indiquent si l’audio est en mono ou en stéréo. Mais
concernant les 3 autres, cela parait moins trivial. En effet, ils indiquent si l’audio est un
langage additionnel. Ainsi lorsqu’un audio TV bilingue est utilisé dans des régions
spécifiques, leurs représentations sont les suivantes :
• AMTVAUDIO_MODE_LANG_A : l’audio multilingue principal.
• AMTVAUDIO_MODE_LANG_B : l’audio multilingue secondaire.
• AMTVAUDIO_MODE_LANG_C : l’audio multilingue tertiaire s’il y a, sinon le
principal plus le second. Par exemple, ceci peut-être utilisé pour avoir de l’anglais
dans l’enceinte gauche et du japonais dans l’enceinte droite.
Le filtre Crossbar Video Analogique représente un crossbar vidéo sur un
périphérique de capture vidéo qui supporte le modèle WDM. Chaque borne en entrée
représente un chemin physique pour l’obtention d’un signal vidéo analogique. Une de ces
bornes d’entrée provient du Tuner TV, les autres supportent des flux vidéo ou audio. Ce
filtre ne peut pas être directement créé par CoCreateInstance. Mais sachant qu’il est
inséré dans un graphe de capture en amont d’un filtre de capture dès qu’il est nécessaire,
nous pouvons alors nous contenter de chercher une interface de type IAMCrossbar
(exposée par le filtre) dans le graphe, ou d’utiliser ICaptureGraphBuilder2 qui (comme
indiqué précédemment) ajoutera alors automatiquement ce filtre au graphe.
Sa présence se justifie par le fait que c’est par lui que la sélection de l’entrée vidéo
analogique s’effectuera. La borne de sortie vidéo devra alors être routée en interne vers la
borne d’entrée sélectionnée. Nous pouvons retrouver sur le tableau les différents types
physiques reconnus à une broche d’un crossbar. Les deux types en rouge correspondent
aux broches de sorties. Attention, ce sont les types gérés par DirectShow, mais le
crossbar qui reflète le matériel physique ne devrait pas disposer de tout cela.
Page 63/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Types physiques d’une borne du crossbar
Vidéo
audio
PhysConn_Video_Tuner
PhysConn_Video_Composite
PhysConn_Video_SVideo
PhysConn_Video_RGB
PhysConn_Video_YRYBY
PhysConn_Video_SerialDigital
PhysConn_Video_ParallelDigital
PhysConn_Video_SCSI
PhysConn_Video_AUX
PhysConn_Video_1394
PhysConn_Video_USB
PhysConn_Video_VideoDecoder
PhysConn_Video_VideoEncoder
PhysConn_Video_SCART
PhysConn_Audio_Tuner
PhysConn_Audio_Line
PhysConn_Audio_Mic
PhysConn_Audio_AESDigital
PhysConn_Audio_SPDIFDigital
PhysConn_Audio_SCSI
PhysConn_Audio_AUX
PhysConn_Audio_1394
PhysConn_Audio_USB
PhysConn_Audio_AudioDecoder
Types physiques des bornes du crossbar
Dans notre cas la borne de sortie correspondant au type
"PhysConn_Video_VideoDecoder" devra être routée sur la borne en entrée correspondant
au type "PhysConn_Video_Tuner".
Concernant la partie audio, s’il est décidé de ne seulement avoir qu’un aperçu, il
suffit de réaliser l’opération identique à la précédente mais sur les bornes de types audio,
c’est-à-dire que la borne dont le type est "PhysConn_Audio_AudioDecoder" devra être
routée (cela toujours de façon interne) sur la borne en entrée correspondant au type
"PhysConn_Audio_Tuner", comme le montre la figure. Aucun filtre de capture audio, ni
même de rendu audio ne seront nécessaires puisqu’il y aura une connexion physique
entre la carte tuner et la carte son.
Symbolisation du routage sur la partie audio du crossbar pour un aperçu audio.
En revanche, s’il est décidé de rediriger la partie audio dans un fichier, le filtre de
capture sera alors nécessaire. Alors la démarche évoquée dans la partie précédente sera à
renouveler. Et le filtre de capture audio ne verra toujours pas ses bornes en entrée
connecter à d’autres filtres. Il faudra alors sélectionner la broche qui participe à
l’enregistrement et qui physiquement connectée à la carte tuner.
Page 64/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
En ce qui concerne la sortie du crossbar, sa borne dédiée à la vidéo doit être reliée
au filtre de capture vidéo. Ce dernier contrôlant le périphérique de capture qui utilise des
pilotes basés sur WDM, le filtre est un plug-in KsProxy en mode noyau. Une application
peut le considérer comme un simple filtre. Il est nécessaire de passer par l’énumérateur
de périphériques systèmes afin de l’insérer au graphe. Le filtre expose différentes
interfaces qui permettent (entre autre) : de retrouver le format TV utilisé, de déterminer si
la synchronisation horizontale est verrouillée (s’il reçoit bien un signal), de retrouver le
nombre de lignes scannées dans le signal, de récupérer le nombre de trames qui ont été
délivrées par le filtre depuis le lancement du graphe, etc...
Nous allons maintenant nous pencher sur les données véhiculées dans le signal
analogique TV mais qui ne sont pas visibles. Mais tout d’abord, rappelons le
fonctionnement d'un écran. Une image est affichée sur un moniteur pixels par pixels. Les
faisceaux d'électrons balaient l'écran cathodique horizontalement, ligne par ligne.
Lorsqu'une ligne est finie, ils descendent d'un cran et font la ligne suivante. Lorsqu'ils
atteignent le bas de l'écran, ils reviennent à la première ligne et recommencent leur
balayage. Le temps mis par les faisceaux pour aller du bas droite de l'écran au coin haut
gauche est appelé intervalle vide vertical (soit le Vertical Blank Interval).
Le VBI est exprimé en nombre de lignes horizontales scannée. Le signal VBI se
doit d’être faible afin de ne pas affecter défavorablement le faisceau d’électrons qui
transporte le signal de l’image principale. En fait, les signaux analogiques TV doivent
indiquer une intensité nulle pour le faisceau durant le VBI afin de s’assurer que l’image
ne sera pas affectée. Mais grâce à d’autres circuits internes aux téléviseurs, il est possible
de détecter et d’interpréter ce faible signal. Les signaux transmis pendant le VBI sont
habituellement numériques, mais on peut se rappeler que si la télévision n’intègre pas de
circuit (matériel) permettant de les décoder, cela n’a aucun effet sur la diffusion, et ne
sont pas vu par le téléspectateur. A titre d’exemple, sur les 525 lignes horizontales à
balayer spécifiées dans le format NTSC, seulement 486 sont visibles et donc qui fait une
quarantaine de lignes pour le VBI. Le VBI peut contenir des données concernant le
"Closed Captioning" et le Teletext.
Les Closed Captions (CC) sont des versions textuelles des "parties parlées" d’une
émission, d’un film ou d’une présentation sur ordinateur. Leurs utilisations ont été
conçues afin d’aider les personnes malentendantes. Ceci peut être utile à toute personne
lorsque l’environnement est trop bruyant ou, au contraire lorsque le silence est requis
(comme dans un hôpital par exemple). Ils peuvent être considérés comme des sous-titres
plus précis, puisque cela ne se limite pas qu’aux dialogues. Par exemple, pourront être
perçus la sonnerie de téléphone ou le fait que quelqu’un frappe à la porte. "Caption"
pourrait être traduit par sous-titre ou légende et le "Closed" se justifie par le fait que ces
informations sont encodées dans la ligne 21 du VBI (et donc cachées) d’un signal NTSC.
Le texte ne devient visible qu’avec l’utilisation d’un décodeur, qu’il soit intégré à la
télévision ou sous forme d’un boîtier venant se placer entre la source et la télévision. La
plupart des programmes télévisuels se voient insérer en avance de telles données avant la
diffusion, mais pour d’autre, comme la diffusion d’émissions en direct, cela nécessite
d’être effectué en temps réel. Auquel cas, un sténographe écoute la diffusion et saisie en
sténo ce qu’il perçoit dans un programme, celui-ci se chargeant de les convertir en "soustitres" et de les insérés dans le signal vidéo.
Page 65/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Le teletext est un système de transmission (à sens unique) de texte et de
graphiques le plus utilisé en Europe (mais aussi disponible dans différentes régions aux
Etats-Unis) qui utilise des lignes du VBI des diffusions de signaux vidéo PAL et
SECAM. Un décodeur (tout comme le CC) est nécessaire quant à l’extraction de ces
données. C’est une boucle cachée de pages d’informations qui sont transmises les unes
après les autres. L’utilisateur peut sélectionner les pages qu’il souhaite visualiser.
Lorsque qu’un numéro de page est entré, après un certain délai, celle-ci est affichée sur
l’écran. Bien que teletext puisse paraître interactif, il ne l’est pas. Lorsqu’une page est
demandée, le décodeur attend simplement que la page soit diffusée, la capture et l’affiche
sur le poste. La variation du délai peut dépendre du nombre de "trames" dans la boucle
teletext ou du poste, mais cela est généralement compris entre 5 et 30 secondes.
XDS (auparavant connu sous le nom EDS) pour Extended Data Services. C’est un
concept qui n’a pas encore été complètement implémenté. L’idée est d’utiliser un des
champs auparavant réservés pour les captions pour transporter des informations
concernant le programme diffusé mais pas sous forme de captions. Les informations XDS
devront être sous forme de paquets, contenant des informations comme le moment de la
journée, le réseau ou le programme actuel. Cela signifie que les télévisions et les
magnétoscopes pourraient être capables de régler automatiquement leur horloge interne et
qu’un utilisateur pourra rechercher après un programme par son nom ou son réseau mais
plus par son numéro de canal.
Dans le cas où nous souhaiterions visualiser ces informations cachées, nous pouvons
voir sur les figures suivantes, les graphes qui seront à construire. On peut constater que
dans les deux cas, le filtre de capture vidéo est à la base du graphe. Pour supporter les CC
en télévision analogique, le filtre expose une borne qui délivre les données VBI ou CC.
Cette borne doit appartenir à l’une des catégories suivantes :
• PIN_CATEGORY_VBI : délivre un flux d’échantillons VBI. Ils seront
passés à un filtre décodeur qui extraira les données CC.
• PIN_CATEGORY_CC : délivre des paires d’octets de CC, extraites à
partir de la ligne 21.
• PINNAME_VIDEO_CC_CAPTURE
Représentation du graphe de prévisualisation des "Closed Captions"
Page 66/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Représentation du graphe de prévisualisation du Teletext
Dans le cas des CC, l’utilisation d’une méthode (appartenant à
ICaptureGraphBuilder2) de demande de rendu sur cette borne du filtre de capture,
procure l’avantage que les filtres suivants seront automatiquement insérés :
• le filtre "Tee/Sink-to-Sink Converter" : qui accepte les informations VBI
du filtre de capture et les scinde en flux séparés chacun des services
présents dans le signal. Microsoft fournit des codecs VBI pour CC,
NABTS et World Standard Teletext.
• le filtre "CC Decoder" : qui décode les données CC d’un échantillon VBI
fourni par le filtre de capture.
• le filtre "Line 21 Decoder" : qui traduit les paires d’octets CC et dessine le
texte sur les images.
Dans le cas du Teletext, les filtres insérés entre le "Tee/Sink-to-Sink Converter" et
l’"Overlay Mixer" sont : le filtre "WST Codec" qui décode les données teletext à partir
des échantillons VBI et le filtre "WST Decoder" qui traduit les données teletext et
dessine le texte sur les images. Il est à noter que dans ce cas, ces filtres ne pourront pas
être insérés automatiquement.
Page 67/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Annexe D: Contrôle d'un DVD
En général, les applications DVD sont très complexes. Cela dépend des
fonctionnalités attendues par l’utilisateur. S’il souhaite simplement regarder un film ou
paramétrer chaque angles de vues d’une scène, …
DirectShow nous propose, pour nous aider dans cette tâche, un filtre source appelé
« DVD Navigator ». Ce navigateur de DVD contient absolument toutes les
fonctionnalités que vous pourrez trouver dans un lecteur de DVD de salon, et à cela
s’ajoute des fonctionnalités spécifiques pour la lecture de DVD sur un ordinateur
personnel. Ainsi, il est possible de développer des lecteurs de DVD sans se référer aux
spécifications du DVD. Le navigateur, en coordination avec le décodeur, gère les
problèmes de région du DVD et de sa protection contre le piratage.
Le navigateur fonctionne sur un DVD entier qui comporte tous ses fichiers .vob
dans un répertoire nommé « VIDEO_TS ». Contrairement aux autres filtres sources de
DirectShow qui ne gèrent qu’un flux ou fichier à la fois, le navigateur utilise la structure
en titres et chapitres du DVD.
Avant de pouvoir visionner un film avec DirectShow, il est primordial d’installer
préalablement un décodeur MPEG-2 non fournie avec le SDK de DirectX.
L’ensemble des fonctionnalités du navigateur est divisé en deux catégories.
Chaque catégorie est représentée par une interface spécifique qui permet de les contrôler.
La première est l’interface « IDvdControl2 ». Elle regroupe toutes les méthodes « set ».
La seconde est l’interface « IDvdInfo2 ». Elle rassemble toutes les fonctions « get ».
1) Ecrire une application DVD
De la même façon que pour créer un graphe de capture, il existe un objet
spécifique pour concevoir un graphe destiné à lire un DVD. L’interface qui lui ait
attribuée est « IDvdGraphBuilder ». Elle dispose de trois fonctions :
• GetFilterGraph : permet de spécifier le graphe utiliser.
• GetDvdInterface : permet de récupérer un pointeur sur l’une des interfaces
« IDvdControl2 » ou « IDvdInfo2 ».
• RenderDvdVideoVolume : Cette fonction crée le graphe du début à la fin.
Il y a eu quelques changements lors de l’évolution de Windows et du passage à la
version 9 de DirectX. Dans les précédentes versions de DirectX, seul le filtre « Overlay
Mixer » était disponible. Dans Windows XP, le filtre « Video Mixing Rendere 7 » fut
introduit. Puis, avec DirectX 9, le filtre « Video Mixing Renderer 9 » vient s’ajouter.
Donc, maintenant, il y a trois filtres de rendu disponibles. Le choix de l’un d’entre eux
dépendra du système d’exploitation, du type du décodeur MPEG-2 et du matériel vidéo
présent dans le système de l’utilisateur.
Le schéma suivant montre un graphe de lecture de DVD qui fonctionne sous
Windows 98SE, Windows 2000, ou Windows Me. Ici, un décodeur MPEG-2 est installé.
Page 68/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Sur Windows XP, les filtres « Overlay Mixer » et « Video Renderer » sont
remplacés par le filtre « Video Mixing Renderer 7 ». Et le filtre « Line 21 Decoder » est
remplacé par le filtre « Line 21 Decoder 2 », comme le montre le schéma suivant. Ici
également, un décodeur MPEG-2 est installé.
Lorsqu’un décodeur matériel est présent, il est directement connecté à la carte
vidéo. Ceci permet de passez directement à la carte graphique sans passer par la mémoire
centrale. Pour réaliser cette connexion sur les anciennes versions de Windows,
DirectShow utilise « DirectDraw Video Port Extensions » (VPE) à travers une interface
sur le filtre « Overlay Mixer ». Le diagramme suivant illustre ce cas.
Le diagramme suivant montre le même cas mais sous Windows XP.
Page 69/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
Dans l’ensemble de ces graphes, le navigateur de DVD est le filtre source; il
réalise différentes tâches:
• Lire la navigation et la vidéo sur le disque.
• Sépare les flux vidéo, audio et sous-titres.
• Envoie les flux dans les différentes broches.
• Informe l’application des évènements du DVD.
2) Recevoir des évènements du DVD
Le navigateur de DVD prévient l’application lorsqu’il reçoit un évènement
provenant du DVD. Le genre d’évènement que l’on peut recevoir est : le DVD change de
domaine, le niveau de contrôle parental change pour une certaine scène, ou il y a
plusieurs angles de vues disponible pour la même scène. Les paramètres des évènements
peuvent varier en fonction du type de l’évènement. Les messages d’erreurs sont
également transmis de cette manière. L’application informe la fenêtre de l’évènement en
utilisant un pointeur sur l’interface « IMediaEventEx » puis appelle la fonction
« SetNotifyWindow ».
L’évènement lui-même est récupérer par l’application grâce à un appelle de la
méthode « IMediaEvent::GetEvent ». Du fait que plus d’un évènement peut survenir à
n’importe quel moment, l’application doit effectuer un appel à « GetEvent » dans une
boucle jusqu’à ce que tous les évènements soient traités.
Voir les codes « Sources\3 - DVD\lire_DVD » et « Sources\3 - DVD\lire_film ».
3) Le filtre MPEG-2 Demultiplexeur
Comme vous l’aurez remarqué, pour l’instant, nous n’avons vu que le navigateur
de DVD qui permet uniquement de lire un DVD. J’ai essayé de l’utiliser afin
d’enregistrer le film dans un fichier AVI compressé en DivX par exemple.
Malheureusement, ce n’est pas possible de cette façon. De plus, aucune documentation
n’est disponible dans le SDK de DirectX ;-).
Après de multiples recherches, j’ai finalement trouvé un filtre : le « MPEG-2
Demultiplexeur » qui permet de séparer les flux audio, vidéos et sous-titre d’un fichier
.vob. Il y a également le filtre « I-Media Multiple MPEG2 Source » qui permet de mettre
en source non pas un fichier mais une liste de fichiers .vob. (Malheureusement, ce filtre
ne fonctionne pas correctement.) Mais cela n’est qu’un détail, il suffit de réitérer le
Page 70/71
Université de Reims Champagne-Ardennes
Programmation Multimédia
Master d'Informatique 2004-2005
processus sur tous les fichiers .vob contenu dans le DVD puis de regrouper les bouts de
film et le tour est joué.
Etant conscient du caractère interdit de cette application, je ne l’ai développé qu’à
titre d’exemple et d’apprentissage, et en aucun cas, j’en aurais recours pour un usage
illégal.
La première chose à faire pour espérer réussir convertir un DVD en DivX, il faut
copier tous les fichiers .vob du DVD sur le disque dur. Voici déjà la première difficulté :
la plupart des DVD sont protégés contre la copie directe. Si c’est la cas pour votre DVD,
il va falloir avoir recourt à un programme externe qui se chargera de supprimer cette
protection (uniquement pour tester).
Une fois l’intégralité du film sur le disque (cela prend 5 ou 6 Gigas, voir plus en
fonction du film), on peut commencer à créer le graphe de cette manière :
Dans cet exemple, seul le flux vidéo est compressé. Pour compresser également le
flux audio, il suffit de rajouter un filtre de compression MP3 (par exemple) entre les
filtres « AC3Filter » et « AVI Mux ».
Pour un exemple de cette application et un exemple avec le filtre de multiples
sources, voir les codes « Sources\3 - DVD\VOB_to_DivX » et « Sources\3 DVD\DVD_to_DivX ».
Page 71/71
Université de Reims Champagne-Ardennes

Documents pareils