/*  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"
//---------------------------------------------------------------------------
 
//---------------------------------------------------------------------------
#if defined(MEDIAINFO_DVDIF_YES)
//---------------------------------------------------------------------------
 
//---------------------------------------------------------------------------
#include "MediaInfo/Multiple/File_DvDif.h"
#if defined(MEDIAINFO_EIA608_YES)
    #include "MediaInfo/Text/File_Eia608.h"
#endif
#include "MediaInfo/MediaInfo_Config_MediaInfo.h"
#if MEDIAINFO_SEEK
    #include "MediaInfo/MediaInfo_Internal.h"
#endif //MEDIAINFO_SEEK
//---------------------------------------------------------------------------
 
namespace MediaInfoLib
{
 
//---------------------------------------------------------------------------
static const char*  Dv_sct[]=
{
    "Header",
    "Subcode",
    "VAUX",
    "Audio",
    "Video",
    "",
    "",
    "",
};
 
//---------------------------------------------------------------------------
static const char*  Dv_Disp[]=
{
    "4/3",                              //S306M, S314M
    "16/9",                             //S306M
    "16/9",                             //S306M, S314M
    "4/3",                              //Which spec?
    "",
    "",
    "",
    "16/9 or 4/3 depends of ssyb AP3", //Which spec?
};
 
//---------------------------------------------------------------------------
static const int32u  Dv_Audio_SamplingRate[]=
{
    48000,
    44100,
    32000,
    0,
    0,
    0,
    0,
    0,
};
 
//---------------------------------------------------------------------------
static const char*  Dv_StereoMode[]=
{
    "Multi-Stero",
    "Lumped",
};
 
//---------------------------------------------------------------------------
static const int32u  Dv_Audio_BitDepth[]=
{
    16,
    12,
    0,
    0,
    0,
    0,
    0,
    0,
};
 
//---------------------------------------------------------------------------
static const int8u  Dv_ChannelsPerBlock[]=
{
    1,
    2,
    0,
    0,
};
 
//---------------------------------------------------------------------------
static const char*  Dv_Pair[]=
{
    "One pair of channels",
    "Independent channels",
};
 
//---------------------------------------------------------------------------
static const char*  Dv_CopyGenerationManagementSystem[]=
{
    "Unrestricted",
    "Not used",
    "One generation only",
    "No copy",
};
 
//---------------------------------------------------------------------------
static const char*  Dv_InputType[]=
{
    "Analog",
    "Digital",
    "Reserved",
    "No information",
};
 
//---------------------------------------------------------------------------
static const char*  Dv_CompressionTimes[]=
{
    "Once",
    "Twice",
    "Three+",
    "No information",
};
 
//---------------------------------------------------------------------------
static const char*  Dv_Emphasis[]=
{
    "Enphasis off",
    "Enphasis on",
    "Reserved",
    "Reserved",
};
 
//---------------------------------------------------------------------------
const char*  Dv_consumer_camera_1_ae_mode[]=
{
    "full automatic",
    "gain priority mode",
    "shutter priority mode",
    "iris priority mode",
    "manual",
    "",
    "",
    "",
    "",
    "",
    "",
    "",
    "",
    "",
    "",
    "", //no info
};
 
//---------------------------------------------------------------------------
const char*  Dv_consumer_camera_1_wb_mode[]=
{
    "automatic",
    "hold",
    "one push",
    "pre-set",
    "",
    "",
    "",
    "", //no info
};
 
//---------------------------------------------------------------------------
static const char*  Dv_APT[] =
{
    "IEC",
    "SMPTE",
    "",
    "",
    "",
    "",
    "",
    "", //no info
};
 
//---------------------------------------------------------------------------
const char* Dv_consumer_camera_1_white_balance(int8u white_balance)
{
    switch (white_balance)
    {
        case 0x00 : return "candle";
        case 0x01 : return "incandescent lamp";
        case 0x02 : return "low color temperature; florescent lamp";
        case 0x03 : return "high color temperature; florescent lamp";
        case 0x04 : return "sunlight";
        case 0x05 : return "cloudy weather";
        case 0x1F : return ""; //No info
        default   : return "";
    }
}
 
//---------------------------------------------------------------------------
const char*  Dv_consumer_camera_1_fcm[]=
{
    "auto focus",
    "manual focus",
};
 
//***************************************************************************
// Constructor/Destructor
//***************************************************************************
 
//---------------------------------------------------------------------------
File_DvDif::File_DvDif()
:File__Analyze()
{
    //Configuration
    ParserName="DV";
    #if MEDIAINFO_EVENTS
        ParserIDs[0]=MediaInfo_Parser_DvDif;
        StreamIDs_Width[0]=4;
    #endif //MEDIAINFO_EVENTS
    #if MEDIAINFO_DEMUX
        Demux_Level=3; //Container and Stream
    #endif //MEDIAINFO_DEMUX
    MustSynchronize=true;
    Buffer_TotalBytes_FirstSynched_Max=64*1024;
 
    //In
    Frame_Count_Valid=2;
    AuxToAnalyze=0x00; //No Aux to analyze
    IgnoreAudio=false;
 
    //Temp
    FrameSize_Theory=0;
    Synched_Test_Reset();
    DSF_IsValid=false;
    APT=0xFF; //Impossible
    video_source_stype=0xFF;
    audio_source_stype=0xFF;
    aspect=0xFF;
    ssyb_AP3=0xFF;
    TF1=false; //Valid by default, for direct analyze
    TF2=false; //Valid by default, for direct analyze
    TF3=false; //Valid by default, for direct analyze
    system=false;
    FSC_WasSet=false;
    FSP_WasNotSet=false;
    video_sourcecontrol_IsParsed=false;
    audio_locked=false;
 
    #if MEDIAINFO_SEEK
        Duration_Detected=false;
    #endif //MEDIAINFO_SEEK
 
    #ifdef MEDIAINFO_DVDIF_ANALYZE_YES
    Analyze_Activated=false;
    Speed_FrameCount_StartOffset=(int64u)-1;
    Speed_FrameCount=0;
    Speed_FrameCount_Video_STA_Errors=0;
    Speed_FrameCount_Audio_Errors.resize(8);
    Speed_FrameCount_Timecode_Incoherency=0;
    Speed_FrameCount_Contains_NULL=0;
    Speed_Contains_NULL=0;
    Speed_FrameCount_Arb_Incoherency=0;
    Speed_FrameCount_Stts_Fluctuation=0;
    Speed_FrameCount_system[0]=0;
    Speed_FrameCount_system[1]=0;
    AbstBf_Current=(0x7FFFFF)<<1;
    AbstBf_Previous=(0x7FFFFF)<<1;
    AbstBf_Previous_MaxAbst=0xFFFFFF;
    SMP=(int8u)-1;
    QU=(int8u)-1;
    Speed_TimeCode_IsValid=false;
    Speed_Arb_IsValid=false;
    Mpeg4_stts=NULL;
    Mpeg4_stts_Pos=0;
    Stats.resize(10);
    Stats_Total=0;
    Stats_Total_WithoutArb=0;
    Stats_Total_AlreadyDetected=false;
    memset(BlockStatus, 0, BlockStatus_MaxSize);
    #endif //MEDIAINFO_DVDIF_ANALYZE_YES
}
 
//---------------------------------------------------------------------------
File_DvDif::~File_DvDif()
{
    for (size_t Pos=0; Pos<Streams_Audio.size(); Pos++)
        delete Streams_Audio[Pos];
 
    #if defined(MEDIAINFO_EIA608_YES)
        for (size_t Pos=0; Pos<CC_Parsers.size(); Pos++)
            delete CC_Parsers[Pos]; //CC_Parsers[Pos]=NULL;
    #endif
    #if defined(MEDIAINFO_DVDIF_ANALYZE_YES)
        delete Mpeg4_stts; //Mpeg4_stts=NULL;
    #endif
}
 
//***************************************************************************
// Streams management
//***************************************************************************
 
//---------------------------------------------------------------------------
void File_DvDif::Streams_Fill()
{
    Fill(Stream_General, 0, General_Format, "DV", Unlimited, true, true);
 
    Stream_Prepare(Stream_Video);
    Fill(Stream_Video, 0, Video_Format, "DV");
    Fill(Stream_Video, 0, Video_Codec, "DV");
    Fill(Stream_Video, 0, Video_Standard, system?"PAL":"NTSC");
    Fill(Stream_Video, 0, Video_BitDepth, 8);
    bool IsHd=false;
    float FrameRate_Multiplicator=1;
    switch (video_source_stype)
    {
        case 0x00 :
        case 0x04 :
                    Fill(Stream_Video, 0, Video_Width, 720);
                    Fill(Stream_Video, 0, Video_Height, system?576:480);
                    break;
        case 0x14 :
        case 0x15 :
                    Fill(Stream_Video, 0, Video_Width, system?1440:1280);
                    Fill(Stream_Video, 0, Video_Height, video_source_stype==0x14?1080:1035);
                    IsHd=true;
                    break;
        case 0x18 :
                    Fill(Stream_Video, 0, Video_Width, 960);
                    Fill(Stream_Video, 0, Video_Height, 720);
                    FrameRate_Multiplicator=2;
                    IsHd=true;
                    break;
        default   : ;
    }
    Fill(Stream_Video, 0, Video_FrameRate, (system?25.000:29.970)*FrameRate_Multiplicator);
    Fill(Stream_Video, 0, Video_FrameRate_Mode, "CFR");
    if (video_sourcecontrol_IsParsed)
    {
        if (FSC_WasSet && FSP_WasNotSet)
        {
            switch (video_source_stype)
            {
                case 0x14 :
                case 0x15 :
                            Fill(Stream_Video, 0, Video_ScanType, "Interlaced");
                            if (FieldOrder_FF)
                                Fill(Stream_Video, 0, Video_ScanOrder, FieldOrder_FS?"TFF":"BFF");
                            else
                                Fill(Stream_Video, 0, Video_ScanOrder, FieldOrder_FS?"Top field only":"Bottom field only");
                            Fill(Stream_Video, 0, Video_Interlacement, "Interlaced");
                            break;
                case 0x18 :
                            Fill(Stream_Video, 0, Video_ScanType, "Progressive");
                            Fill(Stream_Video, 0, Video_Interlacement, "Progressive");
                            break;
                default   : ;
            }
        }
        else if (Interlaced)
        {
            Fill(Stream_Video, 0, Video_ScanType, "Interlaced");
            if (FieldOrder_FF)
                Fill(Stream_Video, 0, Video_ScanOrder, FieldOrder_FS?"BFF":"TFF");
            else
                Fill(Stream_Video, 0, Video_ScanOrder, FieldOrder_FS?"Bottom field only":"Top field only");
            Fill(Stream_Video, 0, Video_Interlacement, "Interlaced");
        }
        else
        {
            Fill(Stream_Video, 0, Video_ScanType, "Progressive");
            Fill(Stream_Video, 0, Video_Interlacement, "PFF");
        }
        switch (aspect)
        {
            case 0 :
            case 4 : Fill(Stream_Video, 0, Video_DisplayAspectRatio, 4.0/3.0, 3, true); break;
            case 1 :
            case 2 : Fill(Stream_Video, 0, Video_DisplayAspectRatio, 16.0/9.0, 3, true); break;
            case 7 : switch (ssyb_AP3)
                     {
                        case 0 : Fill(Stream_Video, 0, Video_DisplayAspectRatio, 16.0/9.0, 3, true); break;
                        case 7 : Fill(Stream_Video, 0, Video_DisplayAspectRatio, 4.0/3.0, 3, true); break;
                        default: ; //No indication of aspect ratio?
                     }
            default: ;
        }
    }
 
    Fill(Stream_Video, 0, Video_ColorSpace, "YUV");
    if (!FSC_WasSet) //Original DV 25 Mbps
    {
        if (system==false) //NTSC
        {
            switch (video_source_stype)
            {
                case  0 : Fill(Stream_Video, 0, Video_ChromaSubsampling, "4:1:1"); break; //NTSC 25 Mbps
                default : ;
            }
        }
        else //PAL
        {
            switch (video_source_stype)
            {
                case  0 : if (APT==0)
                            Fill(Stream_Video, 0, Video_ChromaSubsampling, "4:2:0");      //PAL 25 Mbps (IEC 61834)
                          else
                            Fill(Stream_Video, 0, Video_ChromaSubsampling, "4:1:1");      //PAL 25 Mbps (SMPTE 314M)
                          break;
                default : ;
            }
        }
    }
    else //DV 50 Mbps and 100 Mbps
        Fill(Stream_Video, 0, Video_ChromaSubsampling, "4:2:2");
 
    if (FrameSize_Theory && !IsHd)
    {
        float64 OverallBitRate=FrameSize_Theory*(DSF?((float64)25.000):((float64)30000/1001))*8;
        if (FSC_WasSet)
        {
            if (FSP_WasNotSet)
                OverallBitRate*=4; //DV100
            else
                OverallBitRate*=2; //DV50
        }
        if (OverallBitRate)
        {
            if (IsSub)
                Fill(Stream_Video, 0, Video_BitRate_Encoded, OverallBitRate, 0);
            else
                Fill(Stream_General, 0, General_OverallBitRate, OverallBitRate, 0);
            Fill(Stream_Video, 0, (FSC_WasSet && FSP_WasNotSet)?Video_BitRate_Maximum:Video_BitRate, OverallBitRate*134/150*76/80, 0); //134 Video DIF from 150 DIF, 76 bytes from 80 byte DIF
        }
    }
 
    if (!Config->File_DvDif_DisableAudioIfIsInContainer_Get())
        for (size_t Pos=0; Pos<Streams_Audio.size(); Pos++)
        {
            Stream_Prepare(Stream_Audio);
            for (std::map<std::string, Ztring>::iterator Info=Streams_Audio[Pos]->Infos.begin(); Info!=Streams_Audio[Pos]->Infos.end(); ++Info)
                Fill(Stream_Audio, StreamPos_Last, Info->first.c_str(), Info->second, true);
            if (IsSub)
                Fill(Stream_Audio, StreamPos_Last, Audio_BitRate_Encoded, 0);
        }
 
    if (Stream_BitRateFromContainer && Retrieve(Stream_Video, 0, Video_BitRate).empty())
    {
        if (Stream_BitRateFromContainer>=28800000*0.98 && Stream_BitRateFromContainer<=28800000*1.02)
        {
            Fill(Stream_Video, 0, Video_BitRate, ((float64)28800000)*134/150*76/80, 0);
            Fill(Stream_Video, 0, Video_BitRate_Encoded, 28800000);
        }
        if (Stream_BitRateFromContainer>=57600000*0.98 && Stream_BitRateFromContainer<=57600000*1.02)
        {
            Fill(Stream_Video, 0, Video_BitRate, ((float64)57600000)*134/150*76/80, 0);
            Fill(Stream_Video, 0, Video_BitRate_Encoded, 57600000);
        }
        if (Stream_BitRateFromContainer>=115200000*0.98 && Stream_BitRateFromContainer<=115200000*1.02)
        {
            Fill(Stream_Video, 0, Video_BitRate, ((float64)115200000)*134/150*76/80, 0);
            Fill(Stream_Video, 0, Video_BitRate_Encoded, 115200000);
        }
    }
 
    //Library settings
    Fill(Stream_Video, 0, Video_Encoded_Library_Settings, Encoded_Library_Settings);
 
    //Profile
    if (FSC_WasSet || IsHd)
    {
        if (FSP_WasNotSet || IsHd)
        {
            Fill(Stream_General, 0, General_Format_Commercial_IfAny, "DVCPRO HD");
            Fill(Stream_Video, 0, Video_Format_Commercial_IfAny, "DVCPRO HD");
            Clear(Stream_Video, 0, Video_BitDepth); //MXF files say that DVCPRO HD streams are 8 or 10 bits, exact?
        }
        else
        {
            Fill(Stream_General, 0, General_Format_Commercial_IfAny, "DVCPRO 50");
            Fill(Stream_Video, 0, Video_Format_Commercial_IfAny, "DVCPRO 50");
            Fill(Stream_Video, 0, Video_BitRate_Mode, "CBR");
        }
    }
    else if (audio_locked && Retrieve(Stream_Video, 0, Video_Standard) == __T("PAL") && Retrieve(Stream_Video, 0, Video_ChromaSubsampling) == __T("4:2:0"))
    {
        Fill(Stream_General, 0, General_Format_Commercial_IfAny, "DVCAM");
        Fill(Stream_Video, 0, Video_Format_Commercial_IfAny, "DVCAM");
        Fill(Stream_Video, 0, Video_BitRate_Mode, "CBR");
    }
    else if (audio_locked || (Retrieve(Stream_Video, 0, Video_Standard)==__T("PAL") && Retrieve(Stream_Video, 0, Video_ChromaSubsampling)==__T("4:1:1")))
    {
        Fill(Stream_General, 0, General_Format_Commercial_IfAny, "DVCPRO");
        Fill(Stream_Video, 0, Video_Format_Commercial_IfAny, "DVCPRO");
        Fill(Stream_Video, 0, Video_BitRate_Mode, "CBR");
    }
    else
        Fill(Stream_Video, 0, Video_BitRate_Mode, "CBR");
 
    //Delay
    TimeCode_FirstFrame.FramesPerSecond=(system?25:30);
    if (FrameRate_Multiplicator>=2)
        TimeCode_FirstFrame.MustUseSecondField=true;
    if (TimeCode_FirstFrame.IsValid())
    {
        string TimeCode_FirstFrame_String=TimeCode_FirstFrame.ToString();
        int64u TimeCode_FirstFrame_ms=TimeCode_FirstFrame.ToMilliseconds();
        Fill(Stream_Video, 0, Video_Delay, TimeCode_FirstFrame_ms);
        if (TimeCode_FirstFrame_String.size()==11)
            Fill(Stream_Video, 0, Video_Delay_DropFrame, TimeCode_FirstFrame_String[8]==';'?"Yes":"No");
        Fill(Stream_Video, 0, Video_Delay_Source, "Stream");
        Fill(Stream_Video, 0, Video_TimeCode_FirstFrame, TimeCode_FirstFrame_String.c_str());
        Fill(Stream_Video, 0, Video_TimeCode_Source, "Subcode time code");
        for (size_t Pos=0; Pos<Count_Get(Stream_Audio); Pos++)
        {
            Fill(Stream_Audio, Pos, Audio_Delay, TimeCode_FirstFrame_ms);
            Fill(Stream_Audio, Pos, Audio_Delay_Source, "Stream");
        }
    }
 
    #if defined(MEDIAINFO_EIA608_YES)
        for (size_t Pos=0; Pos<CC_Parsers.size(); Pos++)
            if (CC_Parsers[Pos] && CC_Parsers[Pos]->Status[IsAccepted])
            {
                Finish(CC_Parsers[Pos]);
                for (size_t Pos2=0; Pos2<CC_Parsers[Pos]->Count_Get(Stream_Text); Pos2++)
                {
                    Stream_Prepare(Stream_Text);
                    Merge(*CC_Parsers[Pos], Stream_Text, Pos2, StreamPos_Last);
                    Fill(Stream_Text, StreamPos_Last, Text_ID, CC_Parsers[Pos]->Retrieve(Stream_Text, Pos2, Text_ID), true);
                }
            }
    #endif //defined(MEDIAINFO_EIA608_YES)
}
 
//---------------------------------------------------------------------------
void File_DvDif::Streams_Finish()
{
    if (!Recorded_Date_Date.empty())
    {
        Ztring Recorded_Date(Recorded_Date_Date);
        if (Recorded_Date_Time.size()>4)
        {
            Recorded_Date+=__T(" ");
            Recorded_Date+=Recorded_Date_Time;
        }
        if (Count_Get(Stream_General)==0)
            Stream_Prepare(Stream_General);
        Fill(Stream_General, 0, General_Recorded_Date, Recorded_Date, true);
    }
 
    float64 OverallBitRate=Retrieve_Const(Stream_General, 0, General_OverallBitRate).To_float64();
    if (OverallBitRate && File_Size && File_Size!=(int64u)-1)
    {
        float64 Duration=File_Size/OverallBitRate*8*1000;
        if (Duration)
        {
            for (size_t StreamKind=0; StreamKind<Stream_Max; StreamKind++)
                for (size_t StreamPos=0; StreamPos<Count_Get((stream_t)StreamKind); StreamPos++)
                    Fill((stream_t)StreamKind, StreamPos, Fill_Parameter((stream_t)StreamKind, Generic_Duration), Duration, 0);
        }
    }
 
    #ifdef MEDIAINFO_DVDIF_ANALYZE_YES
        if (Config->File_DvDif_Analysis_Get())
        {
            //Errors stats
            Status[IsFinished]=true; //We need to fill it before the call to Errors_Stats_Update
            Errors_Stats_Update_Finnish();
        }
    #endif //MEDIAINFO_DVDIF_ANALYZE_YES
}
 
//***************************************************************************
// Buffer - File header
//***************************************************************************
 
//---------------------------------------------------------------------------
bool File_DvDif::FileHeader_Begin()
{
    //Must have enough buffer for having header
    if (Buffer_Size<8)
        return false; //Must wait for more data
 
    //False positives detection: detect some headers from other files, DV parser is not smart enough
    if (CC4(Buffer)==0x52494646  //RIFF
     || CC4(Buffer+4)==0x66747970  //ftyp
     || CC4(Buffer+4)==0x66726565  //free
     || CC4(Buffer+4)==0x6D646174  //mdat
     || CC4(Buffer+4)==0x6D6F6F76  //moov
     || CC4(Buffer+4)==0x736B6970  //skip
     || CC4(Buffer+4)==0x77696465  //wide
     || CC4(Buffer)==0x060E2B34) //MXF begin
    {
        Finish();
        return false;
    }
 
    //All should be OK...
    return true;
}
 
//***************************************************************************
// Buffer - Synchro
//***************************************************************************
 
//---------------------------------------------------------------------------
bool File_DvDif::Synchronize()
{
    if (AuxToAnalyze)
    {
        Accept();
        return true;
    }
 
    while (Buffer_Offset+8*80<=Buffer_Size //8 blocks
        && !((Buffer[Buffer_Offset+0*80]&0xE0)==0x00 && (Buffer[Buffer_Offset+0*80+1]&0xF0)==0x00 && Buffer[Buffer_Offset+0*80+2]==0x00   //Header 0
          && (Buffer[Buffer_Offset+1*80]&0xE0)==0x20 && (Buffer[Buffer_Offset+1*80+1]&0xF0)==0x00 && Buffer[Buffer_Offset+1*80+2]==0x00   //Subcode 0
          && (Buffer[Buffer_Offset+2*80]&0xE0)==0x20 && (Buffer[Buffer_Offset+2*80+1]&0xF0)==0x00 && Buffer[Buffer_Offset+2*80+2]==0x01   //Subcode 1
          && (Buffer[Buffer_Offset+3*80]&0xE0)==0x40 && (Buffer[Buffer_Offset+3*80+1]&0xF0)==0x00 && Buffer[Buffer_Offset+3*80+2]==0x00   //VAUX 0
          && (Buffer[Buffer_Offset+4*80]&0xE0)==0x40 && (Buffer[Buffer_Offset+4*80+1]&0xF0)==0x00 && Buffer[Buffer_Offset+4*80+2]==0x01   //VAUX 1
          && (Buffer[Buffer_Offset+5*80]&0xE0)==0x40 && (Buffer[Buffer_Offset+5*80+1]&0xF0)==0x00 && Buffer[Buffer_Offset+5*80+2]==0x02   //VAUX 2
          && (Buffer[Buffer_Offset+6*80]&0xE0)==0x60 && (Buffer[Buffer_Offset+6*80+1]&0xF0)==0x00 && Buffer[Buffer_Offset+6*80+2]==0x00   //Audio 0
          && (Buffer[Buffer_Offset+7*80]&0xE0)==0x80 && (Buffer[Buffer_Offset+7*80+1]&0xF0)==0x00 && Buffer[Buffer_Offset+7*80+2]==0x00)) //Video 0
            Buffer_Offset++;
 
    if (Buffer_Offset+8*80>Buffer_Size)
        return false;
 
    if (!Status[IsAccepted])
    {
        Accept();
 
        #if MEDIAINFO_DEMUX
            if (Config->Demux_Unpacketize_Get())
                Demux_UnpacketizeContainer=true;
        #endif //MEDIAINFO_DEMUX
    }
 
    return true;
}
 
//---------------------------------------------------------------------------
bool File_DvDif::Synched_Test()
{
    if (AuxToAnalyze)
        return true;
 
    //Must have enough buffer for having header
    if (Buffer_Offset+80>Buffer_Size)
        return false;
 
    //NULL blocks
    if (Buffer[Buffer_Offset  ]==0x00
     && Buffer[Buffer_Offset+1]==0x00
     && Buffer[Buffer_Offset+2]==0x00)
        return true;
 
    SCT =(Buffer[Buffer_Offset  ]&0xE0)>>5;
    Dseq= Buffer[Buffer_Offset+1]>>4;
    DBN = Buffer[Buffer_Offset+2];
 
    //DIF Sequence Numbers
    if (DSF_IsValid)
    {
        if (Dseq_Old!=Dseq)
        {
            if (Dseq==0
             && !(!DSF && Dseq_Old==9)
             && !( DSF && Dseq_Old==11))
            {
                if (!Status[IsAccepted])
                    Trusted_IsNot("Wrong order");
                else
                    Synched_Test_Reset();
            }
            Dseq_Old=Dseq;
        }
    }
 
    //DIF Block Numbers
    if (SCT!=(int8u)-1)
    {
        int8u Number=DBN_Olds[SCT]+1;
        switch (SCT)
        {
            case 0 : //Header
                        if (SCT_Old!=4
                         || DBN!=0)
                        {
                            if (!Status[IsAccepted])
                                Trusted_IsNot("Wrong order");
                            else
                                Synched_Test_Reset();
                        }
                        break;
            case 1 : //Subcode
                        if (!((DBN==0 && SCT_Old==0) || (DBN!=0 && SCT_Old==1))
                         || (Number!=DBN && !(Number==2 && DBN==0)))
                        {
                            if (!Status[IsAccepted])
                                Trusted_IsNot("Wrong order");
                            else
                                Synched_Test_Reset();
                        }
                        break;
            case 2 : //VAUX
                        if (!((DBN==0 && SCT_Old==1) || (DBN!=0 && SCT_Old==2))
                         || (Number!=DBN && !(Number==3 && DBN==0)))
                        {
                            if (!Status[IsAccepted])
                                Trusted_IsNot("Wrong order");
                            else
                                Synched_Test_Reset();
                        }
                        break;
            case 3 : //Audio
                        if (!((DBN==0 && SCT_Old==2) || (DBN!=0 && SCT_Old==4))
                         || (Number!=DBN && !(Number==9 && DBN==0)))
                        {
                            if (!Status[IsAccepted])
                                Trusted_IsNot("Wrong order");
                            else
                                Synched_Test_Reset();
                        }
                        break;
            case 4 : //Video
                        if (!(SCT_Old==3 || SCT_Old==4)
                         || (Number!=DBN && !(Number==135 && DBN==0)))
                        {
                            if (!Status[IsAccepted])
                                Trusted_IsNot("Wrong order");
                            else
                                Synched_Test_Reset();
                        }
                        break;
            default: ;
        }
 
        if (SCT!=(int8u)-1)
        {
            SCT_Old=SCT;
            DBN_Olds[SCT]=DBN;
        }
    }
 
    //We continue
    return true;
}
 
//---------------------------------------------------------------------------
void File_DvDif::Synched_Test_Reset()
{
    //Temp
    SCT=(int8u)-1;
    SCT_Old=4; //Video
    DBN_Olds[0]=0;
    DBN_Olds[1]=1; //SubCode
    DBN_Olds[2]=2; //Vaux
    DBN_Olds[3]=8; //Audio
    DBN_Olds[4]=134; //Video
    DBN_Olds[5]=0;
    DBN_Olds[6]=0;
    DBN_Olds[7]=0;
 
    //Synch
    Synched=false;
}
 
//---------------------------------------------------------------------------
void File_DvDif::Synched_Init()
{
    //FrameInfo
    if (!IsSub && FrameInfo.DTS==(int64u)-1)
        FrameInfo.DTS=0; //No DTS in container
    if (!IsSub && FrameInfo.PTS==(int64u)-1)
        FrameInfo.PTS=0; //No PTS in container
    if (!IsSub && Frame_Count_NotParsedIncluded==(int64u)-1)
        Frame_Count_NotParsedIncluded=0; //No Frame_Count_NotParsedIncluded in the container
}
 
//***************************************************************************
// Buffer - Demux
//***************************************************************************
 
//---------------------------------------------------------------------------
#if MEDIAINFO_DEMUX
bool File_DvDif::Demux_UnpacketizeContainer_Test()
{
    //Must have enough buffer for having header
    if (Buffer_Offset+8*80>Buffer_Size)
        return false;
 
    if ((Buffer[Buffer_Offset]&0xE0)==0x00   //Speed up the parsing
     && (CC3(Buffer+Buffer_Offset+0*80)&0xE0FCFF)==0x000400   //Header 0 (with FSC==false and FSP==true)
     && (CC3(Buffer+Buffer_Offset+1*80)&0xE0F0FF)==0x200000   //Subcode 0
     && (CC3(Buffer+Buffer_Offset+2*80)&0xE0F0FF)==0x200001   //Subcode 1
     && (CC3(Buffer+Buffer_Offset+3*80)&0xE0F0FF)==0x400000   //VAUX 0
     && (CC3(Buffer+Buffer_Offset+4*80)&0xE0F0FF)==0x400001   //VAUX 1
     && (CC3(Buffer+Buffer_Offset+5*80)&0xE0F0FF)==0x400002   //VAUX 2
     && (CC3(Buffer+Buffer_Offset+6*80)&0xE0F0FF)==0x600000   //Audio 0
     && (CC3(Buffer+Buffer_Offset+7*80)&0xE0F0FF)==0x800000)  //Video 0
    {
        if (Demux_Offset==0)
        {
            Demux_Offset=Buffer_Offset+1;
        }
 
        while (Demux_Offset+8*80<=Buffer_Size //8 blocks
            && !((Buffer[Demux_Offset]&0xE0)==0x00   //Speed up the parsing
              && (CC3(Buffer+Demux_Offset+0*80)&0xE0FCFF)==0x000400   //Header 0 (with FSC==false and FSP==true)
              && (CC3(Buffer+Demux_Offset+1*80)&0xE0F0FF)==0x200000   //Subcode 0
              && (CC3(Buffer+Demux_Offset+2*80)&0xE0F0FF)==0x200001   //Subcode 1
              && (CC3(Buffer+Demux_Offset+3*80)&0xE0F0FF)==0x400000   //VAUX 0
              && (CC3(Buffer+Demux_Offset+4*80)&0xE0F0FF)==0x400001   //VAUX 1
              && (CC3(Buffer+Demux_Offset+5*80)&0xE0F0FF)==0x400002   //VAUX 2
              && (CC3(Buffer+Demux_Offset+6*80)&0xE0F0FF)==0x600000   //Audio 0
              && (CC3(Buffer+Demux_Offset+7*80)&0xE0F0FF)==0x800000)) //Video 0
                Demux_Offset++;
 
        if (Demux_Offset+8*80>Buffer_Size && File_Offset+Buffer_Size!=File_Size)
            return false; //No complete frame
        if (Demux_Offset+8*80>Buffer_Size && File_Offset+Buffer_Size==File_Size)
            Demux_Offset=(size_t)(File_Size-File_Offset); //Using the complete buffer (no next sync)
 
        Element_Code=-1;
        FrameInfo.DTS=FrameInfo.PTS=Speed_FrameCount_system[0]*100100000/3+Speed_FrameCount_system[1]*40000000;
        Speed_FrameCount_system[system]++;
        int64u NextPTS=Speed_FrameCount_system[0]*100100000/3+Speed_FrameCount_system[1]*40000000;
        Speed_FrameCount_system[system]--;
        FrameInfo.DUR=(int64u)-1; // Unknown, system flag is not yet checked
        Demux_UnpacketizeContainer_Demux();
    }
 
    return true;
}
#endif //MEDIAINFO_DEMUX
 
//***************************************************************************
// Buffer - Global
//***************************************************************************
 
//---------------------------------------------------------------------------
void File_DvDif::Read_Buffer_Unsynched()
{
    Synched_Test_Reset();
        if (!IsSub && File_GoTo!=(int64u)-1 && (Frame_Count
    #if MEDIAINFO_SEEK
          || Duration_Detected
    #endif //MEDIAINFO_SEEK
          ) && !FSP_WasNotSet)
    {
        int64u BytesPerFrame=12000*(DSF?12:10);
        if (FSC_WasSet)
            BytesPerFrame*=2;
        Frame_Count_NotParsedIncluded=File_GoTo/BytesPerFrame;
        FrameInfo.PTS=FrameInfo.DTS=float64_int64s(Frame_Count_NotParsedIncluded/(DSF?25.000:(30.000*1000/1001))*1000000000);
    }
}
 
//---------------------------------------------------------------------------
#if MEDIAINFO_SEEK
size_t File_DvDif::Read_Buffer_Seek (size_t Method, int64u Value, int64u /*ID*/)
{
    //Init
    if (!Duration_Detected)
    {
        MediaInfo_Internal MI;
        MI.Option(__T("File_KeepInfo"), __T("1"));
        Ztring ParseSpeed_Save=MI.Option(__T("ParseSpeed_Get"), __T(""));
        Ztring Demux_Save=MI.Option(__T("Demux_Get"), __T(""));
        MI.Option(__T("ParseSpeed"), __T("0"));
        MI.Option(__T("Demux"), Ztring());
        size_t MiOpenResult=MI.Open(File_Name);
        MI.Option(__T("ParseSpeed"), ParseSpeed_Save); //This is a global value, need to reset it. TODO: local value
        MI.Option(__T("Demux"), Demux_Save); //This is a global value, need to reset it. TODO: local value
        if (!MiOpenResult || MI.Get(Stream_General, 0, General_Format)!=__T("DV"))
            return 0;
 
        TotalFrames=Ztring(MI.Get(Stream_Video, 0, Video_FrameCount)).To_int64u();
        int64u VideoBitRate=Ztring(MI.Get(Stream_Video, 0, Video_BitRate)).To_int64u();
        if (VideoBitRate==0 || VideoBitRate>=50000000)
        {
            FSC_WasSet=true;
            FSP_WasNotSet=true;
        }
        else if (VideoBitRate>=30000000)
            FSC_WasSet=true;
        float32 FrameRate=Ztring(MI.Get(Stream_Video, 0, Video_FrameRate)).To_float32();
        if (FrameRate>=24.0 && FrameRate<26.0)
            DSF=system=true;
        if (FrameRate>=29.0 && FrameRate<31.0)
            DSF=system=false;
        Duration_Detected=true;
    }
 
    //Parsing
    switch (Method)
    {
        case 0  :
                    GoTo(Value);
                    Open_Buffer_Unsynch();
                    return 1;
        case 1  :
                    GoTo(File_Size*Value/10000);
                    Open_Buffer_Unsynch();
                    return 1;
        case 2  :   //Timestamp
                    {
                        //We transform TimeStamp to a frame number
                        Value=float64_int64s(((float64)Value)*(DSF?25.000:(30.000*1000/1001))/1000000000);
                    }
                    //No break;
        case 3  :   //FrameNumber
                    if (!FSP_WasNotSet)
                    {
                        int64u BytesPerFrame=12000*(DSF?12:10);
                        if (FSC_WasSet)
                            BytesPerFrame*=2;
                        GoTo(BytesPerFrame*Value);
                        Open_Buffer_Unsynch();
                        Frame_Count_NotParsedIncluded=Value;
                        FrameInfo.PTS=FrameInfo.DTS=float64_int64s(Frame_Count_NotParsedIncluded/(DSF?25.000:(30.000*1000/1001))*1000000000);
                        return 1;
                    }
                    else
                        return (size_t)-1; //Not supported
        default :   return (size_t)-1; //Not supported
    }
}
#endif //MEDIAINFO_SEEK
 
