HC 原始碼分析 6:MediaInfo選項卡 (CPPageFileMediaInfo)
=====================================================
Media Player Classic - HC 原始碼分析系列文章列表:
=====================================================
前幾篇文章分析了Media Player Classic - HC(mpc-hc)的核心類(CMainFrame):
核心類分析完之後,分析了一下CAboutDlg:
發現CAboutDlg和普通的MFC對話方塊類其實沒有什麼區別。CAboutDlg功能相對比較簡單,本文將會分析一個功能相對比較複雜的類:MediaInfo選項卡。在播放視訊的時候,右鍵點選視訊->選擇“屬性”->MediaInfo就可以檢視該選項卡。一般情況下,該選項卡給出了正在播放的視訊檔案的詳細引數(確實是非常的詳細),包括:封裝格式,視訊編碼,音訊編碼等等。是獲取視訊詳細引數的最佳途徑。該選項卡的功能實際上是呼叫了開源專案MediaInfo的庫。MediaInfo之前已經進行過詳細介紹:
在此不再重複。先看看該選項卡長什麼樣子。
先來看看MediaInfo選項卡類的定義是什麼樣的吧。該類的定義位於PPageFileMediaInfo.h檔案中。
/* 雷霄驊 * 中國傳媒大學/數字電視技術 * [email protected] * */ /* * (C) 2009-2013 see Authors.txt * * This file is part of MPC-HC. * * MPC-HC is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 3 of the License, or * (at your option) any later version. * * MPC-HC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ #pragma once // CPPageFileMediaInfo dialog // 【屬性】頁面裡面的【MediaInfo】 class CPPageFileMediaInfo : public CPropertyPage { DECLARE_DYNAMIC(CPPageFileMediaInfo) private: CComPtr<IFilterGraph> m_pFG; public: //建構函式都是兩個引數 CPPageFileMediaInfo(CString fn, IFilterGraph* pFG); virtual ~CPPageFileMediaInfo(); // Dialog Data enum { IDD = IDD_FILEMEDIAINFO }; //顯示資訊的控制元件 CEdit m_mediainfo; CString m_fn; CFont* m_pCFont; //資訊 CString MI_Text; #if !USE_STATIC_MEDIAINFO static bool HasMediaInfo(); #endif protected: virtual void DoDataExchange(CDataExchange* pDX); // DDX/DDV support //初始化,載入MediaInfo庫,讀取檔案資訊 virtual BOOL OnInitDialog(); DECLARE_MESSAGE_MAP() public: //顯示視窗,並不做其他事情 afx_msg void OnShowWindow(BOOL bShow, UINT nStatus); };
該類和普通的MFC對話方塊類差別也不大。需要注意的有以下幾點:
1.有一個變數:CComPtr<IFilterGraph> m_pFG,這個是mpc-hc中的變數,先不分析該變數的全部程式碼,在這裡僅說一下它的作用:獲取正在播放的視訊檔案的路徑。
2.有一個控制元件類:CEdit m_mediainfo,對應介面上那個大框框,用於顯示資訊。
3.有一個字串變數:CString MI_Text,用於儲存MediaInfo得到的媒體資訊。
下面來看看具體類的實現,該類的實現位於PPageFileMediaInfo.cpp檔案中。
/* 雷霄驊
* 中國傳媒大學/數字電視技術
* [email protected]
*
*/
/*
* (C) 2009-2013 see Authors.txt
*
* This file is part of MPC-HC.
*
* MPC-HC is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* MPC-HC is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
// PPageFileMediaInfo.cpp : implementation file
#include "stdafx.h"
#include "mplayerc.h"
#include "PPageFileMediaInfo.h"
#include "WinAPIUtils.h"
#if USE_STATIC_MEDIAINFO
#include "MediaInfo/MediaInfo.h"
using namespace MediaInfoLib;
#else
#include "MediaInfoDLL.h"
using namespace MediaInfoDLL;
#endif
// CPPageFileMediaInfo dialog
IMPLEMENT_DYNAMIC(CPPageFileMediaInfo, CPropertyPage)
CPPageFileMediaInfo::CPPageFileMediaInfo(CString fn, IFilterGraph* pFG)
: CPropertyPage(CPPageFileMediaInfo::IDD, CPPageFileMediaInfo::IDD)
, m_fn(fn)
, m_pFG(pFG)
, m_pCFont(nullptr)
{
}
CPPageFileMediaInfo::~CPPageFileMediaInfo()
{
delete m_pCFont;
m_pCFont = nullptr;
}
void CPPageFileMediaInfo::DoDataExchange(CDataExchange* pDX)
{
__super::DoDataExchange(pDX);
DDX_Control(pDX, IDC_MIEDIT, m_mediainfo);
}
BEGIN_MESSAGE_MAP(CPPageFileMediaInfo, CPropertyPage)
ON_WM_SHOWWINDOW()
END_MESSAGE_MAP()
// CPPageFileMediaInfo message handlers
static WNDPROC OldControlProc;
static LRESULT CALLBACK ControlProc(HWND control, UINT message, WPARAM wParam, LPARAM lParam)
{
if (message == WM_KEYDOWN) {
if ((LOWORD(wParam) == 'A' || LOWORD(wParam) == 'a')
&& (GetKeyState(VK_CONTROL) < 0)) {
CEdit* pEdit = (CEdit*)CWnd::FromHandle(control);
pEdit->SetSel(0, pEdit->GetWindowTextLength(), TRUE);
return 0;
}
}
return CallWindowProc(OldControlProc, control, message, wParam, lParam); // call edit control's own windowproc
}
//初始化,載入MediaInfo庫,讀取檔案資訊
BOOL CPPageFileMediaInfo::OnInitDialog()
{
__super::OnInitDialog();
if (!m_pCFont) {
m_pCFont = DEBUG_NEW CFont;
}
if (!m_pCFont) {
return TRUE;
}
if (m_fn.IsEmpty()) {
BeginEnumFilters(m_pFG, pEF, pBF) {
CComQIPtr<IFileSourceFilter> pFSF = pBF;
if (pFSF) {
//當前檔案路徑
LPOLESTR pFN = nullptr;
//媒體型別
AM_MEDIA_TYPE mt;
//獲取當前檔案的路徑和媒體型別
if (SUCCEEDED(pFSF->GetCurFile(&pFN, &mt)) && pFN && *pFN) {
m_fn = CStringW(pFN);
CoTaskMemFree(pFN);
}
break;
}
}
EndEnumFilters;
}
#if USE_STATIC_MEDIAINFO
//使用靜態庫MediaInfo
//檔案路徑
MediaInfoLib::String f_name = m_fn;
MediaInfoLib::MediaInfo MI;
#else
MediaInfoDLL::String f_name = m_fn;
MediaInfo MI;
#endif
//設定
MI.Option(_T("ParseSpeed"), _T("0"));
MI.Open(f_name);
MI.Option(_T("Complete"));
MI.Option(_T("Language"), _T(" Config_Text_ColumnSize;30"));
//資訊字串
MI_Text = MI.Inform().c_str();
MI.Close();
if (!MI_Text.Find(_T("Unable to load"))) {
MI_Text = _T("");
}
LOGFONT lf;
ZeroMemory(&lf, sizeof(lf));
lf.lfPitchAndFamily = DEFAULT_PITCH | FF_MODERN;
// The empty string will fallback to the first font that matches the other specified attributes.
LPCTSTR fonts[] = { _T("Lucida Console"), _T("Courier New"), _T("") };
// Use a negative value to match the character height instead of the cell height.
int fonts_size[] = { -10, -11, -11 };
UINT i = 0;
BOOL success;
do {
_tcscpy_s(lf.lfFaceName, fonts[i]);
lf.lfHeight = fonts_size[i];
success = IsFontInstalled(fonts[i]) && m_pCFont->CreateFontIndirect(&lf);
i++;
} while (!success && i < _countof(fonts));
//控制元件設定字型和內容
m_mediainfo.SetFont(m_pCFont);
m_mediainfo.SetWindowText(MI_Text);
// subclass the edit control
OldControlProc = (WNDPROC)SetWindowLongPtr(m_mediainfo.m_hWnd, GWLP_WNDPROC, (LONG_PTR)ControlProc);
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
//顯示or不顯示?
void CPPageFileMediaInfo::OnShowWindow(BOOL bShow, UINT nStatus)
{
__super::OnShowWindow(bShow, nStatus);
if (bShow) {
GetParent()->GetDlgItem(IDC_BUTTON_MI)->ShowWindow(SW_SHOW);
} else {
GetParent()->GetDlgItem(IDC_BUTTON_MI)->ShowWindow(SW_HIDE);
}
}
#if !USE_STATIC_MEDIAINFO
bool CPPageFileMediaInfo::HasMediaInfo()
{
MediaInfo MI;
return MI.IsReady();
}
#endif
可以看出,主要的工作都是在OnInitDialog()函式中實現的。大體的步驟如下:
1.通過呼叫pFSF->GetCurFile(&pFN, &mt),獲得當前檔案的路徑,存入pFN中。
2.因為字串型別不同,幾經轉換把pFN轉換為MediaInfo可以識別的字串f_name
3.根據該路徑,呼叫MediaInfo庫,獲得視訊的詳細資訊存入字串變數MI_Text。
4.將MI_Text顯示到控制元件上。
總體說來,過程並不複雜,理解起來還是比較簡單的。
相關推薦
HC 原始碼分析 6:MediaInfo選項卡 (CPPageFileMediaInfo)
=====================================================Media Player Classic - HC 原始碼分析系列文章列表:===============================================
XBMC原始碼分析 6:視訊播放器(dvdplayer)-檔案頭(以ffmpeg為例)
XBMC分析系列文章: XBMC原始碼簡析 5:視訊播放器(dvdplayer)-解複用器(以ffmpeg為例)本文我們分析XBMC中視訊播放器(dvdplayer)中的檔案頭部分。檔案頭部分裡包含的是封裝Dll用到的標頭檔案。由於檔案頭種類很多,不可能一一分析,
XBMC原始碼分析 4:視訊播放器(dvdplayer)-解碼器(以ffmpeg為例)
XBMC分析系列文章: 本文我們分析XBMC中視訊播放器(dvdplayer)中的解碼器部分。由於解碼器種類很多,不可能一一分析,因此以ffmpeg解碼器為例進行分析。 XBMC解碼器部分檔案目錄如下圖所示: 解碼器分為音訊解碼器和視訊解碼器。在這裡我們看一下視訊
tab選項卡(1):一級tab選項卡
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> </head> <style>
選項卡(1)
lec set 樣式 gin relative ctype ive css樣式 lac 選項卡控件它提供一系列操作按鈕,單擊不同的按鈕可以在各個頁面之間進行切換。 選項卡實現的幾種方法: html+css <!DOCTYPE html> <htm
【spring原始碼分析】IOC容器初始化(二)
前言:在【spring原始碼分析】IOC容器初始化(一)中已經分析了匯入bean階段,本篇接著分析bean解析階段。 1.解析bean程式呼叫鏈 同樣,先給出解析bean的程式呼叫鏈: 根據程式呼叫鏈,整理出在解析bean過程中主要涉及的類和相關方法。 2.解析bean原始碼分
Java原始碼分析——java.util工具包解析(五)——UUID、Base64、內建觀察者模式Observer介面、EventListener、RandomAccess
UUID 關於UUID,我們需要知道它最重要的一點,就是它會生成全地球唯一的一個id,它可以作為資料庫的主鍵存在,標識各個元組。 UUID保證對在同一時空中的所有機器都是唯一的,利用機器的當前日期和時間、時鐘序列、全域性唯一的IEEE機
Java原始碼分析——java.util工具包解析(四)——四大引用型別以及WeakHashMap類解析
WeakHashMap是Map的一種很獨特的實現,從它的名字可以看出,它是存貯弱引用的對映的,先來複習一下Java中的四大引用型別: 強引用:我們使用的大部分引用實際上都是強引用,這是使用最普遍的引用。強引用的物件垃圾回收器絕不
Java原始碼分析——java.util工具包解析(三)——HashMap、TreeMap、LinkedHashMap、Hashtable類解析
Map,中文名字對映,它儲存了鍵-值對的一對一的關係形式,並用雜湊值來作為存貯的索引依據,在查詢、插入以及刪除時的時間複雜度都為O(1),是一種在程式中用的最多的幾種資料結構。Java在java.util工具包中實現了Map介面,來作為各大
Java原始碼分析——java.util工具包解析(二)——HashSet、TreeSet、LinkedHashSet類解析
Set,即集合,與數學上的定義一樣,集合具有三個特點: 無序性:一個集合中,每個元素的地位都是相同的,元素之間是無序的。 互異性:一個集合中,任何兩個元素都認為是不相同的,即每個元素只能出現一次。 確定性:給定一個集
Java原始碼分析——java.util工具包解析(一)——ArrayList、LinkedList、Vector類解析
Java中,List列表類與Set集合類的共同源頭是Collection介面,而Collection的父介面是Iterable介面,在Collection介面下又實現了三個常用的介面以及一個抽象方法,分別為Queue介面、List介面、Se
Spark core原始碼分析之spark叢集的啟動(二)
2.2 Worker的啟動 org.apache.spark.deploy.worker 1 從Worker的伴生物件的main方法進入 在main方法中首先是得到一個SparkConf例項conf,然後將conf和啟動Worker傳入的引數封裝得到Wor
Rxjava2.x 原始碼分析,以及手動實現Rxjava(一)
這兩年Rxjava火的一塌糊塗,不會點Rxjava+Okhttp+Retrofit+MVP+Dagger2架構都不好意思說自己混Android的。Rxjava 到底是什麼和Rxjava到底怎麼用,這裡就不講了,網上太多了,具體可以參考 這位大佬 和扔物線的。 Rxjava
選項卡(Tab)切換事件
選項卡切換事件 <style type="text/css"> *{margin: 0; padding: 0; font-family: "微軟雅黑";font-size: 14px;} #container{ width: 398px; ma
springMVC原始碼分析--HandlerInterceptor攔截器呼叫過程(二)
在上一篇部落格springMVC原始碼分析--HandlerInterceptor攔截器(一)中我們介紹了HandlerInterceptor攔截器相關的內容,瞭解到了HandlerInterceptor提供的三個介面方法:(1)preHandle: 在執行controlle
Vue學習之原始碼分析--VNode節點(Vue.js實現(五)
抽象DOM樹 在刀耕火種的年代,我們需要在各個事件方法中直接操作DOM來達到修改檢視的目的。但是當應用一大就會變得難以維護。 那我們是不是可以把真實DOM樹抽象成一棵以JavaScript物件構成的抽象樹,在修改抽象樹資料後將抽象樹轉化成真實DOM重繪到頁面
spark mllib原始碼分析之隨機森林(Random Forest)(二)
4. 特徵處理 這部分主要在DecisionTree.scala的findSplitsBins函式,將所有特徵封裝成Split,然後裝箱Bin。首先對split和bin的結構進行說明 4.1. 資料結構 4.1.1. Split cl
Java選項卡(JTabbedPane)的使用
JTabbedPane是一種可以放多個面板的並且可以方便切換的容器 1. 建構函式 (1)JTabbedPane( ) 建立空的JTabbedPane物件,但實際它的默 認值為JTabbedPane.Top,也就是說卡片名將放在容器頂部。 (2
springboot原始碼分析7-環境屬性構造過程(上)
使用springboot的目的就是在專案開發中,快速出東西,因此springboot對於配置檔案的格式支援是非常豐富的,最常見的配置檔案字尾有如下四種:properties、xml、yml、yaml,比
(萊昂氏unix原始碼分析導讀-11)系統初啟(4)
本章討論程序複製,繼續Main函式。 1625 */ 1626 1627 if(newproc()) { …… 現在看newproc的程式碼。 1826 newproc() 1827 { ......