- 浏览: 4202846 次
最新评论
MediaInfo源代码分析 5:JPEG解析代码分析
注:此前已经写了一系列分析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(); }
详细的代码暂时没有时间研究了,先这样了。
相关推荐
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 用来分析视频和音频文件的编码和内容信息,是一款是自由软件 (免费使用、免费获得源代码,许可协议:GNU GPL/LGPL)。 支持格式:视频:MKV, OGM, AVI, DivX, WMV, QuickTime, Real, MPEG-1, MPEG-2, MPEG-4...
MediaInfo 用来分析视频和音频文件的编码和内容信息,是一款是自由软件 (免费使用、免费获得源代码,许可协议:GNU GPL/LGPL)。 MediaInfo可以获得多媒体文件的哪些信息? 内容信息:标题,作者,专辑名,音轨号,...
一个可以获取媒体文件...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]...
音视频信息解析工具_MediaInfo.rar
使用MediaInfo可以分析多媒体的信息如下: 内容信息:标题,作者,专辑名,音轨号,日期,总时间…… 视频:编码器,长宽比,帧频率,比特率…… 音频:编码器,采样率,声道数,语言,比特率……
视频编码分析查询器 查询视频的编码形式
mediainfo源码vs可以编译通过,mediainfo的版本0.7.31
媒体格式分析MediaInfo可以查询媒体文件编码,比特率等
MediaInfo 支持众多音频和视频格式,它可以快速分析音频或视频文件的编码及信息,对于一些喜爱收藏高清视频的人来说,它可以快速帮你诊断出你下载的视频是不是真正的高清文件。当然 MediaInfo 其实不仅仅可以查阅...
MediaInfo(绿色中文版)用来分析视频和音频文件的编码和内容信息,检测视频编码信息,把目前几个主流的CODEC viewer的功能都给包进来了.像是对新格式的支持, 提供相关CODECs和播放软件的网页连结等等 使用MediaInfo...
Mediainfo-模板 命令行示例标准通知文件mediainfo --Inform=file:///Path/To-File/Inform-Example.txt 'Blue Planet II - S01E02 - The Deep.mkv' 命令行示例$ if()通知文件通过管道传递到“ TR”以删除空白行...
MediaInfo 是自由软件 (免费使用、免费获得源代码,许可协议: BSD) (版本号:0.7.90/图形界面/安装程序/Windows, 32/64 bit/5 MB) -----------------------------------------------------------------------------...
mediainfo是命令行实用程序mediainfo的包装,用于从音频/视频文件中读取信息。 还支持图像文件。 要求 您必须在系统上安装mediainfo命令行实用程序。 以下是基于Debian的系统: $ sudo apt install mediainfo 文献...
有源码和说明,包括一些简单的实例,适合自己二次封装并使用。
MediaInfo 用来分析视频和音频文件的编码和内容信息,是一款是自由软件 (免费使用、免费获得源代码)。 可获取视频宽、高、编码等等信息。C++编写。 本工程在vs2010下编译。
该工具可以分析媒体文件的文件格式、编码格式以及音视频码率等信息,对研究流媒体研究的工作者很有帮助。
MediaInfo是一款非常实用的视频参数检测工具,除了可以对...MediaInfo 用来分析视频和音频文件的编码和内容信息,是一款是自由软件 (免费使用、免费获得源代码,许可协议:GNU GPL/LGPL)。MediaInfo_DLL为它的开发库。
MediaInfo 0.7.31 源码。MediaInfo是一款优秀的识别媒体文件格式的软件。