//***************************************************************************
// Buffer
//***************************************************************************
 
//---------------------------------------------------------------------------
void File_DvDif::Header_Parse()
#if MEDIAINFO_TRACE
{
    if (AuxToAnalyze!=0x00)
    {
        SCT=(int8u)-1;
        Header_Fill_Code(AuxToAnalyze, Ztring::ToZtring(AuxToAnalyze, 16));
        Header_Fill_Size(4);
        return;
    }
 
    //Unsynch problems
    if (Element_Size<80)
    {
        Element_WaitForMoreData();
        return;
    }
    if (Buffer[Buffer_Offset  ]==0x00
     && Buffer[Buffer_Offset+1]==0x00
     && Buffer[Buffer_Offset+2]==0x00)
    {
        SCT=(int8u)-1;
        Header_Fill_Code((int64u)-1);
        Header_Fill_Size(80);
        return;
    }
 
    //Parsing
    BS_Begin();
    //0
    Get_S1 (3, SCT,                                             "SCT - Section Type"); Param_Info1(Dv_sct[SCT]);
    Skip_SB(                                                    "Res - Reserved");
    Skip_S1(4,                                                  "Arb - Arbitrary bits");
    //1
    Get_S1 (4, Dseq,                                            "Dseq - DIF sequence number"); //0-9 for 525/60; 0-11 for 625/50
    Get_SB (   FSC,                                             "FSC - Channel number");
    Get_SB (   FSP,                                             "FSP - Channel number"); //SMPTE 370M only
    Skip_S1(2,                                                  "Res - Reserved");
    BS_End();
    //2
    Get_B1 (DBN,                                                "DBN - DIF block number"); //Video: 0-134, Audio: 0-8
 
    Header_Fill_Code(SCT, Dv_sct[SCT]);
    Header_Fill_Size(80);
}
#else //MEDIAINFO_TRACE
{
    if (AuxToAnalyze!=0x00)
    {
        SCT=(int8u)-1;
        Header_Fill_Code(AuxToAnalyze);
        Header_Fill_Size(4);
        return;
    }
 
    //Unsynch problems
    if (Element_Size<80)
    {
        Element_WaitForMoreData();
        return;
    }
    if (Buffer[Buffer_Offset  ]==0x00
     && Buffer[Buffer_Offset+1]==0x00
     && Buffer[Buffer_Offset+2]==0x00)
    {
        SCT=(int8u)-1;
        Header_Fill_Code((int64u)-1);
        Header_Fill_Size(80);
        return;
    }
 
    //Parsing
    SCT =(Buffer[Buffer_Offset  ]&0xE0)>>5;
    Dseq=(Buffer[Buffer_Offset+1]&0xF0)>>4;
    FSC =(Buffer[Buffer_Offset+1]&0x08)==0x08;
    FSP =(Buffer[Buffer_Offset+1]&0x04)==0x04;
    DBN = Buffer[Buffer_Offset+2];
    Element_Offset+=3;
 
    Header_Fill_Code(SCT);
    Header_Fill_Size(80);
}
#endif //MEDIAINFO_TRACE
 
