/* 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.
*/
//---------------------------------------------------------------------------
// Pre-compilation
#include "MediaInfo/PreComp.h"
#ifdef __BORLANDC__
#pragma hdrstop
#endif
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include "MediaInfo/Setup.h"
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#ifdef MEDIAINFO_RIFF_YES
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include "MediaInfo/Multiple/File_Riff.h"
#include "MediaInfo/Audio/File_DolbyAudioMetadata.h"
#if defined(MEDIAINFO_MPEG4V_YES)
#include "MediaInfo/Video/File_Mpeg4v.h"
#endif
#if defined(MEDIAINFO_MPEGA_YES)
#include "MediaInfo/Audio/File_Mpega.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_DVDIF_YES)
#include "MediaInfo/Multiple/File_DvDif.h"
#endif
#if MEDIAINFO_EVENTS
#include "MediaInfo/MediaInfo_Events.h"
#endif //MEDIAINFO_EVENTS
#include "MediaInfo/MediaInfo_Config_MediaInfo.h"
#if defined(MEDIAINFO_FILE_YES)
#include <ZenLib/File.h>
#endif //defined(MEDIAINFO_FILE_YES)
#include <ZenLib/Utils.h>
using namespace ZenLib;
//---------------------------------------------------------------------------
namespace MediaInfoLib
{
//***************************************************************************
// Const
//***************************************************************************
namespace Elements
{
const int32u AIFF_SSND=0x53534E44;
const int32u AVI_=0x41564920;
const int32u AVI__hdlr_strl_strh_txts=0x74787473;
const int32u FORM=0x464F524D;
const int32u LIST=0x4C495354;
const int32u MThd=0x4D546864;
const int32u ON2_=0x4F4E3220;
const int32u ON2f=0x4F4E3266;
const int32u RIFF=0x52494646;
const int32u riff=0x72696666;
const int32u RF64=0x52463634;
const int32u SMV0=0x534D5630;
const int32u SMV0_xxxx=0x534D563A;
const int32u W3DI=0x57334449;
const int32u WAVE=0x57415645;
const int32u WAVE_data=0x64617461;
const int32u WAVE_ds64=0x64733634;
}
//***************************************************************************
// Format
//***************************************************************************
//---------------------------------------------------------------------------
File_Riff::File_Riff()
:File__Analyze()
{
//Configuration
#if MEDIAINFO_EVENTS
ParserIDs[0]=MediaInfo_Parser_Riff;
StreamIDs_Width[0]=4;
#endif //MEDIAINFO_EVENTS
#if MEDIAINFO_DEMUX
Demux_Level=2; //Container
#endif //MEDIAINFO_DEMUX
DataMustAlwaysBeComplete=false;
//In/Out
#if defined(MEDIAINFO_ANCILLARY_YES)
Ancillary=NULL;
#endif //defined(MEDIAINFO_ANCILLARY_YES)
//Data
Interleaved0_1=0;
Interleaved0_10=0;
Interleaved1_1=0;
Interleaved1_10=0;
//Temp
DolbyAudioMetadata=NULL;
#if defined(MEDIAINFO_ADM_YES)
Adm=NULL;
#endif
WAVE_data_Size=(int64u)-1;
WAVE_fact_samplesCount=(int64u)-1;
Buffer_DataToParse_Begin=(int64u)-1;
Buffer_DataToParse_End=0;
#if MEDIAINFO_DEMUX
AvgBytesPerSec=0;
#endif //!MEDIAINFO_DEMUX
avih_FrameRate=0;
avih_TotalFrame=0;
dmlh_TotalFrame=0;
Idx1_Offset=(int64u)-1;
movi_Size=0;
TimeReference=(int64u)-1;
SMV_BlockSize=0;
SamplesPerSec=0;
stream_Count=0;
BlockAlign=0;
rec__Present=false;
NeedOldIndex=true;
IsBigEndian=false;
IsWave64=false;
IsRIFF64=false;
IsWaveBroken=false;
IsNotWordAligned=false;
IsNotWordAligned_Tested=false;
SecondPass=false;
DV_FromHeader=NULL;
Kind=Kind_None;
#if MEDIAINFO_DEMUX
Demux_Parser=NULL;
#endif //MEDIAINFO_DEMUX
//Pointers
Stream_Structure_Temp=Stream_Structure.end();
}
//---------------------------------------------------------------------------
File_Riff::~File_Riff()
{
#ifdef MEDIAINFO_DVDIF_YES
delete (File_DvDif*)DV_FromHeader; //DV_FromHeader=NULL
#endif //MEDIAINFO_DVDIF_YES
delete DolbyAudioMetadata;
#if defined(MEDIAINFO_ADM_YES)
delete Adm;
#endif
}
//***************************************************************************
// Streams management
//***************************************************************************
//---------------------------------------------------------------------------
void File_Riff::Streams_Finish ()
{
//Ancillary specific
#if defined(MEDIAINFO_ANCILLARY_YES)
if (Ancillary && (*Ancillary))
{
Clear();
Stream_Prepare(Stream_General);
Finish(*Ancillary);
Merge(**Ancillary);
Ztring LawRating=(*Ancillary)->Retrieve(Stream_General, 0, General_LawRating);
if (!LawRating.empty())
Fill(Stream_General, 0, General_LawRating, LawRating, true);
Ztring Title=(*Ancillary)->Retrieve(Stream_General, 0, General_Title);
if (!Title.empty() && Retrieve(Stream_General, 0, General_Title).empty())
Fill(Stream_General, 0, General_Title, Title);
return;
}
#endif //defined(MEDIAINFO_ANCILLARY_YES)
//Global
if (IsRIFF64)
Fill(Stream_General, 0, General_Format_Profile, "RF64");
if (DolbyAudioMetadata) //Before ADM for having content before all ADM stuff
Merge(*DolbyAudioMetadata, Stream_Audio, 0, 0);
if (Adm)
Merge(*Adm, Stream_Audio, 0, 0);
if (Adm && (!DolbyAudioMetadata || !DolbyAudioMetadata->HasSegment9) && Retrieve_Const(Stream_Audio, 0, "AdmProfile_Format")==__T("Dolby Atmos Master"))
{
Clear(Stream_Audio, 0, "AdmProfile");
Clear(Stream_Audio, 0, "AdmProfile_Format");
Clear(Stream_Audio, 0, "AdmProfile_Version");
}
//Time codes
TimeCode_Fill(__T("ISMP"), INFO_ISMP);
TimeCode_Fill(__T("Adobe tc_A"), Tdat_tc_A);
TimeCode_Fill(__T("Adobe tc_O"), Tdat_tc_O);
//For each stream
std::map<int32u, stream>::iterator Temp=Stream.begin();
while (Temp!=Stream.end())
{
//Preparing
StreamKind_Last=Temp->second.StreamKind;
StreamPos_Last=Temp->second.StreamPos;
//StreamSize
if (Temp->second.StreamSize>0)
Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_StreamSize), Temp->second.StreamSize);
//When there are few frames, difficult to detect PCM
if (Temp->second.IsPcm && !Temp->second.Parsers.empty() && !Temp->second.Parsers[0]->Status[IsAccepted])
{
for (size_t Pos=0; Pos<Temp->second.Parsers.size()-1; Pos++)
delete Temp->second.Parsers[Pos];
Temp->second.Parsers.erase(Temp->second.Parsers.begin(), Temp->second.Parsers.begin()+Temp->second.Parsers.size()-1);
Temp->second.Parsers[0]->Accept();
}
//PAR
if (PAR && StreamKind_Last==Stream_Video)
Fill(Stream_Video, StreamPos_Last, Video_PixelAspectRatio, PAR);
Ztring ID;
if (Temp->first!=(int32u)-1)
ID.From_Number(((Temp->first>>24)-'0')*10+(((Temp->first>>16)&0xFF)-'0'));
//Parser specific
if (Temp->second.Parsers.size()==1)
{
//Finalizing and Merging (except Video codec and 120 fps hack)
Temp->second.Parsers[0]->ShouldContinueParsing=false;
//Hack - Before
Ztring StreamSize, Codec_Temp;
if (StreamKind_Last==Stream_Video)
Codec_Temp=Retrieve(Stream_Video, StreamPos_Last, Video_Codec); //We want to keep the 4CC of AVI
StreamSize=Retrieve(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_StreamSize)); //We want to keep the 4CC of AVI
//Merging
if (Config->ParseSpeed<=1.0)
{
Fill(Temp->second.Parsers[0]);
Temp->second.Parsers[0]->Open_Buffer_Unsynch();
}
Finish(Temp->second.Parsers[0]);
if (!Temp->second.Parsers.empty() && Temp->second.Parsers[0]->Count_Get(StreamKind_Last))
{
//Special case: Compressed audio hidden in PCM
if (StreamKind_Last==Stream_Audio
&& Temp->second.Compression==1
&& Retrieve(Stream_General, 0, General_Format)==__T("Wave")
&& Temp->second.Parsers[0]->Get(Stream_Audio, 0, Audio_Format)!=__T("PCM")) //Some DTS or SMPTE ST 337 streams are coded "1"
Clear(Stream_Audio, 0, Audio_Channel_s_);
size_t StreamPos_Base=StreamPos_Last;
if (StreamKind_Last==Stream_Audio && (Temp->second.Parsers[0]->Count_Get(Stream_Audio)>1 || (!Temp->second.Parsers[0]->Get(Stream_Audio, 0, Audio_MuxingMode).empty() && Temp->second.Parsers[0]->Get(Stream_Audio, 0, Audio_MuxingMode)!=__T("ADTS"))))
{
//Content from underlying format is preffered
Clear(Stream_Audio, StreamPos_Last, Audio_Channel_s_);
Fill(Stream_Audio, StreamPos_Last, Audio_BitRate_Encoded, Retrieve(Stream_Audio, StreamPos_Last, Audio_BitRate), true);
Clear(Stream_Audio, StreamPos_Last, Audio_BitRate);
Clear(Stream_Audio, StreamPos_Last, Audio_SamplingRate);
Fill(Stream_Audio, StreamPos_Last, Audio_StreamSize_Encoded, Retrieve(Stream_Audio, StreamPos_Last, Audio_StreamSize), true);
Clear(Stream_Audio, StreamPos_Last, Audio_StreamSize);
}
for (size_t Pos=0; Pos<Temp->second.Parsers[0]->Count_Get(StreamKind_Last); Pos++)
{
Ztring Temp_ID=ID;
Ztring Temp_ID_String=ID;
Merge(*Temp->second.Parsers[0], StreamKind_Last, Pos, StreamPos_Base+Pos);
if (!Retrieve(StreamKind_Last, StreamPos_Last, General_ID).empty())
{
if (!Temp_ID.empty())
{
Temp_ID+=__T('-');
Temp_ID_String+=__T('-');
}
Temp_ID+=Retrieve(StreamKind_Last, StreamPos_Last, General_ID);
Temp_ID_String+=Retrieve(StreamKind_Last, StreamPos_Last, General_ID);
}
Fill(StreamKind_Last, StreamPos_Last, General_ID, Temp_ID, true);
Fill(StreamKind_Last, StreamPos_Last, General_StreamOrder, Temp_ID_String, true);
//Special case - MPEG Video + Captions
if (StreamKind_Last==Stream_Video && Temp->second.Parsers[0]->Count_Get(Stream_Text))
{
//Video and Text are together
size_t Parser_Text_Count=Temp->second.Parsers[0]->Count_Get(Stream_Text);
for (size_t Parser_Text_Pos=0; Parser_Text_Pos<Parser_Text_Count; Parser_Text_Pos++)
{
size_t StreamPos_Video=StreamPos_Last;
Fill_Flush();
Stream_Prepare(Stream_Text);
Temp->second.Parsers[0]->Finish();
Merge(*Temp->second.Parsers[0], Stream_Text, Parser_Text_Pos, StreamPos_Last);
Fill(Stream_Text, StreamPos_Last, Text_Duration, Retrieve(Stream_Video, StreamPos_Video, Video_Duration));
Ztring ID=Retrieve(Stream_Text, StreamPos_Last, Text_ID);
Fill(Stream_Text, StreamPos_Last, Text_ID, Retrieve(Stream_Video, Count_Get(Stream_Video)-1, Video_ID)+__T("-")+ID, true);
Fill(Stream_Text, StreamPos_Last, Text_ID_String, Retrieve(Stream_Video, Count_Get(Stream_Video)-1, Video_ID_String)+__T("-")+ID, true);
Fill(Stream_Text, StreamPos_Last, Text_Title, Retrieve(Stream_Video, Count_Get(Stream_Video)-1, Video_Title), true);
Fill(Stream_Text, StreamPos_Last, "MuxingMode_MoreInfo", __T("Muxed in Video #")+Ztring().From_Number(Count_Get(Stream_Video)), true);
}
StreamKind_Last=Stream_Video;
StreamPos_Last=Count_Get(Stream_Video)-1;
}
}
//Special case - Multiple Audio
if (StreamKind_Last==Stream_Audio)
{
for (size_t Pos=0; Pos<Temp->second.Parsers[0]->Count_Get(Stream_Audio); Pos++)
{
if (Retrieve(Stream_Audio, StreamPos_Base+Pos, Audio_CodecID).empty())
Fill(Stream_Audio, StreamPos_Base+Pos, Audio_CodecID, Retrieve(Stream_Audio, StreamPos_Base, Audio_CodecID));
if (Retrieve(Stream_Audio, StreamPos_Base+Pos, Audio_Duration).empty())
Fill(Stream_Audio, StreamPos_Base+Pos, Audio_Duration, Retrieve(Stream_Audio, StreamPos_Base, Audio_Duration));
if (Pos)
Fill(Stream_Audio, StreamPos_Base+Pos, Audio_StreamSize_Encoded, 0, 10, true);
}
}
}
else
{
Fill(StreamKind_Last, StreamPos_Last, General_ID, ID, true);
Fill(StreamKind_Last, StreamPos_Last, General_StreamOrder, ID, true);
}
//Hacks - After
if (!Temp->second.Parsers.empty() && Temp->second.Parsers[0]->Count_Get(StreamKind_Last)==1)
Fill(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Retrieve(StreamKind_Last, StreamPos_Last, Fill_Parameter(StreamKind_Last, Generic_StreamSize_Encoded)).empty()?Generic_StreamSize:Generic_StreamSize_Encoded), StreamSize, true);
if (StreamKind_Last==Stream_Video)
{
if (!Codec_Temp.empty())
Fill(Stream_Video, StreamPos_Last, Video_Codec, Codec_Temp, true);
//120 fps hack
const Ztring &FrameRate=Retrieve(Stream_Video, StreamPos_Last, Video_FrameRate);
if (FrameRate.To_int32u()==120)
{
float32 FrameRateF=FrameRate.To_float32();
Fill(Stream_Video, StreamPos_Last, Video_FrameRate_Minimum, FrameRateF/5, 3, true);
Fill(Stream_Video, StreamPos_Last, Video_FrameRate_Maximum, FrameRateF/4, 3, true);
Fill(Stream_Video, StreamPos_Last, Video_FrameRate_Mode, "VFR");
}
}
//Hack - SMPTE ST 337, RIFF channels count is wrong
if (StreamKind_Last==Stream_Audio && Retrieve(Stream_Audio, StreamPos_Last, Audio_MuxingMode)==__T("SMPTE ST 337") && Temp->second.Parsers[0]->Get(Stream_Audio, 0, Audio_Channel_s_).empty())
Clear(Stream_Audio, StreamPos_Last, Audio_Channel_s_);
//Alignment
if (StreamKind_Last==Stream_Audio && Count_Get(Stream_Video)>0) //Only if this is not a WAV file
{
Fill(Stream_Audio, StreamPos_Last, Audio_Alignment, Temp->second.ChunksAreComplete?"Aligned":"Split");
Fill(Stream_Audio, StreamPos_Last, Audio_Alignment_String, MediaInfoLib::Config.Language_Get(Temp->second.ChunksAreComplete?__T("Alignment_Aligned"):__T("Alignment_Split")));
}
//Delay
if (StreamKind_Last==Stream_Audio && Count_Get(Stream_Video)==1 && Temp->second.Rate!=0 && Temp->second.Parsers[0]->Status[IsAccepted])
{
float Delay=0;
bool Delay_IsValid=false;
if (Temp->second.Parsers[0]->Buffer_TotalBytes_FirstSynched==0)
{
Delay=0;
Delay_IsValid=true;
}
else if (Temp->second.Rate!=0)
{
Delay=((float)Temp->second.Parsers[0]->Buffer_TotalBytes_FirstSynched)*1000/Temp->second.Rate;
Delay_IsValid=true;
}
else if (Temp->second.Parsers[0]->Retrieve(Stream_Audio, 0, Audio_BitRate).To_int64u()!=0)
{
Delay=((float)Temp->second.Parsers[0]->Buffer_TotalBytes_FirstSynched)*1000/Temp->second.Parsers[0]->Retrieve(Stream_Audio, 0, Audio_BitRate).To_int64u();
Delay_IsValid=true;
}
else if (Temp->second.Parsers[0]->Retrieve(Stream_Audio, 0, Audio_BitRate_Nominal).To_int64u()!=0)
{
Delay=((float)Temp->second.Parsers[0]->Buffer_TotalBytes_FirstSynched)*1000/Temp->second.Parsers[0]->Retrieve(Stream_Audio, 0, Audio_BitRate_Nominal).To_int64u();
Delay_IsValid=true;
}
if (Delay_IsValid)
{
Delay+=((float)Temp->second.Start)*1000/Temp->second.Rate;
Fill(Stream_Audio, StreamPos_Last, Audio_Delay, Delay, 0, true);
Fill(Stream_Audio, StreamPos_Last, Audio_Delay_Source, "Stream", Unlimited, true, true);
for (size_t StreamPos=0; StreamPos<Count_Get(Stream_Video); StreamPos++)
Fill(Stream_Video, StreamPos, Video_Delay, 0, 10, true);
}
}
//Special case: AAC
if (StreamKind_Last==Stream_Audio
&& (Retrieve(Stream_Audio, StreamPos_Last, Audio_Format)==__T("AAC")
|| Retrieve(Stream_Audio, StreamPos_Last, Audio_Format)==__T("MPEG Audio")
|| Retrieve(Stream_Audio, StreamPos_Last, Audio_Format)==__T("Vorbis")))
Clear(Stream_Audio, StreamPos_Last, Audio_BitDepth); //Resolution is not valid for AAC / MPEG Audio / Vorbis
//Format specific
#if defined(MEDIAINFO_DVDIF_YES)
if (StreamKind_Last==Stream_Video && (MediaInfoLib::Config.Codec_Get(Ztring().From_CC4(Temp->second.Compression), InfoCodec_KindofCodec).find(__T("DV"))==0
|| Retrieve(Stream_Video, StreamPos_Last, Video_Format)==__T("DV")
|| Retrieve(Stream_Video, StreamPos_Last, Video_Codec)==__T("DV")))
{
if (Retrieve(Stream_General, 0, General_Recorded_Date).empty())
Fill(Stream_General, 0, General_Recorded_Date, Temp->second.Parsers[0]->Retrieve(Stream_General, 0, General_Recorded_Date));
//Video and Audio are together
size_t Audio_Count=Temp->second.Parsers[0]->Count_Get(Stream_Audio);
for (size_t Audio_Pos=0; Audio_Pos<Audio_Count; Audio_Pos++)
{
Fill_Flush();
Stream_Prepare(Stream_Audio);
size_t Pos=Count_Get(Stream_Audio)-1;
Merge(*Temp->second.Parsers[0], Stream_Audio, Audio_Pos, StreamPos_Last);
Fill(Stream_Audio, Pos, Audio_MuxingMode, "DV");
Fill(Stream_Audio, Pos, Audio_Duration, Retrieve(Stream_Video, Temp->second.StreamPos, Video_Duration));
Fill(Stream_Audio, Pos, "MuxingMode_MoreInfo", __T("Muxed in Video #")+Ztring().From_Number(Temp->second.StreamPos+1));
Fill(Stream_Audio, Pos, Audio_StreamSize_Encoded, 0); //Included in the DV stream size
Ztring ID=Retrieve(Stream_Audio, Pos, Audio_ID);
Fill(Stream_Audio, Pos, Audio_ID, Retrieve(Stream_Video, Temp->second.StreamPos, Video_ID)+__T("-")+ID, true);
}
StreamKind_Last=Stream_Video;
StreamPos_Last=Temp->second.StreamPos;
}
#endif
}
else if (StreamKind_Last!=Stream_General)
Fill(StreamKind_Last, StreamPos_Last, General_ID, ID);
//Duration
if (Temp->second.PacketCount>0)
{
if (StreamKind_Last==Stream_Video) // && Retrieve(Stream_Video, StreamPos_Last, Video_Duration).empty())
{
//Duration in case it is missing from header (malformed header...)
if (Temp->second.indx_Duration && Temp->second.Rate)
Fill(Stream_Video, StreamPos_Last, Video_Duration, ((float64)Temp->second.indx_Duration)*1000*Temp->second.Scale/Temp->second.Rate, 0, true);
else
Fill(Stream_Video, StreamPos_Last, Video_FrameCount, Temp->second.PacketCount, 10, true);
}
if (StreamKind_Last==Stream_Audio)
{
//Duration in case it is missing from header (malformed header...)
int64u SamplingCount=0;
#if defined(MEDIAINFO_MPEGA_YES)
if (Retrieve(Stream_Audio, StreamPos_Last, Audio_Format)==__T("MPEG Audio"))
{
if (Temp->second.Parsers[0] && Temp->second.PacketPos==((File_Mpega*)Temp->second.Parsers[0])->Frame_Count_Valid) //Only for stream with one frame per chunk
{
Ztring Version=Retrieve(Stream_Audio, StreamPos_Last, Audio_Format_Version);
Ztring Layer=Retrieve(Stream_Audio, StreamPos_Last, Audio_Format_Profile);
if (Version==__T("Version 1") && Layer==__T("Layer 1"))
SamplingCount = (int64u)Temp->second.PacketCount * 384; //MPEG-1 Layer 1
else if ((Version==__T("Version 2") || Version==__T("Version 2.5")) && Layer==__T("Layer 1"))
SamplingCount = (int64u)Temp->second.PacketCount * 192; //MPEG-2 or 2.5 Layer 1
else if ((Version==__T("Version 2") || Version==__T("Version 2.5")) && Layer==__T("Layer 3"))
SamplingCount = (int64u)Temp->second.PacketCount * 576; //MPEG-2 or 2.5 Layer 3
else
SamplingCount = (int64u)Temp->second.PacketCount * 1152;
}
}
#endif
if (Retrieve(Stream_Audio, StreamPos_Last, Audio_Format)==__T("PCM"))
{
int64u Resolution=Retrieve(Stream_Audio, StreamPos_Last, Audio_BitDepth).To_int64u();
int64u Channels=Retrieve(Stream_Audio, StreamPos_Last, Audio_Channel_s_).To_int64u();
if (Resolution>0 && Channels>0)
SamplingCount=Temp->second.StreamSize*8/Resolution/Channels;
}
if (Retrieve(Stream_Audio, StreamPos_Last, Audio_Format)==__T("ADPCM"))
{
int64u Resolution=Retrieve(Stream_Audio, StreamPos_Last, Audio_BitDepth).To_int64u();
int64u Channels=Retrieve(Stream_Audio, StreamPos_Last, Audio_Channel_s_).To_int64u();
if (Resolution>0 && Channels>0)
SamplingCount=(int64u)(Temp->second.StreamSize*8/Resolution/Channels*0.98); //0.98 is not precise!
//ADPCM estimation is not precise, if container sampling count is around our value, using it rather than the estimation
float32 SamplingRate=Retrieve(Stream_Audio, StreamPos_Last, Audio_SamplingRate).To_float32();
if (SamplingRate>0
&& SamplingCount*1000/SamplingRate<((float32)avih_TotalFrame)/avih_FrameRate*1000*1.10
&& SamplingCount*1000/SamplingRate>((float32)avih_TotalFrame)/avih_FrameRate*1000*0.10)
SamplingCount=0; //Value disabled
}
//One AC-3 frame is 32 ms
//One DTS frame is 21 ms
float32 SamplingRate=Retrieve(Stream_Audio, StreamPos_Last, Audio_SamplingRate).To_float32();
if (SamplingCount>0 && SamplingRate>0)
Fill(Stream_Audio, StreamPos_Last, Audio_Duration, SamplingCount*1000/SamplingRate, 0, true);
else if (Temp->second.indx_Duration && Temp->second.Rate)
Fill(Stream_Audio, StreamPos_Last, Audio_Duration, ((float64)Temp->second.indx_Duration)*1000*Temp->second.Scale/Temp->second.Rate, 0, true);
else if (Temp->second.Rate && Temp->second.Scale!=1) //Note: some files with Scale==1 are buggy
Fill(Stream_Audio, StreamPos_Last, Audio_Duration, ((float64)Temp->second.Length)*1000*Temp->second.Scale/Temp->second.Rate, 0, true);
//Interleave
if (Stream[0x30300000].PacketCount && Temp->second.PacketCount)
{
Fill(Stream_Audio, StreamPos_Last, "Interleave_VideoFrames", (float)Stream[0x30300000].PacketCount/Temp->second.PacketCount, 2);
if (Retrieve(Stream_Video, 0, Video_FrameRate).To_float32())
{
Fill(Stream_Audio, StreamPos_Last, "Interleave_Duration", (float)Stream[0x30300000].PacketCount/Temp->second.PacketCount*1000/Retrieve(Stream_Video, 0, Video_FrameRate).To_float32(), 0);
Ztring Interleave_Duration_String;
Interleave_Duration_String+=Retrieve(Stream_Audio, StreamPos_Last, "Interleave_Duration");
Interleave_Duration_String+=__T(" ");
Interleave_Duration_String+=MediaInfoLib::Config.Language_Get(__T("ms"));
if (!Retrieve(Stream_Audio, StreamPos_Last, "Interleave_VideoFrames").empty())
{
Interleave_Duration_String+=__T(" (");
Interleave_Duration_String+=MediaInfoLib::Config.Language_Get(Retrieve(Stream_Audio, StreamPos_Last, "Interleave_VideoFrames"), __T(" video frames"));
Interleave_Duration_String+=__T(")");
}
Fill(Stream_Audio, StreamPos_Last, "Interleave_Duration/String", Interleave_Duration_String);
}
int64u Audio_FirstBytes=0;
for (std::map<int64u, stream_structure>::iterator Stream_Structure_Temp=Stream_Structure.begin(); Stream_Structure_Temp!=Stream_Structure.end(); ++Stream_Structure_Temp)
{
if (Stream_Structure_Temp->second.Name==0x30300000)
break;
if (Stream_Structure_Temp->second.Name==Temp->first)
Audio_FirstBytes+=Stream_Structure_Temp->second.Size;
}
if (Audio_FirstBytes && Temp->second.AvgBytesPerSec)
{
Fill(Stream_Audio, StreamPos_Last, "Interleave_Preload", Audio_FirstBytes*1000/Temp->second.AvgBytesPerSec);
Fill(Stream_Audio, StreamPos_Last, "Interleave_Preload/String", Retrieve(Stream_Audio, StreamPos_Last, "Interleave_Preload")+__T(" ")+MediaInfoLib::Config.Language_Get(__T("ms")));
}
}
}
//Source duration
if (Temp->second.PacketCount && Temp->second.Length!=Temp->second.PacketCount)
{
if (StreamKind_Last==Stream_Video && Temp->second.Rate)
Fill(Stream_Video, StreamPos_Last, "Source_Duration", ((float64)Temp->second.PacketCount)*1000*Temp->second.Scale/Temp->second.Rate, 0);
if (StreamKind_Last==Stream_Audio && Temp->second.Rate)
{
float64 Duration_Source=((float64)Temp->second.StreamSize)*1000/Temp->second.AvgBytesPerSec;
float64 Duration_Header=Retrieve(Stream_Audio, StreamPos_Last, Audio_Duration).To_float64();
float64 Difference=Duration_Source-Duration_Header;
if (Temp->second.Scale!=1 && float64_int64s(Duration_Header/Duration_Source)==Temp->second.Scale)
Fill(Stream_Audio, StreamPos_Last, Audio_Duration, Duration_Source, 0, true); //Found 1 stream with Scale not being right
else if (Difference<-2 || Difference>2) //+/- 2 ms
Fill(Stream_Audio, StreamPos_Last, "Source_Duration", Duration_Source, 0);
}
}
}
if (StreamKind_Last==Stream_Audio && Retrieve(Stream_Audio, StreamPos_Last, Audio_Format)==__T("MPEG Audio"))
{
Ztring Delay = Retrieve(Stream_Audio, StreamPos_Last, Audio_Delay);
Ztring Delay_Original = Retrieve(Stream_Audio, StreamPos_Last, Audio_Delay_Original);
if (!Delay.empty() && !Delay_Original.empty())
{
Fill(Stream_Audio, StreamPos_Last, Audio_Delay, Delay.To_float64()+ Delay_Original.To_float64(), 0, true);
Ztring Delay_Source = Retrieve(Stream_Audio, StreamPos_Last, Audio_Delay_Source);
Ztring Delay_Original_Source = Retrieve(Stream_Audio, StreamPos_Last, Audio_Delay_Original_Source);
Fill(Stream_Audio, StreamPos_Last, Audio_Delay_Source, Delay_Source+__T(" + ")+Delay_Original_Source, true);
Clear(Stream_Audio, StreamPos_Last, Audio_Delay_Original);
Clear(Stream_Audio, StreamPos_Last, Audio_Delay_Original_Source);
}
}
++Temp;
}
//Some work on the first video stream
if (Count_Get(Stream_Video))
{
//ODML
if (dmlh_TotalFrame!=0 && Retrieve(Stream_Video, 0, Video_Duration).empty())
for (size_t StreamPos=0; StreamPos<Count_Get(Stream_Video); StreamPos++)
Fill(Stream_Video, StreamPos, Video_FrameCount, dmlh_TotalFrame, 10, true);
}
//Rec
if (rec__Present)
Fill(Stream_General, 0, General_Format_Settings, "rec");
//Interleaved
if (Interleaved0_1 && Interleaved0_10 && Interleaved1_1 && Interleaved1_10)
Fill(Stream_General, 0, General_Interleaved, ((Interleaved0_1<Interleaved1_1 && Interleaved0_10>Interleaved1_1)
|| (Interleaved1_1<Interleaved0_1 && Interleaved1_10>Interleaved0_1))?"Yes":"No");
//MD5
size_t Pos=0;
for (size_t StreamKind=Stream_General+1; StreamKind<Stream_Max; StreamKind++)
for (size_t StreamPos=0; StreamPos<Count_Get((stream_t)StreamKind); StreamPos++)
if (Pos<MD5s.size())
{
Fill((stream_t)StreamKind, StreamPos, "MD5", MD5s[Pos]);
Pos++;
}
//Commercial names
if (Count_Get(Stream_Video)==1)
{
Streams_Finish_StreamOnly();
if (!Retrieve(Stream_Video, 0, Video_Format_Commercial_IfAny).empty())
{
Fill(Stream_General, 0, General_Format_Commercial_IfAny, Retrieve(Stream_Video, 0, Video_Format_Commercial_IfAny));
Fill(Stream_General, 0, General_Format_Commercial, __T("AVI ")+Retrieve(Stream_Video, 0, Video_Format_Commercial_IfAny));
}
else if (Retrieve(Stream_Video, 0, Video_Format)==__T("DV"))
{
Fill(Stream_General, 0, General_Format_Commercial_IfAny, "DV");
Fill(Stream_General, 0, General_Format_Commercial, "AVI DV");
}
else if (Retrieve(Stream_Video, 0, Video_Format)==__T("MPEG Video") && Retrieve(Stream_Video, 0, Video_Format_Settings_GOP)==__T("N=1") && Retrieve(Stream_Video, 0, Video_ChromaSubsampling)==__T("4:2:2") && Retrieve(Stream_Video, 0, Video_BitRate)==__T("30000000"))
{
Fill(Stream_General, 0, General_Format_Commercial_IfAny, "MPEG IMX 30");
Fill(Stream_Video, 0, Video_Format_Commercial_IfAny, "MPEG IMX 30");
}
else if (Retrieve(Stream_Video, 0, Video_Format)==__T("MPEG Video") && Retrieve(Stream_Video, 0, Video_Format_Settings_GOP)==__T("N=1") && Retrieve(Stream_Video, 0, Video_ChromaSubsampling)==__T("4:2:2") && Retrieve(Stream_Video, 0, Video_BitRate)==__T("40000000"))
{
Fill(Stream_General, 0, General_Format_Commercial_IfAny, "MPEG IMX 40");
Fill(Stream_Video, 0, Video_Format_Commercial_IfAny, "MPEG IMX 40");
}
else if (Retrieve(Stream_Video, 0, Video_Format)==__T("MPEG Video") && Retrieve(Stream_Video, 0, Video_Format_Settings_GOP)==__T("N=1") && Retrieve(Stream_Video, 0, Video_ChromaSubsampling)==__T("4:2:2") && Retrieve(Stream_Video, 0, Video_BitRate)==__T("50000000"))
{
Fill(Stream_General, 0, General_Format_Commercial_IfAny, "MPEG IMX 50");
Fill(Stream_Video, 0, Video_Format_Commercial_IfAny, "MPEG IMX 50");
}
}
else if (Count_Get(Stream_Audio)==1)
{
if (Retrieve(Stream_Audio, StreamPos_Last, Audio_Format)==__T("PCM"))
{
int64u Resolution=Retrieve(Stream_Audio, StreamPos_Last, Audio_BitDepth).To_int64u();
if (Resolution==24)
{
int64u SamplingRate=Retrieve(Stream_Audio, StreamPos_Last, Audio_SamplingRate).To_int64u();
if (SamplingRate==44100*8 || SamplingRate==48000*8)
Fill(Stream_Audio, StreamPos_Last, Audio_Format_Commercial_IfAny, "DXD");
}
}
}
}
//***************************************************************************
// Buffer - Global
//***************************************************************************
//---------------------------------------------------------------------------
void File_Riff::Read_Buffer_Init()
{
#if MEDIAINFO_DEMUX
Demux_UnpacketizeContainer=Config->Demux_Unpacketize_Get();
Demux_Rate=Config->Demux_Rate_Get();
if (Demux_UnpacketizeContainer && Demux_Rate==0)
Demux_Rate=25; //Default value
#endif //MEDIAINFO_DEMUX
PAR=0;
}
//---------------------------------------------------------------------------
#if MEDIAINFO_SEEK
size_t File_Riff::Read_Buffer_Seek (size_t Method, int64u Value, int64u /*ID*/)
{
//Only Wave and AIFF
switch (Kind)
{
case Kind_Wave :
case Kind_Aiff :
break;
default : return (size_t)-1;
}
//Parsing
switch (Method)
{
case 0 :
if (Value<Buffer_DataToParse_Begin)
Value=Buffer_DataToParse_Begin;
if (Value>Buffer_DataToParse_End)
Value=Buffer_DataToParse_End;
GoTo(Value);
Open_Buffer_Unsynch();
return 1;
case 1 :
GoTo(Buffer_DataToParse_Begin+(Buffer_DataToParse_End-Buffer_DataToParse_Begin)*Value/10000);
Open_Buffer_Unsynch();
return 1;
case 2 : //Timestamp
{
if (AvgBytesPerSec==0)
return (size_t)-1;
float64 ValueF=(float64)Value;
ValueF/=1000000000; //Value is in ns
ValueF*=AvgBytesPerSec;
GoTo(Buffer_DataToParse_Begin+float64_int64s(ValueF));
return 1;
}
case 3 : //FrameNumber
{
if (AvgBytesPerSec==0 || Demux_Rate==0 || BlockAlign==0)
return (size_t)-1;
float64 BytesPerFrame=AvgBytesPerSec/Demux_Rate;
int64u StreamOffset=(int64u)(Value*BytesPerFrame);
StreamOffset/=BlockAlign;
StreamOffset*=BlockAlign;
GoTo(Buffer_DataToParse_Begin+StreamOffset);
return 1;
}
default : return (size_t)-1; //Not supported
}
}
#endif //MEDIAINFO_SEEK
//---------------------------------------------------------------------------
void File_Riff::Read_Buffer_Unsynched()
{
for (std::map<int32u, stream>::iterator Stream_Item=Stream.begin(); Stream_Item!=Stream.end(); ++Stream_Item)
for (size_t Pos=0; Pos<Stream_Item->second.Parsers.size(); Pos++)
Stream_Item->second.Parsers[Pos]->Open_Buffer_Unsynch();
if (IsSub)
{
while(Element_Level)
Element_End0();
#if defined(MEDIAINFO_ANCILLARY_YES)
//Ancillary specific
if (Ancillary && (*Ancillary))
(*Ancillary)->Open_Buffer_Unsynch();
#endif //defined(MEDIAINFO_ANCILLARY_YES)
}
}
//---------------------------------------------------------------------------
#if MEDIAINFO_DEMUX
void File_Riff::Read_Buffer_Continue()
{
if (Demux_Parser)
{
Open_Buffer_Continue(Demux_Parser, Buffer+Buffer_Offset, 0, false);
if (Config->Demux_EventWasSent)
return;
Demux_Parser=NULL;
}
}
#endif //MEDIAINFO_DEMUX
//***************************************************************************
// Buffer
//***************************************************************************
//---------------------------------------------------------------------------
bool File_Riff::Header_Begin()
{
while (File_Offset+Buffer_Offset<Buffer_DataToParse_End)
{
#if MEDIAINFO_DEMUX
if (AvgBytesPerSec && Demux_Rate && BlockAlign)
{
float64 BytesPerFrame=((float64)AvgBytesPerSec)/Demux_Rate;
Frame_Count_NotParsedIncluded=float64_int64s(((float64)(File_Offset+Buffer_Offset-Buffer_DataToParse_Begin))/BytesPerFrame);
Element_Size=float64_int64s(BytesPerFrame*(Frame_Count_NotParsedIncluded+1));
Element_Size/=BlockAlign;
Element_Size*=BlockAlign;
Element_Size-=File_Offset+Buffer_Offset-Buffer_DataToParse_Begin;
FrameInfo.PTS=FrameInfo.DTS=float64_int64s(((float64)Frame_Count_NotParsedIncluded)*1000000000/Demux_Rate);
while (Element_Size && File_Offset+Buffer_Offset+Element_Size>Buffer_DataToParse_End)
Element_Size-=BlockAlign;
if (Element_Size==0)
Element_Size=BlockAlign;
if (Buffer_Offset+Element_Size>Buffer_Size)
return false;
}
else
#endif //MEDIAINFO_DEMUX
if (File_Offset+Buffer_Size<=Buffer_DataToParse_End)
Element_Size=Buffer_Size; //All the buffer is used
else
{
Element_Size=Buffer_DataToParse_End-(File_Offset+Buffer_Offset);
Buffer_DataToParse_End=0;
}
if (Buffer_Offset+(size_t)Element_Size>Buffer_Size)
return false;
// Fake header
Element_Begin1("...Continued"); //TODO: better method
Element_ThisIsAList();
Element_Begin1("...Continued");
Element_ThisIsAList();
if (Buffer_DataToParse_End)
Header_Fill_Size(Buffer_DataToParse_End-(File_Offset+Buffer_Offset));
else
Header_Fill_Size(Element_Size);
Element_End();
switch (Kind)
{
case Kind_Wave : WAVE_data_Continue(); break;
case Kind_Aiff : AIFF_SSND_Continue(); break;
case Kind_Rmp3 : RMP3_data_Continue(); break;
default : AVI__movi_xxxx();
}
bool ShouldStop=false;
if (Config->ParseSpeed<1.0 && File_Offset+Buffer_Offset+Element_Offset-Buffer_DataToParse_Begin>=256*1024)
{
ShouldStop=true;
for (std::map<int32u, stream>::iterator StreamItem=Stream.begin(); StreamItem!=Stream.end(); ++StreamItem)
if (StreamItem->second.Parsers.size()>1 || (!StreamItem->second.Parsers.empty() && !StreamItem->second.Parsers[0]->Status[IsFilled]))
ShouldStop=false;
}
if (ShouldStop)
{
File_GoTo=Buffer_DataToParse_End;
Buffer_Offset=Buffer_Size;
Element_Size=0;
}
else
{
Buffer_Offset+=(size_t)Element_Size;
Element_Size-=Element_Offset;
}
Element_Offset=0;
Element_End0();
if (Status[IsFinished] || (File_GoTo!=(int64u)-1 && (File_GoTo<=Buffer_DataToParse_Begin || File_GoTo>=Buffer_DataToParse_End)))
{
Buffer_DataToParse_Begin=(int64u)-1;
Buffer_DataToParse_End=0;
return false;
}
if (Buffer_Offset>=Buffer_Size)
return false;
#if MEDIAINFO_DEMUX
if (Config->Demux_EventWasSent)
return false;
#endif //MEDIAINFO_DEMUX
}
return true;
}
//---------------------------------------------------------------------------
void File_Riff::Header_Parse()
{
//Special case : W3DI tags (unknown format!) are at the end of the file
if (Element_Level==2 && File_Offset+Buffer_Size==File_Size && Buffer_Size>8)
{
if (CC4(Buffer+Buffer_Size-4)==Elements::W3DI)
{
int32u Size=LittleEndian2int32u(Buffer+Buffer_Size-8);
if (Size>8 && Size<=Buffer_Size && Buffer_Offset+Size==Buffer_Size)
{
//Filling
Header_Fill_Code(Elements::W3DI, "W3DI");
Header_Fill_Size(Size);
return;
}
}
}
//Special case : SMV file detected
if (SMV_BlockSize)
{
//Filling
Header_Fill_Code(Elements::SMV0_xxxx, "SMV Block");
Header_Fill_Size(SMV_BlockSize);
return;
}
//Parsing
int32u Size, Name;
Get_C4 (Name, "Name");
if (Name==Elements::SMV0)
{
//SMV specific
//Filling
Header_Fill_Code(Elements::SMV0, "SMV header");
Header_Fill_Size(51);
return;
}
if (Name==Elements::riff)
IsWave64=true;
if (IsWave64)
{
//Wave64 specific
int64u Size_Complete;
Skip_XX(12, "Name (GUID)");
Get_L8 (Size_Complete, "Size");
//Alignment
if (Name!=Elements::riff && Size_Complete%8)
{
Alignement_ExtraByte=Size_Complete%8;
Size_Complete+=Alignement_ExtraByte; //Always 8-byte aligned
}
else
Alignement_ExtraByte=0;
//Top level chunks
if (Name==Elements::riff)
{
Get_C4 (Name, "Real Name");
Skip_XX(12, "Real Name (GUID)");
}
//Special case: we don't need the full data
if (Name==Elements::WAVE_data)
{
Buffer_DataToParse_Begin=File_Offset+Buffer_Offset;
if (Size_Complete)
Buffer_DataToParse_End=File_Offset+Buffer_Offset+Size_Complete;
else
Buffer_DataToParse_End=File_Size; //Found one file with 0 as size of data part
Size_Complete=Element_Offset;
}
//Filling
Header_Fill_Code(Name, Ztring().From_CC4(Name));
Header_Fill_Size(Size_Complete);
return;
}
if (Name==Elements::FORM
|| Name==Elements::MThd)
IsBigEndian=true; //Swap from Little to Big Endian for "FORM" files (AIFF...)
if (IsBigEndian)
Get_B4 (Size, "Size");
else
Get_L4 (Size, "Size");
//RF64
int64u Size_Complete=Size;
if (Size==0 && Name==Elements::RIFF)
Size_Complete=File_Size-8;
else if (Size==0xFFFFFFFF)
{
if (Element_Size<0x1C)
{
Element_WaitForMoreData();
return;
}
if (Name==Elements::RF64 && CC4(Buffer+Buffer_Offset+0x0C)==Elements::WAVE_ds64)
{
Size_Complete=LittleEndian2int64u(Buffer+Buffer_Offset+0x14);
Param_Info1(Size_Complete);
}
else if (Name==Elements::WAVE_data)
{
Size_Complete=WAVE_data_Size;
Param_Info1(Size_Complete);
}
}
//Testing malformed (not word aligned)
if (!IsNotWordAligned_Tested && !IsBigEndian && Size_Complete %2)
{
if (File_Offset+Buffer_Offset+8+Size_Complete==File_Size)
IsNotWordAligned=true;
#if defined(MEDIAINFO_FILE_YES) //TODO: seek if file API is not available
else if (!File_Name.empty())
{
File F(File_Name);
F.GoTo(File_Offset+Buffer_Offset+8+Size);
int8u Temp;
if (F.Read(&Temp, 1))
{
if (!((Temp<'A' || Temp>'z') && Temp!=' '))
IsNotWordAligned=true;
}
}
#endif //defined(MEDIAINFO_FILE_YES)
IsNotWordAligned_Tested=true;
}
//Coherency
if (Stream_Structure_Temp!=Stream_Structure.end() && Stream_Structure_Temp->second.Size==0)
{
Name=(int32u)-1;
Size_Complete=0; //Hack in some indexes with Size==0 (why?), ignoring content of header
}
if (File_Offset+Buffer_Offset+8+Size_Complete>File_Size)
{
Size_Complete=File_Size-(File_Offset+Buffer_Offset+8);
if (Element_Level<=2) //Incoherencies info only at the top level chunk
Fill(Stream_General, 0, "IsTruncated", "Yes");
}
//Alignment
if (Size_Complete%2 && !IsNotWordAligned && File_Offset+Buffer_Offset+Element_Offset+Size_Complete<File_Size)
{
Size_Complete++; //Always 2-byte aligned
Alignement_ExtraByte=1;
}
else
Alignement_ExtraByte=0;
//Top level chunks
if (Name==Elements::LIST
|| Name==Elements::RIFF
|| Name==Elements::RF64
|| Name==Elements::ON2_
|| Name==Elements::FORM)
{
if (Name==Elements::RF64)
IsRIFF64=true;
Get_C4 (Name, "Real Name");
//Handling buggy files
if (Size_Complete>=8 && Size_Complete<12) //Not possible (would contain only the name of the RIFF block + the name of the sub-element, no size)
{
Size_Complete=Element_TotalSize_Get()-8;
Fill(Stream_General, 0, "BuggyHeader", Ztring().From_CC4(Name));
}
}
//Integrity
if (Name==0x00000000)
{
//Filling
Header_Fill_Code(0, "Junk");
Header_Fill_Size(File_Size-(File_Offset+Buffer_Offset));
Alignement_ExtraByte=0;
return;
}
//Specific
if (Name==Elements::ON2f)
Name=Elements::AVI_;
//Tests
if (Element_Level==2 && Name==Elements::WAVE && !IsRIFF64 && File_Size>0xFFFFFFFF)
IsWaveBroken=true; //Non standard big files detection
if (IsWaveBroken && (Name==Elements::WAVE || Name==Elements::WAVE_data))
Size_Complete=File_Size-(File_Offset+Buffer_Offset+8); //Non standard big files detection
if (movi_Size && Size_Complete>movi_Size/2 && 8+Size_Complete>1024*1024 && !((Name&0xFFFF0000)==0x69780000 || (Name&0x0000FFFF)==0x00006978) && Element_Level==(rec__Present?(size_t)5:(size_t)4) && Buffer_Offset+8+Size_Complete>Buffer_Size)
{
Buffer_DataToParse_End=File_Offset+Buffer_Offset+8+Size_Complete;
Size_Complete=Buffer_Size-(Buffer_Offset+8);
}
if ((Name==Elements::WAVE_data || Name==Elements::AIFF_SSND))
{
Buffer_DataToParse_Begin=File_Offset+Buffer_Offset+8;
if (Size_Complete)
Buffer_DataToParse_End=File_Offset+Buffer_Offset+8+Size_Complete;
else
Buffer_DataToParse_End=File_Size; //Found one file with 0 as size of data part
Size_Complete=(Name==Elements::AIFF_SSND?8:0);
}
//Filling
Header_Fill_Code(Name, Ztring().From_CC4(Name));
Header_Fill_Size(Size_Complete+8);
}
//---------------------------------------------------------------------------
bool File_Riff::BookMark_Needed()
{
if (!movi_Size || SecondPass)
return false;
//Go to the first usefull chunk
if (stream_Count==0 && Stream_Structure.empty())
return false; //No need
Stream_Structure_Temp=Stream_Structure.begin();
if (!Stream_Structure.empty())
{
#if MEDIAINFO_HASH
if (Config->File_Hash_Get().to_ulong())
{
GoTo(0);
Hash_ParseUpTo=Stream_Structure_Temp->first;
}
else
#endif //MEDIAINFO_HASH
GoTo(Stream_Structure_Temp->first);
}
NeedOldIndex=false;
SecondPass=true;
Index_Pos.clear(); //We didn't succeed to find theses indexes :(
return true;
}
//***************************************************************************
// Helpers
//***************************************************************************
//---------------------------------------------------------------------------
void File_Riff::TimeCode_Fill(const Ztring &Name, const Ztring &Value)
{
if (Value.empty())
return;
for (size_t StreamPos=0; StreamPos<Count_Get(Stream_Video); StreamPos++)
{
Fill(Stream_Video, StreamPos, Video_TimeCode_FirstFrame, Value);
Fill(Stream_Video, StreamPos, Video_TimeCode_Source, Name);
}
}
//***************************************************************************
// C++
//***************************************************************************
} //NameSpace
#endif //MEDIAINFO_RIFF_YES
↑ V688 The 'Stream_Structure_Temp' local variable possesses the same name as one of the class members, which can result in a confusion.
↑ V730 Not all members of a class are initialized inside the constructor. Consider inspecting: Stream_ID, Alignement_ExtraByte, AvgBytesPerSec, PAR, Demux_Rate, SMV_FrameCount, ...
↑ V1051 Consider checking for misprints. It's possible that the 'StreamPos_Base' should be used inside 'Temp->second.Parsers[0]->Get' function.
↑ V550 An odd precise comparison. It's probably better to use a comparison with defined precision: fabs(A) > Epsilon.
↑ V636 The 'SamplingCount * 1000' expression was implicitly cast from 'unsigned __int64' type to 'double' type. Consider utilizing an explicit type cast to avoid overflow. An example: double A = (double)(X) * Y;.
↑ V636 The 'SamplingCount * 1000' expression was implicitly cast from 'unsigned __int64' type to 'double' type. Consider utilizing an explicit type cast to avoid overflow. An example: double A = (double)(X) * Y;.
↑ V760 Two identical blocks of text were found. The second block begins from line 808.
↑ V807 Decreased performance. Consider creating a reference to avoid using the 'Temp->second.Parsers' expression repeatedly.
↑ V807 Decreased performance. Consider creating a pointer to avoid using the 'Temp->second.Parsers[0]' expression repeatedly.
↑ V807 Decreased performance. Consider creating a reference to avoid using the 'Stream_Structure_Temp->second' expression repeatedly.
↑ V807 Decreased performance. Consider creating a reference to avoid using the 'StreamItem->second' expression repeatedly.