Media Player Classic - HC 源代码分析 2:核心类 (CMainFrame)(1)
上一篇文章概括性的介绍了Media Player Classic - Home Cinema (mpc-hc)播放器的源代码:Media Player Classic - HC 源代码分析 1:整体结构
现在可以开始看看具体的源代码了。
mpc-hc最核心的类名字叫CMainFrame,它的定义位于MainFrm.h文件中
CMainFrame定义非常的长,包含了视频播放器的方方面面,一共900多行,在这里应该快放不下了。因此我删掉了很多代码,只保留了部分代码。关键的函数上面都写上了注释。
//打开文件void CMainFrame::OpenFile(OpenFileData* pOFD){ if (pOFD->fns.IsEmpty()) { throw (UINT)IDS_MAINFRM_81; }//获取设置 CAppSettings& s = AfxGetAppSettings(); bool bMainFile = true; POSITION pos = pOFD->fns.GetHeadPosition(); while (pos) { CString fn = pOFD->fns.GetNext(pos); fn.Trim(); if (fn.IsEmpty() && !bMainFile) { break; }//使用DirectShow播放文件 HRESULT hr = m_pGB->RenderFile(CStringW(fn), nullptr); if (bMainFile) { // Don't try to save file position if source isn't seekable REFERENCE_TIME rtDur = 0; m_pMS->GetDuration(&rtDur); m_bRememberFilePos = s.fKeepHistory && s.fRememberFilePos && rtDur > 0; if (m_bRememberFilePos && !s.filePositions.AddEntry(fn)) { REFERENCE_TIME rtPos = s.filePositions.GetLatestEntry()->llPosition; if (m_pMS) { m_pMS->SetPositions(&rtPos, AM_SEEKING_AbsolutePositioning, nullptr, AM_SEEKING_NoPositioning); } } } QueryPerformanceCounter(&m_liLastSaveTime); if (FAILED(hr)) { if (bMainFile) { if (s.fReportFailedPins) { CComQIPtr<IGraphBuilderDeadEnd> pGBDE = m_pGB; if (pGBDE && pGBDE->GetCount()) { CMediaTypesDlg(pGBDE, GetModalParent()).DoModal(); } } UINT err; switch (hr) { case E_ABORT: case RFS_E_ABORT: err = IDS_MAINFRM_82; break; case E_FAIL: case E_POINTER: default: err = IDS_MAINFRM_83; break; case E_INVALIDARG: err = IDS_MAINFRM_84; break; case E_OUTOFMEMORY: err = IDS_AG_OUT_OF_MEMORY; break; case VFW_E_CANNOT_CONNECT: err = IDS_MAINFRM_86; break; case VFW_E_CANNOT_LOAD_SOURCE_FILTER: err = IDS_MAINFRM_87; break; case VFW_E_CANNOT_RENDER: err = IDS_MAINFRM_88; break; case VFW_E_INVALID_FILE_FORMAT: err = IDS_MAINFRM_89; break; case VFW_E_NOT_FOUND: err = IDS_MAINFRM_90; break; case VFW_E_UNKNOWN_FILE_TYPE: err = IDS_MAINFRM_91; break; case VFW_E_UNSUPPORTED_STREAM: err = IDS_MAINFRM_92; break; case RFS_E_NO_FILES: err = IDS_RFS_NO_FILES; break; case RFS_E_COMPRESSED: err = IDS_RFS_COMPRESSED; break; case RFS_E_ENCRYPTED: err = IDS_RFS_ENCRYPTED; break; case RFS_E_MISSING_VOLS: err = IDS_RFS_MISSING_VOLS; break; } throw err; } } // We don't keep track of the standard input since that hardly makes any sense if (s.fKeepHistory && fn != _T("pipe:0")) { CRecentFileList* pMRU = bMainFile ? &s.MRU : &s.MRUDub; pMRU->ReadList(); pMRU->Add(fn); pMRU->WriteList(); SHAddToRecentDocs(SHARD_PATH, fn); } if (bMainFile) { pOFD->title = fn; } bMainFile = false; if (m_fCustomGraph) { break; } } if (s.fReportFailedPins) { CComQIPtr<IGraphBuilderDeadEnd> pGBDE = m_pGB; if (pGBDE && pGBDE->GetCount()) { CMediaTypesDlg(pGBDE, GetModalParent()).DoModal(); } } if (!(m_pAMOP = m_pGB)) { BeginEnumFilters(m_pGB, pEF, pBF); if (m_pAMOP = pBF) { break; } EndEnumFilters; } if (FindFilter(CLSID_MPCShoutcastSource, m_pGB)) { m_fUpdateInfoBar = true; } SetupChapters(); CComQIPtr<IKeyFrameInfo> pKFI; BeginEnumFilters(m_pGB, pEF, pBF); if (pKFI = pBF) { break; } EndEnumFilters; UINT nKFs = 0; if (pKFI && S_OK == pKFI->GetKeyFrameCount(nKFs) && nKFs > 0) { UINT k = nKFs; if (!m_kfs.SetCount(k) || S_OK != pKFI->GetKeyFrames(&TIME_FORMAT_MEDIA_TIME, m_kfs.GetData(), k) || k != nKFs) { m_kfs.RemoveAll(); } }//设置播放模式 SetPlaybackMode(PM_FILE);}
HRESULT hr = m_pGB->RenderFile(CStringW(fn), nullptr);