/* Copyright (c) MediaArea.net SARL. All Rights Reserved.
*
* Use of this source code is governed by a BSD-style license that can
* be found in the License.html file in the root of the source tree.
*/
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//
// Elements part
//
// Contributor: Lionel Duchateau, kurtnoise@free.fr
//
//+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
//---------------------------------------------------------------------------
// Pre-compilation
#include "MediaInfo/PreComp.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include "MediaInfo/Setup.h"
#include "tinyxml2.h"
#include <ZenLib/Ztring.h>
#include <string>
#include <algorithm>
using namespace tinyxml2;
using namespace std;
using namespace ZenLib;
//---------------------------------------------------------------------------
//***************************************************************************
// Infos
//***************************************************************************
//---------------------------------------------------------------------------
#if defined(MEDIAINFO_RIFF_YES) || defined(MEDIAINFO_MK_YES)
//---------------------------------------------------------------------------
namespace MediaInfoLib
{
//---------------------------------------------------------------------------
std::string ExtensibleWave_ChannelMask (int32u ChannelMask)
{
std::string Text;
if ((ChannelMask&0x0007)!=0x0000)
Text+="Front:";
if (ChannelMask&0x0001)
Text+=" L";
if (ChannelMask&0x0004)
Text+=" C";
if (ChannelMask&0x0002)
Text+=" R";
if ((ChannelMask&0x0600)!=0x0000)
Text+=", Side:";
if (ChannelMask&0x0200)
Text+=" L";
if (ChannelMask&0x0400)
Text+=" R";
if ((ChannelMask&0x0130)!=0x0000)
Text+=", Back:";
if (ChannelMask&0x0010)
Text+=" L";
if (ChannelMask&0x0100)
Text+=" C";
if (ChannelMask&0x0020)
Text+=" R";
if ((ChannelMask&0x0008)!=0x0000)
Text+=", LFE";
return Text;
}
//---------------------------------------------------------------------------
std::string ExtensibleWave_ChannelMask2 (int32u ChannelMask)
{
std::string Text;
int8u Count=0;
if (ChannelMask&0x0001)
Count++;
if (ChannelMask&0x0004)
Count++;
if (ChannelMask&0x0002)
Count++;
Text+=Ztring::ToZtring(Count).To_UTF8();
Count=0;
if (ChannelMask&0x0200)
Count++;
if (ChannelMask&0x0400)
Count++;
Text+="/"+Ztring::ToZtring(Count).To_UTF8();
Count=0;
if (ChannelMask&0x0010)
Count++;
if (ChannelMask&0x0100)
Count++;
if (ChannelMask&0x0020)
Count++;
Text+="/"+Ztring::ToZtring(Count).To_UTF8();
Count=0;
if (ChannelMask&0x0008)
Text+=".1";
return Text;
}
//---------------------------------------------------------------------------
static const size_t ExtensibleWave_ChannelLayoutNames_Size=18;
const char* ExtensibleWave_ChannelLayoutNames[ExtensibleWave_ChannelLayoutNames_Size]=
{
"FL",
"FR",
"FC",
"LFE",
"BL",
"BR",
"FLC",
"FRC",
"BC",
"SL",
"SR",
"TC",
"TFL",
"TFC",
"TFR",
"TBL",
"TBC",
"TBR",
};
std::string ExtensibleWave_ChannelMask_ChannelLayout(int32u ChannelMask)
{
std::string Text;
for (size_t i=0; i<ExtensibleWave_ChannelLayoutNames_Size; i++)
if (ChannelMask&(1<<i))
{
if (!Text.empty())
Text+=' ';
Text+=ExtensibleWave_ChannelLayoutNames[i];
}
return Text;
}
}
//---------------------------------------------------------------------------
#endif
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#ifdef MEDIAINFO_RIFF_YES
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include "MediaInfo/Multiple/File_Riff.h"
#if defined(MEDIAINFO_DVDIF_YES)
#include "MediaInfo/Multiple/File_DvDif.h"
#endif
#if defined(MEDIAINFO_OGG_YES)
#include "MediaInfo/Multiple/File_Ogg.h"
#include "MediaInfo/Multiple/File_Ogg_SubElement.h"
#endif
#if defined(MEDIAINFO_CINEFORM_YES)
#include "MediaInfo/Video/File_CineForm.h"
#endif
#if defined(MEDIAINFO_FFV1_YES)
#include "MediaInfo/Video/File_Ffv1.h"
#endif
#if defined(MEDIAINFO_HUFFYUV_YES)
#include "MediaInfo/Video/File_HuffYuv.h"
#endif
#if defined(MEDIAINFO_MPEG4V_YES)
#include "MediaInfo/Video/File_Mpeg4v.h"
#endif
#if defined(MEDIAINFO_MPEGV_YES)
#include "MediaInfo/Video/File_Mpegv.h"
#endif
#if defined(MEDIAINFO_PRORES_YES)
#include "MediaInfo/Video/File_ProRes.h"
#endif
#if defined(MEDIAINFO_AVC_YES)
#include "MediaInfo/Video/File_Avc.h"
#endif
#if defined(MEDIAINFO_CANOPUS_YES)
#include "MediaInfo/Video/File_Canopus.h"
#endif
#if defined(MEDIAINFO_FRAPS_YES)
#include "MediaInfo/Video/File_Fraps.h"
#endif
#if defined(MEDIAINFO_LAGARITH_YES)
#include "MediaInfo/Video/File_Lagarith.h"
#endif
#if defined(MEDIAINFO_MPEGA_YES)
#include "MediaInfo/Audio/File_Mpega.h"
#endif
#if defined(MEDIAINFO_AAC_YES)
#include "MediaInfo/Audio/File_Aac.h"
#endif
#if defined(MEDIAINFO_AC3_YES)
#include "MediaInfo/Audio/File_Ac3.h"
#endif
#if defined(MEDIAINFO_ADM_YES)
#include "MediaInfo/Audio/File_Adm.h"
#endif
#if defined(MEDIAINFO_DTS_YES)
#include "MediaInfo/Audio/File_Dts.h"
#endif
#if defined(MEDIAINFO_JPEG_YES)
#include "MediaInfo/Image/File_Jpeg.h"
#endif
#if defined(MEDIAINFO_SUBRIP_YES)
#include "MediaInfo/Text/File_SubRip.h"
#endif
#if defined(MEDIAINFO_OTHERTEXT_YES)
#include "MediaInfo/Text/File_OtherText.h"
#endif
#if defined(MEDIAINFO_ADPCM_YES)
#include "MediaInfo/Audio/File_Adpcm.h"
#endif
#if defined(MEDIAINFO_PCM_YES)
#include "MediaInfo/Audio/File_Pcm.h"
#endif
#if defined(MEDIAINFO_SMPTEST0337_YES)
#include "MediaInfo/Audio/File_SmpteSt0337.h"
#include "MediaInfo/Audio/File_ChannelSplitting.h"
#endif
#if defined(MEDIAINFO_ID3_YES)
#include "MediaInfo/Tag/File_Id3.h"
#endif
#if defined(MEDIAINFO_ID3V2_YES)
#include "MediaInfo/Tag/File_Id3v2.h"
#endif
#if defined(MEDIAINFO_GXF_YES)
#if defined(MEDIAINFO_CDP_YES)
#include "MediaInfo/Text/File_Cdp.h"
#include <cstring>
#endif
#endif //MEDIAINFO_GXF_YES
#include "MediaInfo/Audio/File_DolbyAudioMetadata.h"
#include <vector>
#include "MediaInfo/MediaInfo_Config_MediaInfo.h"
#if defined(MEDIAINFO_ADM_YES)
#include <zlib.h>
#endif
using namespace std;
//---------------------------------------------------------------------------
namespace MediaInfoLib
{
//***************************************************************************
// Const
//***************************************************************************
namespace Elements
{
const int32u FORM=0x464F524D;
const int32u LIST=0x4C495354;
const int32u ON2_=0x4F4E3220;
const int32u RIFF=0x52494646;
const int32u RF64=0x52463634;
const int32u AIFC=0x41494643;
const int32u AIFC_COMM=0x434F4D4D;
const int32u AIFC_COMT=0x434F4D54;
const int32u AIFC_FVER=0x46564552;
const int32u AIFC_SSND=0x53534E44;
const int32u AIFF=0x41494646;
const int32u AIFF_COMM=0x434F4D4D;
const int32u AIFF_COMT=0x434F4D54;
const int32u AIFF_SSND=0x53534E44;
const int32u AIFF__c__=0x28632920;
const int32u AIFF_ANNO=0x414E4E4F;
const int32u AIFF_AUTH=0x41555448;
const int32u AIFF_NAME=0x4E414D45;
const int32u AIFF_ID3_=0x49443320;
const int32u AVI_=0x41564920;
const int32u AVI__cset=0x63736574;
const int32u AVI__Cr8r=0x43723872;
const int32u AVI__exif=0x65786966;
const int32u AVI__exif_ecor=0x65636F72;
const int32u AVI__exif_emdl=0x656D646C;
const int32u AVI__exif_emnt=0x656D6E74;
const int32u AVI__exif_erel=0x6572656C;
const int32u AVI__exif_etim=0x6574696D;
const int32u AVI__exif_eucm=0x6575636D;
const int32u AVI__exif_ever=0x65766572;
const int32u AVI__goog=0x676F6F67;
const int32u AVI__goog_GDAT=0x47444154;
const int32u AVI__GMET=0x474D4554;
const int32u AVI__hdlr=0x6864726C;
const int32u AVI__hdlr_avih=0x61766968;
const int32u AVI__hdlr_JUNK=0x4A554E4B;
const int32u AVI__hdlr_strl=0x7374726C;
const int32u AVI__hdlr_strl_indx=0x696E6478;
const int32u AVI__hdlr_strl_JUNK=0x4A554E4B;
const int32u AVI__hdlr_strl_strd=0x73747264;
const int32u AVI__hdlr_strl_strf=0x73747266;
const int32u AVI__hdlr_strl_strh=0x73747268;
const int32u AVI__hdlr_strl_strh_auds=0x61756473;
const int32u AVI__hdlr_strl_strh_iavs=0x69617673;
const int32u AVI__hdlr_strl_strh_mids=0x6D696473;
const int32u AVI__hdlr_strl_strh_vids=0x76696473;
const int32u AVI__hdlr_strl_strh_txts=0x74787473;
const int32u AVI__hdlr_strl_strn=0x7374726E;
const int32u AVI__hdlr_strl_vprp=0x76707270;
const int32u AVI__hdlr_odml=0x6F646D6C;
const int32u AVI__hdlr_odml_dmlh=0x646D6C68;
const int32u AVI__hdlr_ON2h=0x4F4E3268;
const int32u AVI__idx1=0x69647831;
const int32u AVI__INFO=0x494E464F;
const int32u AVI__INFO_IARL=0x4941524C;
const int32u AVI__INFO_IART=0x49415254;
const int32u AVI__INFO_IAS1=0x49415331;
const int32u AVI__INFO_IAS2=0x49415332;
const int32u AVI__INFO_IAS3=0x49415333;
const int32u AVI__INFO_IAS4=0x49415334;
const int32u AVI__INFO_IAS5=0x49415335;
const int32u AVI__INFO_IAS6=0x49415336;
const int32u AVI__INFO_IAS7=0x49415337;
const int32u AVI__INFO_IAS8=0x49415338;
const int32u AVI__INFO_IAS9=0x49415339;
const int32u AVI__INFO_ICDS=0x49434453;
const int32u AVI__INFO_ICMS=0x49434D53;
const int32u AVI__INFO_ICMT=0x49434D54;
const int32u AVI__INFO_ICNT=0x49434E54;
const int32u AVI__INFO_ICOP=0x49434F50;
const int32u AVI__INFO_ICNM=0x49434E4D;
const int32u AVI__INFO_ICRD=0x49435244;
const int32u AVI__INFO_ICRP=0x49435250;
const int32u AVI__INFO_IDIM=0x4944494D;
const int32u AVI__INFO_IDIT=0x49444954;
const int32u AVI__INFO_IDPI=0x49445049;
const int32u AVI__INFO_IDST=0x49445354;
const int32u AVI__INFO_IEDT=0x49454454;
const int32u AVI__INFO_IENG=0x49454E47;
const int32u AVI__INFO_IFRM=0x4946524D;
const int32u AVI__INFO_IGNR=0x49474E52;
const int32u AVI__INFO_IID3=0x49494433;
const int32u AVI__INFO_IKEY=0x494B4559;
const int32u AVI__INFO_ILGT=0x494C4754;
const int32u AVI__INFO_ILNG=0x494C4E47;
const int32u AVI__INFO_ILYC=0x494C5943;
const int32u AVI__INFO_IMED=0x494D4544;
const int32u AVI__INFO_IMP3=0x494D5033;
const int32u AVI__INFO_IMUS=0x494D5553;
const int32u AVI__INFO_INAM=0x494E414D;
const int32u AVI__INFO_IPLT=0x49504C54;
const int32u AVI__INFO_IPDS=0x49504453;
const int32u AVI__INFO_IPRD=0x49505244;
const int32u AVI__INFO_IPRT=0x49505254;
const int32u AVI__INFO_IPRO=0x4950524F;
const int32u AVI__INFO_IRTD=0x49525444;
const int32u AVI__INFO_ISBJ=0x4953424A;
const int32u AVI__INFO_ISGN=0x4953474E;
const int32u AVI__INFO_ISTD=0x49535444;
const int32u AVI__INFO_ISTR=0x49535452;
const int32u AVI__INFO_ISFT=0x49534654;
const int32u AVI__INFO_ISHP=0x49534850;
const int32u AVI__INFO_ISMP=0x49534D50;
const int32u AVI__INFO_ISRC=0x49535243;
const int32u AVI__INFO_ISRF=0x49535246;
const int32u AVI__INFO_ITCH=0x49544348;
const int32u AVI__INFO_IWEB=0x49574542;
const int32u AVI__INFO_IWRI=0x49575249;
const int32u AVI__INFO_JUNK=0x4A554E4B;
const int32u AVI__JUNK=0x4A554E4B;
const int32u AVI__MD5_=0x4D443520;
const int32u AVI__movi=0x6D6F7669;
const int32u AVI__movi_rec_=0x72656320;
const int32u AVI__movi_xxxx_____=0x00005F5F;
const int32u AVI__movi_xxxx___db=0x00006462;
const int32u AVI__movi_xxxx___dc=0x00006463;
const int32u AVI__movi_xxxx___sb=0x00007362;
const int32u AVI__movi_xxxx___tx=0x00007478;
const int32u AVI__movi_xxxx___wb=0x00007762;
const int32u AVI__PrmA=0x50726D41;
const int32u AVI__Tdat=0x54646174;
const int32u AVI__Tdat_rn_A=0x726E5F41;
const int32u AVI__Tdat_rn_O=0x726E5F4F;
const int32u AVI__Tdat_tc_A=0x74635F41;
const int32u AVI__Tdat_tc_O=0x74635F4F;
const int32u AVIX=0x41564958;
const int32u AVIX_idx1=0x69647831;
const int32u AVIX_movi=0x6D6F7669;
const int32u AVIX_movi_rec_=0x72656320;
const int32u CADP=0x43414450;
const int32u CDDA=0x43444441;
const int32u CDDA_fmt_=0x666D7420;
const int32u CMJP=0x434D4A50;
const int32u CMP4=0x434D5034;
const int32u IDVX=0x49445658;
const int32u INDX=0x494E4458;
const int32u JUNK=0x4A554E4B;
const int32u menu=0x6D656E75;
const int32u MThd=0x4D546864;
const int32u MTrk=0x4D54726B;
const int32u PAL_=0x50414C20;
const int32u QLCM=0x514C434D;
const int32u QLCM_fmt_=0x666D7420;
const int32u rcrd=0x72637264;
const int32u rcrd_desc=0x64657363;
const int32u rcrd_fld_=0x666C6420;
const int32u rcrd_fld__anc_=0x616E6320;
const int32u rcrd_fld__anc__pos_=0x706F7320;
const int32u rcrd_fld__anc__pyld=0x70796C64;
const int32u rcrd_fld__finf=0x66696E66;
const int32u RDIB=0x52444942;
const int32u RMID=0x524D4944;
const int32u RMMP=0x524D4D50;
const int32u RMP3=0x524D5033;
const int32u RMP3_data=0x64617461;
const int32u RMP3_INFO=0x494E464F;
const int32u RMP3_INFO_IID3=0x49494433;
const int32u RMP3_INFO_ILYC=0x494C5943;
const int32u RMP3_INFO_IMP3=0x494D5033;
const int32u RMP3_INFO_JUNK=0x4A554E4B;
const int32u SMV0=0x534D5630;
const int32u SMV0_xxxx=0x534D563A;
const int32u WAVE=0x57415645;
const int32u WAVE__pmx=0x20786D70;
const int32u WAVE_adtl=0x6164746C;
const int32u WAVE_adtl_labl=0x6C61626C;
const int32u WAVE_adtl_ltxt=0x6C747874;
const int32u WAVE_adtl_note=0x6E6F7465;
const int32u WAVE_axml=0x61786D6C;
const int32u WAVE_bext=0x62657874;
const int32u WAVE_bxml=0x62786D6C;
const int32u WAVE_cue_=0x63756520;
const int32u WAVE_data=0x64617461;
const int32u WAVE_dbmd=0x64626D64;
const int32u WAVE_ds64=0x64733634;
const int32u WAVE_fact=0x66616374;
const int32u WAVE_fmt_=0x666D7420;
const int32u WAVE_ID3_=0x49443320;
const int32u WAVE_id3_=0x69643320;
const int32u WAVE_INFO=0x494E464F;
const int32u WAVE_iXML=0x69584D4C;
const int32u WAVE_mext=0x6D657874;
const int32u wave=0x77617665;
const int32u wave_data=0x64617461;
const int32u wave_fmt_=0x666D7420;
const int32u W3DI=0x57334449;
#define UUID(NAME, PART1, PART2, PART3, PART4, PART5) \
const int64u NAME =((int64u(0x##PART1))&0xFF)<<56 | ((int64u(0x##PART1)>>8)&0xFF)<<48 | ((int64u(0x##PART1)>>16)&0xFF)<<40 | ((int64u(0x##PART1)>>24)&0xFF)<<32 | ((int64u(0x##PART2))&0xFF)<<24 | ((int64u(0x##PART2)>>8)&0xFF)<<16 | ((int64u(0x##PART3))&0xFF)<<8 | ((int64u(0x##PART3)>>8)&0xFF); \
const int64u NAME##2=0x##PART4##PART5##ULL; \
UUID(QLCM_QCELP1, 5E7F6D41, B115, 11D0, BA91, 00805FB4B97E)
UUID(QLCM_QCELP2, 5E7F6D42, B115, 11D0, BA91, 00805FB4B97E)
UUID(QLCM_EVRC, E689D48D, 9076, 46B5, 91EF, 736A5100CEB4)
UUID(QLCM_SMV, 8D7C2B75, A797, ED49, 985E, D53C8CC75F84)
}
//***************************************************************************
// Format
//***************************************************************************
//---------------------------------------------------------------------------
void File_Riff::Data_Parse()
{
//Alignement specific
if (Alignement_ExtraByte<=Element_Size)
Element_Size-=Alignement_ExtraByte;
DATA_BEGIN
LIST(AIFC)
ATOM_BEGIN
ATOM(AIFC_COMM)
ATOM(AIFC_COMT)
ATOM(AIFC_FVER)
ATOM(AIFC_SSND)
ATOM_DEFAULT(AIFC_xxxx)
ATOM_END_DEFAULT
LIST(AIFF)
ATOM_BEGIN
ATOM(AIFF_COMM)
ATOM(AIFF_COMT)
ATOM(AIFF_ID3_)
LIST_SKIP(AIFF_SSND)
ATOM_DEFAULT(AIFF_xxxx)
ATOM_END_DEFAULT
LIST(AVI_)
ATOM_BEGIN
ATOM(AVI__Cr8r);
ATOM(AVI__cset)
LIST(AVI__exif)
ATOM_DEFAULT_ALONE(AVI__exif_xxxx)
LIST(AVI__goog)
ATOM_BEGIN
ATOM(AVI__goog_GDAT)
ATOM_END
ATOM(AVI__GMET)
LIST(AVI__hdlr)
ATOM_BEGIN
ATOM(AVI__hdlr_avih)
ATOM(AVI__hdlr_JUNK)
LIST(AVI__hdlr_strl)
ATOM_BEGIN
ATOM(AVI__hdlr_strl_indx)
ATOM(AVI__hdlr_strl_JUNK)
ATOM(AVI__hdlr_strl_strd)
ATOM(AVI__hdlr_strl_strf)
ATOM(AVI__hdlr_strl_strh)
ATOM(AVI__hdlr_strl_strn)
ATOM(AVI__hdlr_strl_vprp)
ATOM_END
LIST(AVI__hdlr_odml)
ATOM_BEGIN
ATOM(AVI__hdlr_odml_dmlh)
ATOM_END
ATOM(AVI__hdlr_ON2h)
LIST(AVI__INFO)
ATOM_BEGIN
ATOM(AVI__INFO_IID3)
ATOM(AVI__INFO_ILYC)
ATOM(AVI__INFO_IMP3)
ATOM(AVI__INFO_JUNK)
ATOM_DEFAULT(AVI__INFO_xxxx)
ATOM_END_DEFAULT
ATOM_DEFAULT(AVI__hdlr_xxxx)
ATOM_END_DEFAULT
ATOM(AVI__idx1)
LIST(AVI__INFO)
ATOM_BEGIN
ATOM(AVI__INFO_IID3)
ATOM(AVI__INFO_ILYC)
ATOM(AVI__INFO_IMP3)
ATOM(AVI__INFO_JUNK)
ATOM_DEFAULT(AVI__INFO_xxxx)
ATOM_END_DEFAULT
ATOM(AVI__JUNK)
ATOM(AVI__MD5_)
LIST(AVI__movi)
ATOM_BEGIN
LIST(AVI__movi_rec_)
ATOM_DEFAULT_ALONE(AVI__movi_xxxx)
ATOM_DEFAULT(AVI__movi_xxxx)
ATOM_END_DEFAULT
ATOM(AVI__PrmA);
LIST(AVI__Tdat)
ATOM_BEGIN
ATOM(AVI__Tdat_rn_A)
ATOM(AVI__Tdat_rn_O)
ATOM(AVI__Tdat_tc_A)
ATOM(AVI__Tdat_tc_O)
ATOM_END
ATOM_DEFAULT(AVI__xxxx)
ATOM_END_DEFAULT
LIST(AVIX) //OpenDML
ATOM_BEGIN
ATOM(AVIX_idx1)
LIST(AVIX_movi)
ATOM_BEGIN
LIST(AVIX_movi_rec_)
ATOM_DEFAULT_ALONE(AVIX_movi_xxxx)
ATOM_DEFAULT(AVIX_movi_xxxx)
ATOM_END_DEFAULT
ATOM_END
ATOM_PARTIAL(CADP)
LIST(CDDA)
ATOM_BEGIN
ATOM(CDDA_fmt_)
ATOM_END
ATOM_PARTIAL(CMJP)
ATOM(CMP4)
ATOM(IDVX)
LIST(INDX)
ATOM_DEFAULT_ALONE(INDX_xxxx)
LIST_SKIP(JUNK)
LIST_SKIP(menu)
ATOM(MThd)
LIST_SKIP(MTrk)
LIST_SKIP(PAL_)
LIST(QLCM)
ATOM_BEGIN
ATOM(QLCM_fmt_)
ATOM_END
#if defined(MEDIAINFO_GXF_YES)
LIST(rcrd)
ATOM_BEGIN
ATOM(rcrd_desc)
LIST(rcrd_fld_)
ATOM_BEGIN
LIST(rcrd_fld__anc_)
ATOM_BEGIN
ATOM(rcrd_fld__anc__pos_)
ATOM(rcrd_fld__anc__pyld)
ATOM_END
ATOM(rcrd_fld__finf)
ATOM_END
ATOM_END
#endif //defined(MEDIAINFO_GXF_YES)
LIST_SKIP(RDIB)
LIST_SKIP(RMID)
LIST_SKIP(RMMP)
LIST(RMP3)
ATOM_BEGIN
LIST(RMP3_data)
break;
LIST(RMP3_INFO)
ATOM_BEGIN
ATOM(RMP3_INFO_IID3)
ATOM(RMP3_INFO_ILYC)
ATOM(RMP3_INFO_IMP3)
ATOM(RMP3_INFO_JUNK)
ATOM_DEFAULT(RMP3_INFO_xxxx)
ATOM_END_DEFAULT
ATOM_END
ATOM(SMV0)
ATOM(SMV0_xxxx)
ATOM(W3DI)
LIST(WAVE)
ATOM_BEGIN
ATOM(WAVE__pmx)
LIST(WAVE_adtl)
ATOM_BEGIN
ATOM(WAVE_adtl_labl)
ATOM(WAVE_adtl_ltxt)
ATOM(WAVE_adtl_note)
ATOM_END
LIST(WAVE_axml)
break;
ATOM(WAVE_bext)
LIST(WAVE_bxml)
break;
LIST(WAVE_data)
break;
ATOM(WAVE_cue_)
ATOM(WAVE_dbmd)
ATOM(WAVE_ds64)
ATOM(WAVE_fact)
ATOM(WAVE_fmt_)
ATOM(WAVE_ID3_)
ATOM(WAVE_id3_)
LIST(WAVE_INFO)
ATOM_DEFAULT_ALONE(WAVE_INFO_xxxx)
ATOM(WAVE_iXML)
ATOM(WAVE_mext)
ATOM_END
LIST(wave)
ATOM_BEGIN
LIST(wave_data)
break;
ATOM(wave_fmt_)
ATOM_END
DATA_END
if (Alignement_ExtraByte)
{
Element_Size+=Alignement_ExtraByte;
if (Element_Offset+Alignement_ExtraByte==Element_Size)
Skip_XX(Alignement_ExtraByte, "Alignement");
}
}
//***************************************************************************
// Elements
//***************************************************************************
//---------------------------------------------------------------------------
void File_Riff::AIFC()
{
Data_Accept("AIFF Compressed");
Element_Name("AIFF Compressed");
//Filling
Fill(Stream_General, 0, General_Format, "AIFF");
Stream_Prepare(Stream_Audio);
Kind=Kind_Aiff;
#if MEDIAINFO_EVENTS
StreamIDs_Width[0]=0;
#endif //MEDIAINFO_EVENTS
}
//---------------------------------------------------------------------------
void File_Riff::AIFC_COMM()
{
AIFF_COMM();
}
//---------------------------------------------------------------------------
void File_Riff::AIFC_COMT()
{
AIFF_COMT();
}
//---------------------------------------------------------------------------
void File_Riff::AIFC_FVER()
{
Element_Name("Format Version");
//Parsing
Skip_B4( "Version");
}
//---------------------------------------------------------------------------
void File_Riff::AIFC_SSND()
{
AIFF_SSND();
}
//---------------------------------------------------------------------------
void File_Riff::AIFC_xxxx()
{
AIFF_xxxx();
}
//---------------------------------------------------------------------------
void File_Riff::AIFF()
{
Data_Accept("AIFF");
Element_Name("AIFF");
//Filling
Fill(Stream_General, 0, General_Format, "AIFF");
Stream_Prepare(Stream_Audio);
Kind=Kind_Aiff;
#if MEDIAINFO_EVENTS
StreamIDs_Width[0]=0;
#endif //MEDIAINFO_EVENTS
}
//---------------------------------------------------------------------------
void File_Riff::AIFF_COMM()
{
Element_Name("Common");
int32u numSampleFrames;
int16u numChannels, sampleSize;
float80 sampleRate80;
float64 sampleRate;
//Parsing
Get_B2 (numChannels, "numChannels");
Get_B4 (numSampleFrames, "numSampleFrames");
Get_B2 (sampleSize, "sampleSize");
Get_BF10(sampleRate80, "sampleRate");
sampleRate=(float64)sampleRate80;
if (Data_Remain()) //AIFC
{
int32u compressionType;
Get_C4 (compressionType, "compressionType");
Skip_PA( "compressionName");
//Filling
CodecID_Fill(Ztring().From_CC4(compressionType), Stream_Audio, StreamPos_Last, InfoCodecID_Format_Mpeg4);
Fill(Stream_Audio, StreamPos_Last, Audio_Codec, Ztring().From_CC4(compressionType));
}
else
{
//Filling
Fill(Stream_Audio, StreamPos_Last, Audio_Format, "PCM");
Fill(Stream_Audio, StreamPos_Last, Audio_Codec, "PCM");
}
//Filling
Fill(Stream_Audio, StreamPos_Last, Audio_Channel_s_, numChannels);
Fill(Stream_Audio, StreamPos_Last, Audio_BitDepth, sampleSize);
if (sampleRate)
Fill(Stream_Audio, StreamPos_Last, Audio_Duration, numSampleFrames/sampleRate*1000, 0);
Fill(Stream_Audio, StreamPos_Last, Audio_SamplingRate, sampleRate, 0);
//Compute the current codec ID
Element_Code=(int64u)-1;
Stream_ID=(int32u)-1;
stream_Count=1;
//Specific cases
#if defined(MEDIAINFO_PCM_YES) || defined(MEDIAINFO_DTS_YES) || defined(MEDIAINFO_SMPTEST0337_YES)
stream& StreamItem=Stream[Stream_ID];
Ztring Codec=Retrieve(Stream_Audio, StreamPos_Last, Audio_CodecID);
Parser_Pcm(StreamItem, numChannels, sampleSize, sampleSize, sampleRate, (Codec.empty() || Codec==__T("NONE"))?'B':'\0');
#endif
#if MEDIAINFO_DEMUX
unsigned int ComputedBlockAlign=numChannels*sampleSize/8;
if (ComputedBlockAlign<0x10000)
{
BlockAlign=(int16u)ComputedBlockAlign;
AvgBytesPerSec=(int32u)float64_int64s(ComputedBlockAlign*sampleRate);
}
#endif //MEDIAINFO_DEMUX
Element_Code=(int64u)-1;
Open_Buffer_Init_All();
}
//---------------------------------------------------------------------------
void File_Riff::AIFF_COMT()
{
//Parsing
int16u numComments;
Get_B2(numComments, "numComments");
for (int16u Pos=0; Pos<=numComments; Pos++)
{
Ztring text;
int16u count;
Element_Begin1("Comment");
Skip_B4( "timeStamp");
Skip_B4( "marker");
Get_B2 (count, "count");
count+=count%1; //always even
Get_Local(count, text, "text");
Element_End0();
//Filling
Fill(Stream_General, 0, General_Comment, text);
}
}
//---------------------------------------------------------------------------
void File_Riff::AIFF_SSND()
{
Skip_B4( "offset"); //TODO: support offset
Skip_B4( "blockSize");
Buffer_DataToParse_Begin+=Element_Offset;
WAVE_data();
}
//---------------------------------------------------------------------------
void File_Riff::AIFF_SSND_Continue()
{
WAVE_data_Continue();
}
//---------------------------------------------------------------------------
void File_Riff::AIFF_xxxx()
{
#define ELEMENT_CASE(_ELEMENT, _NAME) \
case Elements::_ELEMENT : Element_Name(_NAME); Name=_NAME; break;
//Known?
std::string Name;
switch(Element_Code)
{
ELEMENT_CASE(AIFF__c__, "Copyright");
ELEMENT_CASE(AIFF_ANNO, "Comment");
ELEMENT_CASE(AIFF_AUTH, "Performer");
ELEMENT_CASE(AIFF_NAME, "Title");
default : Skip_XX(Element_Size, "Unknown");
return;
}
//Parsing
Ztring text;
Get_Local(Element_Size, text, "text");
//Filling
Fill(Stream_General, 0, Name.c_str(), text);
}
//---------------------------------------------------------------------------
void File_Riff::AVI_()
{
Element_Name("AVI");
//Test if there is only one AVI chunk
if (Status[IsAccepted])
{
Element_Info1("Problem: 2 AVI chunks, this is not normal");
Skip_XX(Element_TotalSize_Get(), "Data");
return;
}
Data_Accept("AVI");
//Filling
Fill(Stream_General, 0, General_Format, "AVI");
Kind=Kind_Avi;
//Configuration
Buffer_MaximumSize=64*1024*1024; //Some big frames are possible (e.g YUV 4:2:2 10 bits 1080p)
}
//---------------------------------------------------------------------------
void File_Riff::AVI__Cr8r()
{
Element_Name("Adobe Premiere Cr8r");
//Parsing
Skip_C4( "FourCC");
Skip_B4( "Size");
Skip_XX(Element_Size-Element_Offset, "Unknown");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__cset()
{
Element_Name("Regional settings");
//Parsing
Skip_L2( "CodePage"); //TODO: take a look about IBM/MS RIFF/MCI Specification 1.0
Skip_L2( "CountryCode");
Skip_L2( "LanguageCode");
Skip_L2( "Dialect");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__exif()
{
Element_Name("Exif (Exchangeable Image File Format)");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__exif_xxxx()
{
Element_Name("Value");
//Parsing
Ztring Value;
Get_Local(Element_Size, Value, "Value");
//Filling
switch (Element_Code)
{
case Elements::AVI__exif_ecor : Fill(Stream_General, 0, "Make", Value); break;
case Elements::AVI__exif_emdl : Fill(Stream_General, 0, "Model", Value); break;
case Elements::AVI__exif_emnt : Fill(Stream_General, 0, "MakerNotes", Value); break;
case Elements::AVI__exif_erel : Fill(Stream_General, 0, "RelatedImageFile", Value); break;
case Elements::AVI__exif_etim : Fill(Stream_General, 0, "Written_Date", Value); break;
case Elements::AVI__exif_eucm : Fill(Stream_General, 0, General_Comment, Value); break;
case Elements::AVI__exif_ever : break; //Exif version
default: Fill(Stream_General, 0, Ztring().From_CC4((int32u)Element_Code).To_Local().c_str(), Value);
}
}
//---------------------------------------------------------------------------
void File_Riff::AVI__goog()
{
Element_Name("Google specific");
//Filling
Fill(Stream_General, 0, General_Format, "Google Video", Unlimited, true, true);
}
//---------------------------------------------------------------------------
void File_Riff::AVI__goog_GDAT()
{
Element_Name("Google datas");
}
//---------------------------------------------------------------------------
// Google Metadata
//
void File_Riff::AVI__GMET()
{
Element_Name("Google Metadatas");
//Parsing
Ztring Value; Value.From_UTF8((const char*)(Buffer+Buffer_Offset+0), (size_t)Element_Size);
ZtringListList List;
List.Separator_Set(0, __T("\n"));
List.Separator_Set(1, __T(":"));
List.Max_Set(1, 2);
List.Write(Value);
//Details
#if MEDIAINFO_TRACE
if (Config_Trace_Level)
{
//for (size_t Pos=0; Pos<List.size(); Pos++)
// Details_Add_Info(Pos, List(Pos, 0).To_Local().c_str(), List(Pos, 1));
}
#endif //MEDIAINFO_TRACE
//Filling
for (size_t Pos=0; Pos<List.size(); Pos++)
{
if (List(Pos, 0)==__T("title")) Fill(Stream_General, 0, General_Title, List(Pos, 1));
if (List(Pos, 0)==__T("description")) Fill(Stream_General, 0, General_Title_More, List(Pos, 1));
if (List(Pos, 0)==__T("url")) Fill(Stream_General, 0, General_Title_Url, List(Pos, 1));
if (List(Pos, 0)==__T("docid")) Fill(Stream_General, 0, General_UniqueID, List(Pos, 1));
}
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr()
{
Element_Name("AVI Header");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_avih()
{
Element_Name("File header");
//Parsing
int32u MicrosecPerFrame, Flags;
Get_L4 (MicrosecPerFrame, "MicrosecPerFrame");
Skip_L4( "MaxBytesPerSec");
Skip_L4( "PaddingGranularity");
Get_L4 (Flags, "Flags");
Skip_Flags(Flags, 4, "HasIndex");
Skip_Flags(Flags, 5, "MustUseIndex");
Skip_Flags(Flags, 8, "IsInterleaved");
Skip_Flags(Flags, 9, "UseCKTypeToFindKeyFrames");
Skip_Flags(Flags, 11, "TrustCKType");
Skip_Flags(Flags, 16, "WasCaptureFile");
Skip_Flags(Flags, 17, "Copyrighted");
Get_L4 (avih_TotalFrame, "TotalFrames");
Skip_L4( "InitialFrames");
Skip_L4( "StreamsCount");
Skip_L4( "SuggestedBufferSize");
Skip_L4( "Width");
Skip_L4( "Height");
Skip_L4( "Reserved");
Skip_L4( "Reserved");
Skip_L4( "Reserved");
Skip_L4( "Reserved");
if(Element_Offset<Element_Size)
Skip_XX(Element_Size-Element_Offset, "Unknown");
//Filling
if (MicrosecPerFrame>0)
avih_FrameRate=1000000.0/MicrosecPerFrame;
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_JUNK()
{
Element_Name("Garbage");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_odml()
{
Element_Name("OpenDML");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_odml_dmlh()
{
Element_Name("OpenDML Header");
//Parsing
Get_L4(dmlh_TotalFrame, "GrandFrames");
if (Element_Offset<Element_Size)
Skip_XX(Element_Size-Element_Offset, "Unknown");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_ON2h()
{
Element_Name("On2 header");
//Parsing
Skip_XX(Element_Size, "Unknown");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl()
{
Element_Name("Stream info");
Element_Info1(stream_Count);
//Clean up
StreamKind_Last=Stream_Max;
StreamPos_Last=(size_t)-1;
//Compute the current codec ID
Stream_ID=(('0'+stream_Count/10)*0x01000000
+('0'+stream_Count )*0x00010000);
stream_Count++;
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_indx()
{
Element_Name("Index");
int32u Entry_Count, ChunkId;
int16u LongsPerEntry;
int8u IndexType, IndexSubType;
Get_L2 (LongsPerEntry, "LongsPerEntry"); //Size of each entry in aIndex array
Get_L1 (IndexSubType, "IndexSubType");
Get_L1 (IndexType, "IndexType");
Get_L4 (Entry_Count, "EntriesInUse"); //Index of first unused member in aIndex array
Get_C4 (ChunkId, "ChunkId"); //FCC of what is indexed
//Depends of size of structure...
switch (IndexType)
{
case 0x01 : //AVI_INDEX_OF_CHUNKS
switch (IndexSubType)
{
case 0x00 : AVI__hdlr_strl_indx_StandardIndex(Entry_Count, ChunkId); break;
case 0x01 : AVI__hdlr_strl_indx_FieldIndex(Entry_Count, ChunkId); break; //AVI_INDEX_2FIELD
default: Skip_XX(Element_Size-Element_Offset, "Unknown");
}
break;
case 0x0 : //AVI_INDEX_OF_INDEXES
switch (IndexSubType)
{
case 0x00 :
case 0x01 : AVI__hdlr_strl_indx_SuperIndex(Entry_Count, ChunkId); break; //AVI_INDEX_2FIELD
default: Skip_XX(Element_Size-Element_Offset, "Unknown");
}
break;
default: Skip_XX(Element_Size-Element_Offset, "Unknown");
}
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_indx_StandardIndex(int32u Entry_Count, int32u ChunkId)
{
Element_Name("Standard Index");
//Parsing
int64u BaseOffset, StreamSize=0;
Get_L8 (BaseOffset, "BaseOffset");
Skip_L4( "Reserved3");
for (int32u Pos=0; Pos<Entry_Count; Pos++)
{
//Is too slow
/*
Element_Begin1("Index");
int32u Offset, Size;
Get_L4 (Offset, "Offset"); //BaseOffset + this is absolute file offset
Get_L4 (Size, "Size"); //Bit 31 is set if this is NOT a keyframe
Element_Info1(Size&0x7FFFFFFF);
if (Size)
Element_Info1("KeyFrame");
Element_End0();
*/
//Faster method
if (Element_Offset+8>Element_Size)
break; //Malformed index
int32u Offset=LittleEndian2int32u(Buffer+Buffer_Offset+(size_t)Element_Offset );
int32u Size =LittleEndian2int32u(Buffer+Buffer_Offset+(size_t)Element_Offset+4)&0x7FFFFFFF;
Element_Offset+=8;
//Stream Position and size
if (Pos<300 || Config->ParseSpeed>=1.0)
{
stream_structure& Stream_Structure_Item=Stream_Structure[BaseOffset+Offset-8];
Stream_Structure_Item.Name=ChunkId&0xFFFF0000;
Stream_Structure_Item.Size=Size;
}
StreamSize+=(Size&0x7FFFFFFF);
Stream[ChunkId&0xFFFF0000].PacketCount++;
//Interleaved
if (Pos== 0 && (ChunkId&0xFFFF0000)==0x30300000 && Interleaved0_1 ==0)
Interleaved0_1 =BaseOffset+Offset-8;
if (Pos==Entry_Count/10 && (ChunkId&0xFFFF0000)==0x30300000 && Interleaved0_10==0)
Interleaved0_10=BaseOffset+Offset-8;
if (Pos== 0 && (ChunkId&0xFFFF0000)==0x30310000 && Interleaved1_1 ==0)
Interleaved1_1 =BaseOffset+Offset-8;
if (Pos==Entry_Count/10 && (ChunkId&0xFFFF0000)==0x30310000 && Interleaved1_10==0)
Interleaved1_10=BaseOffset+Offset-8;
}
Stream[ChunkId&0xFFFF0000].StreamSize+=StreamSize;
if (Element_Offset<Element_Size)
Skip_XX(Element_Size-Element_Offset, "Garbage");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_indx_FieldIndex(int32u Entry_Count, int32u)
{
Element_Name("Field Index");
//Parsing
Skip_L8( "Offset");
Skip_L4( "Reserved2");
for (int32u Pos=0; Pos<Entry_Count; Pos++)
{
Element_Begin1("Index");
Skip_L4( "Offset"); //BaseOffset + this is absolute file offset
Skip_L4( "Size"); //Bit 31 is set if this is NOT a keyframe
Skip_L4( "OffsetField2"); //Offset to second field
Element_End0();
}
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_indx_SuperIndex(int32u Entry_Count, int32u ChunkId)
{
Element_Name("Index of Indexes");
//Parsing
int64u Offset;
Skip_L4( "Reserved0");
Skip_L4( "Reserved1");
Skip_L4( "Reserved2");
stream& StreamItem = Stream[Stream_ID];
for (int32u Pos=0; Pos<Entry_Count; Pos++)
{
int32u Duration;
Element_Begin1("Index of Indexes");
Get_L8 (Offset, "Offset");
Skip_L4( "Size"); //Size of index chunk at this offset
Get_L4 (Duration, "Duration"); //time span in stream ticks
Index_Pos[Offset]=ChunkId;
StreamItem.indx_Duration+=Duration;
Element_End0();
}
//We needn't anymore Old version
NeedOldIndex=false;
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_JUNK()
{
Element_Name("Garbage");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strd()
{
Element_Name("Stream datas");
//Parsing
Skip_XX(Element_Size, "Unknown");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strf()
{
Element_Name("Stream format");
//Parse depending of kind of stream
stream& StreamItem = Stream[Stream_ID];
switch (StreamItem.fccType)
{
case Elements::AVI__hdlr_strl_strh_auds : AVI__hdlr_strl_strf_auds(); break;
case Elements::AVI__hdlr_strl_strh_iavs : AVI__hdlr_strl_strf_iavs(); break;
case Elements::AVI__hdlr_strl_strh_mids : AVI__hdlr_strl_strf_mids(); break;
case Elements::AVI__hdlr_strl_strh_txts : AVI__hdlr_strl_strf_txts(); break;
case Elements::AVI__hdlr_strl_strh_vids : AVI__hdlr_strl_strf_vids(); break;
default : Element_Info1("Unknown");
}
//Registering stream
StreamItem.StreamKind=StreamKind_Last;
StreamItem.StreamPos=StreamPos_Last;
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strf_auds()
{
Element_Info1("Audio");
//Parsing
#if !MEDIAINFO_DEMUX
int32u AvgBytesPerSec;
#endif //!MEDIAINFO_DEMUX
int16u FormatTag, Channels;
BitsPerSample=0;
Get_L2 (FormatTag, "FormatTag");
Get_L2 (Channels, "Channels");
Get_L4 (SamplesPerSec, "SamplesPerSec");
Get_L4 (AvgBytesPerSec, "AvgBytesPerSec");
Get_L2 (BlockAlign, "BlockAlign");
if (Element_Offset+2<=Element_Size)
Get_L2 (BitsPerSample, "BitsPerSample");
if (FormatTag==1) //Only for PCM
{
//Coherancy
if (BitsPerSample && SamplesPerSec*BitsPerSample*Channels/8==AvgBytesPerSec*8)
AvgBytesPerSec*=8; //Found in one file. TODO: Provide information to end user about such error
//Computing of missing value
if (!BitsPerSample && AvgBytesPerSec && SamplesPerSec && Channels)
BitsPerSample=(int16u)(AvgBytesPerSec*8/SamplesPerSec/Channels);
}
//Filling
Stream_Prepare(Stream_Audio);
stream& StreamItem = Stream[Stream_ID];
StreamItem.Compression=FormatTag;
Ztring Codec; Codec.From_Number(FormatTag, 16);
Codec.MakeUpperCase();
CodecID_Fill(Codec, Stream_Audio, StreamPos_Last, InfoCodecID_Format_Riff);
Fill(Stream_Audio, StreamPos_Last, Audio_Codec, Codec); //May be replaced by codec parser
Fill(Stream_Audio, StreamPos_Last, Audio_Codec_CC, Codec);
if (Channels)
{
Ztring Format=MediaInfoLib::Config.CodecID_Get(Stream_Audio, InfoCodecID_Format_Riff, Codec);
if (!(Channels==5 && (Format==__T("AC-3") || Format==__T("DTS")))) //Lot of 5.1 streams fill 5 here, but we don't know if it is 5.1 or 5.0, so we let info from container blank. TODO: streams without crosscheck error should be only with 5 or 6 channels
Fill(Stream_Audio, StreamPos_Last, Audio_Channel_s_, Channels);
}
if (SamplesPerSec)
Fill(Stream_Audio, StreamPos_Last, Audio_SamplingRate, SamplesPerSec);
if (AvgBytesPerSec)
Fill(Stream_Audio, StreamPos_Last, Audio_BitRate, AvgBytesPerSec*8);
if (BitsPerSample)
Fill(Stream_Audio, StreamPos_Last, Audio_BitDepth, BitsPerSample);
StreamItem.AvgBytesPerSec=AvgBytesPerSec; //Saving bitrate for each stream
if (SamplesPerSec && TimeReference!=(int64u)-1)
{
Fill(Stream_Audio, 0, Audio_Delay, float64_int64s(((float64)TimeReference)*1000/SamplesPerSec));
Fill(Stream_Audio, 0, Audio_Delay_Source, "Container (bext)");
}
//Creating the parser
if (0);
#if defined(MEDIAINFO_MPEGA_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Audio, InfoCodecID_Format_Riff, Codec)==__T("MPEG Audio"))
{
File_Mpega* Parser=new File_Mpega;
Parser->CalculateDelay=true;
Parser->ShouldContinueParsing=true;
StreamItem.Parsers.push_back(Parser);
}
#endif
#if defined(MEDIAINFO_AC3_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Audio, InfoCodecID_Format_Riff, Codec)==__T("AC-3"))
{
File_Ac3* Parser=new File_Ac3;
Parser->Frame_Count_Valid=2;
Parser->CalculateDelay=true;
Parser->ShouldContinueParsing=true;
StreamItem.Parsers.push_back(Parser);
}
#endif
#if defined(MEDIAINFO_DTS_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Audio, InfoCodecID_Format_Riff, Codec)==__T("DTS"))
{
File_Dts* Parser=new File_Dts;
Parser->Frame_Count_Valid=2;
Parser->ShouldContinueParsing=true;
StreamItem.Parsers.push_back(Parser);
}
#endif
#if defined(MEDIAINFO_AAC_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Audio, InfoCodecID_Format_Riff, Codec)==__T("AAC"))
{
File_Aac* Parser=new File_Aac;
Parser->Mode=File_Aac::Mode_ADTS;
Parser->Frame_Count_Valid=1;
Parser->ShouldContinueParsing=true;
StreamItem.Parsers.push_back(Parser);
}
#endif
#if defined(MEDIAINFO_PCM_YES) || defined(MEDIAINFO_DTS_YES) || defined(MEDIAINFO_SMPTEST0337_YES)
if (MediaInfoLib::Config.CodecID_Get(Stream_Audio, InfoCodecID_Format_Riff, Codec) == __T("PCM"))
{
Parser_Pcm(StreamItem, Channels, BitsPerSample, BitsPerSample, SamplesPerSec);
}
#endif
#if defined(MEDIAINFO_ADPCM_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Audio, InfoCodecID_Format_Riff, Codec)==__T("ADPCM"))
{
//Creating the parser
File_Adpcm MI;
MI.Codec=Codec;
//Parsing
Open_Buffer_Init(&MI);
Open_Buffer_Continue(&MI, 0);
//Filling
Finish(&MI);
Merge(MI, StreamKind_Last, 0, StreamPos_Last);
}
#endif
#if defined(MEDIAINFO_OGG_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Audio, InfoCodecID_Format_Riff, Codec)==__T("Vorbis")
&& FormatTag!=0x566F) //0x566F has config in this chunk
{
File_Ogg* Parser=new File_Ogg;
Parser->ShouldContinueParsing=true;
StreamItem.Parsers.push_back(Parser);
}
#endif
Open_Buffer_Init_All();
//Options
if (Element_Offset+2>Element_Size)
return; //No options
//Parsing
int16u Option_Size;
Get_L2 (Option_Size, "cbSize");
//Filling
if (Option_Size>0)
{
if (0);
else if (MediaInfoLib::Config.CodecID_Get(Stream_Audio, InfoCodecID_Format_Riff, Codec)==__T("MPEG Audio"))
{
if (Option_Size==12)
AVI__hdlr_strl_strf_auds_Mpega();
else
Skip_XX(Option_Size, "MPEG Audio - Uknown");
}
else if (Codec==__T("AAC") || Codec==__T("FF") || Codec==__T("8180"))
AVI__hdlr_strl_strf_auds_Aac();
else if (FormatTag==0x566F) //Vorbis with Config in this chunk
AVI__hdlr_strl_strf_auds_Vorbis();
else if (FormatTag==0x6750) //Vorbis with Config in this chunk
AVI__hdlr_strl_strf_auds_Vorbis2();
else if (FormatTag==0xFFFE) //Extensible Wave
AVI__hdlr_strl_strf_auds_ExtensibleWave(BitsPerSample);
else if (Element_Offset+Option_Size<=Element_Size)
Skip_XX(Option_Size, "Unknown");
else if (Element_Offset!=Element_Size)
Skip_XX(Element_Size-Element_Offset, "Error");
}
if (Retrieve(Stream_Audio, 0, Audio_Format)==__T("PCM"))
{
//BlockAlign
int32u ComputedBlockAlign=Channels*BitsPerSample/8;
if (BlockAlign && BlockAlign==(int16u)-1)
{
if (BlockAlign!=ComputedBlockAlign)
Fill(Stream_Audio, StreamKind_Last, "BlockAlignIssue", Ztring::ToZtring(BlockAlign)+__T(", expected ")+Ztring::ToZtring(ComputedBlockAlign));
}
else // For WAVE data
BlockAlign=ComputedBlockAlign;
}
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strf_auds_Mpega()
{
//Parsing
Element_Begin1("MPEG Audio options");
Skip_L2( "ID");
Skip_L4( "Flags");
Skip_L2( "BlockSize");
Skip_L2( "FramesPerBlock");
Skip_L2( "CodecDelay");
Element_End0();
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strf_auds_Aac()
{
//Parsing
Element_Begin1("AAC options");
#if defined(MEDIAINFO_AAC_YES)
File_Aac* MI=new File_Aac();
MI->Mode=File_Aac::Mode_AudioSpecificConfig;
Open_Buffer_Init(MI);
Open_Buffer_Continue(MI);
Finish(MI);
Merge(*MI, StreamKind_Last, 0, StreamPos_Last);
delete MI; //MI=NULL;
#else //MEDIAINFO_MPEG4_YES
Skip_XX(Element_Size-Element_Offset, "(AudioSpecificConfig)");
#endif
Element_End0();
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strf_auds_Vorbis()
{
//Parsing
Element_Begin1("Vorbis options");
#if defined(MEDIAINFO_OGG_YES)
File_Ogg_SubElement MI;
Open_Buffer_Init(&MI);
Element_Begin1("Element sizes");
//All elements parsing, except last one
std::vector<size_t> Elements_Size;
size_t Elements_TotalSize=0;
int8u Elements_Count;
Get_L1(Elements_Count, "Element count");
Elements_Size.resize(Elements_Count+1); //+1 for the last block
for (int8u Pos=0; Pos<Elements_Count; Pos++)
{
int8u Size;
Get_L1(Size, "Size");
Elements_Size[Pos]=Size;
Elements_TotalSize+=Size;
}
Element_End0();
if (Element_Offset+Elements_TotalSize>Element_Size)
return;
//Adding the last block
Elements_Size[Elements_Count]=(size_t)(Element_Size-(Element_Offset+Elements_TotalSize));
Elements_Count++;
//Parsing blocks
for (int8u Pos=0; Pos<Elements_Count; Pos++)
{
Open_Buffer_Continue(&MI, Elements_Size[Pos]);
Open_Buffer_Continue(&MI, 0);
Element_Offset+=Elements_Size[Pos];
}
//Finalizing
Finish(&MI);
Merge(MI, StreamKind_Last, 0, StreamPos_Last);
Clear(Stream_Audio, StreamPos_Last, Audio_BitDepth); //Resolution is not valid for Vorbis
Element_Show();
#else //MEDIAINFO_MPEG4_YES
Skip_XX(Element_Size-Element_Offset, "(Vorbis headers)");
#endif
Element_End0();
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strf_auds_Vorbis2()
{
//Parsing
Skip_XX(8, "Vorbis Unknown");
Element_Begin1("Vorbis options");
#if defined(MEDIAINFO_OGG_YES)
stream& StreamItem = Stream[Stream_ID];
Open_Buffer_Continue(StreamItem.Parsers[0]);
Open_Buffer_Continue(StreamItem.Parsers[0], 0);
Finish(StreamItem.Parsers[0]);
Merge(*StreamItem.Parsers[0], StreamKind_Last, 0, StreamPos_Last);
Element_Show();
#else //MEDIAINFO_MPEG4_YES
Skip_XX(Element_Size-Element_Offset, "(Vorbis headers)");
#endif
Element_End0();
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strf_auds_ExtensibleWave(int16u BitsPerSample)
{
//Parsing
int128u SubFormat;
int32u ChannelMask;
int16u ValidBitsPerSample;
Get_L2 (ValidBitsPerSample, "ValidBitsPerSample / SamplesPerBlock");
Get_L4 (ChannelMask, "ChannelMask");
Get_GUID(SubFormat, "SubFormat");
FILLING_BEGIN();
if ((SubFormat.hi&0x0000FFFFFFFFFFFFLL)==0x0000000000001000LL && SubFormat.lo==0x800000AA00389B71LL)
{
int16u LegacyCodecID=(int16u)((((SubFormat.hi>>48)&0xFF)<<8) | (SubFormat.hi>>56)); // It is Little Endian
CodecID_Fill(Ztring().From_Number(LegacyCodecID, 16), Stream_Audio, StreamPos_Last, InfoCodecID_Format_Riff);
Fill(Stream_Audio, StreamPos_Last, Audio_CodecID, Ztring().From_GUID(SubFormat), true);
Fill(Stream_Audio, StreamPos_Last, Audio_Codec, MediaInfoLib::Config.Codec_Get(Ztring().From_Number(LegacyCodecID, 16)), true);
//Creating the parser
stream& StreamItem=Stream[Stream_ID];
if (0);
#if defined(MEDIAINFO_PCM_YES) || defined(MEDIAINFO_DTS_YES) || defined(MEDIAINFO_SMPTEST0337_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Audio, InfoCodecID_Format_Riff, Ztring().From_Number(LegacyCodecID, 16))==__T("PCM"))
{
int16u Channels=Retrieve(Stream_Audio, StreamPos_Last, "Channel(s)").To_int16u();
Parser_Pcm(StreamItem, Channels, BitsPerSample, ValidBitsPerSample, SamplesPerSec);
}
#endif
Open_Buffer_Init_All();
}
else
{
CodecID_Fill(Ztring().From_GUID(SubFormat), Stream_Audio, StreamPos_Last, InfoCodecID_Format_Riff);
}
Fill(Stream_Audio, StreamPos_Last, Audio_ChannelPositions, ExtensibleWave_ChannelMask(ChannelMask));
Fill(Stream_Audio, StreamPos_Last, Audio_ChannelPositions_String2, ExtensibleWave_ChannelMask2(ChannelMask));
Fill(Stream_Audio, StreamPos_Last, Audio_ChannelLayout, ExtensibleWave_ChannelMask_ChannelLayout(ChannelMask));
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strf_iavs()
{
//Standard video header before Iavs?
if (Element_Size==72)
{
Element_Begin0();
AVI__hdlr_strl_strf_vids();
Element_End0();
}
Element_Info1("Interleaved Audio/Video");
#ifdef MEDIAINFO_DVDIF_YES
if (Element_Size<8*4)
return;
//Parsing
DV_FromHeader=new File_DvDif();
Open_Buffer_Init(DV_FromHeader);
//DVAAuxSrc
((File_DvDif*)DV_FromHeader)->AuxToAnalyze=0x50; //Audio source
Open_Buffer_Continue(DV_FromHeader, 4);
//DVAAuxCtl
((File_DvDif*)DV_FromHeader)->AuxToAnalyze=0x51; //Audio control
Open_Buffer_Continue(DV_FromHeader, Buffer+Buffer_Offset+(size_t)Element_Offset, 4);
Element_Offset+=4;
//DVAAuxSrc1
Skip_L4( "DVAAuxSrc1");
//DVAAuxCtl1
Skip_L4( "DVAAuxCtl1");
//DVVAuxSrc
((File_DvDif*)DV_FromHeader)->AuxToAnalyze=0x60; //Video source
Open_Buffer_Continue(DV_FromHeader, 4);
//DVAAuxCtl
((File_DvDif*)DV_FromHeader)->AuxToAnalyze=0x61; //Video control
Open_Buffer_Continue(DV_FromHeader, 4);
//Reserved
if (Element_Offset<Element_Size)
{
Skip_L4( "DVReserved");
Skip_L4( "DVReserved");
}
Finish(DV_FromHeader);
Stream_Prepare(Stream_Video);
stream& StreamItem = Stream[Stream_ID];
StreamItem.Parsers.push_back(new File_DvDif);
Open_Buffer_Init(StreamItem.Parsers[0]);
#else //MEDIAINFO_DVDIF_YES
//Parsing
Skip_L4( "DVAAuxSrc");
Skip_L4( "DVAAuxCtl");
Skip_L4( "DVAAuxSrc1");
Skip_L4( "DVAAuxCtl1");
Skip_L4( "DVVAuxSrc");
Skip_L4( "DVVAuxCtl");
Skip_L4( "DVReserved");
Skip_L4( "DVReserved");
//Filling
Ztring Codec; Codec.From_CC4(Stream[Stream_ID].fccHandler);
Stream_Prepare(Stream_Video);
float32 FrameRate=Retrieve(Stream_Video, StreamPos_Last, Video_FrameRate).To_float32();
Fill(Stream_Video, StreamPos_Last, Video_Codec, Codec); //May be replaced by codec parser
Fill(Stream_Video, StreamPos_Last, Video_Codec_CC, Codec);
if (Codec==__T("dvsd")
|| Codec==__T("dvsl"))
{
Fill(Stream_Video, StreamPos_Last, Video_Width, 720);
if (FrameRate==25.000) Fill(Stream_Video, StreamPos_Last, Video_Height, 576);
else if (FrameRate==29.970) Fill(Stream_Video, StreamPos_Last, Video_Height, 480);
Fill(Stream_Video, StreamPos_Last, Video_DisplayAspectRatio, 4.0/3, 3, true);
}
else if (Codec==__T("dvhd"))
{
Fill(Stream_Video, StreamPos_Last, Video_Width, 1440);
if (FrameRate==25.000) Fill(Stream_Video, StreamPos_Last, Video_Height, 1152);
else if (FrameRate==30.000) Fill(Stream_Video, StreamPos_Last, Video_Height, 960);
Fill(Stream_Video, StreamPos_Last, Video_DisplayAspectRatio, 4.0/3, 3, true);
}
Stream_Prepare(Stream_Audio);
CodecID_Fill(Codec, Stream_Audio, StreamPos_Last, InfoCodecID_Format_Riff);
Fill(Stream_Audio, StreamPos_Last, Audio_Codec, Codec); //May be replaced by codec parser
Fill(Stream_Audio, StreamPos_Last, Audio_Codec_CC, Codec);
#endif //MEDIAINFO_DVDIF_YES
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strf_mids()
{
Element_Info1("Midi");
//Filling
Stream_Prepare(Stream_Audio);
Fill(Stream_Audio, StreamPos_Last, Audio_Format, "MIDI");
Fill(Stream_Audio, StreamPos_Last, Audio_Codec, "Midi");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strf_txts()
{
Element_Info1("Text");
//Parsing
Ztring Format;
if (Element_Size)
{
Get_Local(10, Format, "Format");
Skip_XX(22, "Unknown");
}
FILLING_BEGIN_PRECISE();
Stream_Prepare(Stream_Text);
if (Element_Size==0)
{
//Creating the parser
stream& StreamItem = Stream[Stream_ID];
#if defined(MEDIAINFO_SUBRIP_YES)
StreamItem.Parsers.push_back(new File_SubRip);
#endif
#if defined(MEDIAINFO_OTHERTEXT_YES)
StreamItem.Parsers.push_back(new File_OtherText); //For SSA
#endif
Open_Buffer_Init_All();
}
else
{
Fill(Stream_Text, StreamPos_Last, Text_Format, Format);
}
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strf_vids()
{
Element_Info1("Video");
//Parsing
int32u Size, Compression, Width, Height;
int16u Resolution;
Get_L4 (Size, "Size");
Get_L4 (Width, "Width");
Get_L4 (Height, "Height");
Skip_L2( "Planes");
Get_L2 (Resolution, "BitCount"); //Do not use it
Get_C4 (Compression, "Compression");
Skip_L4( "SizeImage");
Skip_L4( "XPelsPerMeter");
Skip_L4( "YPelsPerMeter");
Skip_L4( "ClrUsed");
Skip_L4( "ClrImportant");
//Filling
Stream[Stream_ID].Compression=Compression;
if (Compression==CC4("DXSB"))
{
//Divx.com hack for subtitle, this is a text stream in a DivX Format
Fill(Stream_General, 0, General_Format, "DivX", Unlimited, true, true);
Stream_Prepare(Stream_Text);
}
else
Stream_Prepare(Stream_Video);
//Filling
CodecID_Fill(Ztring().From_CC4(Compression), StreamKind_Last, StreamPos_Last, InfoCodecID_Format_Riff);
Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Codec), Ztring().From_CC4(Compression).To_UTF8().c_str()); //FormatTag, may be replaced by codec parser
Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Codec_CC), Ztring().From_CC4(Compression).To_UTF8().c_str()); //FormatTag
Fill(StreamKind_Last, StreamPos_Last, "Width", Width, 10, true);
Fill(StreamKind_Last, StreamPos_Last, "Height", Height>=0x80000000?(-((int32s)Height)):Height, 10, true); // AVI can use negative height for raw to signal that it's coded top-down, not bottom-up
if (Resolution==32 && Compression==0x74736363) //tscc
Fill(StreamKind_Last, StreamPos_Last, "BitDepth", 8);
else if (Compression==0x44495633) //DIV3
Fill(StreamKind_Last, StreamPos_Last, "BitDepth", 8);
else if (MediaInfoLib::Config.CodecID_Get(StreamKind_Last, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression)).find(__T("Canopus"))!=std::string::npos) //Canopus codecs
Fill(StreamKind_Last, StreamPos_Last, "BitDepth", Resolution/3);
else if (Compression==0x44585342) //DXSB
Fill(StreamKind_Last, StreamPos_Last, "BitDepth", Resolution);
else if (MediaInfoLib::Config.CodecID_Get(StreamKind_Last, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression), InfoCodecID_ColorSpace).find(__T("RGBA"))!=std::string::npos) //RGB codecs
Fill(StreamKind_Last, StreamPos_Last, "BitDepth", Resolution/4);
else if (Compression==0x00000000 //RGB
|| MediaInfoLib::Config.CodecID_Get(StreamKind_Last, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression), InfoCodecID_ColorSpace).find(__T("RGB"))!=std::string::npos) //RGB codecs
{
if (Resolution==32)
{
Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Format), "RGBA", Unlimited, true, true);
if (StreamKind_Last==Stream_Video)
Fill(Stream_Video, StreamPos_Last, Video_ColorSpace, "RGBA", Unlimited, true, true);
Fill(StreamKind_Last, StreamPos_Last, "BitDepth", Resolution/4); //With Alpha
}
else
{
Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_Format), "RGB", Unlimited, true, true);
if (StreamKind_Last==Stream_Video)
Fill(Stream_Video, StreamPos_Last, Video_ColorSpace, "RGB", Unlimited, true, true);
Fill(StreamKind_Last, StreamPos_Last, "BitDepth", Resolution<=16?8:(Resolution/3)); //indexed or normal
}
}
else if (Compression==0x56503632 //VP62
|| MediaInfoLib::Config.CodecID_Get(StreamKind_Last, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression), InfoCodecID_Format)==__T("H.263") //H.263
|| MediaInfoLib::Config.CodecID_Get(StreamKind_Last, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression), InfoCodecID_Format)==__T("VC-1")) //VC-1
Fill(StreamKind_Last, StreamPos_Last, "BitDepth", Resolution/3);
Stream[Stream_ID].StreamKind=StreamKind_Last;
//Creating the parser
if (0);
#if defined(MEDIAINFO_FFV1_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Video, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression), InfoCodecID_Format)==__T("FFV1"))
{
File_Ffv1* Parser=new File_Ffv1;
Parser->Width=Width;
Parser->Height=Height;
Stream[Stream_ID].Parsers.push_back(Parser);
}
#endif
#if defined(MEDIAINFO_CINEFORM_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Video, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression), InfoCodecID_Format)==__T("CineForm"))
{
File_CineForm* Parser=new File_CineForm;
Stream[Stream_ID].Parsers.push_back(Parser);
}
#endif
#if defined(MEDIAINFO_HUFFYUV_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Video, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression), InfoCodecID_Format)==__T("HuffYUV"))
{
File_HuffYuv* Parser=new File_HuffYuv;
Stream[Stream_ID].Parsers.push_back(Parser);
}
#endif
#if defined(MEDIAINFO_MPEGV_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Video, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression), InfoCodecID_Format)==__T("MPEG Video"))
{
File_Mpegv* Parser=new File_Mpegv;
Parser->FrameIsAlwaysComplete=true;
Parser->TimeCodeIsNotTrustable=true;
Stream[Stream_ID].Parsers.push_back(Parser);
}
#endif
#if defined(MEDIAINFO_MPEG4V_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Video, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression))==__T("MPEG-4 Visual"))
{
File_Mpeg4v* Parser=new File_Mpeg4v;
Stream[Stream_ID].Specific_IsMpeg4v=true;
Parser->FrameIsAlwaysComplete=true;
if (Config->ParseSpeed>=0.5)
Parser->ShouldContinueParsing=true;
Stream[Stream_ID].Parsers.push_back(Parser);
}
#endif
#if defined(MEDIAINFO_PRORES_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Video, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression), InfoCodecID_Format)==__T("ProRes"))
{
File_ProRes* Parser=new File_ProRes;
Stream[Stream_ID].Parsers.push_back(Parser);
}
#endif
#if defined(MEDIAINFO_AVC_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Video, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression))==__T("AVC"))
{
File_Avc* Parser=new File_Avc;
Parser->FrameIsAlwaysComplete=true;
Stream[Stream_ID].Parsers.push_back(Parser);
}
#endif
#if defined(MEDIAINFO_CANOPUS_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Video, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression))==__T("Canopus HQ"))
{
File_Canopus* Parser=new File_Canopus;
Stream[Stream_ID].Parsers.push_back(Parser);
}
#endif
#if defined(MEDIAINFO_JPEG_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Video, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression))==__T("JPEG"))
{
File_Jpeg* Parser=new File_Jpeg;
Parser->StreamKind=Stream_Video;
Stream[Stream_ID].Parsers.push_back(Parser);
}
#endif
#if defined(MEDIAINFO_DVDIF_YES)
else if (MediaInfoLib::Config.CodecID_Get(Stream_Video, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression))==__T("DV"))
{
File_DvDif* Parser=new File_DvDif;
Parser->IgnoreAudio=true;
Stream[Stream_ID].Parsers.push_back(Parser);
}
#endif
#if defined(MEDIAINFO_FRAPS_YES)
else if (Compression==0x46505331) //"FPS1"
{
File_Fraps* Parser=new File_Fraps;
Stream[Stream_ID].Parsers.push_back(Parser);
}
#endif
else if (Compression==0x48465955) //"HFUY"
{
switch (Resolution)
{
case 16 : Fill(Stream_Video, StreamPos_Last, Video_ColorSpace, "YUV"); Fill(Stream_Video, StreamPos_Last, Video_ChromaSubsampling, "4:2:2"); Fill(Stream_Video, StreamPos_Last, Video_BitDepth, 8); break;
case 24 : Fill(Stream_Video, StreamPos_Last, Video_ColorSpace, "RGB"); Fill(Stream_Video, StreamPos_Last, Video_BitDepth, 8); break;
case 32 : Fill(Stream_Video, StreamPos_Last, Video_ColorSpace, "RGBA"); Fill(Stream_Video, StreamPos_Last, Video_BitDepth, 8); break;
default : ;
}
}
#if defined(MEDIAINFO_LAGARITH_YES)
else if (Compression==0x4C414753) //"LAGS"
{
File_Lagarith* Parser=new File_Lagarith;
Stream[Stream_ID].Parsers.push_back(Parser);
}
#endif
Open_Buffer_Init_All();
//Options
if (Element_Offset>=Element_Size)
return; //No options
//Filling
int32u Element_Size_Save=0;
if (Size<Element_Size)
{
Element_Size_Save=Element_Size;
Element_Size=Size;
}
if (0);
else if (MediaInfoLib::Config.CodecID_Get(Stream_Video, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression))==__T("AVC"))
AVI__hdlr_strl_strf_vids_Avc();
else if (MediaInfoLib::Config.CodecID_Get(Stream_Video, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression))==__T("FFV1"))
AVI__hdlr_strl_strf_vids_Ffv1();
else if (MediaInfoLib::Config.CodecID_Get(Stream_Video, InfoCodecID_Format_Riff, Ztring().From_CC4(Compression))==__T("HuffYUV"))
AVI__hdlr_strl_strf_vids_HuffYUV(Resolution, Height);
else Skip_XX(Element_Size-Element_Offset, "Unknown");
if (Element_Size_Save)
Element_Size=Element_Size_Save;
Skip_XX(Element_Size-Element_Offset, "Unknown");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strf_vids_Avc()
{
//Parsing
Element_Begin1("AVC options");
#if defined(MEDIAINFO_AVC_YES)
//Can be sized block or with 000001
stream& StreamItem = Stream[Stream_ID];
File_Avc* Parser=(File_Avc*)StreamItem.Parsers[0];
Parser->MustParse_SPS_PPS=false;
Parser->SizedBlocks=false;
Parser->MustSynchronize=true;
int64u Element_Offset_Save=Element_Offset;
Open_Buffer_Continue(Parser);
if (!Parser->Status[IsAccepted])
{
Element_Offset=Element_Offset_Save;
delete StreamItem.Parsers[0]; StreamItem.Parsers[0]=new File_Avc;
Parser=(File_Avc*)StreamItem.Parsers[0];
Open_Buffer_Init(Parser);
Parser->FrameIsAlwaysComplete=true;
Parser->MustParse_SPS_PPS=true;
Parser->SizedBlocks=true;
Parser->MustSynchronize=false;
Open_Buffer_Continue(Parser);
Element_Show();
}
#else //MEDIAINFO_AVC_YES
Skip_XX(Element_Size-Element_Offset, "(AVC headers)");
#endif
Element_End0();
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strf_vids_Ffv1()
{
//Parsing
Element_Begin1("FFV1 options");
#if defined(MEDIAINFO_FFV1_YES)
Open_Buffer_OutOfBand(Stream[Stream_ID].Parsers[0]);
#else //MEDIAINFO_FFV1_YES
Skip_XX(Element_Size-Element_Offset, "(FFV1 headers)");
#endif
Element_End0();
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strf_vids_HuffYUV(int16u BitCount, int32u Height)
{
//Parsing
Element_Begin1("HuffYUV options");
#if defined(MEDIAINFO_HUFFYUV_YES)
File_HuffYuv* Parser=(File_HuffYuv*)Stream[Stream_ID].Parsers[0];
Parser->BitCount=BitCount;
Parser->Height=Height;
Open_Buffer_OutOfBand(Parser);
#else //MEDIAINFO_HUFFYUV_YES
Skip_XX(Element_Size-Element_Offset, "(HuffYUV headers)");
#endif
Element_End0();
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strh()
{
Element_Name("Stream header");
//Parsing
int32u fccType, fccHandler, Scale, Rate, Start, Length;
int16u Left, Top, Right, Bottom;
Get_C4 (fccType, "fccType");
switch (fccType)
{
case Elements::AVI__hdlr_strl_strh_auds :
Get_L4 (fccHandler, "fccHandler");
break;
default:
Get_C4 (fccHandler, "fccHandler");
}
Skip_L4( "Flags");
Skip_L2( "Priority");
Skip_L2( "Language");
Skip_L4( "InitialFrames");
Get_L4 (Scale, "Scale");
Get_L4 (Rate, "Rate"); //Rate/Scale is stream tick rate in ticks/sec
Get_L4 (Start, "Start");
Get_L4 (Length, "Length");
Skip_L4( "SuggestedBufferSize");
Skip_L4( "Quality");
Skip_L4( "SampleSize");
Get_L2 (Left, "Frame_Left");
Get_L2 (Top, "Frame_Top");
Get_L2 (Right, "Frame_Right");
Get_L2 (Bottom, "Frame_Bottom");
if(Element_Offset<Element_Size)
Skip_XX(Element_Size-Element_Offset, "Unknown");
//Filling
float32 FrameRate=0;
if (Rate>0 && Scale>0)
{
//FrameRate (without known value detection)
FrameRate=((float32)Rate)/Scale;
if (FrameRate>1)
{
float32 Rest=FrameRate-(int32u)FrameRate;
if (Rest<0.01)
FrameRate-=Rest;
else if (Rest>0.99)
FrameRate+=1-Rest;
else
{
float32 Rest1001=FrameRate*1001/1000-(int32u)(FrameRate*1001/1000);
if (Rest1001<0.001)
FrameRate=(float32)((int32u)(FrameRate*1001/1000))*1000/1001;
if (Rest1001>0.999)
FrameRate=(float32)((int32u)(FrameRate*1001/1000)+1)*1000/1001;
}
}
//Duration
if (FrameRate)
{
int64u Duration=float32_int64s((1000*(float32)Length)/FrameRate);
if (avih_TotalFrame>0 //avih_TotalFrame is here because some files have a wrong Audio Duration if TotalFrame==0 (which is a bug, of course!)
&& (avih_FrameRate==0 || Duration<((float32)avih_TotalFrame)/avih_FrameRate*1000*1.10) //Some file have a nearly perfect header, except that the value is false, trying to detect it (false if 10% more than 1st video)
&& (avih_FrameRate==0 || Duration>((float32)avih_TotalFrame)/avih_FrameRate*1000*0.90)) //Some file have a nearly perfect header, except that the value is false, trying to detect it (false if 10% less than 1st video)
{
Fill(StreamKind_Last, StreamPos_Last, "Duration", Duration);
}
}
}
switch (fccType)
{
case Elements::AVI__hdlr_strl_strh_vids :
if (FrameRate>0) Fill(Stream_Video, StreamPos_Last, Video_FrameRate, FrameRate, 3);
if (Right-Left>0) Fill(Stream_Video, StreamPos_Last, Video_Width, Right-Left, 10, true);
if (Bottom-Top>0) Fill(Stream_Video, StreamPos_Last, Video_Height, Bottom-Top, 10, true);
break;
case Elements::AVI__hdlr_strl_strh_txts :
if (Right-Left>0) Fill(Stream_Text, StreamPos_Last, Text_Width, Right-Left, 10, true);
if (Bottom-Top>0) Fill(Stream_Text, StreamPos_Last, Text_Height, Bottom-Top, 10, true);
break;
default: ;
}
stream& StreamItem = Stream[Stream_ID];
StreamItem.fccType=fccType;
StreamItem.fccHandler=fccHandler;
StreamItem.Scale=Scale;
StreamItem.Rate=Rate;
StreamItem.Start=Start;
StreamItem.Length=Length;
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_strn()
{
Element_Name("Stream name");
//Parsing
Ztring Title;
Get_Local(Element_Size, Title, "StreamName");
//Filling
Fill(StreamKind_Last, StreamPos_Last, "Title", Title);
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_strl_vprp()
{
Element_Name("Video properties");
//Parsing
int32u FieldPerFrame;
int16u FrameAspectRatio_H, FrameAspectRatio_W;
Skip_L4( "VideoFormatToken");
Skip_L4( "VideoStandard");
Skip_L4( "VerticalRefreshRate");
Skip_L4( "HTotalInT");
Skip_L4( "VTotalInLines");
Get_L2 (FrameAspectRatio_H, "FrameAspectRatio Height");
Get_L2 (FrameAspectRatio_W, "FrameAspectRatio Width");
Skip_L4( "FrameWidthInPixels");
Skip_L4( "FrameHeightInLines");
Get_L4 (FieldPerFrame, "FieldPerFrame");
vector<int32u> VideoYValidStartLines;
for (int32u Pos=0; Pos<FieldPerFrame; Pos++)
{
Element_Begin1("Field");
int32u VideoYValidStartLine;
Skip_L4( "CompressedBMHeight");
Skip_L4( "CompressedBMWidth");
Skip_L4( "ValidBMHeight");
Skip_L4( "ValidBMWidth");
Skip_L4( "ValidBMXOffset");
Skip_L4( "ValidBMYOffset");
Skip_L4( "VideoXOffsetInT");
Get_L4 (VideoYValidStartLine, "VideoYValidStartLine");
VideoYValidStartLines.push_back(VideoYValidStartLine);
Element_End0();
}
if(Element_Offset<Element_Size)
Skip_XX(Element_Size-Element_Offset, "Unknown");
FILLING_BEGIN();
if (FrameAspectRatio_H && FrameAspectRatio_W)
Fill(Stream_Video, 0, Video_DisplayAspectRatio, ((float32)FrameAspectRatio_W)/FrameAspectRatio_H, 3);
switch (FieldPerFrame)
{
case 1 :
Fill(Stream_Video, 0, Video_ScanType, "Progressive");
break;
case 2 :
Fill(Stream_Video, 0, Video_ScanType, "Interlaced");
if (VideoYValidStartLines.size()==2 && VideoYValidStartLines[0]<VideoYValidStartLines[1])
Fill(Stream_Video, 0, Video_ScanOrder, "TFF");
if (VideoYValidStartLines.size()==2 && VideoYValidStartLines[0]>VideoYValidStartLines[1])
Fill(Stream_Video, 0, Video_ScanOrder, "BFF");
default: ;
}
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Riff::AVI__hdlr_xxxx()
{
AVI__INFO_xxxx();
}
//---------------------------------------------------------------------------
void File_Riff::AVI__idx1()
{
Element_Name("Index (old)");
//Tests
if (!NeedOldIndex || Idx1_Offset==(int64u)-1)
{
Skip_XX(Element_Size, "Data");
return;
}
//Testing malformed index (index is based on start of the file, wrong)
if (16<=Element_Size && Idx1_Offset+4==LittleEndian2int32u(Buffer+Buffer_Offset+(size_t)Element_Offset+ 8))
Idx1_Offset=0; //Fixing base of movi atom, the index think it is the start of the file
//Parsing
while (Element_Offset+16<=Element_Size)
{
//Is too slow
/*
int32u ChunkID, Offset, Size;
Element_Begin1("Index");
Get_C4 (ChunkID, "ChunkID"); //Bit 31 is set if this is NOT a keyframe
Info_L4(Flags, "Flags");
Skip_Flags(Flags, 0, "NoTime");
Skip_Flags(Flags, 1, "Lastpart");
Skip_Flags(Flags, 2, "Firstpart");
Skip_Flags(Flags, 3, "Midpart");
Skip_Flags(Flags, 4, "KeyFrame");
Get_L4 (Offset, "Offset"); //qwBaseOffset + this is absolute file offset
Get_L4 (Size, "Size"); //Bit 31 is set if this is NOT a keyframe
Element_Info1(Ztring().From_CC4(ChunkID));
Element_Info1(Size);
//Stream Pos and Size
int32u StreamID=(ChunkID&0xFFFF0000);
Stream[StreamID].StreamSize+=Size;
Stream[StreamID].PacketCount++;
Stream_Structure[Idx1_Offset+Offset].Name=StreamID;
Stream_Structure[Idx1_Offset+Offset].Size=Size;
Element_End0();
*/
//Faster method
int32u StreamID=BigEndian2int32u (Buffer+Buffer_Offset+(size_t)Element_Offset )&0xFFFF0000;
int32u Offset =LittleEndian2int32u(Buffer+Buffer_Offset+(size_t)Element_Offset+ 8);
int32u Size =LittleEndian2int32u(Buffer+Buffer_Offset+(size_t)Element_Offset+12);
stream& Stream_Item=Stream[StreamID];
Stream_Item.StreamSize+=Size;
Stream_Item.PacketCount++;
stream_structure& Stream_Structure_Item=Stream_Structure[Idx1_Offset+Offset];
Stream_Structure_Item.Name=StreamID;
Stream_Structure_Item.Size=Size;
Element_Offset+=16;
}
//Interleaved
size_t Pos0=0;
size_t Pos1=0;
for (std::map<int64u, stream_structure>::iterator Temp=Stream_Structure.begin(); Temp!=Stream_Structure.end(); ++Temp)
{
switch (Temp->second.Name)
{
case 0x30300000 :
if (Interleaved0_1==0) Interleaved0_1=Temp->first;
if (Interleaved0_10==0)
{
Pos0++;
if (Pos0>1)
Interleaved0_10=Temp->first;
}
break;
case 0x30310000 :
if (Interleaved1_1==0) Interleaved1_1=Temp->first;
if (Interleaved1_10==0)
{
Pos1++;
if (Pos1>1)
Interleaved1_10=Temp->first;
}
break;
default:;
}
}
}
//---------------------------------------------------------------------------
void File_Riff::AVI__INFO()
{
Element_Name("Tags");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__INFO_IID3()
{
Element_Name("ID3 Tag");
//Parsing
#if defined(MEDIAINFO_ID3_YES)
File_Id3 MI;
Open_Buffer_Init(&MI);
Open_Buffer_Continue(&MI);
Finish(&MI);
Merge(MI, Stream_General, 0, 0);
#endif
}
//---------------------------------------------------------------------------
void File_Riff::AVI__INFO_ILYC()
{
Element_Name("Lyrics");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__INFO_IMP3()
{
Element_Name("MP3 Information");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__INFO_JUNK()
{
Element_Name("Garbage");
}
//---------------------------------------------------------------------------
// List of information atoms
// Name X bytes, Pos=0
//
void File_Riff::AVI__INFO_xxxx()
{
//Parsing
Ztring Value;
Get_Local(Element_Size, Value, "Value");
//Filling
stream_t StreamKind=Stream_General;
size_t StreamPos=0;
size_t Parameter=(size_t)-1;
switch (Element_Code)
{
case 0x00000000 : Parameter=General_Comment; break;
case Elements::AVI__INFO_IARL : Parameter=General_Archival_Location; break;
case Elements::AVI__INFO_IART : Parameter=General_Director; break;
case Elements::AVI__INFO_IAS1 : Parameter=Audio_Language; StreamKind=Stream_Audio; StreamPos=0; break;
case Elements::AVI__INFO_IAS2 : Parameter=Audio_Language; StreamKind=Stream_Audio; StreamPos=1; break;
case Elements::AVI__INFO_IAS3 : Parameter=Audio_Language; StreamKind=Stream_Audio; StreamPos=2; break;
case Elements::AVI__INFO_IAS4 : Parameter=Audio_Language; StreamKind=Stream_Audio; StreamPos=3; break;
case Elements::AVI__INFO_IAS5 : Parameter=Audio_Language; StreamKind=Stream_Audio; StreamPos=4; break;
case Elements::AVI__INFO_IAS6 : Parameter=Audio_Language; StreamKind=Stream_Audio; StreamPos=5; break;
case Elements::AVI__INFO_IAS7 : Parameter=Audio_Language; StreamKind=Stream_Audio; StreamPos=6; break;
case Elements::AVI__INFO_IAS8 : Parameter=Audio_Language; StreamKind=Stream_Audio; StreamPos=7; break;
case Elements::AVI__INFO_IAS9 : Parameter=Audio_Language; StreamKind=Stream_Audio; StreamPos=8; break;
case Elements::AVI__INFO_ICDS : Parameter=General_CostumeDesigner; break;
case Elements::AVI__INFO_ICMS : Parameter=General_CommissionedBy; break;
case Elements::AVI__INFO_ICMT : Parameter=General_Comment; break;
case Elements::AVI__INFO_ICNM : Parameter=General_DirectorOfPhotography; break;
case Elements::AVI__INFO_ICNT : Parameter=General_Movie_Country; break;
case Elements::AVI__INFO_ICOP : Parameter=General_Copyright; break;
case Elements::AVI__INFO_ICRD : Parameter=General_Recorded_Date; Value.Date_From_String(Value.To_UTF8().c_str()); break;
case Elements::AVI__INFO_ICRP : Parameter=General_Cropped; break;
case Elements::AVI__INFO_IDIM : Parameter=General_Dimensions; break;
case Elements::AVI__INFO_IDIT : Parameter=General_Mastered_Date; Value.Date_From_String(Value.To_UTF8().c_str()); break;
case Elements::AVI__INFO_IDPI : Parameter=General_DotsPerInch; break;
case Elements::AVI__INFO_IDST : Parameter=General_DistributedBy; break;
case Elements::AVI__INFO_IEDT : Parameter=General_EditedBy; break;
case Elements::AVI__INFO_IENG : Parameter=General_EncodedBy; break;
case Elements::AVI__INFO_IGNR : Parameter=General_Genre; break;
case Elements::AVI__INFO_IFRM : Parameter=General_Part_Position_Total; break;
case Elements::AVI__INFO_IKEY : Parameter=General_Keywords; break;
case Elements::AVI__INFO_ILGT : Parameter=General_Lightness; break;
case Elements::AVI__INFO_ILNG : Parameter=Audio_Language; StreamKind=Stream_Audio; break;
case Elements::AVI__INFO_IMED : Parameter=General_OriginalSourceMedium; break;
case Elements::AVI__INFO_IMUS : Parameter=General_MusicBy; break;
case Elements::AVI__INFO_INAM : Parameter=General_Title; break;
case Elements::AVI__INFO_IPDS : Parameter=General_ProductionDesigner; break;
case Elements::AVI__INFO_IPLT : Parameter=General_OriginalSourceForm_NumColors; break;
case Elements::AVI__INFO_IPRD : Parameter=General_OriginalSourceForm_Name; break;
case Elements::AVI__INFO_IPRO : Parameter=General_Producer; break;
case Elements::AVI__INFO_IPRT : Parameter=General_Part_Position; break;
case Elements::AVI__INFO_IRTD : Parameter=General_LawRating; break;
case Elements::AVI__INFO_ISBJ : Parameter=General_Subject; break;
case Elements::AVI__INFO_ISFT : Parameter=General_Encoded_Application; break;
case Elements::AVI__INFO_ISGN : Parameter=General_Genre; break;
case Elements::AVI__INFO_ISHP : Parameter=General_OriginalSourceForm_Sharpness; break;
case Elements::AVI__INFO_ISRC : Parameter=General_OriginalSourceForm_DistributedBy; break;
case Elements::AVI__INFO_ISRF : Parameter=General_OriginalSourceForm; break;
case Elements::AVI__INFO_ISTD : Parameter=General_ProductionStudio; break;
case Elements::AVI__INFO_ISTR : Parameter=General_Performer; break;
case Elements::AVI__INFO_ITCH : Parameter=General_EncodedBy; break;
case Elements::AVI__INFO_IWEB : Parameter=General_Movie_Url; break;
case Elements::AVI__INFO_IWRI : Parameter=General_WrittenBy; break;
default : ;
}
Element_Name(MediaInfoLib::Config.Info_Get(StreamKind, Parameter, Info_Name));
Element_Info1(Value);
switch (Element_Code)
{
case Elements::AVI__INFO_ISMP : INFO_ISMP=Value;
break;
case Elements::AVI__INFO_IGNR :
{
Ztring ISGN=Retrieve(Stream_General, 0, General_Genre);
Clear(Stream_General, 0, General_Genre);
Fill(StreamKind, StreamPos, General_Genre, Value);
if (!ISGN.empty())
Fill(StreamKind, StreamPos, General_Genre, ISGN);
}
break;
default :
if (!Value.empty())
{
if (Parameter!=(size_t)-1)
Fill(StreamKind, StreamPos, Parameter, Value);
else
Fill(StreamKind, StreamPos, Ztring().From_CC4((int32u)Element_Code).To_UTF8().c_str(), Value, true);
}
}
}
//---------------------------------------------------------------------------
void File_Riff::AVI__JUNK()
{
Element_Name("Garbage"); //Library defined size for padding, often used to store library name
if (Element_Size<8)
{
Skip_XX(Element_Size, "Junk");
return;
}
//Detect DivX files
if (CC5(Buffer+Buffer_Offset)==CC5("DivX "))
{
Fill(Stream_General, 0, General_Format, "DivX", Unlimited, true, true);
}
//MPlayer
else if (CC8(Buffer+Buffer_Offset)==CC8("[= MPlay") && Retrieve(Stream_General, 0, General_Encoded_Library).empty())
Fill(Stream_General, 0, General_Encoded_Library, "MPlayer");
//Scenalyzer
else if (CC8(Buffer+Buffer_Offset)==CC8("scenalyz") && Retrieve(Stream_General, 0, General_Encoded_Library).empty())
Fill(Stream_General, 0, General_Encoded_Library, "Scenalyzer");
//FFMpeg broken files detection
else if (CC8(Buffer+Buffer_Offset)==CC8("odmldmlh"))
dmlh_TotalFrame=0; //this is not normal to have this string in a JUNK block!!! and in files tested, in this case TotalFrame is broken too
//VirtualDubMod
else if (CC8(Buffer+Buffer_Offset)==CC8("INFOISFT"))
{
int32u Size=LittleEndian2int32u(Buffer+Buffer_Offset+8);
if (Size>Element_Size-12)
Size=(int32u)Element_Size-12;
Fill(Stream_General, 0, General_Encoded_Library, (const char*)(Buffer+Buffer_Offset+12), Size);
}
else if (CC8(Buffer+Buffer_Offset)==CC8("INFOIENG"))
{
int32u Size=LittleEndian2int32u(Buffer+Buffer_Offset+8);
if (Size>Element_Size-12)
Size=(int32u)Element_Size-12;
Fill(Stream_General, 0, General_Encoded_Library, (const char*)(Buffer+Buffer_Offset+12), Size);
}
//Other libraries?
else if (CC1(Buffer+Buffer_Offset)>=CC1("A") && CC1(Buffer+Buffer_Offset)<=CC1("z") && Retrieve(Stream_General, 0, General_Encoded_Library).empty())
Fill(Stream_General, 0, General_Encoded_Library, (const char*)(Buffer+Buffer_Offset), (size_t)Element_Size);
Skip_XX(Element_Size, "Data");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__MD5_()
{
//Parsing
while (Element_Offset<Element_Size)
{
int128u MD5Stored;
Get_L16 (MD5Stored, "MD5");
Ztring MD5_PerItem;
MD5_PerItem.From_UTF8(uint128toString(MD5Stored, 16));
while (MD5_PerItem.size()<32)
MD5_PerItem.insert(MD5_PerItem.begin(), '0'); //Padding with 0, this must be a 32-byte string
MD5_PerItem.MakeLowerCase();
MD5s.push_back(MD5_PerItem);
}
}
//---------------------------------------------------------------------------
void File_Riff::AVI__movi()
{
Element_Name("Datas");
//Only the first time, no need in AVIX
if (movi_Size==0)
{
Idx1_Offset=File_Offset+Buffer_Offset-4;
BookMark_Set(); //Remenbering this place, for stream parsing in phase 2
//For each stream
std::map<int32u, stream>::iterator Temp=Stream.begin();
while (Temp!=Stream.end())
{
if ((Temp->second.Parsers.empty() || Temp->second.Parsers[0]==NULL) && Temp->second.fccType!=Elements::AVI__hdlr_strl_strh_txts)
{
Temp->second.SearchingPayload=false;
stream_Count--;
}
++Temp;
}
}
//Probing rec (with index, this is not always tested in the flow
if (Element_Size<12)
{
Element_WaitForMoreData();
return;
}
if (CC4(Buffer+Buffer_Offset+8)==0x72656320) //"rec "
rec__Present=true;
//Filling
if (!SecondPass)
movi_Size+=Element_TotalSize_Get();
//We must parse moov?
if (NeedOldIndex || (stream_Count==0 && Index_Pos.empty()))
{
//Jumping
#if MEDIAINFO_TRACE
if (Trace_Activated)
Param("Data", Ztring("(")+Ztring::ToZtring(Element_TotalSize_Get())+Ztring(" bytes)"));
#endif //MEDIAINFO_TRACE
Element_Offset=Element_TotalSize_Get(); //Not using Skip_XX() because we want to skip data we don't have, and Skip_XX() does a test on size of buffer
return;
}
//Jump to next useful data
AVI__movi_StreamJump();
}
//---------------------------------------------------------------------------
void File_Riff::AVI__movi_rec_()
{
Element_Name("Syncronisation");
rec__Present=true;
}
//---------------------------------------------------------------------------
void File_Riff::AVI__movi_rec__xxxx()
{
AVI__movi_xxxx();
}
//---------------------------------------------------------------------------
void File_Riff::AVI__movi_xxxx()
{
if (Element_Code==Elements::AVI__JUNK)
{
Skip_XX(Element_Size, "Junk");
AVI__movi_StreamJump();
return;
}
if (Element_Code!=(int64u)-1)
Stream_ID=(int32u)(Element_Code&0xFFFF0000);
else
Stream_ID=(int32u)-1;
if (Stream_ID==0x69780000) //ix..
{
//AVI Standard Index Chunk
AVI__hdlr_strl_indx();
Stream_ID=(int32u)(Element_Code&0x0000FFFF)<<16;
AVI__movi_StreamJump();
return;
}
if ((Element_Code&0x0000FFFF)==0x00006978) //..ix (Out of specs, but found in a Adobe After Effects CS4 DV file
{
//AVI Standard Index Chunk
AVI__hdlr_strl_indx();
Stream_ID=(int32u)(Element_Code&0xFFFF0000);
AVI__movi_StreamJump();
return;
}
stream& StreamItem = Stream[Stream_ID];
#if MEDIAINFO_DEMUX
if (StreamItem.Rate) //AVI
{
int64u Element_Code_Old=Element_Code;
Element_Code=((Element_Code_Old>>24)&0xF)*10+((Element_Code_Old>>16)&0xF);
Frame_Count_NotParsedIncluded= StreamItem.PacketPos;
FrameInfo.DTS=Frame_Count_NotParsedIncluded*1000000000* StreamItem.Scale/ StreamItem.Rate;
Demux(Buffer+Buffer_Offset, (size_t)Element_Size, ContentType_MainStream);
Element_Code=Element_Code_Old;
Frame_Count_NotParsedIncluded=(int64u)-1;
}
else //WAV
{
//TODO
}
#endif //MEDIAINFO_DEMUX
StreamItem.PacketPos++;
//Finished?
if (!StreamItem.SearchingPayload)
{
Element_DoNotShow();
AVI__movi_StreamJump();
return;
}
#if MEDIAINFO_TRACE
if (Config_Trace_Level)
{
switch (Element_Code&0x0000FFFF) //2 last bytes
{
case Elements::AVI__movi_xxxx_____ : Element_Info1("DV"); break;
case Elements::AVI__movi_xxxx___db :
case Elements::AVI__movi_xxxx___dc : Element_Info1("Video"); break;
case Elements::AVI__movi_xxxx___sb :
case Elements::AVI__movi_xxxx___tx : Element_Info1("Text"); break;
case Elements::AVI__movi_xxxx___wb : Element_Info1("Audio"); break;
default : Element_Info1("Unknown"); break;
}
Element_Info1(Stream[Stream_ID].PacketPos);
}
#endif //MEDIAINFO_TRACE
//Some specific stuff
switch (Element_Code&0x0000FFFF) //2 last bytes
{
case Elements::AVI__movi_xxxx___tx : AVI__movi_xxxx___tx(); break;
default : ;
}
//Parsing
for (size_t Pos=0; Pos<StreamItem.Parsers.size(); Pos++)
if (StreamItem.Parsers[Pos])
{
if (FrameInfo.PTS!=(int64u)-1)
StreamItem.Parsers[Pos]->FrameInfo.PTS=FrameInfo.PTS;
if (FrameInfo.DTS!=(int64u)-1)
StreamItem.Parsers[Pos]->FrameInfo.DTS=FrameInfo.DTS;
Open_Buffer_Continue(StreamItem.Parsers[Pos], Buffer+Buffer_Offset+(size_t)Element_Offset, (size_t)(Element_Size-Element_Offset));
Element_Show();
if (StreamItem.Parsers.size()==1 && StreamItem.Parsers[Pos]->Buffer_Size>0)
StreamItem.ChunksAreComplete=false;
if (StreamItem.Parsers.size()>1)
{
if (!StreamItem.Parsers[Pos]->Status[IsAccepted] && StreamItem.Parsers[Pos]->Status[IsFinished])
{
delete *(StreamItem.Parsers.begin()+Pos);
StreamItem.Parsers.erase(StreamItem.Parsers.begin()+Pos);
Pos--;
}
else if (StreamItem.Parsers.size()>1 && StreamItem.Parsers[Pos]->Status[IsAccepted])
{
File__Analyze* Parser= StreamItem.Parsers[Pos];
for (size_t Pos2=0; Pos2<StreamItem.Parsers.size(); Pos2++)
{
if (Pos2!=Pos)
delete *(StreamItem.Parsers.begin()+Pos2);
}
StreamItem.Parsers.clear();
StreamItem.Parsers.push_back(Parser);
Pos=0;
}
}
#if MEDIAINFO_DEMUX
if (Config->Demux_EventWasSent)
{
Demux_Parser= StreamItem.Parsers[Pos];
return;
}
#endif //MEDIAINFO_DEMUX
}
Element_Offset=Element_Size;
//Some specific stuff
switch (Element_Code&0x0000FFFF) //2 last bytes
{
case Elements::AVI__movi_xxxx_____ :
case Elements::AVI__movi_xxxx___db :
case Elements::AVI__movi_xxxx___dc : AVI__movi_xxxx___dc(); break;
case Elements::AVI__movi_xxxx___wb : AVI__movi_xxxx___wb(); break;
default : ;
}
//We must always parse moov?
AVI__movi_StreamJump();
Element_Show();
}
//---------------------------------------------------------------------------
void File_Riff::AVI__movi_xxxx___dc()
{
//Finish (if requested)
stream& StreamItem = Stream[Stream_ID];
if (StreamItem.Parsers.empty()
|| StreamItem.Parsers[0]->Status[IsFinished]
|| (StreamItem.PacketPos>=300 && Config->ParseSpeed<1.00))
{
StreamItem.SearchingPayload=false;
stream_Count--;
return;
}
}
//---------------------------------------------------------------------------
void File_Riff::AVI__movi_xxxx___tx()
{
//Parsing
int32u Name_Size;
Ztring Value;
int32u GAB2;
Peek_B4(GAB2);
if (GAB2==0x47414232 && Element_Size>=17)
{
Skip_C4( "GAB2");
Skip_L1( "Zero");
Skip_L2( "CodePage"); //2=Unicode
Get_L4 (Name_Size, "Name_Size");
Skip_UTF16L(Name_Size, "Name");
Skip_L2( "Four");
Skip_L4( "File_Size");
if (Element_Offset>Element_Size)
Element_Offset=Element_Size; //Problem
}
//Skip it
Stream[Stream_ID].SearchingPayload=false;
stream_Count--;
}
//---------------------------------------------------------------------------
void File_Riff::AVI__movi_xxxx___wb()
{
//Finish (if requested)
stream& StreamItem = Stream[Stream_ID];
if (StreamItem.PacketPos>=4 //For having the chunk alignement
&& (StreamItem.Parsers.empty()
|| StreamItem.Parsers[0]->Status[IsFinished]
|| (StreamItem.PacketPos>=300 && Config->ParseSpeed<1.00)))
{
StreamItem.SearchingPayload=false;
stream_Count--;
}
}
//---------------------------------------------------------------------------
void File_Riff::AVI__movi_StreamJump()
{
//Jump to next useful data
if (!Index_Pos.empty())
{
if (Index_Pos.begin()->first<=File_Offset+Buffer_Offset && Element_Code!=Elements::AVI__movi)
Index_Pos.erase(Index_Pos.begin());
int64u ToJump=File_Size;
if (!Index_Pos.empty())
ToJump=Index_Pos.begin()->first;
if (ToJump>File_Size)
ToJump=File_Size;
if (ToJump>=File_Offset+Buffer_Offset+Element_TotalSize_Get(Element_Level-2)) //We want always Element movi
{
#if MEDIAINFO_HASH
if (Config->File_Hash_Get().to_ulong() && SecondPass)
Hash_ParseUpTo=File_Offset+Buffer_Offset+Element_TotalSize_Get(Element_Level-2);
else
#endif //MEDIAINFO_HASH
GoTo(File_Offset+Buffer_Offset+Element_TotalSize_Get(Element_Level-2), "AVI"); //Not in this chunk
}
else if (ToJump!=File_Offset+Buffer_Offset+(Element_Code==Elements::AVI__movi?0:Element_Size))
{
#if MEDIAINFO_HASH
if (Config->File_Hash_Get().to_ulong() && SecondPass)
Hash_ParseUpTo=File_Offset+Buffer_Offset+Element_TotalSize_Get(Element_Level-2);
else
#endif //MEDIAINFO_HASH
GoTo(ToJump, "AVI"); //Not just after
}
}
else if (stream_Count==0)
{
//Jumping
Element_Show();
if (rec__Present)
Element_End0();
Info("movi, Jumping to end of chunk");
if (SecondPass)
{
std::map<int32u, stream>::iterator Temp=Stream.begin();
while (Temp!=Stream.end())
{
for (size_t Pos=0; Pos<Temp->second.Parsers.size(); ++Pos)
{
Temp->second.Parsers[Pos]->Fill();
Temp->second.Parsers[Pos]->Open_Buffer_Unsynch();
}
++Temp;
}
Finish("AVI"); //The rest is already parsed
}
else
GoTo(File_Offset+Buffer_Offset+Element_TotalSize_Get(), "AVI");
}
else if (Stream_Structure_Temp!=Stream_Structure.end())
{
do
Stream_Structure_Temp++;
while (Stream_Structure_Temp!=Stream_Structure.end() && !(Stream[(int32u)Stream_Structure_Temp->second.Name].SearchingPayload && Config->ParseSpeed<1.0));
if (Stream_Structure_Temp!=Stream_Structure.end())
{
int64u ToJump=Stream_Structure_Temp->first;
if (ToJump>=File_Offset+Buffer_Offset+Element_TotalSize_Get(Element_Level-2))
{
#if MEDIAINFO_HASH
if (Config->File_Hash_Get().to_ulong() && SecondPass)
Hash_ParseUpTo=File_Offset+Buffer_Offset+Element_TotalSize_Get(Element_Level-2);
else
#endif //MEDIAINFO_HASH
GoTo(File_Offset+Buffer_Offset+Element_TotalSize_Get(Element_Level-2), "AVI"); //Not in this chunk
}
else if (ToJump!=File_Offset+Buffer_Offset+Element_Size)
{
#if MEDIAINFO_HASH
if (Config->File_Hash_Get().to_ulong() && SecondPass)
Hash_ParseUpTo=ToJump;
else
#endif //MEDIAINFO_HASH
GoTo(ToJump, "AVI"); //Not just after
}
}
else
Finish("AVI");
}
}
//---------------------------------------------------------------------------
void File_Riff::AVI__PrmA()
{
Element_Name("Adobe Premiere PrmA");
//Parsing
int32u FourCC, Size;
Get_C4 (FourCC, "FourCC");
Get_B4 (Size, "Size");
switch (FourCC)
{
case 0x50415266:
if (Size==20)
{
int32u PAR_X, PAR_Y;
Skip_B4( "Unknown");
Get_B4 (PAR_X, "PAR_X");
Get_B4 (PAR_Y, "PAR_Y");
if (PAR_Y)
PAR=((float64)PAR_X)/PAR_Y;
}
else
Skip_XX(Element_Size-Element_Offset, "Unknown");
break;
default:
for (int32u Pos=8; Pos<Size; Pos++)
Skip_B4( "Unknown");
}
}
//---------------------------------------------------------------------------
void File_Riff::AVI__Tdat()
{
Element_Name("Adobe Premiere Tdat");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__Tdat_tc_A()
{
Element_Name("tc_A");
//Parsing
Ztring Value;
Get_UTF8(Element_Size, Value, "Unknown");
if (Value.find_first_not_of(__T("0123456789:;"))==string::npos)
Tdat_tc_A=Value;
}
//---------------------------------------------------------------------------
void File_Riff::AVI__Tdat_tc_O()
{
Element_Name("tc_O");
//Parsing
Ztring Value;
Get_UTF8(Element_Size, Value, "Unknown");
if (Value.find_first_not_of(__T("0123456789:;"))==string::npos)
Tdat_tc_O=Value;
}
//---------------------------------------------------------------------------
void File_Riff::AVI__Tdat_rn_A()
{
Element_Name("rn_A");
//Parsing
Skip_UTF8(Element_Size, "Unknown");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__Tdat_rn_O()
{
Element_Name("rn_O");
//Parsing
Skip_UTF8(Element_Size, "Unknown");
}
//---------------------------------------------------------------------------
void File_Riff::AVI__xxxx()
{
Stream_ID=(int32u)(Element_Code&0xFFFF0000);
if (Stream_ID==0x69780000) //ix..
{
//AVI Standard Index Chunk
AVI__hdlr_strl_indx();
Stream_ID=(int32u)(Element_Code&0x0000FFFF)<<16;
AVI__movi_StreamJump();
return;
}
if ((Element_Code&0x0000FFFF)==0x00006978) //..ix (Out of specs, but found in a Adobe After Effects CS4 DV file
{
//AVI Standard Index Chunk
AVI__hdlr_strl_indx();
Stream_ID=(int32u)(Element_Code&0xFFFF0000);
AVI__movi_StreamJump();
return;
}
}
//---------------------------------------------------------------------------
void File_Riff::AVIX()
{
//Filling
Fill(Stream_General, 0, General_Format_Profile, "OpenDML", Unlimited, true, true);
}
//---------------------------------------------------------------------------
void File_Riff::AVIX_idx1()
{
AVI__idx1();
}
//---------------------------------------------------------------------------
void File_Riff::AVIX_movi()
{
AVI__movi();
}
//---------------------------------------------------------------------------
void File_Riff::AVIX_movi_rec_()
{
AVI__movi_rec_();
}
//---------------------------------------------------------------------------
void File_Riff::AVIX_movi_rec__xxxx()
{
AVIX_movi_xxxx();
}
//---------------------------------------------------------------------------
void File_Riff::AVIX_movi_xxxx()
{
AVI__movi_xxxx();
}
//---------------------------------------------------------------------------
void File_Riff::CADP()
{
Element_Name("CMP4 - ADPCM");
//Testing if we have enough data
if (Element_Size<4)
{
Element_WaitForMoreData();
return;
}
//Parsing
int32u Codec;
Get_C4 (Codec, "Codec");
#if MEDIAINFO_TRACE
if (Trace_Activated)
Param("Data", Ztring("(")+Ztring::ToZtring(Element_TotalSize_Get()-Element_Offset)+Ztring(" bytes)"));
#endif //MEDIAINFO_TRACE
Element_Offset=Element_TotalSize_Get(); //Not using Skip_XX() because we want to skip data we don't have, and Skip_XX() does a test on size of buffer
FILLING_BEGIN();
Stream_Prepare(Stream_Audio);
if (Codec==0x41647063) //Adpc
Fill(Stream_Audio, StreamPos_Last, Audio_Format, "ADPCM");
Fill(Stream_Audio, StreamPos_Last, Audio_StreamSize, Element_TotalSize_Get());
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Riff::CDDA()
{
Element_Name("Compact Disc for Digital Audio");
//Filling
Accept("CDDA");
}
//---------------------------------------------------------------------------
void File_Riff::CDDA_fmt_()
{
//Specs: http://fr.wikipedia.org/wiki/Compact_Disc_Audio_track
//Specs: http://www.moon-soft.com/program/FORMAT/sound/cda.htm
Element_Name("Stream format");
//Parsing
int32u id;
int16u Version, tracknb=1;
int8u TPositionF=0, TPositionS=0, TPositionM=0, TDurationF=0, TDurationS=0, TDurationM=0;
Get_L2 (Version, "Version"); // Always 1
if (Version!=1)
{
//Not supported
Skip_XX(Element_Size-2, "Data");
return;
}
Get_L2 (tracknb, "Number"); // Start at 1
Get_L4 (id, "id");
Skip_L4( "offset"); // in frames //Priority of FSM format
Skip_L4( "Duration"); // in frames //Priority of FSM format
Get_L1 (TPositionF, "Track_PositionF"); // in frames
Get_L1 (TPositionS, "Track_PositionS"); // in seconds
Get_L1 (TPositionM, "Track_PositionM"); // in minutes
Skip_L1( "empty");
Get_L1 (TDurationF, "Track_DurationF"); // in frames
Get_L1 (TDurationS, "Track_DurationS"); // in seconds
Get_L1 (TDurationM, "Track_DurationM"); // in minutes
Skip_L1( "empty");
FILLING_BEGIN();
int32u TPosition=TPositionM*60*75+TPositionS*75+TPositionF;
int32u TDuration=TDurationM*60*75+TDurationS*75+TDurationF;
Fill(Stream_General, 0, General_Track_Position, tracknb);
Fill(Stream_General, 0, General_Format, "CDDA");
Fill(Stream_General, 0, General_Format_Info, "Compact Disc for Digital Audio");
Fill(Stream_General, 0, General_UniqueID, id);
Fill(Stream_General, 0, General_FileSize, File_Size+TDuration*2352, 10, true);
Stream_Prepare(Stream_Audio);
Fill(Stream_Audio, 0, Audio_Format, "PCM");
Fill(Stream_Audio, 0, Audio_Format_Settings_Endianness, "Little");
Fill(Stream_Audio, 0, Audio_BitDepth, 16);
Fill(Stream_Audio, 0, Audio_Channel_s_, 2);
Fill(Stream_Audio, 0, Audio_SamplingRate, 44100);
Fill(Stream_Audio, 0, Audio_FrameRate, (float)75);
Fill(Stream_Audio, 0, Audio_BitRate, 1411200);
Fill(Stream_Audio, 0, Audio_Compression_Mode, "Lossless");
Fill(Stream_Audio, 0, Audio_FrameCount, TDuration);
Fill(Stream_Audio, 0, Audio_Duration, float32_int32s(((float32)TDuration)*1000/75));
Fill(Stream_Audio, 0, Audio_Delay, float32_int32s(((float32)TPosition)*1000/75));
//No more need data
Finish("CDDA");
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Riff::CMJP()
{
Element_Name("CMP4 - JPEG");
//Parsing
#ifdef MEDIAINFO_JPEG_YES
Stream_ID=0;
File_Jpeg* Parser=new File_Jpeg;
Open_Buffer_Init(Parser);
Parser->StreamKind=Stream_Video;
Open_Buffer_Continue(Parser);
Element_Offset=Element_TotalSize_Get(); //Not using Skip_XX() because we want to skip data we don't have, and Skip_XX() does a test on size of buffer
FILLING_BEGIN();
Stream_Prepare(Stream_Video);
Fill(Stream_Video, StreamPos_Last, Video_StreamSize, Element_TotalSize_Get());
Finish(Parser);
Merge(*Parser, StreamKind_Last, 0, StreamPos_Last);
FILLING_END();
Stream[Stream_ID].Parsers.push_back(Parser);
#else
Element_Offset=Element_TotalSize_Get(); //Not using Skip_XX() because we want to skip data we don't have, and Skip_XX() does a test on size of buffer
FILLING_BEGIN();
Stream_Prepare(Stream_Video);
Fill(Stream_Video, StreamPos_Last, Video_Format, "JPEG");
Fill(Stream_Video, StreamPos_Last, Video_StreamSize, Element_TotalSize_Get());
FILLING_END();
#endif
}
//---------------------------------------------------------------------------
void File_Riff::CMP4()
{
Accept("CMP4");
Element_Name("CMP4 - Header");
//Parsing
Ztring Title;
Get_Local(Element_Size, Title, "Title");
FILLING_BEGIN();
Fill(Stream_General, 0, General_Format, "CMP4");
Fill(Stream_General, 0, "Title", Title);
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Riff::IDVX()
{
Element_Name("Tags");
}
//---------------------------------------------------------------------------
void File_Riff::INDX()
{
Element_Name("Index (from which spec?)");
}
//---------------------------------------------------------------------------
void File_Riff::INDX_xxxx()
{
Stream_ID=(int32u)(Element_Code&0xFFFF0000);
if (Stream_ID==0x69780000) //ix..
{
//Index
int32u Entry_Count, ChunkId;
int16u LongsPerEntry;
int8u IndexType, IndexSubType;
Get_L2 (LongsPerEntry, "LongsPerEntry"); //Size of each entry in aIndex array
Get_L1 (IndexSubType, "IndexSubType");
Get_L1 (IndexType, "IndexType");
Get_L4 (Entry_Count, "EntriesInUse"); //Index of first unused member in aIndex array
Get_C4 (ChunkId, "ChunkId"); //FCC of what is indexed
Skip_L4( "Unknown");
Skip_L4( "Unknown");
Skip_L4( "Unknown");
for (int32u Pos=0; Pos<Entry_Count; Pos++)
{
Skip_L8( "Offset");
Skip_L4( "Size");
Skip_L4( "Frame number?");
Skip_L4( "Frame number?");
Skip_L4( "Zero");
}
}
//Currently, we do not use the index
//TODO: use the index
Stream_Structure.clear();
}
//---------------------------------------------------------------------------
void File_Riff::JUNK()
{
Element_Name("Junk");
//Parse
#if MEDIAINFO_TRACE
if (Trace_Activated)
Param("Junk", Ztring("(")+Ztring::ToZtring(Element_TotalSize_Get())+Ztring(" bytes)"));
#endif //MEDIAINFO_TRACE
Element_Offset=Element_TotalSize_Get(); //Not using Skip_XX() because we want to skip data we don't have, and Skip_XX() does a test on size of buffer
}
//---------------------------------------------------------------------------
void File_Riff::menu()
{
Element_Name("DivX Menu");
//Filling
Stream_Prepare(Stream_Menu);
Fill(Stream_Menu, StreamPos_Last, Menu_Format, "DivX Menu");
Fill(Stream_Menu, StreamPos_Last, Menu_Codec, "DivX");
}
//---------------------------------------------------------------------------
void File_Riff::MThd()
{
Element_Name("MIDI header");
//Parsing
Skip_B2( "format");
Skip_B2( "ntrks");
Skip_B2( "division");
FILLING_BEGIN_PRECISE();
Accept("MIDI");
Fill(Stream_General, 0, General_Format, "MIDI");
FILLING_ELSE();
Reject("MIDI");
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Riff::MTrk()
{
Element_Name("MIDI Track");
//Parsing
#if MEDIAINFO_TRACE
if (Trace_Activated)
Param("Data", Ztring("(")+Ztring::ToZtring(Element_TotalSize_Get())+Ztring(" bytes)"));
#endif //MEDIAINFO_TRACE
Element_Offset=Element_TotalSize_Get(); //Not using Skip_XX() because we want to skip data we don't have, and Skip_XX() does a test on size of buffer
FILLING_BEGIN();
Stream_Prepare(Stream_Audio);
Fill(Stream_Audio, StreamPos_Last, Audio_Format, "MIDI");
Fill(Stream_Audio, StreamPos_Last, Audio_Codec, "Midi");
Finish("MIDI");
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Riff::PAL_()
{
Data_Accept("RIFF Palette");
Element_Name("RIFF Palette");
//Filling
Fill(Stream_General, 0, General_Format, "RIFF Palette");
}
//---------------------------------------------------------------------------
void File_Riff::QLCM()
{
Data_Accept("QLCM");
Element_Name("QLCM");
//Filling
Fill(Stream_General, 0, General_Format, "QLCM");
}
//---------------------------------------------------------------------------
void File_Riff::QLCM_fmt_()
{
//Parsing
Ztring codec_name;
int128u codec_guid;
int32u num_rates;
int16u codec_version, average_bps, packet_size, block_size, sampling_rate, sample_size;
int8u major, minor;
Get_L1 (major, "major");
Get_L1 (minor, "minor");
Get_GUID(codec_guid, "codec-guid");
Get_L2 (codec_version, "codec-version");
Get_UTF8(80, codec_name, "codec-name");
Get_L2 (average_bps, "average-bps");
Get_L2 (packet_size, "packet-size");
Get_L2 (block_size, "block-size");
Get_L2 (sampling_rate, "sampling-rate");
Get_L2 (sample_size, "sample-size");
Element_Begin1("rate-map-table");
Get_L4 (num_rates, "num-rates");
for (int32u rate=0; rate<num_rates; rate++)
{
Skip_L2( "rate-size");
Skip_L2( "rate-octet");
}
Element_End0();
Skip_L4( "Reserved");
Skip_L4( "Reserved");
Skip_L4( "Reserved");
Skip_L4( "Reserved");
if (Element_Offset<Element_Size)
Skip_L4( "Reserved"); //Some files don't have the 5th reserved dword
FILLING_BEGIN_PRECISE();
Stream_Prepare (Stream_Audio);
switch (codec_guid.hi)
{
case Elements::QLCM_QCELP1 :
case Elements::QLCM_QCELP2 : Fill(Stream_Audio, 0, Audio_Format, "QCELP"); Fill(Stream_Audio, 0, Audio_Codec, "QCELP"); break;
case Elements::QLCM_EVRC : Fill(Stream_Audio, 0, Audio_Format, "EVRC"); Fill(Stream_Audio, 0, Audio_Codec, "EVRC"); break;
case Elements::QLCM_SMV : Fill(Stream_Audio, 0, Audio_Format, "SMV"); Fill(Stream_Audio, 0, Audio_Codec, "SMV"); break;
default : ;
}
Fill(Stream_Audio, 0, Audio_BitRate, average_bps);
Fill(Stream_Audio, 0, Audio_SamplingRate, sampling_rate);
Fill(Stream_Audio, 0, Audio_BitDepth, sample_size);
Fill(Stream_Audio, 0, Audio_Channel_s_, 1);
FILLING_END();
}
#if defined(MEDIAINFO_GXF_YES)
//---------------------------------------------------------------------------
void File_Riff::rcrd()
{
Data_Accept("Ancillary media packets");
Element_Name("Ancillary media packets");
//Filling
if (Retrieve(Stream_General, 0, General_Format).empty())
Fill(Stream_General, 0, General_Format, "Ancillary media packets"); //GXF, RDD14-2007
//Clearing old data
if (Ancillary)
{
(*Ancillary)->FrameInfo.DTS=FrameInfo.DTS;
Open_Buffer_Continue(*Ancillary, Buffer, 0);
}
}
//---------------------------------------------------------------------------
void File_Riff::rcrd_desc()
{
Element_Name("Ancillary media packet description");
//Parsing
int32u Version;
Get_L4 (Version, "Version");
if (Version==2)
{
Skip_L4( "Number of fields");
Skip_L4( "Length of the ancillary data field descriptions");
Skip_L4( "Byte size of the complete ancillary media packet");
Skip_L4( "Format of the video");
}
else
Skip_XX(Element_Size-Element_Offset, "Unknown");
}
//---------------------------------------------------------------------------
void File_Riff::rcrd_fld_()
{
Element_Name("Ancillary data field description");
}
//---------------------------------------------------------------------------
void File_Riff::rcrd_fld__anc_()
{
Element_Name("Ancillary data sample description");
rcrd_fld__anc__pos__LineNumber=(int32u)-1;
}
//---------------------------------------------------------------------------
void File_Riff::rcrd_fld__anc__pos_()
{
Element_Name("Ancillary data sample description");
//Parsing
Get_L4 (rcrd_fld__anc__pos__LineNumber, "Video line number");
Skip_L4( "Ancillary video color difference or luma space");
Skip_L4( "Ancillary video space");
}
//---------------------------------------------------------------------------
void File_Riff::rcrd_fld__anc__pyld()
{
Element_Name("Ancillary data sample payload");
if (Ancillary)
{
(*Ancillary)->FrameInfo.DTS=FrameInfo.DTS;
(*Ancillary)->LineNumber=rcrd_fld__anc__pos__LineNumber;
Open_Buffer_Continue(*Ancillary);
}
}
//---------------------------------------------------------------------------
void File_Riff::rcrd_fld__finf()
{
Element_Name("Data field description");
//Parsing
Skip_L4( "Video field identifier");
}
#endif //MEDIAINFO_GXF_YES
//---------------------------------------------------------------------------
void File_Riff::RDIB()
{
Data_Accept("RIFF DIB");
Element_Name("RIFF DIB");
//Filling
Fill(Stream_General, 0, General_Format, "RIFF DIB");
}
//---------------------------------------------------------------------------
void File_Riff::RMID()
{
Data_Accept("RIFF MIDI");
Element_Name("RIFF MIDI");
//Filling
Fill(Stream_General, 0, General_Format, "RIFF MIDI");
}
//---------------------------------------------------------------------------
void File_Riff::RMMP()
{
Data_Accept("RIFF MMP");
Element_Name("RIFF MMP");
//Filling
Fill(Stream_General, 0, General_Format, "RIFF MMP");
}
//---------------------------------------------------------------------------
void File_Riff::RMP3()
{
Data_Accept("RMP3");
Element_Name("RMP3");
//Filling
Fill(Stream_General, 0, General_Format, "RMP3");
Kind=Kind_Rmp3;
}
//---------------------------------------------------------------------------
void File_Riff::RMP3_data()
{
Element_Name("Raw datas");
Fill(Stream_Audio, 0, Audio_StreamSize, Buffer_DataToParse_End-Buffer_DataToParse_Begin);
Stream_Prepare(Stream_Audio);
//Creating parser
#if defined(MEDIAINFO_MPEGA_YES)
File_Mpega* Parser=new File_Mpega;
Parser->CalculateDelay=true;
Parser->ShouldContinueParsing=true;
Open_Buffer_Init(Parser);
stream& StreamItem=Stream[(int32u)-1];
StreamItem.StreamKind=Stream_Audio;
StreamItem.StreamPos=0;
StreamItem.Parsers.push_back(Parser);
#else //MEDIAINFO_MPEG4_YES
Fill(Stream_Audio, 0, Audio_Format, "MPEG Audio");
Skip_XX(Buffer_DataToParse_End-Buffer_DataToParse_Begin, "Data");
#endif
}
//---------------------------------------------------------------------------
void File_Riff::RMP3_data_Continue()
{
#if MEDIAINFO_DEMUX
if (Element_Size)
{
Demux_random_access=true;
Demux(Buffer+Buffer_Offset, (size_t)Element_Size, ContentType_MainStream);
}
#endif //MEDIAINFO_DEMUX
Element_Code=(int64u)-1;
AVI__movi_xxxx();
}
//---------------------------------------------------------------------------
void File_Riff::SMV0()
{
Accept("SMV");
//Parsing
int8u Version;
Skip_C1( "Identifier (continuing)");
Get_C1 (Version, "Version");
Skip_C3( "Identifier (continuing)");
if (Version=='1')
{
int32u Width, Height, FrameRate, BlockSize, FrameCount;
Get_B3 (Width, "Width");
Get_B3 (Height, "Height");
Skip_B3( "0x000010");
Skip_B3( "0x000001");
Get_B3 (BlockSize, "Block size");
Get_B3 (FrameRate, "Frame rate");
Get_B3 (FrameCount, "Frame count");
Skip_B3( "0x000000");
Skip_B3( "0x000000");
Skip_B3( "0x000000");
Skip_B3( "0x010101");
Skip_B3( "0x010101");
Skip_B3( "0x010101");
Skip_B3( "0x010101");
//Filling
Fill(Stream_General, 0, General_Format_Profile, "SMV v1");
Stream_Prepare(Stream_Video);
Fill(Stream_Video, 0, Video_MuxingMode, "SMV v1");
Fill(Stream_Video, 0, Video_Width, Width);
Fill(Stream_Video, 0, Video_Height, Height);
Fill(Stream_Video, 0, Video_FrameRate, (float)FrameRate);
Fill(Stream_Video, 0, Video_FrameCount, FrameCount);
Finish("SMV");
}
else if (Version=='2')
{
int32u Width, Height, FrameRate;
Get_L3 (Width, "Width");
Get_L3 (Height, "Height");
Skip_L3( "0x000010");
Skip_L3( "0x000001");
Get_L3 (SMV_BlockSize, "Block size");
Get_L3 (FrameRate, "Frame rate");
Get_L3 (SMV_FrameCount, "Frame count");
Skip_L3( "0x000001");
Skip_L3( "0x000000");
Skip_L3( "Frame rate");
Skip_L3( "0x010101");
Skip_L3( "0x010101");
Skip_L3( "0x010101");
Skip_L3( "0x010101");
//Filling
SMV_BlockSize+=3;
SMV_FrameCount++;
Fill(Stream_General, 0, General_Format_Profile, "SMV v2");
Stream_Prepare(Stream_Video);
Fill(Stream_Video, 0, Video_Format, "JPEG");
Fill(Stream_Video, 0, Video_Codec, "JPEG");
Fill(Stream_Video, 0, Video_MuxingMode, "SMV v2");
Fill(Stream_Video, 0, Video_Width, Width);
Fill(Stream_Video, 0, Video_Height, Height);
Fill(Stream_Video, 0, Video_FrameRate, FrameRate);
Fill(Stream_Video, 0, Video_FrameCount, SMV_FrameCount);
Fill(Stream_Video, 0, Video_StreamSize, SMV_BlockSize*SMV_FrameCount);
}
else
Finish("SMV");
}
//---------------------------------------------------------------------------
void File_Riff::SMV0_xxxx()
{
//Parsing
int32u Size;
Get_L3 (Size, "Size");
#if defined(MEDIAINFO_JPEG_YES)
//Creating the parser
File_Jpeg MI;
Open_Buffer_Init(&MI);
//Parsing
Open_Buffer_Continue(&MI, Size);
//Filling
Finish(&MI);
Merge(MI, Stream_Video, 0, StreamPos_Last);
//Positioning
Element_Offset+=Size;
#else
//Parsing
Skip_XX(Size, "JPEG data");
#endif
Skip_XX(Element_Size-Element_Offset, "Padding");
//Filling
#if MEDIAINFO_HASH
if (Config->File_Hash_Get().to_ulong())
Element_Offset=Element_Size+(SMV_FrameCount-1)*SMV_BlockSize;
#endif //MEDIAINFO_HASH
Data_GoTo(File_Offset+Buffer_Offset+(size_t)Element_Size+(SMV_FrameCount-1)*SMV_BlockSize, "SMV");
SMV_BlockSize=0;
}
//---------------------------------------------------------------------------
void File_Riff::WAVE()
{
Data_Accept("Wave");
Element_Name("Wave");
//Filling
Fill(Stream_General, 0, General_Format, "Wave");
Kind=Kind_Wave;
#if MEDIAINFO_EVENTS
StreamIDs_Width[0]=0;
#endif //MEDIAINFO_EVENTS
}
//---------------------------------------------------------------------------
void File_Riff::WAVE__pmx()
{
Element_Name("XMP");
//Parsing
Ztring XML_Data;
Get_UTF8(Element_Size, XML_Data, "XML data");
}
//---------------------------------------------------------------------------
static const char* profile_names[]=
{
"profileName",
"profileVersion",
"profileID",
"levelID",
};
static const int profile_names_size=(int)sizeof(profile_names)/sizeof(const char*);
static const char* profile_names_InternalID[profile_names_size]=
{
"Format",
"Version",
"Profile",
"Level",
};
struct profile_info
{
string Strings[4];
string profile_info_build(size_t Max=profile_names_size)
{
bool HasParenthsis=false;
string ToReturn;
for (size_t i=0; i<Max; i++)
{
if (!Strings[i].empty())
{
if (!ToReturn.empty())
{
if (i==1)
ToReturn+=", Version";
if (!HasParenthsis)
ToReturn+=' ';
}
if (i>=2)
{
if (!HasParenthsis)
{
ToReturn+='(';
HasParenthsis=true;
}
else
{
ToReturn+=',';
ToReturn+=' ';
}
}
if (i>=2)
{
ToReturn+=profile_names[i];
ToReturn+='=';
}
ToReturn+=Strings[i];
}
}
if (HasParenthsis)
ToReturn+=')';
return ToReturn;
}
};
void File_Riff::WAVE_axml()
{
int64u Element_TotalSize=Element_TotalSize_Get();
if (Element_Size!=Element_TotalSize-Alignement_ExtraByte)
{
if (Buffer_MaximumSize<Element_TotalSize)
Buffer_MaximumSize+=Element_TotalSize;
size_t* File_Buffer_Size_Hint_Pointer=Config->File_Buffer_Size_Hint_Pointer_Get();
if (File_Buffer_Size_Hint_Pointer)
(*File_Buffer_Size_Hint_Pointer)=(size_t)(Element_TotalSize-Element_Size);
Element_WaitForMoreData();
return; //Must wait for more data
}
int8u* UncompressedData;
size_t UncompressedData_Size;
if (Element_Code==Elements::WAVE_bxml)
{
Element_Name("Compressed AXML");
//Header
int16u Version; // Maybe...
Get_L2 (Version, "Version");
if (Version!=1)
{
Skip_XX(Element_Size-Element_Offset, "Data (Unsuported)");
return;
}
//Uncompress init
z_stream strm;
strm.next_in=(Bytef*)Buffer+Buffer_Offset+2;
strm.avail_in=(uInt)Element_Size-2;
strm.next_out=NULL;
strm.avail_out=0;
strm.total_out=0;
strm.zalloc=Z_NULL;
strm.zfree=Z_NULL;
inflateInit2(&strm, 15+16); // 15 + 16 are magic values for gzip
//Prepare out
strm.avail_out=0x10000; //Blocks of 64 KiB, arbitrary chosen, as a begin
strm.next_out=(Bytef*)new Bytef[strm.avail_out];
//Parse compressed data, with handling of the case the output buffer is not big enough
for (;;)
{
//inflate
int inflate_Result=inflate(&strm, Z_NO_FLUSH);
if (inflate_Result<0)
break;
//Check if we need to stop
if (strm.avail_out || inflate_Result)
break;
//Need to increase buffer
size_t UncompressedData_NewMaxSize=strm.total_out*4;
int8u* UncompressedData_New=new int8u[UncompressedData_NewMaxSize];
memcpy(UncompressedData_New, strm.next_out-strm.total_out, strm.total_out);
delete[] (strm.next_out-strm.total_out); strm.next_out=UncompressedData_New;
strm.next_out=strm.next_out+strm.total_out;
strm.avail_out=UncompressedData_NewMaxSize-strm.total_out;
}
UncompressedData=strm.next_out-strm.total_out;
UncompressedData_Size=strm.total_out;
}
else
{
Element_Name("AXML");
UncompressedData=(int8u*)Buffer+Buffer_Offset;
UncompressedData_Size=(size_t)Element_Size;
}
//Parsing
File_Adm* Adm_New=new File_Adm;
Adm_New->MuxingMode=(Element_Code==Elements::WAVE_bxml)?'b':'a';
Adm_New->MuxingMode+="xml";
Open_Buffer_Init(Adm_New);
Open_Buffer_Continue(Adm_New, UncompressedData, UncompressedData_Size);
Finish(Adm_New);
if (Adm_New->Status[IsAccepted])
{
delete Adm;
Adm=Adm_New;
}
//Parsing
Skip_UTF8(Element_Size, "XML data");
}
//---------------------------------------------------------------------------
void File_Riff::WAVE_adtl()
{
Element_Name("Associated Data List");
}
//---------------------------------------------------------------------------
void File_Riff::WAVE_adtl_labl()
{
Element_Name("Label");
//Parsing
Skip_L4( "Cue Point ID");
Skip_UTF8(Element_Size-Element_Offset, "Text");
}
//---------------------------------------------------------------------------
void File_Riff::WAVE_adtl_ltxt()
{
Element_Name("Labeled Text");
//Parsing
Skip_L4( "Cue Point ID");
Skip_L4( "Sample Length");
Skip_C4( "Purpose ID");
Skip_L2( "Country");
Skip_L2( "Language");
Skip_L2( "Dialect");
Skip_L2( "Code Page");
Skip_UTF8(Element_Size-Element_Offset, "Text");
}
//---------------------------------------------------------------------------
void File_Riff::WAVE_adtl_note()
{
Element_Name("Note");
//Parsing
Skip_L4( "Cue Point ID");
Skip_UTF8(Element_Size-Element_Offset, "Text");
}
//---------------------------------------------------------------------------
void File_Riff::WAVE_bext()
{
Element_Name("Broadcast extension");
//Parsing
Ztring Description, Originator, OriginatorReference, OriginationDate, OriginationTime, History;
int128u UMID1, UMID2, UMID3, UMID4;
int16u Version, LoudnessValue=0x7FFF, LoudnessRange=0x7FFF, MaxTruePeakLevel=0x7FFF, MaxMomentaryLoudness=0x7FFF, MaxShortTermLoudness=0x7FFF;
Get_Local(256, Description, "Description");
Get_Local( 32, Originator, "Originator");
Get_Local( 32, OriginatorReference, "OriginatorReference");
Get_Local( 10, OriginationDate, "OriginationDate");
Get_Local( 8, OriginationTime, "OriginationTime");
Get_L8 ( TimeReference, "TimeReference"); //To be divided by SamplesPerSec
Get_L2 ( Version, "Version");
if (Version>=1)
{
Get_UUID (UMID1, "UMID");
Get_UUID (UMID2, "UMID");
Get_UUID (UMID3, "UMID");
Get_UUID (UMID4, "UMID");
}
if (Version>=2)
{
Get_L2 (LoudnessValue, "LoudnessValue");
Get_L2 (LoudnessRange, "LoudnessRange");
Get_L2 (MaxTruePeakLevel, "MaxTruePeakLevel");
Get_L2 (MaxMomentaryLoudness, "MaxMomentaryLoudness");
Get_L2 (MaxShortTermLoudness, "MaxShortTermLoudness");
}
Skip_XX (602-Element_Offset, "Reserved");
if (Element_Offset<Element_Size)
Get_Local(Element_Size-Element_Offset, History, "History");
FILLING_BEGIN();
// Handle some buggy OriginationDate/OriginalTime, prefixed 0 are sometimes missing e.g. 2015-3-2
if (OriginationDate.size()!=10
&& OriginationDate.size()>=8
&& OriginationDate[0]>=__T('0') && OriginationDate[0]<=__T('9')
&& OriginationDate[1]>=__T('0') && OriginationDate[1]<=__T('9')
&& OriginationDate[2]>=__T('0') && OriginationDate[2]<=__T('9')
&& OriginationDate[3]>=__T('0') && OriginationDate[3]<=__T('9')
&& OriginationDate[4]==__T('-')
&& OriginationDate[5]>=__T('0') && OriginationDate[5]<=__T('9'))
{
Ztring Modified(OriginationDate);
if (Modified[6]==__T('-'))
Modified.insert(5, 1, __T('0'));
if (Modified.size()==10
&& Modified[8]>=__T('0') && Modified[8]<=__T('9')
&& Modified[9]>=__T('0') && Modified[9]<=__T('9'))
OriginationDate=Modified;
if (Modified.size()==9
&& Modified[8]>=__T('0') && Modified[8]<=__T('9'))
{
Modified.insert(8, 1, __T('0'));
OriginationDate=Modified;
}
}
if (OriginationTime.size()!=8
&& OriginationTime.size()>=6
&& OriginationTime[0]>=__T('0') && OriginationTime[0]<=__T('9')
&& OriginationTime[1]>=__T('0') && OriginationTime[1]<=__T('9')
&& OriginationTime[2]==__T(':')
&& OriginationTime[3]>=__T('0') && OriginationTime[3]<=__T('9'))
{
Ztring Modified(OriginationTime);
if (Modified[4]==__T(':'))
Modified.insert(3, 1, __T('0'));
if (Modified.size()==8
&& Modified[6]>=__T('0') && Modified[6]<=__T('9')
&& Modified[7]>=__T('0') && Modified[7]<=__T('9'))
OriginationTime=Modified;
if (Modified.size()==7
&& Modified[6]>=__T('0') && Modified[6]<=__T('9'))
{
Modified.insert(6, 1, __T('0'));
OriginationTime=Modified;
}
}
Fill(Stream_General, 0, "bext_Present", "Yes");
Fill_SetOptions(Stream_General, 0, "bext_Present", "N NT");
Fill(Stream_General, 0, "bext_Version", Version);
Fill_SetOptions(Stream_General, 0, "bext_Version", "N NIY");
Fill(Stream_General, 0, General_Description, Description);
Fill(Stream_General, 0, General_Producer, Originator);
Fill(Stream_General, 0, "Producer_Reference", OriginatorReference);
Fill(Stream_General, 0, General_Encoded_Date, OriginationDate+__T(' ')+OriginationTime);
Fill(Stream_General, 0, General_Encoded_Library_Settings, History);
if (SamplesPerSec && TimeReference!=(int64u)-1)
{
Fill(Stream_Audio, 0, Audio_Delay, ((float64)TimeReference*1000/SamplesPerSec), 6);
Fill(Stream_Audio, 0, Audio_Delay_Source, "Container (bext)");
}
if (Version>=1 && UMID1 != 0 && UMID2 != 0)
{
Ztring UMID=__T("0x")+Ztring().From_UTF8(uint128toString(UMID1, 16))+Ztring().From_UTF8(uint128toString(UMID2, 16));
if ((UMID1.lo&0xFF000000)==0x33000000)
UMID+=Ztring().From_UTF8(uint128toString(UMID3, 16))+Ztring().From_UTF8(uint128toString(UMID4, 16));
Fill(Stream_General, 0, "UMID", UMID);
}
if (Version>=2)
{
if (LoudnessValue!=0x7FFF)
Fill(Stream_Audio, 0, "LoudnessValue", (float)((int16s)LoudnessValue)/100, 2);
if (LoudnessRange!=0x7FFF)
Fill(Stream_Audio, 0, "LoudnessRange", (float)((int16s)LoudnessRange)/100, 2);
if (MaxTruePeakLevel!=0x7FFF)
Fill(Stream_Audio, 0, "MaxTruePeakLevel", (float)((int16s)MaxTruePeakLevel)/100, 2);
if (MaxMomentaryLoudness!=0x7FFF)
Fill(Stream_Audio, 0, "MaxMomentaryLoudness", (float)((int16s)MaxMomentaryLoudness)/100, 2);
if (MaxShortTermLoudness!=0x7FFF)
Fill(Stream_Audio, 0, "MaxShortTermLoudness", (float)((int16s)MaxShortTermLoudness)/100, 2);
}
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Riff::WAVE_cue_()
{
Element_Name("Cue points");
//Parsing
int32u numCuePoints;
Get_L4(numCuePoints, "numCuePoints");
for (int32u Pos=0; Pos<numCuePoints; Pos++)
{
Element_Begin1("Cue point");
Skip_L4( "ID");
Skip_L4( "Position");
Skip_C4( "DataChunkID");
Skip_L4( "ChunkStart");
Skip_L4( "BlockStart");
Skip_L4( "SampleOffset");
Element_End0();
}
}
//---------------------------------------------------------------------------
void File_Riff::WAVE_data()
{
Element_Name("Raw datas");
if (Buffer_DataToParse_End-Buffer_DataToParse_Begin<100)
{
Skip_XX(Buffer_DataToParse_End-Buffer_Offset, "Unknown");
return; //This is maybe embeded in another container, and there is only the header (What is the junk?)
}
//Parsing
Element_Code=(int64u)-1;
FILLING_BEGIN();
int64u StreamSize=Buffer_DataToParse_End-Buffer_DataToParse_Begin;
Fill(Stream_Audio, 0, Audio_StreamSize, StreamSize, 10, true);
if (Retrieve(Stream_Audio, 0, Audio_Format)==__T("PCM") && BlockAlign)
Fill(Stream_Audio, 0, Audio_SamplingCount, StreamSize/BlockAlign, 10, true);
float64 Duration=Retrieve(Stream_Audio, 0, Audio_Duration).To_float64();
float64 BitRate=Retrieve(Stream_Audio, 0, Audio_BitRate).To_float64();
if (Duration)
{
float64 BitRate_New=((float64)StreamSize)*8*1000/Duration;
if (BitRate_New<BitRate*0.95 || BitRate_New>BitRate*1.05)
Fill(Stream_Audio, 0, Audio_BitRate, BitRate_New, 10, true); //Correcting the bitrate, it was false in the header
}
else if (BitRate)
{
if (IsSub)
//Retrieving "data" real size, in case of truncated files and/or wave header in another container
Duration=((float64)LittleEndian2int32u(Buffer+Buffer_Offset-4))*8*1000/BitRate; //TODO: RF64 is not handled
else
Duration=((float64)StreamSize)*8*1000/BitRate;
Fill(Stream_General, 0, General_Duration, Duration, 0, true);
Fill(Stream_Audio, 0, Audio_Duration, Duration, 0, true);
}
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Riff::WAVE_data_Continue()
{
#if MEDIAINFO_DEMUX
Element_Code=(int64u)-1;
if (AvgBytesPerSec && Demux_Rate)
{
FrameInfo.DTS=float64_int64s((File_Offset+Buffer_Offset-Buffer_DataToParse_Begin)*1000000000.0/AvgBytesPerSec);
FrameInfo.PTS=FrameInfo.DTS;
Frame_Count_NotParsedIncluded=float64_int64s(((float64)FrameInfo.DTS)/1000000000.0*Demux_Rate);
}
Demux_random_access=true;
Demux(Buffer+Buffer_Offset, (size_t)Element_Size, ContentType_MainStream);
Frame_Count_NotParsedIncluded=(int64u)-1;
#endif //MEDIAINFO_DEMUX
Element_Code=(int64u)-1;
AVI__movi_xxxx();
}
//---------------------------------------------------------------------------
void File_Riff::WAVE_dbmd()
{
Element_Name("Dolby Audio Metadata");
//Parsing
File_DolbyAudioMetadata* DolbyAudioMetadata_New=new File_DolbyAudioMetadata;
Open_Buffer_Init(DolbyAudioMetadata_New);
Open_Buffer_Continue(DolbyAudioMetadata_New);
if (DolbyAudioMetadata_New->Status[IsAccepted])
{
delete DolbyAudioMetadata;
DolbyAudioMetadata=DolbyAudioMetadata_New;
}
}
//---------------------------------------------------------------------------
void File_Riff::WAVE_ds64()
{
Element_Name("DataSize64");
//Parsing
int64u dataSize, sampleCount;
int32u tableLength;
Skip_L8( "riffSize"); //Is directly read from the header parser
Get_L8 (dataSize, "dataSize");
Get_L8 (sampleCount, "sampleCount");
Get_L4 (tableLength, "tableLength");
for (int32u Pos=0; Pos<tableLength; Pos++)
Skip_L8( "table[]");
FILLING_BEGIN();
if (dataSize && dataSize<File_Size)
{
WAVE_data_Size=dataSize;
if (Retrieve(Stream_Audio, 0, Audio_StreamSize).empty()) // Not the priority
Fill(Stream_Audio, 0, Audio_StreamSize, WAVE_data_Size);
}
if (sampleCount && sampleCount<File_Size)
{
WAVE_fact_samplesCount=sampleCount;
if (WAVE_fact_samplesCount && WAVE_fact_samplesCount<File_Size && Retrieve(Stream_Audio, 0, Audio_SamplingCount).empty()) // Not the priority
Fill(Stream_Audio, 0, Audio_SamplingCount, WAVE_fact_samplesCount);
}
if (WAVE_data_Size && WAVE_data_Size<File_Size && WAVE_fact_samplesCount && WAVE_fact_samplesCount<File_Size)
{
int64u ComputedBlockAlign=WAVE_data_Size/WAVE_fact_samplesCount;
if (ComputedBlockAlign<0x10000)
BlockAlign=ComputedBlockAlign;
}
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Riff::WAVE_fact()
{
Element_Name("Sample count");
//Parsing
int32u SamplesCount;
Get_L4 (SamplesCount, "SamplesCount");
FILLING_BEGIN();
if (!Retrieve(Stream_Audio, 0, Audio_SamplingCount).empty()) // Not the priority
{
int64u SamplesCount64=SamplesCount==(int32u)-1?WAVE_fact_samplesCount:SamplesCount;
float64 SamplingRate=Retrieve(Stream_Audio, 0, Audio_SamplingRate).To_float64();
if (SamplesCount64!=(int64u)-1 && SamplingRate)
{
//Calculating
float64 Duration=((float64)SamplesCount64)*1000/SamplingRate;
//Coherency test
bool IsOK=true;
if (File_Size!=(int64u)-1)
{
float64 BitRate=Retrieve(Stream_Audio, 0, Audio_BitRate).To_float64();
if (BitRate)
{
int64u Duration_FromBitRate = File_Size * 8 * 1000 / BitRate;
if (Duration_FromBitRate > Duration*1.02 || Duration_FromBitRate < Duration*0.98)
IsOK = false;
}
}
//Filling
if (IsOK)
Fill(Stream_Audio, 0, Audio_SamplingCount, SamplesCount, 10, true);
}
}
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Riff::WAVE_fmt_()
{
//Compute the current codec ID
Element_Code=(int64u)-1;
Stream_ID=(int32u)-1;
stream_Count=1;
Stream[(int32u)-1].fccType=Elements::AVI__hdlr_strl_strh_auds;
AVI__hdlr_strl_strf();
}
//---------------------------------------------------------------------------
void File_Riff::WAVE_ID3_()
{
Element_Name("ID3v2 tags");
//Parsing
#if defined(MEDIAINFO_ID3V2_YES)
File_Id3v2 MI;
Open_Buffer_Init(&MI);
Open_Buffer_Continue(&MI);
Finish(&MI);
Merge(MI, Stream_General, 0, 0);
#endif
}
//---------------------------------------------------------------------------
void File_Riff::WAVE_iXML()
{
Element_Name("iXML");
//Parsing
Skip_UTF8(Element_Size, "XML data");
}
//---------------------------------------------------------------------------
void File_Riff::WAVE_mext()
{
Element_Name("MPEG Audio extension");
//Parsing
Info_L2( SoundInformation, "SoundInformation");
Skip_Flags(SoundInformation, 0, "Homogeneous sound data");
Skip_Flags(SoundInformation, 1, "Padding bit is used");
Skip_Flags(SoundInformation, 2, "File contains a sequence of frames with padding bit set to 0");
Skip_Flags(SoundInformation, 3, "Free format is used");
Skip_L2( "FrameSize");
Skip_L2( "AncillaryDataLength");
Info_L2( AncillaryDataDef, "AncillaryDataDef");
Skip_Flags(AncillaryDataDef, 0, "Energy of left channel present");
Skip_Flags(AncillaryDataDef, 1, "A private byte is free for internal use");
Skip_Flags(AncillaryDataDef, 2, "Energy of right channel present ");
Skip_L4( "Reserved");
}
//---------------------------------------------------------------------------
void File_Riff::wave()
{
Data_Accept("Wave64");
Element_Name("Wave64");
//Filling
Fill(Stream_General, 0, General_Format, "Wave64");
}
//---------------------------------------------------------------------------
void File_Riff::W3DI()
{
Element_Name("IDVX tags (Out of specs!)");
//Parsing
int32u Size=(int32u)Element_Size;
Ztring Title, Artist, Album, Unknown, Genre, Comment;
int32u TrackPos;
Get_Local(Size, Title, "Title");
Element_Offset=(int32u)Title.size();
Size-=(int32u)Title.size();
if (Size==0) return;
Skip_L1( "Zero"); Size--; //NULL char
Get_Local(Size, Artist, "Artist");
Element_Offset=(int32u)Title.size()+1+(int32u)Artist.size();
Size-=(int32u)Artist.size();
if (Size==0) return;
Skip_L1( "Zero"); Size--; //NULL char
Get_Local(Size, Album, "Album");
Element_Offset=(int32u)Title.size()+1+(int32u)Artist.size()+1+(int32u)Album.size();
Size-=(int32u)Album.size();
if (Size==0) return;
Skip_L1( "Zero"); Size--; //NULL char
Get_Local(Size, Unknown, "Unknown");
Element_Offset=(int32u)Title.size()+1+(int32u)Artist.size()+1+(int32u)Album.size()+1+(int32u)Unknown.size();
Size-=(int32u)Unknown.size();
if (Size==0) return;
Skip_L1( "Zero"); Size--; //NULL char
Get_Local(Size, Genre, "Genre");
Element_Offset=(int32u)Title.size()+1+(int32u)Artist.size()+1+(int32u)Album.size()+1+(int32u)Unknown.size()+1+(int32u)Genre.size();
Size-=(int32u)Genre.size();
if (Size==0) return;
Skip_L1( "Zero"); Size--; //NULL char
Get_Local(Size, Comment, "Comment");
Element_Offset=(int32u)Title.size()+1+(int32u)Artist.size()+1+(int32u)Album.size()+1+(int32u)Unknown.size()+1+(int32u)Genre.size()+1+(int32u)Comment.size();
Size-=(int32u)Comment.size();
if (Size==0) return;
Skip_L1( "Zero"); Size--; //NULL char
Get_L4 (TrackPos, "Track_Position");
if(Element_Offset+8<Element_Size)
Skip_XX(Element_Size-Element_Offset, "Unknown");
Element_Begin1("Footer");
Skip_L4( "Size");
Skip_C4( "Name");
Element_End0();
//Filling
Fill(Stream_General, 0, General_Track, Title);
Fill(Stream_General, 0, General_Performer, Artist);
Fill(Stream_General, 0, General_Album, Album);
Fill(Stream_General, 0, "Unknown", Unknown);
Fill(Stream_General, 0, General_Genre, Genre);
Fill(Stream_General, 0, General_Comment, Comment);
Fill(Stream_General, 0, General_Track_Position, TrackPos);
}
void File_Riff::Open_Buffer_Init_All()
{
stream& StreamItem = Stream[Stream_ID];
for (size_t Pos = 0; Pos<StreamItem.Parsers.size(); Pos++)
Open_Buffer_Init(StreamItem.Parsers[Pos]);
}
//---------------------------------------------------------------------------
void File_Riff::Parser_Pcm(stream& StreamItem, int16u Channels, int16u BitsPerSample, int16u ValidBitsPerSample, int32u SamplesPerSec, char Endianness)
{
#if defined(MEDIAINFO_DTS_YES)
{
File_Dts* Parser=new File_Dts;
Parser->Frame_Count_Valid=2;
Parser->ShouldContinueParsing=true;
#if MEDIAINFO_DEMUX
if (Config->Demux_Unpacketize_Get() && Retrieve(Stream_General, 0, General_Format)==__T("Wave"))
{
Parser->Demux_Level=2; //Container
Parser->Demux_UnpacketizeContainer=true;
Demux_Level=4; //Intermediate
}
#endif //MEDIAINFO_DEMUX
StreamItem.Parsers.push_back(Parser);
}
#endif
#if defined(MEDIAINFO_SMPTEST0337_YES)
if (Channels==2 && BitsPerSample<=32 && SamplesPerSec==48000) //Some SMPTE ST 337 streams are hidden in PCM stream
{
File_SmpteSt0337* Parser=new File_SmpteSt0337;
Parser->Container_Bits=(int8u)BitsPerSample;
Parser->Aligned=true;
Parser->ShouldContinueParsing=true;
#if MEDIAINFO_DEMUX
if (Config->Demux_Unpacketize_Get() && Retrieve(Stream_General, 0, General_Format)==__T("Wave"))
{
Parser->Demux_Level=2; //Container
Parser->Demux_UnpacketizeContainer=true;
Demux_Level=4; //Intermediate
}
#endif //MEDIAINFO_DEMUX
StreamItem.Parsers.push_back(Parser);
}
if (Channels>=2 && BitsPerSample<=32 && SamplesPerSec==48000) //Some SMPTE ST 337 streams are hidden in PCM stream
{
File_ChannelSplitting* Parser=new File_ChannelSplitting;
Parser->Codec=Retrieve(Stream_Audio, StreamPos_Last, Audio_CodecID);
Parser->BitDepth=(int8u)BitsPerSample;
Parser->Endianness=Endianness;
Parser->Channel_Total=(int8u)Channels;
Parser->ShouldContinueParsing=true;
Parser->SamplingRate=48000;
#if MEDIAINFO_DEMUX
if (Config->Demux_Unpacketize_Get())
{
Parser->Demux_Level=2; //Container
Parser->Demux_UnpacketizeContainer=true;
Demux_Level=4; //Intermediate
}
#endif //MEDIAINFO_DEMUX
Stream[Stream_ID].Parsers.push_back(Parser);
}
#endif
#if defined(MEDIAINFO_PCM_YES)
File_Pcm* Parser=new File_Pcm;
Parser->Codec=Retrieve(Stream_Audio, StreamPos_Last, Audio_CodecID);
if (Endianness)
Parser->Endianness=Endianness;
Parser->BitDepth=(int8u)BitsPerSample;
if (ValidBitsPerSample!=BitsPerSample)
Parser->BitDepth_Significant=(int8u)ValidBitsPerSample;
#if MEDIAINFO_DEMUX
if (Config->Demux_Unpacketize_Get())
{
Parser->Demux_Level=2; //Container
Parser->Demux_UnpacketizeContainer=true;
Demux_Level=4; //Intermediate
}
#else //MEDIAINFO_DEMUX
Parser->Frame_Count_Valid=(int64u)-1; //Disabling it, waiting for SMPTE ST 337 parser reject
#endif //MEDIAINFO_DEMUX
StreamItem.Parsers.push_back(Parser);
StreamItem.IsPcm=true;
StreamItem.StreamKind=Stream_Audio;
#endif
}
//***************************************************************************
// C++
//***************************************************************************
} //NameSpace
#endif //MEDIAINFO_RIFF_YES
↑ V220 Suspicious sequence of types castings: memsize -> 32-bit integer -> memsize. The value being cast: 'sizeof (profile_names)'.
↑ V1063 The modulo by 1 operation is meaningless. The result will always be zero.
↑ V560 A part of conditional expression is always true: StreamItem.Parsers.size() > 1.
↑ V560 A part of conditional expression is always true: WAVE_fact_samplesCount < File_Size.
↑ V560 A part of conditional expression is always true: WAVE_fact_samplesCount.
↑ V581 The conditional expressions of the 'if' statements situated alongside each other are identical. Check lines: 3586, 3599.
↑ V601 The integer type is implicitly cast to the char type.
↑ V688 The 'AvgBytesPerSec' local variable possesses the same name as one of the class members, which can result in a confusion.
↑ V1037 Two or more case-branches perform the same actions. Check lines: 2280, 2294
↑ V1037 Two or more case-branches perform the same actions. Check lines: 2305, 2328
↑ V1037 Two or more case-branches perform the same actions. Check lines: 2306, 2322
↑ V1051 Consider checking for misprints. It's possible that the 'ComputedBlockAlign' should be checked here.
↑ V524 It is odd that the body of 'AVI__hdlr_strl_strd' function is fully equivalent to the body of 'AVI__hdlr_ON2h' function.
↑ V524 It is odd that the body of 'AVI__Tdat_rn_O' function is fully equivalent to the body of 'AVI__Tdat_rn_A' function.
↑ V524 It is odd that the body of 'rcrd_fld__finf' function is fully equivalent to the body of 'AIFC_FVER' function.
↑ V524 It is odd that the body of 'WAVE_adtl_note' function is fully equivalent to the body of 'WAVE_adtl_labl' function.
↑ V524 It is odd that the body of 'WAVE_data_Continue' function is fully equivalent to the body of 'RMP3_data_Continue' function.
↑ V525 The code contains the collection of similar blocks. Check items '2', '4', '2', '2', '2' in lines 1433, 1434, 1435, 1436, 1437.
↑ V550 An odd precise comparison. It's probably better to use a comparison with defined precision: fabs(sampleRate) > Epsilon.
↑ V550 An odd precise comparison. It's probably better to use a comparison with defined precision: fabs(FrameRate) > Epsilon.
↑ V550 An odd precise comparison: avih_FrameRate == 0. It's probably better to use a comparison with defined precision: fabs(A - B) < Epsilon.
↑ V550 An odd precise comparison: avih_FrameRate == 0. It's probably better to use a comparison with defined precision: fabs(A - B) < Epsilon.
↑ V550 An odd precise comparison. It's probably better to use a comparison with defined precision: fabs(Duration) > Epsilon.
↑ V550 An odd precise comparison. It's probably better to use a comparison with defined precision: fabs(BitRate) > Epsilon.
↑ V550 An odd precise comparison. It's probably better to use a comparison with defined precision: fabs(BitRate) > Epsilon.
↑ V656 Variables 'Element_Offset', 'Size' are initialized through the call to the same function. It's probably an error or un-optimized code. Consider inspecting the '(int32u) Title.size()' expression. Check lines: 4116, 4117.
↑ V688 The 'BitsPerSample' function argument possesses the same name as one of the class members, which can result in a confusion.
↑ V688 The 'BitsPerSample' function argument possesses the same name as one of the class members, which can result in a confusion.
↑ V688 The 'SamplesPerSec' function argument possesses the same name as one of the class members, which can result in a confusion.
↑ V829 Lifetime of the heap-allocated variable 'MI' is limited to the current function's scope. Consider allocating it on the stack instead.
↑ V807 Decreased performance. Consider creating a reference to avoid using the 'Temp->second' expression repeatedly.
↑ V820 The 'Value' variable is not used after copying. Copying can be replaced with move/swap for optimization.
↑ V820 The 'Value' variable is not used after copying. Copying can be replaced with move/swap for optimization.
↑ V820 The 'Modified' variable is not used after copying. Copying can be replaced with move/swap for optimization.
↑ V820 The 'Modified' variable is not used after copying. Copying can be replaced with move/swap for optimization.
↑ V807 Decreased performance. Consider creating a pointer to avoid using the 'StreamItem.Parsers[Pos]' expression repeatedly.
↑ V807 Decreased performance. Consider creating a reference to avoid using the 'Temp->second' expression repeatedly.