Direct Show Direct Show n n n A

  • Slides: 61
Download presentation
Direct. Show

Direct. Show

Direct. Show 정의 n n n A media-streaming architecture for the Microsoft® Windows® platform.

Direct. Show 정의 n n n A media-streaming architecture for the Microsoft® Windows® platform. 고품질의 비디오/오디오 재생과 녹음이 가능. 다양한 형식 지원 w ASF(Advanced Streaming Format), MPEG, AVI, MP 3, Wav n n n WDM(Windows Driver Model) 기반의 캡쳐 기능을 지원. 재생, 캡쳐, 변환 기능 지원 주요 응용 프로그램 w w w w DVD Players Video Editing Application AVI to ASF Converts MP 3 Players, Digital Video Captures. 2

Supports formats in Direct. Show File formats: n n n Windows Media™ Audio (WMA)*

Supports formats in Direct. Show File formats: n n n Windows Media™ Audio (WMA)* Windows Media™ Video (WMV)* Advanced Streaming Format (ASF)* Motion Picture Experts Group (MPEG) Audio-Video Interleaved (AVI) Quick. Time (version 2 and lower) WAV AIFF AU SND MIDI Compression formats: n n n Microsoft Windows Media Video codec version 7. 0* ISO MPEG-4 video version 1. 0* Microsoft MPEG-4 version 3* Sipro Labs ACELP* Windows Media Audio* MPEG Audio Layer-3 (MP 3) (decompression only) Digital Video (DV) MPEG-1 MJPEG Indeo Voxware* Cinepak 3

Introduction to Direct. Show Application Programming Filter Graphs n n The basic building block

Introduction to Direct. Show Application Programming Filter Graphs n n The basic building block of Direct. Show is a software component 기능 w w Read files. Get video from a video capture device. Decode a particular stream format, such as MPEG-1 video. Pass data to the graphics or sound card. 7

Writing a Direct. Show Application Typical three basic steps 1. 2. 3. Creates an

Writing a Direct. Show Application Typical three basic steps 1. 2. 3. Creates an instance of the Filter Graph Manager, using the Co. Create. Instance function. Uses the Filter Graph Manager to build a filter graph. (You might use other Direct. Show helper components as well. ) Controls the filter graph and responds to events. 8

Setting Up the Build Environment Building Direct. Show Applications n Dshow. h Library File

Setting Up the Build Environment Building Direct. Show Applications n Dshow. h Library File Description Strmiids. lib Exports class identifiers (CLSIDs) and interface identifiers (IIDs). All Direct. Show applications require this library Quartz. lib Exports the AMGet. Error. Text function. If you do not call this function, this library is not required. Strmbase. lib Required only if you use the Direct. Show base classes 9

How To Play a File Playing the File n four-step process 1. 2. 3.

How To Play a File Playing the File n four-step process 1. 2. 3. 4. n Create an instance of the filter graph manager. Use the filter graph manager to create a filter graph. Use the filter graph manager to run the filter graph. Wait for playback to complete. COM interfaces w IGraph. Builder : Constructs the filter graph. w IMedia. Control : Handles media streaming in the filter graph. w IMedia. Event : Handles filter graph events. 10

