MediaInfo源代码分析 3:Open()函数
我们来看一下MediaInfo中的Open()函数的内部调用过程
首先open函数封装了MediaInfo_Internal类中的open()函数
//打开文件
size_t MediaInfo::Open(const String &File_Name_)
{
//封装了一层
return Internal->Open(File_Name_);
}
查看一下MediaInfo_Internal类中的open()函数的源代码:
//打开文件
size_t MediaInfo_Internal::Open(const String &File_Name_)
{
Close(); CS.Enter();
MEDIAINFO_DEBUG_CONFIG_TEXT(Debug+=__T("Open, File=");Debug+=Ztring(File_Name_).c_str();)
//清空文件列表
Config.File_Names.clear();
if (Config.File_FileNameFormat_Get()==__T("CSV"))
{
Config.File_Names.Separator_Set(0, __T(","));
Config.File_Names.Write(File_Name_);
}
//添加文件名到文件名列表
else if (!File_Name_.empty())
Config.File_Names.push_back(File_Name_);
if (Config.File_Names.empty())
{
CS.Leave();
return 0;
}
Config.File_Names_Pos=1;
CS.Leave(); //Parsing
//解析
if (BlockMethod==1)
{
if (!IsInThread) //If already created, the routine will read the new files
{
Run();
IsInThread=true;
}
return 0;
}
else
{
Entry(); //Normal parsing
return Count_Get(Stream_General);
}
}
在打开之前首先调用Close()进行清理,将文件路径添加到一个列表(实际上是一个Vector)中,调用Entry()进行解析。
查看一下Entry()函数的源代码:
//解析函数
void MediaInfo_Internal::Entry()
{
CS.Enter();
MEDIAINFO_DEBUG_CONFIG_TEXT(Debug+=__T("Entry");)
Config.State_Set(0);
CS.Leave();
//解析文件名(是否包含MMS?)
//需要libmms
if ((Config.File_Names[0].size()>=6
&& Config.File_Names[0][0]==__T('m')
&& Config.File_Names[0][1]==__T('m')
&& Config.File_Names[0][2]==__T('s')
&& Config.File_Names[0][3]==__T(':')
&& Config.File_Names[0][4]==__T('/')
&& Config.File_Names[0][5]==__T('/'))
|| (Config.File_Names[0].size()>=7
&& Config.File_Names[0][0]==__T('m')
&& Config.File_Names[0][1]==__T('m')
&& Config.File_Names[0][2]==__T('s')
&& Config.File_Names[0][3]==__T('h')
&& Config.File_Names[0][4]==__T(':')
&& Config.File_Names[0][5]==__T('/')
&& Config.File_Names[0][6]==__T('/')))
#if defined(MEDIAINFO_LIBMMS_YES)
Reader_libmms().Format_Test(this, Config.File_Names[0]);
#else //MEDIAINFO_LIBMMS_YES
{
#if MEDIAINFO_EVENTS
struct MediaInfo_Event_Log_0 Event;
Event.EventCode=MediaInfo_EventCode_Create(MediaInfo_Parser_None, MediaInfo_Event_Log, 0);
Event.Type=0xC0;
Event.Severity=0xFF;
Event.MessageCode=0;
Event.MessageStringU=L"Libmms cupport is disabled due to compilation options";
Event.MessageStringA="Libmms cupport is disabled due to compilation options";
MediaInfoLib::Config.Event_Send((const int8u*)&Event, sizeof(MediaInfo_Event_Log_0));
#endif //MEDIAINFO_EVENTS
}
#endif //MEDIAINFO_LIBMMS_YES
//是否包含网络协议?(标记为://)
//需要使用libcurl - the multiprotocol file transfer library
else if (Config.File_Names[0].find(__T("://"))!=string::npos)
#if defined(MEDIAINFO_LIBCURL_YES)
{
CS.Enter();
if (Reader)
{
CS.Leave();
return; //There is a problem
}
Reader=new Reader_libcurl();
CS.Leave(); Reader->Format_Test(this, Config.File_Names[0]); #if MEDIAINFO_NEXTPACKET
if (Config.NextPacket_Get())
return;
#endif //MEDIAINFO_NEXTPACKET
}
#else //MEDIAINFO_LIBCURL_YES
{
#if MEDIAINFO_EVENTS
struct MediaInfo_Event_Log_0 Event;
Event.EventCode=MediaInfo_EventCode_Create(MediaInfo_Parser_None, MediaInfo_Event_Log, 0);
Event.Type=0xC0;
Event.Severity=0xFF;
Event.MessageCode=0;
Event.MessageStringU=L"Libcurl support is disabled due to compilation options";
Event.MessageStringA="Libcurl support is disabled due to compilation options";
MediaInfoLib::Config.Event_Send((const int8u*)&Event, sizeof(MediaInfo_Event_Log_0));
#endif //MEDIAINFO_EVENTS
}
#endif //MEDIAINFO_LIBCURL_YES #if defined(MEDIAINFO_DIRECTORY_YES)
else if (Dir::Exists(Config.File_Names[0]))
Reader_Directory().Format_Test(this, Config.File_Names[0]);
#endif //MEDIAINFO_DIRECTORY_YES
//是普通文件,并且文件存在
#if defined(MEDIAINFO_FILE_YES)
else if (File::Exists(Config.File_Names[0]))
{
#if defined(MEDIAINFO_REFERENCES_YES)
string Dxw;
if (Config.File_CheckSideCarFiles_Get() && !Config.File_IsReferenced_Get())
{
//Zenlib中竟然包含专用于文件名操作的类!
FileName Test(Config.File_Names[0]);
//获得小写的文件名后缀
Ztring FileExtension=Test.Extension_Get();
FileExtension.MakeLowerCase();
//逐个比较(这些都是文本文件的后缀)
if (FileExtension!=__T("dfxp"))
{
Test.Extension_Set(__T("dfxp"));
if (File::Exists(Test))
Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".dfxp\" />\r\n";
}
if (FileExtension!=__T("sami"))
{
Test.Extension_Set(__T("sami"));
if (File::Exists(Test))
Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".sami\" />\r\n";
}
if (FileExtension!=__T("sc2"))
{
Test.Extension_Set(__T("sc2"));
if (File::Exists(Test))
Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".sc2\" />\r\n";
}
if (FileExtension!=__T("scc"))
{
Test.Extension_Set(__T("scc"));
if (File::Exists(Test))
Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".scc\" />\r\n";
}
if (FileExtension!=__T("smi"))
{
Test.Extension_Set(__T("smi"));
if (File::Exists(Test))
Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".smi\" />\r\n";
}
//字幕
if (FileExtension!=__T("srt"))
{
Test.Extension_Set(__T("srt"));
if (File::Exists(Test))
Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".srt\" />\r\n";
}
if (FileExtension!=__T("stl"))
{
Test.Extension_Set(__T("stl"));
if (File::Exists(Test))
Dxw+=" <clip file=\""+Test.Name_Get().To_UTF8()+".stl\" />\r\n";
} Ztring Name=Test.Name_Get();
Ztring BaseName=Name.SubString(Ztring(), __T("_"));
if (!BaseName.empty())
{
ZtringList List;
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_audio.mp4"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_sub.dfxp"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_sub.sami"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_sub.sc2"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_sub.scc"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_sub.smi"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_sub.srt"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_sub.stl"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_forcesub.dfxp"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_forcesub.sami"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_forcesub.sc2"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_forcesub.scc"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_forcesub.smi"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_forcesub.srt"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_forcesub.stl"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_cc.dfxp"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_cc.sami"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_cc.sc2"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_cc.scc"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_cc.smi"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_cc.srt"), Dir::Include_Files);
List+=Dir::GetAllFileNames(Test.Path_Get()+PathSeparator+BaseName+__T("_*_cc.stl"), Dir::Include_Files);
for (size_t Pos=0; Pos<List.size(); Pos++)
Dxw+=" <clip file=\""+List[Pos].To_UTF8()+"\" />\r\n";
} if (!Dxw.empty())
{
Dxw.insert(0, "<?xml version=\"1.0\" encoding=\"UTF-8\" ?>\r\n"
"<indexFile xmlns=\"urn:digimetrics-xml-wrapper\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:schemaLocation=\"urn:digimetrics-xml-wrapper DMSCLIP.XSD\">\r\n"
" <clip source=\"main\" file=\""+FileName(Config.File_Names[0]).Name_Get().To_UTF8()+"."+FileName(Config.File_Names[0]).Extension_Get().To_UTF8()+"\" />\r\n");
Dxw.append("</indexFile>\r\n");
Config.File_FileNameFormat_Set(__T("Dxw"));
}
}
//为空
if (Dxw.empty())
{
CS.Enter();
if (Reader)
{
CS.Leave();
return; //There is a problem
}
Reader=new Reader_File();
CS.Leave();
//测试格式
Reader->Format_Test(this, Config.File_Names[0]);
}
else
{
//初始化Buffer
Open_Buffer_Init(Dxw.size(), FileName(Config.File_Names[0]).Path_Get()+PathSeparator+FileName(Config.File_Names[0]).Name_Get());
Open_Buffer_Continue((const int8u*)Dxw.c_str(), Dxw.size());
Open_Buffer_Finalize();
}
#else //defined(MEDIAINFO_REFERENCES_YES)
CS.Enter();
if (Reader)
{
CS.Leave();
return; //There is a problem
}
Reader=new Reader_File();
CS.Leave(); Reader->Format_Test(this, Config.File_Names[0]);
#endif //defined(MEDIAINFO_REFERENCES_YES) #if MEDIAINFO_NEXTPACKET
if (Config.NextPacket_Get())
return;
#endif //MEDIAINFO_NEXTPACKET
}
#endif //MEDIAINFO_FILE_YES CS.Enter();
Config.State_Set(1);
CS.Leave();
}
我们可以看出,MediaInfo支持流媒体协议作为输入源(例如mms),但前提是要使用相应的库(libmms,或者libcurl)。它会首先查找文件路径中有没有“://”,判断是否是流媒体输入。
大多数情况下,我们使用本地文件路径作为输入源。这是我们就进入了代码中“#if defined(MEDIAINFO_FILE_YES) "部分下面的代码。具体每块代码的左右都写在代码注释中了,不再细说。最后使用 Reader_File的Format_Test()测试输入文件的格式。
看一下Reader_File的Format_Test()的源代码:
//用于测试文件格式
size_t Reader_File::Format_Test(MediaInfo_Internal* MI, String File_Name)
{
//std::cout<<Ztring(File_Name).To_Local().c_str()<<std::endl; //With Parser MultipleParsing
/*
MI->Open_Buffer_Init((int64u)-1, File_Name);
if (Format_Test_PerParser(MI, File_Name))
return 1;
return 0; //There is a problem
*/ //Get the Extension
//文件后缀
Ztring Extension=FileName::Extension_Get(File_Name);
Extension.MakeLowerCase(); //Search the theorical format from extension
InfoMap &FormatList=MediaInfoLib::Config.Format_Get();
InfoMap::iterator Format=FormatList.end();
if (!MI->Config.File_ForceParser_Get().empty())
Format=FormatList.find(MI->Config.File_ForceParser_Get());
if (Format==FormatList.end())
{
Format=FormatList.begin();
while (Format!=FormatList.end())
{
const Ztring &Extensions=FormatList.Get(Format->first, InfoFormat_Extensions);
if (Extensions.find(Extension)!=Error)
{
if(Extension.size()==Extensions.size())
break; //Only one extenion in the list
if(Extensions.find(Extension+__T(" "))!=Error
|| Extensions.find(__T(" ")+Extension)!=Error)
break;
}
++Format;
}
}
if (Format!=FormatList.end())
{
const Ztring &Parser=Format->second(InfoFormat_Parser);
if (MI->SelectFromExtension(Parser))
{
//Test the theorical format
if (Format_Test_PerParser(MI, File_Name)>0)
return 1;
}
}
//遍历所有支持格式,测试格式
size_t ToReturn=MI->ListFormats(File_Name);
return ToReturn;
}
可以看出,最后遍历了所有支持的格式,试图找出合适的格式。
至此Open()函数的分析完毕。
MediaInfo源代码分析 3:Open()函数的更多相关文章
- MediaInfo源代码分析 2:API函数
本文主要分析MediaInfo的API函数.它的API函数位于MediaInfo.h文件中的一个叫做MediaInfo的类中. 该类如下所示,部分重要的方法已经加上了注释: //MediaInfo类 ...
- MediaInfo源代码分析 4:Inform()函数
我们来看一下MediaInfo中的Inform()函数的内部调用过程 首先Inform()函数封装了MediaInfo_Internal类中的Inform()函数 //返回文件信息 String Me ...
- MediaInfo源代码分析 1:整体结构
MediaInfo 用来分析视频和音频文件的编码和内容信息,是一款是自由软件 (免费使用.免费获得源代码).之前编程的时候,都是直接调用它提供的Dll,这次突然来了兴趣,想研究一下它内部究竟是怎么实现 ...
- 1.2. chromium源代码分析 - chromiumframe - 入口函数
ChromiumFrame的入口函数在main.cpp中,打开main.cpp.中包含3个类和_tWinMain函数._tWinMain就是我们要找的入口函数.我做了部分注释: int APIENTR ...
- javascript 引擎Rhino源代码分析 浅析 实例函数对象及this
http://blog.csdn.net/liantian_wu/article/details/49797481
- Media Player Classic - HC 源代码分析 6:MediaInfo选项卡 (CPPageFileMediaInfo)
===================================================== Media Player Classic - HC 源代码分析系列文章列表: Media P ...
- Media Player Classic - HC 源代码分析 7:详细信息选项卡(CPPageFileInfoDetails)
===================================================== Media Player Classic - HC 源代码分析系列文章列表: Media P ...
- Media Player Classic - HC 源代码分析 5:关于对话框 (CAboutDlg)
===================================================== Media Player Classic - HC 源代码分析系列文章列表: Media P ...
- Media Player Classic - HC 源代码分析 4:核心类 (CMainFrame)(3)
===================================================== Media Player Classic - HC 源代码分析系列文章列表: Media P ...
随机推荐
- 如何写类库方法、属性等的注释,才能在其他地方调用dll文件时,在代码里出现智能提示?
我的本意是想整理下以往写过的代码库,给自己的代码增加复用性.一段时间后,可能自己对写过的代码是什么含义会忘掉,或者别人看自己的代码, 增加可懂性的考虑,决定要添加注释.(好像语句不通:)可是发现,在其 ...
- jQuery easyUI框架中经常出现的问题
相信开发者对于我们jquery来说都不会陌生吧,jquery为我们的开发提供了很多各式各样的库,满足各种开发的需求,其中我们知道的有轻量级的,但是也有一些基于富客服端的一些重量级库,顾名思义,当我们在 ...
- group By 和 Union 、 Union all的用法
我学习的是MySQL,学习写sql语句过程中遇到Group By 和 Union. 大家乐意看这两个链接,写的很好 Group By: www.cnblogs.com/rainman/archive/ ...
- C++类型转换总结 转
一.前言: C风格的强制类型转换(Type Cast)很简单,不管什么类型的转换统统是: TYPE b = (TYPE)a. C++风格的类型转换提供了4种类型转换操作符来应对不同场合的应用. con ...
- 读书笔记之 - javascript 设计模式 - 门面模式
门面模式有俩个作用: 简化类的接口 消除类与使用它的客户代码之间的耦合 在javascript中,门面模式常常是开发人员最亲密的朋友.它是几乎所有javascript库的核心原则,门面模式可以使库提供 ...
- Convention插件与“约定”支持
主要用于Action映射和Result映射 struts2-convention-plugin-2.3.16.3.jar 会将 |--实现了com.opensymphony.xwork2.Action ...
- XPATH 注入的介绍与代码防御
0x01 介绍 软件未正确对 XML 中使用的特殊元素进行无害化处理,导致攻击者能够在终端系统处理 XML 的语法.内容或命令之前对其进行修改.在 XML 中,特殊元素可能包括保留字或字符,例如“&l ...
- 2016022603 - redis数据类型
Redis支持5种类型的数据类型 1.字符串:Redis字符串是字节序列.Redis字符串是二进制安全的,这意味着他们有一个已知的长度没有任何特殊字符终止,所以你可以存储任何东西,512兆为上限.[类 ...
- jq实现瀑布流效果
<!doctype html><html><head><meta http-equiv="Content-Type" content=&q ...
- OS X Lion版 如果我忘记了我的账户密码 我该怎么办?
来到了 mac os x lion 10.7 上. 忘记密码的朋友不会减少. 除了努力回忆和询问自己的老婆外还有其他办发不? 那是自然有的. 帐户密码很重要虽然有时候我们设置了帐户自动登陆但是如果您需 ...