//---------------------------------------------------------------------------
void File_DvDif::Data_Parse()
{
    if (Element_Code==(int64u)-1)
    {
        Skip_XX(Element_Size,                                   "Junk");
        return;
    }
 
    //Config
    if (SCT!=(int8u)-1)
    {
        if (!FSC_WasSet && FSC)
            FSC_WasSet=true;
 
        if (!FSP_WasNotSet && !FSP)
            FSP_WasNotSet=true;
    }
 
    if (AuxToAnalyze!=0x00)
    {
        Element();
        return;
    }
 
    Element_Info1(DBN);
 
    switch (SCT)
    {
        case 0 : Header(); break;
        case 1 : Subcode(); break;
        case 2 : VAUX(); break;
        case 3 : Audio(); break;
        case 4 : Video(); break;
        default: Skip_XX(Element_Size,                          "Unknown");
    }
}
 
//***************************************************************************
// Elements
//***************************************************************************
 
//---------------------------------------------------------------------------
void File_DvDif::Header()
#if MEDIAINFO_TRACE
{
    BS_Begin();
    //3
    Get_SB (   DSF,                                             "DSF - DIF Sequence Flag"); //0=NTSC, 1=PAL
    Skip_SB(                                                    "Zero");
    Skip_S1(6,                                                  "Reserved");
 
    //4
    Skip_S1(5,                                                  "Reserved");
    Get_S1 (3, APT,                                             "APT"); //Track application ID, 0=4:2:0, 1=not 4:2:0
 
    //5
    Get_SB (   TF1,                                             "TF1 - Audio data is not valid");
    Skip_S1(4,                                                  "Reserved");
    Skip_S1(3,                                                  "AP1 - Audio application ID");
 
    //6
    Get_SB (  TF2,                                              "TF2 - Video data is not valid");
    Skip_S1(4,                                                  "Reserved");
    Skip_S1(3,                                                  "AP2 - Video application ID");
 
    //7
    Get_SB (  TF3,                                              "TF3 - Subcode is not valid");
    Skip_S1(4,                                                  "Reserved");
    Skip_S1(3,                                                  "AP3 - Subcode application ID");
 
    //8-79
    BS_End();
    Skip_XX(72,                                                 "Reserved"); //Should be filled with 0xFF
 
    if (Config->File_DvDif_IgnoreTransmittingFlags_Get())
    {
        TF1=false;
        TF2=false;
        TF3=false;
    }
 
    FILLING_BEGIN();
        DSF_IsValid=true;
        Dseq_Old=DSF?11:9;
        FrameSize_Theory=(DSF?12:10)*150*80; //12 DIF sequences for PAL, 10 for NTSC
 
        if (TF1 && TF2)
        {
            //This is not logic, the header says no audio and no video! We do not trust the header, resetting all
            TF1=false;
            TF2=false;
            TF3=false;
        }
    FILLING_END();
}
#else //MEDIAINFO_TRACE
{
    if (Element_Size<77)
    {
        Trusted_IsNot("Size is wrong");
        return;
    }
 
    DSF=(Buffer[Buffer_Offset  ]&0x80)?true:false;
    APT=(Buffer[Buffer_Offset+1]&0x07);
    TF1=(Buffer[Buffer_Offset+2]&0x80)?true:false;
    TF2=(Buffer[Buffer_Offset+3]&0x80)?true:false;
    TF3=(Buffer[Buffer_Offset+4]&0x80)?true:false;
 
    if (Config->File_DvDif_IgnoreTransmittingFlags_Get())
    {
        TF1=false;
        TF2=false;
        TF3=false;
    }
 
    FILLING_BEGIN();
        DSF_IsValid=true;
        Dseq_Old=DSF?11:9;
        FrameSize_Theory=(DSF?12:10)*150*80; //12 DIF sequences for PAL, 10 for NTSC
 
        if (TF1 && TF2)
        {
            //This is not logic, the header says no audio and no video! We do not trust the header, resetting all
            TF1=false;
            TF2=false;
            TF3=false;
        }
    FILLING_END();
}
#endif //MEDIAINFO_TRACE
 