초기화 IGraph. Builder *p. Graph; Co. Initialize(NULL); Co. Create. Instance(CLSID_Filter. Graph, NULL, CLSCTX_INPROC_SERVER, IID_IGraph.

초기화 IGraph. Builder *p. Graph; Co. Initialize(NULL); Co. Create. Instance(CLSID_Filter. Graph, NULL, CLSCTX_INPROC_SERVER, IID_IGraph. Builder, (void **)&p. Graph); n n Co. Create. Instance function returns a pointer to the filter graph manager's IGraph. Builder interface. Use this interface pointer to query for the other two interfaces that are needed, IMedia. Control and IMedia. Event: IMedia. Control *p. Media. Control; IMedia. Event *p. Event; p. Graph->Query. Interface(IID_IMedia. Control, (void **)&p. Media. Control); p. Graph->Query. Interface(IID_IMedia. Event, (void **)&p. Event); 11

실행 p. Graph->Render. File(L"C: \Hello_World. avi", NULL); p. Media. Control->Run(); p. Event->Wait. For. Completion(INFINITE,

실행 p. Graph->Render. File(L"C: \Hello_World. avi", NULL); p. Media. Control->Run(); p. Event->Wait. For. Completion(INFINITE, &ev. Code); Clean Up p. Media. Control->Release(); p. Event->Release(); p. Graph->Release(); Co. Uninitialize(); 12

샘플 코드 #include <dshow. h> void main(void) { IGraph. Builder *p. Graph; IMedia. Control

샘플 코드 #include <dshow. h> void main(void) { IGraph. Builder *p. Graph; IMedia. Control *p. Media. Control; IMedia. Event *p. Event; Co. Initialize(NULL); // Create the filter graph manager and query for interfaces. Co. Create. Instance( CLSID_Filter. Graph, NULL, CLSCTX_INPROC_SERVER, IID_IGraph. Builder, (void **)&p. Graph); p. Graph->Query. Interface(IID_IMedia. Control, (void **)&p. Media. Control); p. Graph->Query. Interface(IID_IMedia. Event, (void **)&p. Event); 13

샘플 코드 // Build the graph. IMPORTANT: Change string to a file on your

샘플 코드 // Build the graph. IMPORTANT: Change string to a file on your system. p. Graph->Render. File(L"C: \Hello_World. avi", NULL); // Run the graph. p. Media. Control->Run(); // Wait for completion. long ev. Code; p. Event->Wait. For. Completion(INFINITE, &ev. Code); // Clean up. p. Media. Control->Release(); p. Event->Release(); p. Graph->Release(); Co. Uninitialize(); } 14

Setting the Video Window Attach video playback to a particular window IVideo. Window interface

Setting the Video Window Attach video playback to a particular window IVideo. Window interface n which contains methods for setting and retrieving properties on the video window Using the IVideo. Window Interface n Attach the video playback window to the desired parent window. w To do this, call the IVideo. Window: : put_Owner method and pass it a handle to the owner window. This method takes a variable of type OAHWND, so cast the handle to this type, if necessary: IVideo. Window *p. Vid. Win = NULL; p. Graph->Query. Interface(IID_IVideo. Window, (void **)&p. Vid. Win); p. Vid. Win->put_Owner((OAHWND)g_hwnd); 15

Setting the Video Window Change the style of the video window to a child

Setting the Video Window Change the style of the video window to a child window. To do this, call the IVideo. Window: : put_Window. Style method and pass it a combination of style flags. The WS_CHILD flag indicates that the window is a child window; the WS_CLIPSIBLINGS flag prevents the window from drawing inside the client area of another child window. p. Vid. Win->put_Window. Style(WS_CHILD | WS_CLIPSIBLINGS); n Set the position of the video window by calling the IVideo. Window: : Set. Window. Position method. This method takes device coordinates specifying the left edge (x-axis), top edge (y-axis), width, and height of the window. The sample program stretches the video window to fill the entire parent window: RECT grc; w Get. Client. Rect(g_hwnd, &grc); p. Vid. Win->Set. Window. Position(0, 0, grc. right, grc. bottom); HRESULT hr = p. Vid. Win->put_Visible(OAFALSE); hr = p. Vid. Win->put_Owner(NULL); 16

Video Window Sample Code (1/5) #include <windows. h> #include <dshow. h> #define CLASSNAME "Video.

Video Window Sample Code (1/5) #include <windows. h> #include <dshow. h> #define CLASSNAME "Video. Window" IGraph. Builder *p. Graph = NULL; IMedia. Control *p. Media. Control = NULL; IVideo. Window HWND *p. Vid. Win = NULL; g_hwnd; void Play. File(void) { // Create the filter graph manager. Co. Create. Instance(CLSID_Filter. Graph, NULL, CLSCTX_INPROC, IID_IGraph. Builder, (void **)&p. Graph); 17

Video Window Sample Code (2/5) p. Graph->Query. Interface(IID_IMedia. Control, (void **)&p. Media. Control); p.

Video Window Sample Code (2/5) p. Graph->Query. Interface(IID_IMedia. Control, (void **)&p. Media. Control); p. Graph->Query. Interface(IID_IVideo. Window, (void **)&p. Vid. Win); // Build the graph. p. Graph->Render. File(L"Test. avi", NULL); //Set the video window. p. Vid. Win->put_Owner((OAHWND)g_hwnd); p. Vid. Win->put_Window. Style(WS_CHILD | WS_CLIPSIBLINGS); RECT grc; Get. Client. Rect(g_hwnd, &grc); p. Vid. Win->Set. Window. Position(0, 0, grc. right, grc. bottom); // Run the graph. p. Media. Control->Run(); } 18

Video Window Sample Code (3/5) void Clean. Up(void) { p. Vid. Win->put_Visible(OAFALSE); p. Vid.

Video Window Sample Code (3/5) void Clean. Up(void) { p. Vid. Win->put_Visible(OAFALSE); p. Vid. Win->put_Owner(NULL); p. Media. Control->Release(); p. Vid. Win->Release(); p. Graph->Release(); } // Message handler. long FAR PASCAL Window. Proc( HWND hwnd, UINT msg, UINT w. Param, LONG l. Param) { switch (msg) { case WM_DESTROY: Clean. Up(); Post. Quit. Message(0); break; default: return (Def. Window. Proc(hwnd, msg, w. Param, l. Param)); } return(NULL); } 19

Video Window Sample Code (4/5) int PASCAL Win. Main( HINSTANCE h. Inst, HINSTANCE h.

Video Window Sample Code (4/5) int PASCAL Win. Main( HINSTANCE h. Inst, HINSTANCE h. Prev. Inst, LPSTR lp. Cmd. Line, n. Cmd. Show ) int { MSG msg; WNDCLASS wc; Co. Initialize(NULL); Zero. Memory(&wc, sizeof wc); wc. lpfn. Wnd. Proc = Window. Proc; wc. h. Instance wc. h. Icon wc. h. Cursor = h. Inst; = Load. Icon( NULL, IDI_APPLICATION ); = Load. Cursor( NULL, IDC_ARROW ); wc. hbr. Background = (HBRUSH)Get. Stock. Object( BLACK_BRUSH ); wc. lpsz. Menu. Name = NULL; wc. lpsz. Class. Name = CLASSNAME; Register. Class( &wc ); 20

Video Window Sample Code (5/5) g_hwnd = Create. Window( CLASSNAME, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, "Direct. Show

Video Window Sample Code (5/5) g_hwnd = Create. Window( CLASSNAME, WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, "Direct. Show Sample", CW_USEDEFAULT, NULL, CW_USEDEFAULT, NULL, h. Inst, NULL); Show. Window( g_hwnd, n. Cmd. Show ); Update. Window( g_hwnd ); Play. File(); while( Get. Message( &msg, NULL, 0, 0 ) ) { Translate. Message( &msg ); Dispatch. Message( &msg ); } Co. Uninitialize(); return msg. w. Param; } 21

Responding to Events Using Event Notification n 윈도우 메시지 루프에서 이벤트를 처리. n 윈도우

Responding to Events Using Event Notification n 윈도우 메시지 루프에서 이벤트를 처리. n 윈도우 프로시져에서 다음과 같이 표시 case WM_GRAPHNOTIFY: Handle. Event(); break; n Sequence of events 1. 2. 3. 4. 5. A filter sends an event notification to the filter graph manager. If the filter graph manager does not handle the event, it places the event in the event queue. The filter graph manager posts a WM_GRAPHNOTIFY message to the application window. The application responds to the message from within the window's message loop. The application retrieves the event notification from the queue. 23

Events Nofication Sample Code (1/5) #include <windows. h> #include <dshow. h> #define WM_GRAPHNOTIFY WM_APP

Events Nofication Sample Code (1/5) #include <windows. h> #include <dshow. h> #define WM_GRAPHNOTIFY WM_APP + 1 #define CLASSNAME "Event. Notify" IGraph. Builder *p. Graph = NULL; IMedia. Control *p. Media. Control = NULL; IMedia. Event. Ex *p. Event = NULL; IVideo. Window HWND *p. Vid. Win = NULL; g_hwnd; void Play. File(void) { // Create the filter graph manager and render the file. Co. Create. Instance( IID_IGraph. Builder, CLSID_Filter. Graph, NULL, CLSCTX_INPROC, (void **)&p. Graph); p. Graph->Render. File(L"C: \Media\Boys. avi", NULL); 24

Events Nofication Sample Code (2/5) // Specify the owner window. p. Graph->Query. Interface(IID_IVideo. Window,

Events Nofication Sample Code (2/5) // Specify the owner window. p. Graph->Query. Interface(IID_IVideo. Window, (void **)&p. Vid. Win); p. Vid. Win->put_Owner((OAHWND)g_hwnd); p. Vid. Win->put_Window. Style( WS_CHILD | WS_CLIPSIBLINGS); // Set the owner window to receive event notices. p. Graph->Query. Interface(IID_IMedia. Event. Ex, (void **)&p. Event); p. Event->Set. Notify. Window((OAHWND)g_hwnd, WM_GRAPHNOTIFY, 0); // Run the graph. p. Graph->Query. Interface(IID_IMedia. Control, (void **)&p. Media. Control); p. Media. Control->Run(); } 25

Events Nofication Sample Code (3/5) void Clean. Up(void) { p. Vid. Win->put_Visible(OAFALSE); p. Vid.

Events Nofication Sample Code (3/5) void Clean. Up(void) { p. Vid. Win->put_Visible(OAFALSE); p. Vid. Win->put_Owner(NULL); // Stop the graph. p. Media. Control->Stop(); p. Media. Control->Release(); p. Vid. Win->Release(); p. Event->Release(); p. Graph->Release(); Post. Quit. Message(0); } 26

Events Nofication Sample Code (4/5) void Handle. Event() { long ev. Code, param 1,

Events Nofication Sample Code (4/5) void Handle. Event() { long ev. Code, param 1, param 2; HRESULT hr; while (hr = p. Event->Get. Event(&ev. Code, &param 1, &param 2, 0), SUCCEEDED(hr)) { hr = p. Event->Free. Event. Params(ev. Code, param 1, param 2); if ((EC_COMPLETE == ev. Code) || (EC_USERABORT == ev. Code)) { Clean. Up(); break; } } } 27

Events Nofication Sample Code (5/5) /* Window. Proc goes here. Add the following case

Events Nofication Sample Code (5/5) /* Window. Proc goes here. Add the following case statement: case WM_GRAPHNOTIFY: Handle. Event(); break; */ // Win. Main goes here. 28

Direct. Show System Overview Direct. Show Solution n Design goal is to simplify the

Direct. Show System Overview Direct. Show Solution n Design goal is to simplify the task of creating multimedia applications on the Windows® platform by isolating applications from the complexities of data transports, hardware differences, and synchronization issues. 29

The Filter Graph And Its Components High-level overview of the components that make up

The Filter Graph And Its Components High-level overview of the components that make up Microsoft® Direct. Show® filter graphs The Filter Graph n n 미디어 파일이나 스트림이 플레이 되거나 기록, 캡쳐, 방송 등의 작 업이 일어 날때, 이러한 작업은 2개 이상의 필터들이 설정된 연결에 의해 의해 동작되어 진행된다. Graph-building process는 응용 프로그램에 의해 작성되거나 Graph Builder or Filter Graph Manager에 의해 자동적으로 생성될 수 있다. 30

The Filter Graph And Its Components Filters n n Basic building blocks of Direct.

The Filter Graph And Its Components Filters n n Basic building blocks of Direct. Show Direct. Draw는 멀티미디어 데이터를 여러 개의 단계로 분류하였으며, 하나의 필터는 그 중 한단계를 담당한다. Three categories: source filters, transform filters, and renderer filters. Source filters w present the raw multimedia data for processing n Transform filters w accept either raw or partially-processed data and process it further before passing it on n Renderer filters w accept fully-processed data and play it on the system's monitor or through the speakers or possibly through some external device. w Also included in this category are "file-writer" filters that save data to disk or other persistent storage. 31

The Filter Graph And Its Components Pins n n n The multimedia data in

The Filter Graph And Its Components Pins n n n The multimedia data in a filter graph moves downstream from a source filter through zero or more intermediate filters and finally to a renderer filter Pins handle the low-level details of the data transfer between filters A COM object which supports the IPin COM interface, has a direction (input or output) Media Sample n After raw bytes have been pulled into the graph, either from a local file or capture card or some other source, the bytes must be parsed into meaningful units. 32

The Filter Graph And Its Components Allocators n n n When two filters connect,

The Filter Graph And Its Components Allocators n n n When two filters connect, their pins must agree on the details of how the media sample objects will be transported from the upstream filter to the downstream filter. To "connect" means to determine the size, location and number of samples that will be used. The creation and management of the samples is handled by an allocator Clocks n n it is vital to synchronize the samples so that video frames are displayed at the proper rate, so that the audio stream does not get ahead of the video, and so on. A Direct. Show filter graph therefore always contains exactly one clock that all filters use to either timestamp, process or render media samples. The Filter Graph Manager selects a clock 33

Building the Filter Graph General Graph Building IGraph. Builder* p. IGB; HRESULT hr; hr

Building the Filter Graph General Graph Building IGraph. Builder* p. IGB; HRESULT hr; hr = Co. Create. Instance(CLSID_Filter. Graph, NULL, CLSCTX_INPROC_SERVER, IID_IGraph. Builder, (void **)&p. IGB); Provide three basic approaches to building the graph: 1. The application instructs the Filter Graph Manager to build the entire graph automatically. 2. The application and Filter Graph Manager share the graph building work. 3. The application builds the entire graph itself by individually adding and connecting each filter. 34

Data Flow in the Filter Graph This article describes how data moves through a

Data Flow in the Filter Graph This article describes how data moves through a Microsoft® Direct. Show® filter graph Samples and Buffers n n n The direction of data flow, from output to input, is called downstream, and the opposite direction is called upstream. A media sample is a COM object that holds a pointer to an allocated memory buffer. This mechanism reduces the amount of memory allocation, because filters re-use the same buffers. 35

Data Flow in the Filter Graph Delivering Samples n The output pin delivers a

Data Flow in the Filter Graph Delivering Samples n The output pin delivers a sample by calling the IMem. Input. Pin: : Receive method on the input pin. w Rejects the sample. w Blocks until it finishes processing the sample. w Returns immediately and processes the sample on another thread. Stop, Pause, and Run n 필터의 3가지 상태 : stopped, paused, and running w Stopped : sample 을 처리하지 않으며 upstream filter들로부터 오는 sample들을 거부한다. w Paused, and Running : 이 경우 샘플들을 접수, 처리하며 새로운 샘 플들을 생성하여 이를 downstream으로 전달한다. n Renderer Filter 의 경우는 예외 36

Data Flow in the Filter Graph n n Filter graph manager 가 전체적으로 필터들의

Data Flow in the Filter Graph n n Filter graph manager 가 전체적으로 필터들의 상태를 조절 한다. Filter graph이 stopped에서 paused 상태로 갈 경우의 단계 w The filter graph manager calls IMedia. Filter: : Pause on each filter, starting from the renderer filter and working upstream. w As each filter switches to paused, it is ready to accept samples from its upstream neighbor. It can safely deliver samples downstream, because the downstream filters are also paused. w The source filter is the last to be paused. At that point, it starts delivering samples. w As the samples move downstream, the intermediate filters process them. w When the first sample reaches the renderer, the renderer completes its state transition and blocks. 37

Event Notification in Direct. Show Event notification n The Filter Graph Manager handles some

Event Notification in Direct. Show Event notification n The Filter Graph Manager handles some filter events by itself, and it leaves others for the application to handle. If the Filter Graph Manager does not handle a filter event, it places the event notification into a queue. The filter graph can also queue its own event notifications for the application An application can also cancel the Filter Graph Manager's default behavior for a given event type. Event mechanism enables n n n The Filter Graph Manager to communicate with the application. Filters to communicate with both the application and the Filter Graph Manager. The application to determine its degree of involvement in handling events. 38

Event Notification in Direct. Show Three interfaces n IMedia. Event. Sink w to post

Event Notification in Direct. Show Three interfaces n IMedia. Event. Sink w to post events. w Filters post event notifications by calling the Media. Event. Sink: : Notify method n IMedia. Event w to retrieve events. w To retrieve an event from the queue, the application calls the IMedia. Event: : Get. Event method on the Filter Graph Manager. w After calling Get. Event, an application should always call the IMedia. Event: : Free. Event. Params method to release any resources associated with the event parameters. n IMedia. Event. Ex w inherits from and extends the IMedia. Event interface. 39

Event Notification in Direct. Show long ev. Code, param 1, param 2; HRESULT hr;

Event Notification in Direct. Show long ev. Code, param 1, param 2; HRESULT hr; while (hr = p. Event->Get. Event(&ev. Code, &param 1, &param 2, 0), SUCCEEDED(hr)) { switch(ev. Code) { // Call application-defined functions for each // type of event that you want to handle. } hr = p. Event->Free. Event. Params(ev. Code, param 1, param 2); } 40

Sample : Play. Wnd n Path w Source: (SDK root)SamplesMultimediaDirect. ShowPlayersPlay. Wnd w Executable:

Sample : Play. Wnd n Path w Source: (SDK root)SamplesMultimediaDirect. ShowPlayersPlay. Wnd w Executable: (SDK root)SamplesMultimediaDirect. ShowBinPlay. Wnd. exe 41

Sample : Play. Wnd // // Global data // HWND HINSTANCE TCHAR BOOL LONG

Sample : Play. Wnd // // Global data // HWND HINSTANCE TCHAR BOOL LONG DWORD PLAYSTATE gh. App=0; gh. Inst; g_sz. File. Name[MAX_PATH]={0}; g_b. Audio. Only=FALSE; g_l. Volume=VOLUME_FULL; g_dw. Graph. Register=0; g_ps. Current=Stopped; // Direct. Show interfaces IGraph. Builder *p. GB = NULL; IMedia. Control *p. MC = NULL; IMedia. Event. Ex *p. ME = NULL; IVideo. Window *p. VW = NULL; IBasic. Audio *p. BA = NULL; IBasic. Video *p. BV = NULL; IMedia. Seeking *p. MS = NULL; 42

Sample : Play. Wnd int PASCAL Win. Main(HINSTANCE h. Inst. C, HINSTANCE h. Inst.

Sample : Play. Wnd int PASCAL Win. Main(HINSTANCE h. Inst. C, HINSTANCE h. Inst. P, LPTSTR lp. Cmd. Line, int n. Cmd. Show) { … // Initialize COM if(FAILED(Co. Initialize(NULL))) { Msg(TEXT("Co. Initialize Failed!rn")); exit(1); } …. …. // Create the main window. The WS_CLIPCHILDREN style is required. gh. App = Create. Window(CLASSNAME, APPLICATIONNAME, 43

Sample : Play. Wnd if(gh. App) { // Main message loop while(Get. Message(&msg, NULL,

Sample : Play. Wnd if(gh. App) { // Main message loop while(Get. Message(&msg, NULL, 0, 0)) { Translate. Message(&msg); Dispatch. Message(&msg); } } else { Msg(TEXT("Failed to create the main window! Error=0 x%xrn"), Get. Last. Error()); } // Finished with COM Co. Uninitialize(); return msg. w. Param; } 44

Sample : Play. Wnd void Open. Clip() { HRESULT hr; if(g_sz. File. Name[0] ==

Sample : Play. Wnd void Open. Clip() { HRESULT hr; if(g_sz. File. Name[0] == L'') { TCHAR sz. Filename[MAX_PATH]; Update. Main. Title(); Init. Player. Window(); Show. Window(gh. App, SW_SHOWNORMAL); Set. Foreground. Window(gh. App); if (! Get. Clip. File. Name(sz. Filename)) { DWORD dw. Dlg. Err = Comm. Dlg. Extended. Error(); if (dw. Dlg. Err) { 45

Sample : Play. Wnd Msg(TEXT("Get. Clip. File. Name Failed! Error=0 x%xrn"), Get. Last. Error());

Sample : Play. Wnd Msg(TEXT("Get. Clip. File. Name Failed! Error=0 x%xrn"), Get. Last. Error()); } return; } lstrcpy(g_sz. File. Name, sz. Filename); } // Reset status variables g_ps. Current = Stopped; g_l. Volume = VOLUME_FULL; hr = Play. Movie. In. Window(g_sz. File. Name); // If we couldn't play the clip, clean up if (FAILED(hr)) Close. Clip(); } 46

Sample : Play. Wnd RESULT Play. Movie. In. Window(LPTSTR sz. File) { WCHAR w.

Sample : Play. Wnd RESULT Play. Movie. In. Window(LPTSTR sz. File) { WCHAR w. File[MAX_PATH]; HRESULT hr; // Clear open dialog remnants before calling Render. File() Update. Window(gh. App); #ifndef UNICODE Multi. Byte. To. Wide. Char(CP_ACP, 0, sz. File, -1, w. File, MAX_PATH); #else lstrcpy(w. File, sz. File); #endif // Get the interface for Direct. Show's Graph. Builder JIF(Co. Create. Instance(CLSID_Filter. Graph, NULL, CLSCTX_INPROC_SERVER, IID_IGraph. Builder, (void **)&p. GB)); 47

Sample : Play. Wnd if(SUCCEEDED(hr)) { // Have the graph construct its the appropriate

Sample : Play. Wnd if(SUCCEEDED(hr)) { // Have the graph construct its the appropriate graph automatically JIF(p. GB->Render. File(w. File, NULL)); // Query. Interface for Direct. Show interfaces JIF(p. GB->Query. Interface(IID_IMedia. Control, (void **)&p. MC)); JIF(p. GB->Query. Interface(IID_IMedia. Event. Ex, (void **)&p. ME)); JIF(p. GB->Query. Interface(IID_IMedia. Seeking, (void **)&p. MS)); // Query for video interfaces, which may not be relevant for audio files JIF(p. GB->Query. Interface(IID_IVideo. Window, (void **)&p. VW)); JIF(p. GB->Query. Interface(IID_IBasic. Video, (void **)&p. BV)); // Query for audio interfaces, which may not be relevant for video-only files JIF(p. GB->Query. Interface(IID_IBasic. Audio, (void **)&p. BA)); 48

Sample : Play. Wnd // Is this an audio-only file (no video component)? Check.

Sample : Play. Wnd // Is this an audio-only file (no video component)? Check. Visibility(); if (!g_b. Audio. Only) { JIF(p. VW->put_Owner((OAHWND)gh. App)); JIF(p. VW->put_Window. Style(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)); } // Have the graph signal event via window callbacks for performance JIF(p. ME->Set. Notify. Window((OAHWND)gh. App, WM_GRAPHNOTIFY, 0)); if (g_b. Audio. Only) { JIF(Init. Player. Window()); } else { JIF(Init. Video. Window(1, 1)); 49 }

Sample : Play. Wnd // Let's get ready to rumble! Show. Window(gh. App, SW_SHOWNORMAL);

Sample : Play. Wnd // Let's get ready to rumble! Show. Window(gh. App, SW_SHOWNORMAL); Update. Window(gh. App); Set. Foreground. Window(gh. App); Set. Focus(gh. App); Update. Main. Title(); #ifdef REGISTER_FILTERGRAPH hr = Add. Graph. To. Rot(p. GB, &g_dw. Graph. Register); if (FAILED(hr)) { Msg(TEXT("Failed to register filter graph with ROT! hr=0 x%x"), hr); g_dw. Graph. Register = 0; } #endif 50

Sample : Play. Wnd // Run the graph to play the media file JIF(p.

Sample : Play. Wnd // Run the graph to play the media file JIF(p. MC->Run()); g_ps. Current=Running; Set. Focus(gh. App); } return hr; } 51

Sample : Play. Wnd void Pause. Clip(void) { HRESULT hr; if (!p. MC) return;

Sample : Play. Wnd void Pause. Clip(void) { HRESULT hr; if (!p. MC) return; // Toggle play/pause behavior if((g_ps. Current == Paused) || (g_ps. Current == Stopped)) { hr = p. MC->Run(); g_ps. Current = Running; } else { hr = p. MC->Pause(); g_ps. Current = Paused; } Update. Main. Title(); } 52

Sample : Play. Wnd void Stop. Clip(void) { HRESULT hr; if ((!p. MC) ||

Sample : Play. Wnd void Stop. Clip(void) { HRESULT hr; if ((!p. MC) || (!p. MS)) return; // Stop and reset postion to beginning if((g_ps. Current == Paused) || (g_ps. Current == Running)) { LONG pos = 0; hr = p. MC->Stop(); g_ps. Current = Stopped; hr = p. MS->Set. Positions(&pos, AM_SEEKING_Absolute. Positioning , NULL, AM_SEEKING_No. Positioning); // Display the first frame to indicate the reset condition hr = p. MC->Pause(); } Update. Main. Title(); } 53

Sample : Play. Wnd void Close. Clip() { HRESULT hr; if(p. MC) hr =

Sample : Play. Wnd void Close. Clip() { HRESULT hr; if(p. MC) hr = p. MC->Stop(); g_ps. Current = Stopped; g_b. Audio. Only = TRUE; Close. Interfaces(); // Clear file name to allow selection of new file with open dialog g_sz. File. Name[0] = L''; g_ps. Current = Init; RECT rect; Get. Client. Rect(gh. App, &rect); Invalidate. Rect(gh. App, &rect, TRUE); Update. Main. Title(); Init. Player. Window(); } 54

Sample : Play. Wnd HRESULT Toggle. Mute(void) { HRESULT hr=S_OK; if ((!p. GB) ||

Sample : Play. Wnd HRESULT Toggle. Mute(void) { HRESULT hr=S_OK; if ((!p. GB) || (!p. BA)) return S_OK; // Read current volume hr = p. BA->get_Volume(&g_l. Volume); if (hr == E_NOTIMPL) { // Fail quietly if this is a video-only media file return S_OK; } else if (FAILED(hr)) { Msg(TEXT("Failed to read audio volume! hr=0 x%xrn"), hr); return hr; } 55

Sample : Play. Wnd // Switch volume levels if (g_l. Volume == VOLUME_FULL) g_l.

Sample : Play. Wnd // Switch volume levels if (g_l. Volume == VOLUME_FULL) g_l. Volume = VOLUME_SILENCE; else g_l. Volume = VOLUME_FULL; // Set new volume JIF(p. BA->put_Volume(g_l. Volume)); Update. Main. Title(); return hr; } 56

Sample : 정지영상 샘플 추출 Sample. Grab. Still 57

Sample : 정지영상 샘플 추출 Sample. Grab. Still 57

Sample : Sample. Grab. Still HRESULT CSample. Grab. Still. App: : On. File. Open()

Sample : Sample. Grab. Still HRESULT CSample. Grab. Still. App: : On. File. Open() { HRESULT hr ; // 필터그래프매니저를 제거하여 필터그래프의 누적 방지! if (m_p. GB != NULL) { JIF(On. File. Close()) ; } … // 필터그래프매니저 생성 (멤버 변수로 보관) // Get the interface for Direct. Show's Graph. Builder JIF(Co. Create. Instance(CLSID_Filter. Graph, NULL, CLSCTX_INPROC_SERVER, IID_IGraph. Builder, (void **)&m_p. GB)) ; // Add a Filter. . . Put a filter in the graph LIF(Co. Create. Instance(CLSID_L 544_Sample. Grabber, NULL, CLSCTX_INPROC_SERVER, IID_IBase. Filter, (void **)&m_p. SG)) ; LIF(m_p. GB->Add. Filter(m_p. SG, L"Sample. Grabber")); 58

Sample : Sample. Grab. Still // // …. . } AM_MEDIA_TYPE mt; Zero. Memory(&mt,

Sample : Sample. Grab. Still // // …. . } AM_MEDIA_TYPE mt; Zero. Memory(&mt, sizeof(mt)); mt. majortype = MEDIATYPE_Audio; mt. subtype = MEDIASUBTYPE_PCM; mt. majortype = MEDIATYPE_Video; mt. subtype = MEDIASUBTYPE_RGB 24; CCom. QIPtr<ISample. Grabber> p. Sample. Grabber(m_p. SG); if (p. Sample. Grabber != NULL) { LIF(p. Sample. Grabber->Set. Media. Type(&mt)); LIF(p. Sample. Grabber->Set. Buffer. Samples(TRUE)); } // Render File. . . // Have the graph construct its the appropriate graph automatically JIF(m_p. GB->Render. File(w. File. Name, NULL)) ; 59

Sample : Sample. Grab. Still void CSample. Grab. Still. App: : Capture. Screen() {

Sample : Sample. Grab. Still void CSample. Grab. Still. App: : Capture. Screen() { if (m_p. SG == NULL) return; HRESULT hr; CCom. QIPtr<ISample. Grabber> p. Sample. Grabber(m_p. SG); if (p. Sample. Grabber == NULL) return; long l. Buffer. Size; hr = p. Sample. Grabber->Get. Current. Buffer(&l. Buffer. Size, NULL); if (FAILED(hr)) return; BYTE* p. Buffer = new BYTE[l. Buffer. Size]; if (!p. Buffer) return; } 60

Sample : Sample. Grab. Still hr = p. Sample. Grabber->Get. Current. Buffer(&l. Buffer. Size,

Sample : Sample. Grab. Still hr = p. Sample. Grabber->Get. Current. Buffer(&l. Buffer. Size, (long *)p. Buffer); if (SUCCEEDED(hr)) { AM_MEDIA_TYPE mt; p. Sample. Grabber->Get. Connected. Media. Type(&mt); VIDEOINFOHEADER *pvi. Header = (VIDEOINFOHEADER *)mt. pb. Format; Save. Image(pvi. Header->bmi. Header, p. Buffer); } delete p. Buffer; } 61