void Play(HWND hWnd) { //ShowWindow(hWnd, SW_SHOWNORMAL); RECT grc; GetClientRect(hWnd, &grc); JIF(pVW->put_Owner((OAHWND)hWnd)); JIF(pVW->SetWindowPosition(0, 25, grc.right, grc.bottom)); pMC->Run(); ::SetForegroundWindow(hWnd); }
HRESULT CMediaPlayerDlg::RenderWMFile(LPCWSTR wFile) { HRESULT hr=S_OK; IFileSourceFilter *pFS=NULL; IBaseFilter *pReader=NULL; // Load the improved ASF reader filter by CLSID hr = CreateFilter(CLSID_WMAsfReader, &pReader); if(FAILED(hr)) { MPRetailOutput(TEXT("Failed to create WMAsfWriter filter! hr=0x%x\n"), hr); return hr; } // Add the ASF reader filter to the graph. For ASF/WMV/WMA content, // this filter is NOT the default and must be added explicitly. hr = pGB_MP->AddFilter(pReader, L"ASF Reader"); if(FAILED(hr)) { MPRetailOutput(TEXT("Failed to add ASF reader filter to graph! hr=0x%x\n"), hr); pReader->Release(); return hr; } // // Windows Media 9 Series (code named 'Corona') no longer requires // a stub library. If using WMF9, we don't need to provide a CKeyProvider // implementation, and we don't need to link with the WMStub.lib library. // #ifndef TARGET_WMF9 // Create the key provider that will be used to unlock the WM SDK JIF(AddKeyProvider(pGB_MP)); #endif // Set its source filename JIF(pReader->QueryInterface(IID_IFileSourceFilter, (void **) &pFS)); JIF(pFS->Load(wFile, NULL)); pFS->Release(); CLEANUP: // If there was a rendering error, make sure that the reader is released // // Otherwise, wince the graph is built and the filters are added to // the graph, the WM ASF reader interface can be released. SAFE_RELEASE(pReader); return hr; }
void ensureVideoPostProcess() { if (host.state < CodecBoxDecoderState::Metadata) return; if (sws) return; auto destFmt = AV_PIX_FMT_RGBA; int align = 4; videoLineSize = av_image_get_buffer_size(destFmt, host.width, 1, align); int numBytes = av_image_get_buffer_size(destFmt, host.width, host.height, align); videoBuffer = (uint8_t *) av_malloc(numBytes); sws = sws_getContext( videoCodecContext->width, videoCodecContext->height, videoCodecContext->pix_fmt, host.width, host.height, AV_PIX_FMT_RGBA, SWS_BILINEAR, NULL, NULL, NULL ); JIF(!videoBuffer || !sws, "failed to alloc video buffers."); return; err: host.state = CodecBoxDecoderState::Failed; close(); }
static AVCodecContext* createCodecContext(AVFormatContext* formatContext, int streamId) { AVCodecContext* codecContext = nullptr; auto orignalContext = formatContext->streams[streamId]->codec; auto codec = avcodec_find_decoder(orignalContext->codec_id); JIF(codec == nullptr, "failed avcodec_find_decoder %d", orignalContext->codec_id); codecContext = avcodec_alloc_context3(codec); JIF(codecContext == nullptr, "failed avcodec_alloc_context3"); JIF(avcodec_copy_context(codecContext, orignalContext) != 0, "failed avcodec_copy_context"); JIF(avcodec_open2(codecContext, codec, nullptr) < 0, "failed avcodec_open2"); return codecContext; err: if (codecContext) avcodec_free_context(&codecContext); return nullptr; }
HRESULT CPlayWMV::ToggleMute(void) { HRESULT hr = S_OK; if ((!m_pGB) || (!m_pBA)) return S_OK; // Read current volume hr = m_pBA->get_Volume(&m_lVolume); 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=0x%x\r\n"), hr); return hr; } // Switch volume levels if (m_lVolume == VOLUME_FULL) m_lVolume = VOLUME_SILENCE; else m_lVolume = VOLUME_FULL; // Set new volume JIF(m_pBA->put_Volume(m_lVolume)); // UpdateMainTitle(); return hr; }
HRESULT InitVideoWindow(int nMultiplier, int nDivider) { LONG lHeight, lWidth; HRESULT hr = S_OK; RECT rect; if (!pBV) return S_OK; // Read the default video size hr = pBV->GetVideoSize(&lWidth, &lHeight); if (hr == E_NOINTERFACE) return S_OK; EnablePlaybackMenu(TRUE, VIDEO); // Account for requests of normal, half, or double size lWidth = lWidth * nMultiplier / nDivider; lHeight = lHeight * nMultiplier / nDivider; int nTitleHeight = GetSystemMetrics(SM_CYCAPTION); int nBorderWidth = GetSystemMetrics(SM_CXBORDER); int nBorderHeight = GetSystemMetrics(SM_CYBORDER); // Account for size of title bar and borders for exact match // of window client area to default video size SetWindowPos(ghApp, NULL, 0, 0, lWidth + 2*nBorderWidth, lHeight + nTitleHeight + 2*nBorderHeight, SWP_NOMOVE | SWP_NOOWNERZORDER); GetClientRect(ghApp, &rect); JIF(pVW->SetWindowPosition(rect.left, rect.top, rect.right, rect.bottom)); return hr; }
HRESULT CPlayWMV::ToggleFullScreen(void) { HRESULT hr = S_OK; LONG lMode = 0; static HWND hDrain = 0; // Don't bother with full-screen for audio-only files if ((m_bAudioOnly) || (!m_pVW)) return S_OK; // Read current state JIF(m_pVW->get_FullScreenMode(&lMode)); if (lMode == 0) /* OAFALSE */ { // Save current message drain LIF(m_pVW->get_MessageDrain((OAHWND *) &hDrain)); // Set message drain to application main window LIF(m_pVW->put_MessageDrain((OAHWND) m_hWnd)); // Switch to full-screen mode lMode = -1; /* OATRUE */ JIF(m_pVW->put_FullScreenMode(lMode)); m_bFullscreen = TRUE; } else { // Switch back to windowed mode lMode = 0; /* OAFALSE */ JIF(m_pVW->put_FullScreenMode(lMode)); // Undo change of message drain LIF(m_pVW->put_MessageDrain((OAHWND) hDrain)); // Reset video window LIF(m_pVW->SetWindowForeground(-1)); // Reclaim keyboard focus for player application UpdateWindow(m_hWnd); SetForegroundWindow(m_hWnd); SetFocus(m_hWnd); m_bFullscreen = FALSE; } return hr; }
HRESULT CMediaPlayerDlg::InitDirectShow(void) { HRESULT hr = S_OK; g_bAudioOnly_MP = FALSE; // Zero interfaces (sanity check) pVW_MP = NULL; pBV_MP = NULL; JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&pGB_MP)); JIF(pGB_MP->QueryInterface(IID_IMediaControl, (void **)&pMC_MP)); JIF(pGB_MP->QueryInterface(IID_IMediaSeeking, (void **)&pMS_MP)); JIF(pGB_MP->QueryInterface(IID_IBasicVideo, (void **)&pBV_MP)); JIF(pGB_MP->QueryInterface(IID_IVideoWindow, (void **)&pVW_MP)); JIF(pGB_MP->QueryInterface(IID_IMediaEventEx, (void **)&pME_MP)); JIF(pGB_MP->QueryInterface(IID_IBasicAudio, (void **)&pBA_MP)); return S_OK; CLEANUP: FreeDirectShow(); return(hr); }
void ensureAudioPostProcess() { if (host.state < CodecBoxDecoderState::Metadata) return; if (swr) return; swr = swr_alloc(); JIF(!swr, "failed to alloc audio resampler."); av_opt_set_channel_layout(swr, "in_channel_layout", audioCodecContext->channel_layout, 0); av_opt_set_channel_layout(swr, "out_channel_layout", AV_CH_LAYOUT_STEREO, 0); av_opt_set_int(swr, "in_sample_rate", audioCodecContext->sample_rate, 0); av_opt_set_int(swr, "out_sample_rate", host.sampleRate, 0); av_opt_set_sample_fmt(swr, "in_sample_fmt", audioCodecContext->sample_fmt, 0); av_opt_set_sample_fmt(swr, "out_sample_fmt", AV_SAMPLE_FMT_FLT, 0); JIF(swr_init(swr), "failed to init audio resampler."); return; err: host.state = CodecBoxDecoderState::Failed; close(); }
int InitMediaEnviront() { JIF( CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&pGB)); //add filter and connect them //hr=CoCreateInstance(INFINITEPINTEEFILTER, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVideorenderFilter); JIF(CoCreateInstance( CLSID_VideoRenderer, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pVMRFilter)); //pGB->FindFilterByName( //hr = pGB->FindFilterByName(L"Video Renderer", &pVMRFilter) ; JIF(CoCreateInstance( CLSID_BouncingBall, NULL, CLSCTX_INPROC_SERVER, IID_IBaseFilter, (void**)&pSnowFilter)); //GET PINS JIF(pGB->QueryInterface(IID_IVideoWindow,(void **)&pVW)); JIF(pGB->AddFilter(pVMRFilter,L"RENDER")); JIF(pGB->AddFilter(pSnowFilter,L"SOURCE")); // EnumPins(pSnowFilter); // EnumPins(pVMRFilter); //hr = pSnowFilter->FindPin(L"Output" , &pPinOut); pPinOut=GetFirstPin(pSnowFilter); //pVMRFilter //JIF( pVMRFilter->FindPin(L"VMR Input0" , &pPinIn)); pPinIn=GetFirstPin(pVMRFilter); //pGB->AddSourceFilter( JIF(pGB->Connect (pPinOut,pPinIn)); JIF( pGB->QueryInterface(IID_IMediaControl, (void **)&pMC)); JIF( pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME)); return 0; }
HRESULT InitializeWindowlessVMR(IBaseFilter **ppVmr9) { IBaseFilter* pVmr = NULL; if (!ppVmr9) return E_POINTER; *ppVmr9 = NULL; // Create the VMR and add it to the filter graph. HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr); if (SUCCEEDED(hr)) { hr = pGB->AddFilter(pVmr, L"Video Mixing Renderer 9"); if (SUCCEEDED(hr)) { // Set the rendering mode and number of streams SmartPtr <IVMRFilterConfig9> pConfig; JIF(pVmr->QueryInterface(IID_IVMRFilterConfig9, (void**)&pConfig)); JIF(pConfig->SetRenderingMode(VMR9Mode_Windowless)); hr = pVmr->QueryInterface(IID_IVMRWindowlessControl9, (void**)&pWC); if( SUCCEEDED(hr)) { hr = pWC->SetVideoClippingWindow(ghApp); hr = pWC->SetBorderColor(RGB(0,0,0)); } // Get alpha-blended bitmap interface hr = pVmr->QueryInterface(IID_IVMRMixerBitmap9, (void**)&pBMP); } // Don't release the pVmr interface because we are copying it into // the caller's ppVmr9 pointer *ppVmr9 = pVmr; } return hr; }
CodecBoxDecoderContext(const char* filePath, CodecBoxDecoder& host_): host(host_), formatContext(nullptr), videoStream(-1), audioStream(-1), videoCodecContext(nullptr), audioCodecContext(nullptr), sws(nullptr), swr(nullptr), decodedFrame(nullptr), videoLineSize(0), videoBuffer(nullptr), audioBuffer(nullptr) { host.state = CodecBoxDecoderState::Init; JIF(avformat_open_input(&formatContext, filePath, nullptr, nullptr) != 0, "failed avformat_open_input: %s", filePath); JIF(avformat_find_stream_info(formatContext, nullptr) < 0, "failed avformat_find_stream_info: %s", filePath); av_dump_format(formatContext, 0, filePath, 0); host.duration = (double)formatContext->duration / AV_TIME_BASE; host.startTime = (double)formatContext->start_time / AV_TIME_BASE; for (int i = 0; i < formatContext->nb_streams; i++) { auto type = formatContext->streams[i]->codec->codec_type; if (videoStream < 0 && type == AVMEDIA_TYPE_VIDEO) videoStream = i; else if (audioStream < 0 && type == AVMEDIA_TYPE_AUDIO) audioStream = i; } JIF(videoStream < 0 && audioStream < 0 , "no audio/video stream found in %s", filePath); if (videoStream >= 0) { videoCodecContext = createCodecContext(formatContext, videoStream); JIF(videoCodecContext == nullptr, "video codec not supported"); host.hasVideo = true; host.width = videoCodecContext->width; host.height = videoCodecContext->height; // videoCodecContext->framerate is usually not useful (0) auto fr = formatContext->streams[videoStream]->avg_frame_rate; host.frameRate = (double)fr.num / fr.den; } if (audioStream >= 0) { audioCodecContext = createCodecContext(formatContext, audioStream); JIF(audioCodecContext == nullptr, "audio codec not supported"); host.hasAudio = true; host.sampleRate = audioCodecContext->sample_rate; host.channels = 2; // will be re-sampled as AV_CH_LAYOUT_STEREO. // audioCodecContext->channels; } decodedFrame = av_frame_alloc(); JIF(!decodedFrame, "faild to alloc decodedFrame"); host.state = CodecBoxDecoderState::Metadata; return; err: host.state = CodecBoxDecoderState::Failed; close(); }
HRESULT CPlayWMV::SetSize(int nLeft, int nTop, int nRight, int nBottom) { HRESULT hr = S_OK; m_Rect.left = nLeft; m_Rect.top = nTop; m_Rect.right = nRight; m_Rect.bottom = nBottom; JIF(m_pVW->SetWindowPosition(m_Rect.left, m_Rect.top, m_Rect.right, m_Rect.bottom)); return hr; }
HRESULT GetInterfaces(void) { HRESULT hr = S_OK; // Instantiate filter graph interface JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC, IID_IGraphBuilder, (void **)&pGB)); // Get interfaces to control playback & screensize JIF(pGB->QueryInterface(IID_IMediaControl, (void **)&pMC)); JIF(pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW)); // Get interface to allow the app to wait for completion of playback JIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME)); return S_OK; // In case of failure, the helper macro jumps here CLEANUP: CleanupInterfaces(); return(hr); }
HRESULT ConfigureMultiFileVMR9(WCHAR *wFile1, WCHAR *wFile2) { HRESULT hr=S_OK; CComPtr <IBaseFilter> pVmr; // Create the Video Mixing Renderer and add it to the graph JIF(InitializeWindowlessVMR(&pVmr)); // Render the files programmatically to use the VMR9 as renderer if (SUCCEEDED(hr = RenderFileToVMR9(pGB, wFile1, pVmr))) hr = RenderFileToVMR9(pGB, wFile2, pVmr); return hr; }
void setSampleRate(int sr) { if (swr) { int64_t outSampleRate; av_opt_get_int(swr, "out_sample_rate", 0, &outSampleRate); if (outSampleRate != host.sampleRate) { av_opt_set_int(swr, "out_sample_rate", host.sampleRate, 0); swr_init(swr); JIF(swr_init(swr), "failed to init audio resampler."); } } host.sampleRate = sr; return; err: host.state = CodecBoxDecoderState::Failed; close(); }
HRESULT MPToggleFullScreen(void) { HRESULT hr=S_OK; LONG lMode; static HWND hDrain=0; CWnd m_hWnd; // Don't bother with full-screen for audio-only files if ((g_bAudioOnly_MP) || (!pVW_MP)) return S_OK; // Read current state JIF(pVW_MP->get_FullScreenMode(&lMode)); if (lMode == OAFALSE) { // Save current message drain LIF(pVW_MP->get_MessageDrain((OAHWND *) &hDrain)); // Set message drain to application main window LIF(pVW_MP->put_MessageDrain((OAHWND) (HWND)m_hWnd)); // Switch to full-screen mode lMode = OATRUE; JIF(pVW_MP->put_FullScreenMode(lMode)); g_bFullScreen_MP = TRUE; } else { // Switch back to windowed mode lMode = OAFALSE; JIF(pVW_MP->put_FullScreenMode(lMode)); // Undo change of message drain LIF(pVW_MP->put_MessageDrain((OAHWND) hDrain)); // Reset video window LIF(pVW_MP->SetWindowForeground(-1)); // Reclaim keyboard focus for player application m_hWnd.UpdateWindow(); m_hWnd.SetForegroundWindow(); m_hWnd.SetFocus(); g_bFullScreen_MP = FALSE; } CLEANUP: return(hr); }
HRESULT InitializeWindowlessVMR(IBaseFilter **ppVmr9) { IBaseFilter* pVmr = NULL; if (!ppVmr9) return E_POINTER; *ppVmr9 = NULL; // Create the VMR and add it to the filter graph. HRESULT hr = CoCreateInstance(CLSID_VideoMixingRenderer9, NULL, CLSCTX_INPROC, IID_IBaseFilter, (void**)&pVmr); if (SUCCEEDED(hr)) { hr = pGB->AddFilter(pVmr, L"Video Mixing Renderer 9"); if (SUCCEEDED(hr)) { // Set the rendering mode and number of streams SmartPtr <IVMRFilterConfig9> pConfig; JIF(pVmr->QueryInterface(IID_IVMRFilterConfig9, (void**)&pConfig)); JIF(pConfig->SetRenderingMode(VMR9Mode_Windowless)); hr = pVmr->QueryInterface(IID_IVMRWindowlessControl9, (void**)&pWC); if( SUCCEEDED(hr)) { hr = pWC->SetVideoClippingWindow(ghApp); hr = pWC->SetBorderColor(RGB(0,0,0)); } #ifndef BILINEAR_FILTERING // Request point filtering (instead of bilinear filtering) // to improve the text quality. In general, if you are // not scaling the app Image, you should use point filtering. // This is very important if you are doing source color keying. IVMRMixerControl9 *pMix; hr = pVmr->QueryInterface(IID_IVMRMixerControl9, (void**)&pMix); if( SUCCEEDED(hr)) { DWORD dwPrefs=0; hr = pMix->GetMixingPrefs(&dwPrefs); if (SUCCEEDED(hr)) { dwPrefs |= MixerPref_PointFiltering; dwPrefs &= ~(MixerPref_BiLinearFiltering); hr = pMix->SetMixingPrefs(dwPrefs); } pMix->Release(); } #endif // Get alpha-blended bitmap interface hr = pVmr->QueryInterface(IID_IVMRMixerBitmap9, (void**)&pBMP); } else Msg(TEXT("Failed to add VMR to graph! hr=0x%x\r\n"), hr); // Don't release the pVmr interface because we are copying it into // the caller's ppVmr9 pointer *ppVmr9 = pVmr; } else Msg(TEXT("Failed to create VMR! hr=0x%x\r\n"), hr); return hr; }
HRESULT BlendVideo(LPTSTR szFile1, LPTSTR szFile2) { USES_CONVERSION; WCHAR wFile1[MAX_PATH], wFile2[MAX_PATH]; HRESULT hr; // Check input string if ((szFile1 == NULL) || (szFile2 == NULL)) return E_POINTER; // Clear open dialog remnants before calling RenderFile() UpdateWindow(ghApp); // Convert filenames to wide character strings wcsncpy(wFile1, T2W(szFile1), NUMELMS(wFile1)-1); wcsncpy(wFile2, T2W(szFile2), NUMELMS(wFile2)-1); wFile1[MAX_PATH-1] = wFile2[MAX_PATH-1] = 0; // Get the interface for DirectShow's GraphBuilder JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGB)); if(SUCCEEDED(hr)) { // Unlike the VMR7 in Windows XP, the VMR9 is not the default renderer // (to preserve backward compatibility). In some multifile graphs, // the filter graph manager could decide to load the default Video Renderer // filter during RenderFile(), even though the VMR9 is already present // in the graph. Since the default Video Renderer has a higher merit // than the VMR9, it would be connected instead of the VMR9, leading to // the video streams being displayed in multiple separate windows. // This could be the case with AVI files created with legacy VfW codecs // or when two Color Space convertors must be used (each requiring its // own allocator). // Therefore, we render the files programmatically instead of using // the standard IGraphBuilder::RenderFile() method. if (FAILED(ConfigureMultiFileVMR9(wFile1, wFile2))) return hr; // QueryInterface for DirectShow interfaces JIF(pGB->QueryInterface(IID_IMediaControl, (void **)&pMC)); JIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME)); JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)); // Is this an audio-only file (no video component)? if (CheckVideoVisibility()) { JIF(InitVideoWindow(1, 1)); } else { // This sample requires video clips to be loaded Msg(TEXT("This sample requires media with a video component. ") TEXT("Please select another file.")); return E_FAIL; } // Have the graph signal event via window callbacks JIF(pME->SetNotifyWindow((OAHWND)ghApp, WM_GRAPHNOTIFY, 0)); // Complete the window setup ShowWindow(ghApp, SW_SHOWNORMAL); UpdateWindow(ghApp); SetForegroundWindow(ghApp); SetFocus(ghApp); #ifdef REGISTER_FILTERGRAPH if (FAILED(AddGraphToRot(pGB, &g_dwGraphRegister))) { Msg(TEXT("Failed to register filter graph with ROT!")); g_dwGraphRegister = 0; } #endif // Run the graph to play the media files MoveVideoWindow(); JIF(pMC->Run()); EnableMenus(TRUE); } return hr; }
HRESULT PlayMovieInWindow(LPTSTR szFile) { USES_CONVERSION; WCHAR wFile[MAX_PATH]; HRESULT hr; // Check input string if (szFile == NULL) return E_POINTER; // Clear open dialog remnants before calling RenderFile() UpdateWindow(ghApp); // Convert filename to wide character string wcsncpy(wFile, T2W(szFile), NUMELMS(wFile)-1); wFile[MAX_PATH-1] = 0; // Get the interface for DirectShow's GraphBuilder JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGB)); if(SUCCEEDED(hr)) { // Create the Video Mixing Renderer and add it to the graph JIF(InitializeWindowlessVMR()); // Have the graph builder construct its the appropriate graph automatically JIF(pGB->RenderFile(wFile, NULL)); // QueryInterface for DirectShow interfaces JIF(pGB->QueryInterface(IID_IMediaControl, (void **)&pMC)); JIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME)); JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)); // Is this an audio-only file (no video component)? if (CheckVideoVisibility()) { JIF(InitVideoWindow(1, 1)); } else { // This sample requires a video clip to be loaded Msg(TEXT("This sample requires media with a video component. ") TEXT("Please select another file.")); return E_FAIL; } // Have the graph signal event via window callbacks for performance JIF(pME->SetNotifyWindow((OAHWND)ghApp, WM_GRAPHNOTIFY, 0)); // Add the bitmap (static image or dynamic text) to the VMR's input if (g_dwTickerFlags & MARK_STATIC_IMAGE) { hr = BlendApplicationImage(ghApp); if (FAILED(hr)) PostMessage(ghApp, WM_CLOSE, 0, 0); CheckMenuItem(ghMenu, ID_TICKER_STATIC_IMAGE, MF_CHECKED); CheckMenuItem(ghMenu, ID_TICKER_DYNAMIC_TEXT, MF_UNCHECKED); } else // MARK_DYNAMIC_TEXT { if (!g_hFont) g_hFont = SetTextFont(FALSE); // Don't display the Windows Font Select dialog // If the initial blend fails, post a close message to exit the app hr = BlendApplicationText(ghApp, g_szAppText); if (FAILED(hr)) PostMessage(ghApp, WM_CLOSE, 0, 0); CheckMenuItem(ghMenu, ID_TICKER_STATIC_IMAGE, MF_UNCHECKED); CheckMenuItem(ghMenu, ID_TICKER_DYNAMIC_TEXT, MF_CHECKED); } // Complete the window setup ShowWindow(ghApp, SW_SHOWNORMAL); UpdateWindow(ghApp); SetForegroundWindow(ghApp); SetFocus(ghApp); #ifdef REGISTER_FILTERGRAPH if (FAILED(AddGraphToRot(pGB, &g_dwGraphRegister))) { Msg(TEXT("Failed to register filter graph with ROT!")); g_dwGraphRegister = 0; } #endif // Run the graph to play the media file JIF(pMC->Run()); // Start animation by default PostMessage(ghApp, WM_COMMAND, ID_SLIDE, 0); } return hr; }
HRESULT CPlayWMV::PlayMovieInWindow(HWND hWnd, LPTSTR szFile) { if(FAILED(CoInitializeEx(NULL, COINIT_APARTMENTTHREADED))) { Msg(TEXT("CoInitialize Failed!\r\n")); return 0; } USES_CONVERSION; WCHAR wFile[MAX_PATH]; HRESULT hr; // Check input string if (!szFile) return E_POINTER; m_hWnd = hWnd; // Clear open dialog remnants before calling RenderFile() UpdateWindow(m_hWnd); // Convert filename to wide character string wcsncpy(wFile, T2W(szFile), NUMELMS(wFile)-1); wFile[MAX_PATH-1] = 0; // Get the interface for DirectShow's GraphBuilder JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&m_pGB)); // Get the media event interface before building the graph JIF(m_pGB->QueryInterface(IID_IMediaEventEx, (void **)&m_pME)); // Have the graph builder construct the appropriate graph automatically JIF(m_pGB->RenderFile(wFile, NULL)); if (SUCCEEDED(hr)) { // QueryInterface for DirectShow interfaces JIF(m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC)); JIF(m_pGB->QueryInterface(IID_IMediaSeeking, (void **)&m_pMS)); // Query for video interfaces, which may not be relevant for audio files JIF(m_pGB->QueryInterface(IID_IVideoWindow, (void **)&m_pVW)); JIF(m_pGB->QueryInterface(IID_IBasicVideo, (void **)&m_pBV)); // Query for audio interfaces, which may not be relevant for video-only files JIF(m_pGB->QueryInterface(IID_IBasicAudio, (void **)&m_pBA)); // Have the graph signal event via window callbacks for performance JIF(m_pME->SetNotifyWindow((OAHWND)m_hWnd, WM_GRAPHNOTIFY, 0)); // Is this an audio-only file (no video component)? CheckVisibility(); if (!m_bAudioOnly) { // Setup the video window JIF(m_pVW->put_Owner((OAHWND)m_hWnd)); JIF(m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)); JIF(m_pVW->SetWindowPosition(m_Rect.left, m_Rect.top, m_Rect.right, m_Rect.bottom)); } else { // Initialize the default player window and enable playback menu items // that don't involve manipulating video size //JIF(InitPlayerWindow()); /* BOOL bRet = SetWindowPos(m_hWnd, NULL, 0, 0, DEFAULT_AUDIO_WIDTH, DEFAULT_AUDIO_HEIGHT, SWP_NOMOVE | SWP_NOOWNERZORDER); */ } // Complete window initialization //ShowWindow(m_hWnd, SW_SHOWNORMAL); //UpdateWindow(m_hWnd); //SetForegroundWindow(m_hWnd); m_bFullscreen = FALSE; // Run the graph to play the media file JIF(m_pMC->Run()); m_nPlayState = Running; SetFocus(m_hWnd); } return hr; }
HRESULT PlayMovieInWindow(LPTSTR szFile) { USES_CONVERSION; WCHAR wFile[MAX_PATH]; HRESULT hr; // Clear open dialog remnants before calling RenderFile() UpdateWindow(ghApp); // Convert filename to wide character string wcscpy(wFile, T2W(szFile)); // Get the interface for DirectShow's GraphBuilder JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGB)); if(SUCCEEDED(hr)) { // Have the graph builder construct its the appropriate graph automatically JIF(pGB->RenderFile(wFile, NULL)); // QueryInterface for DirectShow interfaces JIF(pGB->QueryInterface(IID_IMediaControl, (void **)&pMC)); JIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME)); JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)); JIF(pGB->QueryInterface(IID_IMediaPosition, (void **)&pMP)); // Query for video interfaces, which may not be relevant for audio files JIF(pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW)); JIF(pGB->QueryInterface(IID_IBasicVideo, (void **)&pBV)); // Query for audio interfaces, which may not be relevant for video-only files JIF(pGB->QueryInterface(IID_IBasicAudio, (void **)&pBA)); // Is this an audio-only file (no video component)? CheckVisibility(); // Have the graph signal event via window callbacks for performance JIF(pME->SetNotifyWindow((OAHWND)ghApp, WM_GRAPHNOTIFY, 0)); if (!g_bAudioOnly) { JIF(pVW->put_Owner((OAHWND)ghApp)); JIF(pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)); JIF(InitVideoWindow(1, 1)); GetFrameStepInterface(); } else { JIF(InitPlayerWindow()); } // Let's get ready to rumble! CheckSizeMenu(ID_FILE_SIZE_NORMAL); ShowWindow(ghApp, SW_SHOWNORMAL); UpdateWindow(ghApp); SetForegroundWindow(ghApp); SetFocus(ghApp); g_bFullscreen = FALSE; g_PlaybackRate = 1.0; UpdateMainTitle(); #ifdef REGISTER_FILTERGRAPH hr = AddGraphToRot(pGB, &g_dwGraphRegister); if (FAILED(hr)) { Msg(TEXT("Failed to register filter graph with ROT! hr=0x%x"), hr); g_dwGraphRegister = 0; } #endif // Run the graph to play the media file JIF(pMC->Run()); g_psCurrent=Running; SetFocus(ghApp); } return hr; }
HRESULT HandleNoRightsEx( HRESULT hrStatus, WM_GET_LICENSE_DATA * pLicenseData ) { HRESULT hr = S_OK; BOOL fMonitoring = FALSE; BSTR bstrURL = NULL; if((NULL == pLicenseData) || (NULL == pLicenseData->wszLocalFilename)) { return E_INVALIDARG; } if (FAILED(hrStatus) && (NS_E_DRM_NO_RIGHTS != hrStatus)) { Msg(TEXT("Unable to obtain proper license!! Aborting playback...\r\n")); hr = hrStatus; return hr; } if( TRUE ) { IServiceProvider *pServiceProvider; JIF(g_pReader->QueryInterface(IID_IServiceProvider, (void **) &pServiceProvider)); JIF(pServiceProvider->QueryService(IID_IWMDRMReader, IID_IWMDRMReader, (void **) &g_pDRMReader)); pServiceProvider->Release(); // do silent license acquisition hr = g_pDRMReader->AcquireLicense(TRUE); if (FAILED(hr)) { Msg(TEXT("AcquireLicense Failed! hr=0x%x\n"), hr); SAFE_RELEASE(g_pDRMReader); return hr; } } else // non-silent acquisition { // convert wszs to bstrs so we can pass them to core bstrURL = SysAllocString(pLicenseData->wszLocalFilename); if (!bstrURL) { hr = E_OUTOFMEMORY; } else { // start license monitoring hr = g_pDRMReader->MonitorLicenseAcquisition(); if (FAILED(hr)) { // wmp explicitly ignores hr here g_pDRMReader->CancelMonitorLicenseAcquisition(); } else { fMonitoring = true; } SysFreeString(bstrURL); } } SAFE_RELEASE(g_pDRMReader); return hr; }
HRESULT PlayMovieInWindow(LPTSTR szFile, BOOL bReOpenAfterLicenseAcquired) { USES_CONVERSION; WCHAR wFile[MAX_PATH]; HRESULT hr; // Check input string if (!szFile) return E_POINTER; // Clear open dialog remnants before calling RenderFile() UpdateWindow(ghApp); // Convert filename to wide character string wcsncpy(wFile, T2W(szFile), NUMELMS(wFile)-1); wFile[MAX_PATH-1] = 0; // First pass of rendering the media file. If a DRM license must // be acquired before the file can be loaded, then the reopen flag // will be set. if( !bReOpenAfterLicenseAcquired ) { // Get the interface for DirectShow's GraphBuilder JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGB)); JIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME)); if(SUCCEEDED(hr)) { // Have the graph signal event via window callbacks // // Start this before we insert the reader filter, since we may need // to monitor DRM license acquistion messages on reader creation // JIF(pME->SetNotifyWindow((OAHWND)ghApp, WM_GRAPHNOTIFY, 0)); // Use special handling for Windows Media files if (IsWindowsMediaFile(szFile)) { // Load the improved ASF reader filter by CLSID hr = CreateFilter(CLSID_WMAsfReader, &g_pReader); if(FAILED(hr)) { Msg(TEXT("Failed to create WMAsfWriter filter! hr=0x%x\0"), hr); return hr; } // Add the ASF reader filter to the graph. For ASF/WMV/WMA content, // this filter is NOT the default and must be added explicitly. hr = pGB->AddFilter(g_pReader, L"ASF Reader"); if(FAILED(hr)) { Msg(TEXT("Failed to add ASF reader filter to graph! hr=0x%x\0"), hr); return hr; } // Create the key provider that will be used to unlock the WM SDK JIF(AddKeyProvider(pGB)); // Create the DRM license event g_hLicenseEvent = CreateEvent( NULL, FALSE, FALSE, NULL ); if( !g_hLicenseEvent ) { return E_OUTOFMEMORY; } // Set its source filename JIF(g_pReader->QueryInterface(IID_IFileSourceFilter, (void **) &g_pFileSource)); // Attempt to load this file hr = g_pFileSource->Load(wFile, NULL); // Handle Digital Rights Management (DRM) errors if(NS_E_LICENSE_REQUIRED == hr) { Msg(TEXT("This media file is protected by DRM and needs a license.\r\n\r\n") TEXT("Attempting to acquire a license...\0")); g_bWaitingForLicense = TRUE; return hr; } else if(NS_E_PROTECTED_CONTENT == hr) { Msg(TEXT("This media file is protected by DRM and needs a license.\r\n\r\n") TEXT("In order to play DRM-encoded content, you must acquire a DRM stub library\r\n") TEXT("from Microsoft and link it with this application. The default version of\r\n") TEXT("the WMStub.lib library does not support Digital Rights Management (DRM).")); return hr; } else if (FAILED(hr)) { Msg(TEXT("Failed to load file in source filter (g_pFileSource->Load())! hr=0x%x\0"), hr); return hr; } // Render the output pins of the ASF reader to build the // remainder of the graph automatically JIF(RenderOutputPins(pGB, g_pReader)); // Since the graph is built and the filters are added to the graph, // the WM ASF reader interface can be released. g_pReader->Release(); g_pReader = NULL; } // Not a Windows Media file, so just render the standard way else { // Have the graph builder construct the appropriate graph automatically JIF(pGB->RenderFile(wFile, NULL)); } } } else { hr = g_pFileSource->Load(wFile, NULL); if( SUCCEEDED( hr ) ) { Msg(TEXT("Successfully loaded file after DRM license acquisition!")); // Render the output pins of the ASF reader to build the // remainder of the graph automatically JIF(RenderOutputPins(pGB, g_pReader)); // Since the graph is built and the filters are added to the graph, // the WM ASF reader interface can be released. g_pReader->Release(); // not really necessary g_pReader = NULL; } else { Msg(TEXT("Failed to Load file after acquiring license! hr=0x%x\0"), hr); } } if( SUCCEEDED( hr ) ) { // QueryInterface for DirectShow interfaces JIF(pGB->QueryInterface(IID_IMediaControl, (void **)&pMC)); JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)); // Query for video interfaces, which may not be relevant for audio files JIF(pGB->QueryInterface(IID_IVideoWindow, (void **)&pVW)); JIF(pGB->QueryInterface(IID_IBasicVideo, (void **)&pBV)); // Query for audio interfaces, which may not be relevant for video-only files JIF(pGB->QueryInterface(IID_IBasicAudio, (void **)&pBA)); // Is this an audio-only file (no video component)? CheckVisibility(); if (!g_bAudioOnly) { // Setup the video window JIF(pVW->put_Owner((OAHWND)ghApp)); JIF(pVW->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS | WS_CLIPCHILDREN)); JIF(InitVideoWindow(1, 1)); GetFrameStepInterface(); } else { // Initialize the default player size and enable playback menu items JIF(InitPlayerWindow()); EnablePlaybackMenu(TRUE, AUDIO); } // Complete window initialization CheckSizeMenu(ID_FILE_SIZE_NORMAL); ShowWindow(ghApp, SW_SHOWNORMAL); UpdateWindow(ghApp); SetForegroundWindow(ghApp); g_bFullscreen = FALSE; UpdateMainTitle(); #ifdef REGISTER_FILTERGRAPH hr = AddGraphToRot(pGB, &g_dwGraphRegister); if (FAILED(hr)) { Msg(TEXT("Failed to register filter graph with ROT! hr=0x%x"), hr); g_dwGraphRegister = 0; } #endif // Run the graph to play the media file JIF(pMC->Run()); g_psCurrent=Running; SetFocus(ghApp); } return hr; }
HRESULT PlayMovieInWindow(LPTSTR szFile) { HRESULT hr; // Check input string if (szFile == NULL) return E_POINTER; // Clear open dialog remnants before calling RenderFile() UpdateWindow(ghApp); // Get the interface for DirectShow's GraphBuilder JIF(CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void **)&pGB)); if(SUCCEEDED(hr)) { SmartPtr <IBaseFilter> pVmr; // Create the Video Mixing Renderer and add it to the graph JIF(InitializeWindowlessVMR(&pVmr)); // Render the file programmatically to use the VMR9 as renderer. // Pass TRUE to create an audio renderer also. if (FAILED(hr = RenderFileToVideoRenderer(pGB, szFile, TRUE))) return hr; // QueryInterface for DirectShow interfaces JIF(pGB->QueryInterface(IID_IMediaControl, (void **)&pMC)); JIF(pGB->QueryInterface(IID_IMediaEventEx, (void **)&pME)); JIF(pGB->QueryInterface(IID_IMediaSeeking, (void **)&pMS)); JIF(pGB->QueryInterface(IID_IBasicAudio, (void **)&pBA)); // Is this an audio-only file (no video component)? if (CheckVideoVisibility()) { JIF(InitVideoWindow(1, 1)); } else { // This sample requires a video clip to be loaded Msg(TEXT("This sample requires media with a video component. ") TEXT("Please select another file.")); return E_FAIL; } // Add the bitmap to the VMR's input BlendApplicationImage(ghApp); // Have the graph signal event via window callbacks for performance JIF(pME->SetNotifyWindow((OAHWND)ghApp, WM_GRAPHNOTIFY, 0)); // Complete the window setup ShowWindow(ghApp, SW_SHOWNORMAL); UpdateWindow(ghApp); SetForegroundWindow(ghApp); SetFocus(ghApp); UpdateMainTitle(); #ifdef REGISTER_FILTERGRAPH hr = AddGraphToRot(pGB, &g_dwGraphRegister); if (FAILED(hr)) { Msg(TEXT("Failed to register filter graph with ROT! hr=0x%x"), hr); g_dwGraphRegister = 0; } #endif // Run the graph to play the media file JIF(pMC->Run()); g_psCurrent=Running; } return hr; }