//---------------------------------------------------------------------------
void File_DvDif::Subcode()
#if MEDIAINFO_TRACE
{
    //Present?
    if (TF3)
    {
        Skip_XX(Element_Size,                                   "Unused");
        return;
    }
 
    //Parsing
    for (int8u syb_num=0; syb_num<6; syb_num++)
        Subcode_Ssyb(syb_num);
    Skip_XX(29,                                                 "Unused");
}
#else //MEDIAINFO_TRACE
{
    if (TF3)
        return;
 
    for (int8u syb_num=0; syb_num<6; syb_num++)
        Subcode_Ssyb(syb_num);
}
#endif //MEDIAINFO_TRACE
 
//---------------------------------------------------------------------------
void File_DvDif::Subcode_Ssyb(int8u syb_num)
{
    Element_Begin1("ssyb");
 
    //Parsing
    BS_Begin();
    //ID0-ID1
    Skip_SB(                                                    "FR - Identification of half of channel"); //1=first half, 0=second
    if (syb_num==0)
    {
        if (FSC==false)
            Get_S1 ( 3, ssyb_AP3,                               "AP3 - Subcode application ID");
        else
            Skip_S1( 3,                                         "AP3 - Subcode application ID");
    }
    else if (DBN==1 && syb_num==5)
        Skip_S1(3,                                              "APT - track application ID");
    else
        Skip_S1(3,                                              "Res - Reserved");
    Skip_S1(8,                                                  "ABST/BF - Absolute track number / Blank flag");
    Skip_S1(4,                                                  "Syb - SSYSB number");
    BS_End();
    //FFh
    Skip_B1(                                                    "0xFF");
    //PC0-PC4
    Element();
 
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_DvDif::VAUX()
{
    //Present?
    if (TF2)
    {
        Skip_XX(Element_Size,                                   "Unused");
        return;
    }
 
    //Parsing
    for (int8u i=0; i<15; i++)
        Element();
    Skip_XX(2,                                                  "Unused");
}
 
//---------------------------------------------------------------------------
void File_DvDif::Audio()
{
    //Present?
    if (TF1)
    {
        Skip_XX(Element_Size,                                   "Unused");
        return;
    }
 
    Element_Name("Audio");
 
    Element(); //First 5 bytes
    Skip_XX(Element_Size-Element_Offset,                        "Unknown");
}
 
//---------------------------------------------------------------------------
void File_DvDif::Video()
{
    #if MEDIAINFO_TRACE
    //Present?
    if (TF2)
    {
        Skip_XX(Element_Size,                                   "Unused");
        return;
    }
 
    Element_Name("Video");
 
    //Parsing
    BS_Begin();
    Skip_S1(4,                                                  "STA");
    Skip_S1(4,                                                  "QNO");
    BS_End();
    Skip_XX(Element_Size-Element_Offset,                        "Unknown");
    #endif //MEDIAINFO_TRACE
 
    FILLING_BEGIN();
        if (DBN==134 && video_source_stype!=(int8u)-1)
        {
            if (!Status[IsAccepted])
            {
                Accept("DV DIF");
 
                if (!IsSub)
                    Fill(Stream_General, 0, General_Format, "DV");
            }
            if (!Status[IsFilled] && Frame_Count>=Frame_Count_Valid)
                #ifdef MEDIAINFO_DVDIF_ANALYZE_YES
                {
                    if (Config->File_DvDif_Analysis_Get())
                        Fill("DV DIF");
                    else
                        Finish("DV DIF");
                }
                #else //MEDIAINFO_DVDIF_ANALYZE_YES
                    Finish("DV DIF");
                #endif //MEDIAINFO_DVDIF_ANALYZE_YES
        }
    FILLING_END();
}
 
//---------------------------------------------------------------------------
void File_DvDif::Element()
{
    Element_Begin0();
    int8u PackType;
    if (AuxToAnalyze==0x00)
        Get_B1 (PackType,                                       "Pack Type");
    else
        PackType=AuxToAnalyze; //Forced by parser
 
    switch(PackType)
    {
        case 0x13 : timecode(); break;
        case 0x14 : binary_group(); break;
        case 0x50 : audio_source(); break;
        case 0x51 : audio_sourcecontrol(); break;
        case 0x52 : audio_recdate(); break;
        case 0x53 : audio_rectime(); break;
        case 0x60 : video_source(); break;
        case 0x61 : video_sourcecontrol(); break;
        case 0x62 : video_recdate(); break;
        case 0x63 : video_rectime(); break;
        case 0x65 : closed_captions(); break;
        case 0x70 : consumer_camera_1(); break;
        case 0x71 : consumer_camera_2(); break;
        case 0xFF : Element_Name(Ztring().From_Number(PackType, 16));
                    Skip_B4(                                    "Unused"); break;
        default   : Element_Name(Ztring().From_Number(PackType, 16));
                    Skip_B4(                                    "Unknown");
    }
    Element_End0();
}
 
//---------------------------------------------------------------------------
void File_DvDif::binary_group()
{
    Element_Name("binary_group");
 
    if (Buffer[Buffer_Offset+(size_t)Element_Offset  ]==0xFF
     && Buffer[Buffer_Offset+(size_t)Element_Offset+1]==0xFF
     && Buffer[Buffer_Offset+(size_t)Element_Offset+2]==0xFF
     && Buffer[Buffer_Offset+(size_t)Element_Offset+3]==0xFF
    )
    {
        Skip_XX(4,                                              "All one");
        return;
    }
 
    //Parsing
    BS_Begin();
    Skip_S1(4,                                                  "Binary group 2");
    Skip_S1(4,                                                  "Binary group 1");
    Skip_S1(4,                                                  "Binary group 4");
    Skip_S1(4,                                                  "Binary group 3");
    Skip_S1(4,                                                  "Binary group 6");
    Skip_S1(4,                                                  "Binary group 5");
    Skip_S1(4,                                                  "Binary group 8");
    Skip_S1(4,                                                  "Binary group 7");
    BS_End();
}
 
 
//---------------------------------------------------------------------------
void File_DvDif::timecode()
{
    Element_Name("timecode");
 
    //Parsing
    int8u Frames_Units, Frames_Tens, Seconds_Units, Seconds_Tens, Minutes_Units, Minutes_Tens, Hours_Units, Hours_Tens;
    int64u MilliSeconds=0;
    int8u  Frames=0;
    bool   DropFrame=false;
    bool   FieldIndication;
    BS_Begin();
    Skip_SB(                                                    "CF - Color fame");
    if (!DSF_IsValid)
        Skip_SB(                                                "Arbitrary bit or DP");
    else if (DSF)    //625/50
        Skip_SB(                                                "Arbitrary bit");
    else        //525/60
        Get_SB (DropFrame,                                      "DP - Drop frame"); //525/60
    Get_S1 (2, Frames_Tens,                                     "Frames (Tens)");
    Frames+=Frames_Tens*10;
    Get_S1 (4, Frames_Units,                                    "Frames (Units)");
    Frames+=Frames_Units;
 
    if (!DSF_IsValid)
        Get_SB(FieldIndication,                                 "BGF0 or PC");
    else if (DSF)    //625/50
        Get_SB(FieldIndication,                                 "BGF0 - Binary group flag");
    else        //525/60
        Get_SB(FieldIndication,                                 "PC - Biphase mark polarity correction"); //0=even; 1=odd
    Get_S1 (3, Seconds_Tens,                                    "Seconds (Tens)");
    MilliSeconds+=Seconds_Tens*10*1000;
    Get_S1 (4, Seconds_Units,                                   "Seconds (Units)");
    MilliSeconds+=Seconds_Units*1000;
 
    if (!DSF_IsValid)
        Skip_SB(                                                "BGF2 or BGF0");
    else if (DSF)    //625/50
        Skip_SB(                                                "BGF2 - Binary group flag");
    else        //525/60
        Skip_SB(                                                "BGF0 - Binary group flag");
    Get_S1 (3, Minutes_Tens,                                    "Minutes (Tens)");
    MilliSeconds+=Minutes_Tens*10*60*1000;
    Get_S1 (4, Minutes_Units,                                   "Minutes (Units)");
    MilliSeconds+=Minutes_Units*60*1000;
 
    if (!DSF_IsValid)
        Skip_SB(                                                "PC or BGF1");
    else if (DSF)    //625/50
        Skip_SB(                                                "PC - Biphase mark polarity correction"); //0=even; 1=odd
    else        //525/60
        Skip_SB(                                                "BGF1 - Binary group flag");
    Skip_SB(                                                    "BGF2 - Binary group flag");
    Get_S1 (2, Hours_Tens,                                      "Hours (Tens)");
    MilliSeconds+=Hours_Tens*10*60*60*1000;
    Get_S1 (4, Hours_Units,                                     "Hours (Units)");
    MilliSeconds+=Hours_Units*60*60*1000;
    Element_Info1(Ztring().Duration_From_Milliseconds(MilliSeconds+((DSF_IsValid && Frames!=45)?((int64u)(Frames/(DSF?25.000:29.970)*1000)):0)));
    BS_End();
 
    if (!TimeCode_FirstFrame.HasValue() && MilliSeconds!=167185000) //if all bits are set to 1, this is not a valid timestamp
    {
        TimeCode_FirstFrame=TimeCode(Hours_Tens  *10+Hours_Units,
                                     Minutes_Tens*10+Minutes_Units,
                                     Seconds_Tens*10+Seconds_Units,
                                     (DSF_IsValid && Frames!=45)?(Frames_Tens*10+Frames_Units):0, //if all bits are set to 1, this is not a valid frame number
                                     0, //Unknown
                                     DropFrame,
                                     false, //Unknown
                                     false);
    }
}
 
//---------------------------------------------------------------------------
void File_DvDif::audio_source()
{
    if (TF1)
    {
        Skip_XX(4,                                              "Unused");
        return;
    }
 
    Element_Name("audio_source");
 
    int8u SamplingRate, Resolution;
    BS_Begin();
    //PC1
    Get_SB (   audio_locked,                                    "LF - Locked mode");
    Skip_SB(                                                    "Reserved");
    Skip_S1(6,                                                  "AF - Samples in this frame");
 
    //PC2
    Info_S1(1, StereoMode,                                      "SM - Stereo mode"); Param_Info1(Dv_StereoMode[StereoMode]);
    Info_S1(2, ChannelsPerBlock,                                "CHN - Channels per block"); Param_Info1(Dv_ChannelsPerBlock[ChannelsPerBlock]);
    Info_S1(1, Pair,                                            "PA - Pair"); Param_Info1(Dv_Pair[Pair]);
    Skip_S1(4,                                                  "AM - Audio mode");
 
    Skip_SB(                                                    "Reserved");
    Skip_SB(                                                    "ML - Multi-language");
    Skip_SB(                                                    "50/60");
    Get_S1 (5, audio_source_stype,                              "STYPE - audio blocks per video frame"); Param_Info1(audio_source_stype==0?"2 channels":(audio_source_stype==2?"4 channels":"Unknown")); //0=25 Mbps, 2=50 Mbps
 
    Skip_SB(                                                    "EF - Emphasis off");
    Skip_SB(                                                    "TC - Time constant of emphasis");
    Get_S1 (3, SamplingRate,                                    "SMP - Sampling rate"); Param_Info1(Dv_Audio_SamplingRate[SamplingRate]);
    Get_S1 (3, Resolution,                                      "QU - Resolution"); Param_Info1(Dv_Audio_BitDepth[Resolution]);
    BS_End();
 
    FILLING_BEGIN();
        if (!IgnoreAudio && Streams_Audio.empty() && Dv_Audio_SamplingRate[SamplingRate] && Dv_Audio_BitDepth[Resolution])
        {
            //Calculating the count of audio
            size_t Audio_Count=1;
            if (audio_source_stype==2 || (Resolution==1 && SamplingRate==2)) //stype=2 or (Resolution=12 bits and SamplingRate=32 KHz)
                Audio_Count=2;
            if (audio_source_stype==3)
                Audio_Count=4;
 
            //Filling
            if (Streams_Audio.size()<Audio_Count)
                Streams_Audio.resize(Audio_Count);
            for (size_t Pos=0; Pos<Audio_Count; Pos++)
            {
                if (Streams_Audio[Pos]==NULL)
                    Streams_Audio[Pos]=new stream;
                Streams_Audio[Pos]->Infos["ID"].From_Number(Pos);
                Streams_Audio[Pos]->Infos["Format"]=__T("PCM");
                Streams_Audio[Pos]->Infos["Codec"]=__T("PCM");
                Streams_Audio[Pos]->Infos["BitRate_Mode"]=__T("CBR");
                Streams_Audio[Pos]->Infos["Channel(s)"].From_Number(audio_source_stype==3?1:2);
                Streams_Audio[Pos]->Infos["SamplingRate"].From_Number(Dv_Audio_SamplingRate[SamplingRate]);
                Streams_Audio[Pos]->Infos["BitDepth"].From_Number(Dv_Audio_BitDepth[Resolution]);
                Streams_Audio[Pos]->Infos["Format_Settings"] = __T("Big / Signed");
                Streams_Audio[Pos]->Infos["Format_Settings_Endianness"]=__T("Big");
                Streams_Audio[Pos]->Infos["Format_Settings_Sign"]=__T("Signed");
                Streams_Audio[Pos]->Infos["BitRate"].From_Number((audio_source_stype==3?1:2)*Dv_Audio_SamplingRate[SamplingRate]*Dv_Audio_BitDepth[Resolution]);
            }
        }
    FILLING_END();
}
 
//---------------------------------------------------------------------------
void File_DvDif::audio_sourcecontrol()
{
    if (TF1)
    {
        Skip_XX(4,                                              "Unused");
        return;
    }
 
    Element_Name("audio_control");
 
    BS_Begin();
 
    //PC1
    Info_S1(2, CopyGenerationManagementSystem,                  "CGMS - Copy generation management system"); Param_Info1(Dv_CopyGenerationManagementSystem[CopyGenerationManagementSystem]);
    Info_S1(2, InputType,                                       "ISR - Input type"); Param_Info1(Dv_InputType[InputType]);
    Info_S1(2, CompressionTimes,                                "CMP - Compression times"); Param_Info1(Dv_CompressionTimes[CompressionTimes]);
    Info_S1(2, Emphasis,                                        "EFC - Emphasis"); Param_Info1(Dv_Emphasis[Emphasis]);
 
    //PC2
    Skip_SB(                                                    "REC S Non-recording start point");
    Skip_SB(                                                    "REC E - Non-recording end point");
    Skip_SB(                                                    "FADE S - Recording mode"); //1=Original
    Skip_SB(                                                    "FADE E - Unknown");
    Skip_SB(                                                    "Reserved");
    Skip_SB(                                                    "Reserved");
    Skip_SB(                                                    "Reserved");
    Skip_SB(                                                    "Reserved");
 
    //PC3
    Skip_SB(                                                    "DRF - Direction"); //1=Forward
    Skip_S1(7,                                                  "SPD - Speed");
 
    //PC4
    Skip_SB(                                                    "Reserved");
    Skip_S1(7,                                                  "GEN - Category");
 
    BS_End();
}
 
//---------------------------------------------------------------------------
void File_DvDif::audio_recdate()
{
    if (TF1)
    {
        Skip_XX(4,                                              "Unused");
        return;
    }
 
    Element_Name("audio_recdate");
 
    recdate();
}
 
//---------------------------------------------------------------------------
void File_DvDif::audio_rectime()
{
    if (TF1)
    {
        Skip_XX(4,                                              "Unused");
        return;
    }
 
    Element_Name("audio_rectime");
 
    rectime();
}
 
//---------------------------------------------------------------------------
void File_DvDif::video_source()
{
    if (TF2)
    {
        Skip_XX(4,                                              "Unused");
        return;
    }
 
    Element_Name("video_source");
 
    BS_Begin();
    //PC1
    Skip_S1(4,                                                  "TVCH (tens of units, 0-9)");
    Skip_S1(4,                                                  "TVCH (units, 0-9)");
 
    //PC2
    Skip_SB(                                                    "B/W - Black and White"); //0=Black and White, 1=Color
    Skip_SB(                                                    "EN - Color Frames is not valid");
    Skip_S1(2,                                                  "CLF - Color frames id");
    Skip_S1(4,                                                  "TVCH (hundreds of units, 0-9)");
 
    //PC3
    Skip_S1(2,                                                  "SRC");
    Get_SB (   system,                                          "50/60 - System");
    Get_S1 (5, video_source_stype,                              "STYPE - Signal type of video signal"); //0=not 4:2:2, 4=4:2:2
 
    //PC4
    BS_End();
    Skip_B1(                                                    "TUN/VISC");
 
    FILLING_BEGIN();
        if (FSC==false && FSP==true && Dseq==0)
        {
            Frame_Count++;
            if (Frame_Count_NotParsedIncluded!=(int64u)-1)
                Frame_Count_NotParsedIncluded++;
            FrameInfo.DUR=float64_int64s(((float64)1000000000)/(DSF?25.000:29.970));
            if (FrameInfo.DTS!=(int64u)-1)
                FrameInfo.DTS+=FrameInfo.DUR;
            if (FrameInfo.PTS!=(int64u)-1)
                FrameInfo.PTS+=FrameInfo.DUR;
        }
    FILLING_END();
}
 
//---------------------------------------------------------------------------
void File_DvDif::video_sourcecontrol()
{
    if (TF2)
    {
        Skip_XX(4,                                              "Unused");
        return;
    }
 
    Element_Name("video_control");
 
    BS_Begin();
    //PC1
    Info_S1(2, CopyGenerationManagementSystem,                  "CGMS - Copy generation management system"); Param_Info1(Dv_CopyGenerationManagementSystem[CopyGenerationManagementSystem]);
    Skip_S1(2,                                                  "ISR");
    Skip_S1(2,                                                  "CMP");
    Skip_S2(2,                                                  "SS");
 
    //PC2
    Skip_SB(                                                    "REC S");
    Skip_SB(                                                    "Reserved");
    Skip_S1(2,                                                  "REC M");
    Skip_SB(                                                    "Reserved");
    Get_S1 (3, aspect,                                          "DISP - Aspect ratio"); Param_Info1(Dv_Disp[aspect]);
 
    //PC3
    Get_SB (   FieldOrder_FF,                                   "FF - Frame/Field"); //1=Frame, 0=Field
    Get_SB (   FieldOrder_FS,                                   "FS - First/second field"); //0=Field 2, 1=Field 1, if FF=0 x is output twice, if FF=1, Field x fisrst, other second
    Skip_SB(                                                    "FC - Frame Change"); //0=Same picture as before
    Get_SB (   Interlaced,                                      "IL - Interlaced"); //1=Interlaced
    Skip_SB(                                                    "SF");
    Skip_SB(                                                    "SC");
    Skip_S1(2,                                                  "BCS");
 
    //PC4
    Skip_SB(                                                    "Reserved");
    Skip_S1(7,                                                  "GEN - Category");
 
    BS_End();
 
    FILLING_BEGIN();
        video_sourcecontrol_IsParsed=true;
    FILLING_END();
}
 
//---------------------------------------------------------------------------
void File_DvDif::video_recdate()
{
    if (TF2)
    {
        Skip_XX(4,                                              "Unused");
        return;
    }
 
    Element_Name("video_recdate");
 
    recdate(true);
}
 
//---------------------------------------------------------------------------
void File_DvDif::video_rectime()
{
    if (TF2)
    {
        Skip_XX(4,                                              "Unused");
        return;
    }
 
    Element_Name("video_rectime");
 
    rectime(true);
}
 
//---------------------------------------------------------------------------
void File_DvDif::closed_captions()
{
    Element_Name("closed_captions");
 
    #if defined(MEDIAINFO_EIA608_YES)
        if (CC_Parsers.empty())
        {
            CC_Parsers.resize(2);
            for (int8u Pos=0; Pos<2; Pos++)
            {
                CC_Parsers[Pos]=new File_Eia608();
                ((File_Eia608*)CC_Parsers[Pos])->cc_type=Pos;
            }
            Frame_Count_Valid*=10; //More frames
        }
        if (Dseq==0) //CC are duplicated for each DIF sequence!
        {
            for (size_t Pos=0; Pos<2; Pos++)
            {
                Open_Buffer_Init(CC_Parsers[Pos]);
                Open_Buffer_Continue(CC_Parsers[Pos], 2);
            }
        }
 
    #else
        Skip_XX(4,                                              "Captions");
    #endif
}
 
//---------------------------------------------------------------------------
void File_DvDif::consumer_camera_1()
{
    Element_Name("consumer_camera_1");
 
    //Parsing
    BS_Begin();
    int8u ae_mode, wb_mode, white_balance, fcm;
    Mark_1_NoTrustError();
    Mark_1_NoTrustError();
    Skip_S1(6,                                                  "iris");
    Get_S1 (4, ae_mode,                                         "ae mode"); Param_Info1(Dv_consumer_camera_1_ae_mode[ae_mode]);
    Skip_S1(4,                                                  "agc(Automatic Gain Control)");
    Get_S1 (3, wb_mode,                                         "wb mode (white balance mode)"); Param_Info1(Dv_consumer_camera_1_wb_mode[wb_mode]);
    Get_S1 (5, white_balance,                                   "white balance"); Param_Info1(Dv_consumer_camera_1_white_balance(white_balance));
    Get_S1 (1, fcm,                                             "fcm (Focus mode)"); Param_Info1(Dv_consumer_camera_1_fcm[fcm]);
    Skip_S1(7,                                                  "focus (focal point)");
    BS_End();
 
    if (Encoded_Library_Settings.empty())
    {
        if (ae_mode<0x0F) Encoded_Library_Settings+=__T("ae mode=")+Ztring(Dv_consumer_camera_1_ae_mode[ae_mode])+__T(" / ");
        if (wb_mode<0x08) Encoded_Library_Settings+=__T("wb mode=")+Ztring(Dv_consumer_camera_1_wb_mode[wb_mode])+__T(" / ");
        if (wb_mode<0x1F) Encoded_Library_Settings+=__T("white balance=")+Ztring(Dv_consumer_camera_1_white_balance(white_balance))+__T(" / ");
        Encoded_Library_Settings+=__T("fcm=")+Ztring(Dv_consumer_camera_1_fcm[fcm]);
    }
}
 
//---------------------------------------------------------------------------
void File_DvDif::consumer_camera_2()
{
    Element_Name("consumer_camera_2");
 
    //Parsing
    BS_Begin();
    Mark_1_NoTrustError();
    Mark_1_NoTrustError();
    Skip_S1(1,                                                  "vpd");
    Skip_S1(5,                                                  "vertical panning speed");
    Skip_S1(1,                                                  "is");
    Skip_S1(1,                                                  "hpd");
    Skip_S1(6,                                                  "horizontal panning speed");
    Skip_S1(8,                                                  "focal length");
    Skip_S1(1,                                                  "zen");
    Info_S1(3, zoom_U,                                          "units of e-zoom");
    Info_S1(4, zoom_D,                                          "1/10 of e-zoom"); /*if (zoom_D!=0xF)*/ Param_Info1(__T("zoom=")+Ztring().From_Number(zoom_U+((float32)zoom_U)/10, 2));
    BS_End();
}
 
//***************************************************************************
// Helpers
//***************************************************************************
 
//---------------------------------------------------------------------------
void File_DvDif::recdate(bool FromVideo)
{
    // Coherency test
    int32u Test;
    Peek_B4(Test);
    if (Test==(int32u)-1)
    {
        Skip_B4(                                                "Junk");
        return;
    }
 
    BS_Begin();
 
    int8u Temp;
    int16u Year=0;
    int8u  Month=0, Day=0;
    Skip_S1(8,                                                  "Time zone specific"); //ds, tm, tens of time zone, units of time zone, 0xFF for Unknwon
    Skip_SB(                                                    "1");
    Skip_SB(                                                    "1");
    Get_S1 (2, Temp,                                            "Days (Tens)");
    Day+=Temp*10;
    Get_S1 (4, Temp,                                            "Days (Units)");
    Day+=Temp;
    Skip_SB(                                                    "1");
    Skip_SB(                                                    "1");
    Skip_SB(                                                    "1");
    Get_S1 (1, Temp,                                            "Month (Tens)");
    Month+=Temp*10;
    Get_S1 (4, Temp,                                            "Month (Units)");
    Month+=Temp;
    Get_S1 (4, Temp,                                            "Year (Tens)");
    Year+=Temp*10;
    Get_S1 (4, Temp,                                            "Year (Units)");
    Year+=Temp;
    Year+=Year<25?2000:1900;
    Element_Info1(Ztring::ToZtring(Year)+__T("-")+Ztring::ToZtring(Month)+__T("-")+Ztring::ToZtring(Day));
 
    BS_End();
 
    if (FromVideo && Frame_Count==1 && Year!=2065 && Month && Month<=12 && Day && Day<=31 && Recorded_Date_Date.empty())
    {
        Ztring MonthString;
        if (Month<10)
            MonthString.assign(1, __T('0'));
        MonthString+=Ztring::ToZtring(Month);
        Ztring DayString;
        if (Day<10)
            DayString.assign(1, __T('0'));
        DayString+=Ztring::ToZtring(Day);
        Recorded_Date_Date=Ztring::ToZtring(Year)+__T('-')+MonthString+__T('-')+DayString;
    }
}
 
//---------------------------------------------------------------------------
void File_DvDif::rectime(bool FromVideo)
{
    // Coherency test
    int32u Test;
    Peek_B4(Test);
    if (Test==(int32u)-1)
    {
        Skip_B4(                                            "Junk");
        return;
    }
 
    if (!DSF_IsValid)
    {
        Trusted_IsNot("Not in right order");
        return;
    }
 
    BS_Begin();
 
    if (Buffer[Buffer_Offset+(size_t)Element_Offset  ]==0x00
     && Buffer[Buffer_Offset+(size_t)Element_Offset+1]==0x00
     && Buffer[Buffer_Offset+(size_t)Element_Offset+2]==0x00
     && Buffer[Buffer_Offset+(size_t)Element_Offset+3]==0x00
    )
    {
        Skip_XX(4,                                              "All zero");
        return;
    }
 
    int8u Temp;
    int64u Time=0;
    int8u Frames=0;
    Skip_SB(                                                    "Unknown");
    Skip_SB(                                                    "1");
    Get_S1 (2, Temp,                                            "Frames (Tens)");
    Frames+=Temp*10;
    Get_S1 (4, Temp,                                            "Frames (Units)");
    Frames+=Temp;
    if (Temp!=0xF && DSF_IsValid)
        Time+=(int64u)(Frames/(DSF?25.000:29.970));
    Skip_SB(                                                    "1");
    Get_S1 (3, Temp,                                            "Seconds (Tens)");
    Time+=Temp*10*1000;
    Get_S1 (4, Temp,                                            "Seconds (Units)");
    Time+=Temp*1000;
    Skip_SB(                                                    "1");
    Get_S1 (3, Temp,                                            "Minutes (Tens)");
    Time+=Temp*10*60*1000;
    Get_S1 (4, Temp,                                            "Minutes (Units)");
    Time+=Temp*60*1000;
    Skip_SB(                                                    "1");
    Skip_SB(                                                    "1");
    Get_S1 (2, Temp,                                            "Hours (Tens)");
    Time+=Temp*10*60*60*1000;
    Get_S1 (4, Temp,                                            "Hours (Units)");
    Time+=Temp*60*60*1000;
    Element_Info1(Ztring().Duration_From_Milliseconds(Time));
 
    BS_End();
 
    if (FromVideo && Frame_Count==1 && Time!=167185000 && Recorded_Date_Time.empty()) //If all bits are set to 1, this is invalid
        Recorded_Date_Time.Duration_From_Milliseconds(Time);
}
 
} //NameSpace
 
#endif //MEDIAINFO_DV_YES
 

V1020 The function exited without calling the 'BS_End' function. Check lines: 1855, 1846.

V547 Expression 'Streams_Audio.size() < Audio_Count' is always true.

V523 The 'then' statement is equivalent to the 'else' statement.

V523 The 'then' statement is equivalent to the 'else' statement.

V523 The 'then' statement is equivalent to the 'else' statement.

V523 The 'then' statement is equivalent to the 'else' statement.

V525 The code contains the collection of similar blocks. Check items 'Skip_S1_', 'Skip_S1_', 'Skip_S2_' in lines 1632, 1633, 1634.

V550 An odd precise comparison. It's probably better to use a comparison with defined precision: fabs(OverallBitRate) > Epsilon.

V550 An odd precise comparison. It's probably better to use a comparison with defined precision: fabs(Duration) > Epsilon.

V730 It is possible that not all members of a class are initialized inside the constructor. Consider inspecting: Dseq, Dseq_Old, DBN, FSC, FSP, DSF, ...