注:此前已经写了一系列分析MediaInfo源代码的文章,列表如下:
MediaInfo源代码分析 1:整体结构
MediaInfo源代码分析 2:API函数
MediaInfo源代码分析 3:Open()函数
MediaInfo源代码分析 4:Inform()函数
MediaInfo源代码分析 5:JPEG解析代码分析
===================
本文分析MediaInfo中解码JPEG信息的模块。之前写了几篇文章都是关于MediaInfo主程序的,并没有分析其具体是如何解析不同多媒体文件信息的。在这里分析一下解码JPEG文件的代码。其他格式如BMP,GIF等解析的思路基本上是类似的。
File_Jpeg.h的File_Jpeg类的定义如下所示:
//*************************************************************************** // Class File_Jpeg //*************************************************************************** //继承 File__Analyze class File_Jpeg : public File__Analyze { public : //In stream_t StreamKind; bool Interlaced; //Constructor/Destructor File_Jpeg(); private : //Streams management void Streams_Accept(); //Buffer - File header bool FileHeader_Begin(); //Buffer - Synchro bool Synchronize(); bool Synched_Test(); void Synched_Init(); //Buffer - Demux #if MEDIAINFO_DEMUX bool Demux_UnpacketizeContainer_Test() {return Demux_UnpacketizeContainer_Test_OneFramePerFile();} #endif //MEDIAINFO_DEMUX //Buffer - Global void Read_Buffer_Unsynched(); #if MEDIAINFO_SEEK size_t Read_Buffer_Seek (size_t Method, int64u Value, int64u ID) {return Read_Buffer_Seek_OneFramePerFile(Method, Value, ID);} #endif //MEDIAINFO_SEEK //Buffer - Per element //解析头 void Header_Parse(); bool Header_Parser_Fill_Size(); //解析数据 void Data_Parse(); //Elements //JPEG中的单元 //解析相应的单元,并获得信息 void TEM () {}; void SOC () {} void SIZ (); void COD (); void COC () {Skip_XX(Element_Size, "Data");} void TLM () {Skip_XX(Element_Size, "Data");} void PLM () {Skip_XX(Element_Size, "Data");} void PLT () {Skip_XX(Element_Size, "Data");} void QCD (); void QCC () {Skip_XX(Element_Size, "Data");} void RGN () {Skip_XX(Element_Size, "Data");} void PPM () {Skip_XX(Element_Size, "Data");} void PPT () {Skip_XX(Element_Size, "Data");} void CME () {Skip_XX(Element_Size, "Data");} void SOT () {Skip_XX(Element_Size, "Data");} void SOP () {Skip_XX(Element_Size, "Data");} void EPH () {Skip_XX(Element_Size, "Data");} void SOD (); void SOF_(); void S0F0() {SOF_();}; void S0F1() {SOF_();}; void S0F2() {SOF_();}; void S0F3() {SOF_();} void DHT () {Skip_XX(Element_Size, "Data");} void S0F5() {SOF_();} void S0F6() {SOF_();} void S0F7() {SOF_();} void JPG () {Skip_XX(Element_Size, "Data");} void S0F9() {SOF_();} void S0FA() {SOF_();} void S0FB() {SOF_();} void DAC () {Skip_XX(Element_Size, "Data");} void S0FD() {SOF_();} void S0FE() {SOF_();} void S0FF() {SOF_();} void RST0() {}; void RST1() {}; void RST2() {}; void RST3() {}; void RST4() {}; void RST5() {}; void RST6() {}; void RST7() {}; void SOI () {}; void EOI () {}; void SOS (); void DQT () {Skip_XX(Element_Size, "Data");} void DNL () {Skip_XX(Element_Size, "Data");} void DRI () {Skip_XX(Element_Size, "Data");} void DHP () {Skip_XX(Element_Size, "Data");} void EXP () {Skip_XX(Element_Size, "Data");} void APP0(); void APP0_AVI1(); void APP0_JFIF(); void APP0_JFFF(); void APP0_JFFF_JPEG(); void APP0_JFFF_1B(); void APP0_JFFF_3B(); void APP1(); void APP1_EXIF(); void APP2() {Skip_XX(Element_Size, "Data");} void APP3() {Skip_XX(Element_Size, "Data");} void APP4() {Skip_XX(Element_Size, "Data");} void APP5() {Skip_XX(Element_Size, "Data");} void APP6() {Skip_XX(Element_Size, "Data");} void APP7() {Skip_XX(Element_Size, "Data");} void APP8() {Skip_XX(Element_Size, "Data");} void APP9() {Skip_XX(Element_Size, "Data");} void APPA() {Skip_XX(Element_Size, "Data");} void APPB() {Skip_XX(Element_Size, "Data");} void APPC() {Skip_XX(Element_Size, "Data");} void APPD() {Skip_XX(Element_Size, "Data");} void APPE(); void APPE_Adobe0(); void APPF() {Skip_XX(Element_Size, "Data");} void JPG0() {Skip_XX(Element_Size, "Data");} void JPG1() {Skip_XX(Element_Size, "Data");} void JPG2() {Skip_XX(Element_Size, "Data");} void JPG3() {Skip_XX(Element_Size, "Data");} void JPG4() {Skip_XX(Element_Size, "Data");} void JPG5() {Skip_XX(Element_Size, "Data");} void JPG6() {Skip_XX(Element_Size, "Data");} void JPG7() {Skip_XX(Element_Size, "Data");} void JPG8() {Skip_XX(Element_Size, "Data");} void JPG9() {Skip_XX(Element_Size, "Data");} void JPGA() {Skip_XX(Element_Size, "Data");} void JPGB() {Skip_XX(Element_Size, "Data");} void JPGC() {Skip_XX(Element_Size, "Data");} void JPGD() {Skip_XX(Element_Size, "Data");} void COM () {Skip_XX(Element_Size, "Data");} //Temp int8u APPE_Adobe0_transform; bool APP0_JFIF_Parsed; bool SOS_SOD_Parsed; };
上面代码有以下几个特点:
1.继承了File__Analyze类
2.包含了很多JPEG中的数据单元的解析:DHT(),DQT()等等
下面来分别仔细看看源代码:
1.File__Analyze类代码巨多无比,先不分析。他继承了继承了File__Base
2.看一个解码具体单元的代码:SOF_()
注:SOF0(Start of Image,图像开始)。
SOF0,Start of Frame,帧图像开始
标记代码 2字节 固定值0xFFC0
包含9个具体字段:
① 数据长度 2字节 ①~⑥六个字段的总长度
即不包括标记代码,但包括本字段
② 精度 1字节 每个数据样本的位数
通常是8位,一般软件都不支持 12位和16位
③ 图像高度 2字节 图像高度(单位:像素),如果不支持 DNL 就必须 >0
④ 图像宽度 2字节 图像宽度(单位:像素),如果不支持 DNL 就必须 >0
⑤ 颜色分量数 1字节 只有3个数值可选
1:灰度图;3:YCrCb或YIQ;4:CMYK
而JFIF中使用YCrCb,故这里颜色分量数恒为3
⑥颜色分量信息 颜色分量数×3字节(通常为9字节)
a) 颜色分量ID 1字节
b) 水平/垂直采样因子 1字节 高4位:水平采样因子
低4位:垂直采样因子
(曾经看到某资料把这两者调转了)
c) 量化表 1字节 当前分量使用的量化表的ID
本标记段中,字段⑥应该重复出现,有多少个颜色分量(字段⑤),就出现多少次(一般为3次)。
=====================================
void File_Jpeg::SOF_() { //Parsing vector<Jpeg_samplingfactor> SamplingFactors; int16u Height, Width; int8u Resolution, Count; Get_B1 (Resolution, "P - Sample precision"); Get_B2 (Height, "Y - Number of lines"); Get_B2 (Width, "X - Number of samples per line"); Get_B1 (Count, "Nf - Number of image components in frame"); for (int8u Pos=0; Pos<Count; Pos++) { Jpeg_samplingfactor SamplingFactor; Element_Begin1("Component"); Get_B1 ( SamplingFactor.Ci, "Ci - Component identifier"); if (SamplingFactor.Ci>Count) Element_Info1(Ztring().append(1, (Char)SamplingFactor.Ci)); else Element_Info1(SamplingFactor.Ci); BS_Begin(); Get_S1 (4, SamplingFactor.Hi, "Hi - Horizontal sampling factor"); Element_Info1(SamplingFactor.Hi); Get_S1 (4, SamplingFactor.Vi, "Vi - Vertical sampling factor"); Element_Info1(SamplingFactor.Vi); BS_End(); Skip_B1( "Tqi - Quantization table destination selector"); Element_End0(); //Filling list of HiVi SamplingFactors.push_back(SamplingFactor); } FILLING_BEGIN_PRECISE(); if (Frame_Count==0 && Field_Count==0) { Accept("JPEG"); Fill("JPEG"); if (Count_Get(StreamKind_Last)==0) Stream_Prepare(StreamKind_Last); Fill(StreamKind_Last, 0, Fill_Parameter(StreamKind_Last, Generic_Format), "JPEG"); Fill(StreamKind_Last, 0, Fill_Parameter(StreamKind_Last, Generic_Codec), "JPEG"); if (StreamKind_Last==Stream_Image) Fill(Stream_Image, 0, Image_Codec_String, "JPEG", Unlimited, true, true); //To Avoid automatic filling if (StreamKind_Last==Stream_Video) Fill(Stream_Video, 0, Video_InternetMediaType, "video/JPEG", Unlimited, true, true); Fill(StreamKind_Last, 0, Fill_Parameter(StreamKind_Last, Generic_BitDepth), Resolution); Fill(StreamKind_Last, 0, "Height", Height*(Interlaced?2:1)); Fill(StreamKind_Last, 0, "Width", Width); //ColorSpace from http://docs.oracle.com/javase/1.4.2/docs/api/javax/imageio/metadata/doc-files/jpeg_metadata.html switch (APPE_Adobe0_transform) { case 0x01 : if (Count==3) Fill(StreamKind_Last, 0, "ColorSpace", "YUV"); case 0x02 : if (Count==4) Fill(StreamKind_Last, 0, "ColorSpace", "YCCB"); break; default : { int8u Ci[256]; memset(Ci, 0, 256);; for (int8u Pos=0; Pos<Count; Pos++) Ci[SamplingFactors[Pos].Ci]++; switch (Count) { case 1 : Fill(StreamKind_Last, 0, "ColorSpace", "Y"); break; case 2 : Fill(StreamKind_Last, 0, "ColorSpace", "YA"); break; case 3 : if (!APP0_JFIF_Parsed && Ci['R']==1 && Ci['G']==1 && Ci['B']==1) //RGB Fill(StreamKind_Last, 0, "ColorSpace", "RGB"); else if ((Ci['Y']==1 && ((Ci['C']==1 && Ci['c']==1) //YCc || Ci['C']==2)) //YCC || APP0_JFIF_Parsed //APP0 JFIF header present so YCC || APPE_Adobe0_transform==0 //transform set to YCC || (SamplingFactors[0].Ci==0 && SamplingFactors[1].Ci==1 && SamplingFactors[2].Ci==2) //012 || (SamplingFactors[0].Ci==1 && SamplingFactors[1].Ci==2 && SamplingFactors[2].Ci==3)) //123 Fill(StreamKind_Last, 0, "ColorSpace", "YUV"); break; case 4 : if (!APP0_JFIF_Parsed && Ci['R']==1 && Ci['G']==1 && Ci['B']==1 && Ci['A']==1) //RGBA Fill(StreamKind_Last, 0, "ColorSpace", "RGBA"); else if ((Ci['Y']==1 && Ci['A']==1 && ((Ci['C']==1 && Ci['c']==1) //YCcA || Ci['C']==2)) //YCCA || APP0_JFIF_Parsed //APP0 JFIF header present so YCCA || (SamplingFactors[0].Ci==0 && SamplingFactors[1].Ci==1 && SamplingFactors[2].Ci==2 && SamplingFactors[3].Ci==3) //0123 || (SamplingFactors[0].Ci==1 && SamplingFactors[1].Ci==2 && SamplingFactors[2].Ci==3 && SamplingFactors[3].Ci==4)) //1234 Fill(StreamKind_Last, 0, "ColorSpace", "YUVA"); else if (APPE_Adobe0_transform==0) //transform set to CMYK Fill(StreamKind_Last, 0, "ColorSpace", "YCCB"); break; default: ; } } } //Chroma subsampling if ((SamplingFactors.size()==3 || SamplingFactors.size()==4) && SamplingFactors[1].Hi==1 && SamplingFactors[2].Hi==1 && SamplingFactors[1].Vi==1 && SamplingFactors[2].Vi==1) { string ChromaSubsampling; switch (SamplingFactors[0].Hi) { case 1 : switch (SamplingFactors[0].Vi) { case 1 : ChromaSubsampling="4:4:4"; break; default: ; } break; case 2 : switch (SamplingFactors[0].Vi) { case 1 : ChromaSubsampling="4:2:2"; break; case 2 : ChromaSubsampling="4:2:0"; break; default: ; } break; case 4 : switch (SamplingFactors[0].Vi) { case 1 : ChromaSubsampling="4:1:1"; break; default: ; } break; default: ; } if (!ChromaSubsampling.empty()) { if (SamplingFactors.size()==4) { if (ChromaSubsampling=="4:4:4" && SamplingFactors[3].Hi==1 && SamplingFactors[3].Vi==1) ChromaSubsampling+=":4"; else ChromaSubsampling+=":?"; } Fill(StreamKind_Last, 0, "ChromaSubsampling", ChromaSubsampling); } } } FILLING_END(); }
从代码的含义可知,提取出了图像的宽,高,采样方式等信息。
详细的代码暂时没有时间研究了,先这样了。
相关推荐
1. **加载文件**:首先,你需要使用`MediaInfo_Open()`函数打开你要分析的多媒体文件,该函数会返回一个句柄,用于后续的操作。 2. **提取信息**:接着,你可以调用`MediaInfo_Inform()`或`MediaInfo_Get()`函数,...
MediaInfo是一款强大的多媒体信息分析工具,它能够详细地解析音频和视频文件的各种元数据,包括编码格式、比特率、采样率、声道数等。MediaInfo提供了DLL动态链接库的形式,方便开发者将其集成到自己的应用程序中,...
这个“mediainfo_0.7.31.rar”压缩包包含了mediainfo的源代码,版本为0.7.31,适合开发者用于学习、定制或在Visual Studio环境下进行编译。 Mediainfo的源码是用C++编写的,它的设计目标是提供一个跨平台的解决...
"编码分析"是指通过特定工具,如MediaInfo,解析视频文件的元数据,获取编码信息。这对于视频制作、编辑、传输和播放都是必不可少的步骤。例如,在进行视频转码或压缩时,需要知道原文件的编码类型,以便选择合适的...
《全面解析MediaInfo:探索媒体文件的内在奥秘》 在数字媒体的世界里,了解文件的内部构造和编码参数是至关重要的。MediaInfo就是这样一款强大的工具,专为媒体专业人士和普通用户提供了详尽的媒体文件分析功能。它...
MediaInfo 是一款强大的媒体信息查看工具,专门用于分析和提取各种多媒体文件的详细技术信息。这个软件可以帮助用户轻松地了解视频、音频文件的编码格式、分辨率、比特率、采样率等关键参数,从而在处理多媒体文件时...
MediaInfo遵循开源许可,可能使用的是GPL或MIT等开放源代码许可证,允许自由使用和分享。 4. **History.txt**:这是一个版本历史记录文件,列出了该版本的更新内容、改进和修复的bug,帮助用户了解软件的发展历程...
MediaInfo是一款强大的多媒体信息分析工具,它能够详细地解析各种音视频文件的元数据和编码信息,帮助用户了解媒体文件的详细技术规格。MediaInfo支持众多格式,包括但不限于MP4、AVI、MKV、WMV、MP3、AAC等,涵盖了...
MediaInfo的一大优点是开源且跨平台,它的源代码遵循GPLv2许可协议,这意味着用户可以自由查看、修改并分发源代码。此外,MediaInfo还提供了命令行版本和图形用户界面版本,以满足不同用户的需求。 总的来说,...
The MediaInfo data display includes: Container: format, profile, commercial name of the format, duration, overall bit rate, writing application and library, title, author, director, album, track ...
**MediaInfo 媒体分析工具** MediaInfo 是一款强大的媒体信息分析工具,它能够提供详尽的多媒体文件元数据信息,包括视频、音频、字幕等不同轨道的数据。这款工具对于媒体处理、流媒体研究、视频编码和解码、内容...
MediaInfo 用来分析视频和音频文件的编码和内容信息,是一款是自由软件 (免费使用、免费获得源代码,许可协议:GNU GPL/LGPL)。 支持格式:视频:MKV, OGM, AVI, DivX, WMV, QuickTime, Real, MPEG-1, MPEG-2, MPEG-4...
MediainfoTest这个文件可能是一个测试项目或者示例代码,用于演示如何使用Mediainfo库来获取并解析视频信息。通过这样的测试,开发者可以学习如何在自己的应用程序中集成Mediainfo的功能,以实现多媒体文件的元数据...
MediaInfo 用来分析视频和音频文件的编码和内容信息,是一款是自由软件 (免费使用、免费获得源代码,许可协议:GNU GPL/LGPL)。 MediaInfo可以获得多媒体文件的哪些信息? 内容信息:标题,作者,专辑名,音轨号,...
MediaInfo是一款强大的多媒体信息分析工具,专为用户提供详细的音频、视频文件元数据。这款软件在全球范围内广受欢迎,因其用户友好的界面和免费无限制的特性而备受赞誉。MediaInfo_20.03.dmg.zip是针对Mac OS平台的...
一个可以获取媒体文件...C:\MediaInfo\MediaInfo.exe --help 解析 C:\123.mp4的参数 C:\MediaInfo\MediaInfo.exe C:\123.mp4 解析 C:\123.mp4, 并以XML格式输出 C:\MediaInfo\MediaInfo.exe --Output=XML C:\123.mp4
它使用从C ++源代码编译而来。演示版在浏览器中尝试mediainfo.js: ://mediainfo.js.org用法浏览器您可以使用CDN将脚本文件直接包含在页面中,也可以使用JavaScript捆绑程序(例如webpack)。 CDN : [removed]...
8. **开源项目**:MediaInfo是开源软件,遵循GPL许可证,这意味着源代码公开,用户可以自由查看、修改和分发。 在实际应用中,MediaInfo的使用场景广泛: - **视频编辑**:在剪辑和后期制作过程中,MediaInfo可以...
MediaInfo是一款强大的多媒体信息分析工具,它主要用于获取和展示各种音视频文件的详细技术信息。这个软件可以帮助用户深入了解媒体文件的编码方式、流信息、元数据等关键参数,对于视频编辑、媒体处理以及问题排查...
使用MediaInfo可以分析多媒体的信息如下: 内容信息:标题,作者,专辑名,音轨号,日期,总时间…… 视频:编码器,长宽比,帧频率,比特率…… 音频:编码器,采样率,声道数,语言,比特率……