/* 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"
//---------------------------------------------------------------------------
//***************************************************************************
// Constants
//***************************************************************************
//---------------------------------------------------------------------------
#if defined(MEDIAINFO_AVC_YES) || defined(MEDIAINFO_MPEGPS_YES) || defined(MEDIAINFO_MPEGTS_YES)
//---------------------------------------------------------------------------
namespace MediaInfoLib
{
#include "ZenLib/Conf.h"
using namespace ZenLib;
//---------------------------------------------------------------------------
const char* Avc_profile_idc(int8u profile_idc)
{
switch (profile_idc)
{
case 44 : return "CAVLC 4:4:4 Intra";
case 66 : return "Baseline";
case 77 : return "Main";
case 83 : return "Scalable Baseline";
case 86 : return "Scalable High";
case 88 : return "Extended";
case 100 : return "High";
case 110 : return "High 10";
case 118 : return "Multiview High";
case 122 : return "High 4:2:2";
case 128 : return "Stereo High";
case 138 : return "Multiview Depth High";
case 144 : return "High 4:4:4";
case 244 : return "High 4:4:4 Predictive";
default : return "";
}
}
//---------------------------------------------------------------------------
} //NameSpace
//---------------------------------------------------------------------------
#endif //...
//---------------------------------------------------------------------------
//***************************************************************************
//
//***************************************************************************
//---------------------------------------------------------------------------
#if defined(MEDIAINFO_AVC_YES)
//---------------------------------------------------------------------------
//---------------------------------------------------------------------------
#include "MediaInfo/Video/File_Avc.h"
#if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
#include "MediaInfo/Text/File_DtvccTransport.h"
#endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
#if MEDIAINFO_ADVANCED2
#include "ThirdParty/base64/base64.h"
#endif //MEDIAINFO_ADVANCED2
#include "MediaInfo/MediaInfo_Config_MediaInfo.h"
#if MEDIAINFO_EVENTS
#include "MediaInfo/MediaInfo_Config_PerPackage.h"
#include "MediaInfo/MediaInfo_Events.h"
#include "MediaInfo/MediaInfo_Events_Internal.h"
#endif //MEDIAINFO_EVENTS
#include <cstring>
#include <algorithm>
using namespace std;
using namespace ZenLib;
//---------------------------------------------------------------------------
namespace MediaInfoLib
{
//***************************************************************************
// Infos
//***************************************************************************
//---------------------------------------------------------------------------
const size_t Avc_Errors_MaxCount=32;
//---------------------------------------------------------------------------
extern const int8u Avc_PixelAspectRatio_Size=17;
extern const float32 Avc_PixelAspectRatio[Avc_PixelAspectRatio_Size]=
{
(float32)1, //Reserved
(float32)1,
(float32)12/(float32)11,
(float32)10/(float32)11,
(float32)16/(float32)11,
(float32)40/(float32)33,
(float32)24/(float32)11,
(float32)20/(float32)11,
(float32)32/(float32)11,
(float32)80/(float32)33,
(float32)18/(float32)11,
(float32)15/(float32)11,
(float32)64/(float32)33,
(float32)160/(float32)99,
(float32)4/(float32)3,
(float32)3/(float32)2,
(float32)2,
};
//---------------------------------------------------------------------------
const char* Avc_video_format[]=
{
"Component",
"PAL",
"NTSC",
"SECAM",
"MAC",
"",
"Reserved",
"Reserved",
};
//---------------------------------------------------------------------------
const char* Avc_video_full_range[]=
{
"Limited",
"Full",
};
//---------------------------------------------------------------------------
static const char* Avc_primary_pic_type[]=
{
"I",
"I, P",
"I, P, B",
"SI",
"SI, SP",
"I, SI",
"I, SI, P, SP",
"I, SI, P, SP, B",
};
//---------------------------------------------------------------------------
static const char* Avc_slice_type[]=
{
"P",
"B",
"I",
"SP",
"SI",
"P",
"B",
"I",
"SP",
"SI",
};
//---------------------------------------------------------------------------
const int8u Avc_pic_struct_Size=9;
static const char* Avc_pic_struct[]=
{
"frame",
"top field",
"bottom field",
"top field, bottom field",
"bottom field, top field",
"top field, bottom field, top field repeated",
"bottom field, top field, bottom field repeated",
"frame doubling",
"frame tripling",
};
//---------------------------------------------------------------------------
static const int8u Avc_NumClockTS[]=
{
1,
1,
1,
2,
2,
3,
3,
2,
3,
};
//---------------------------------------------------------------------------
static const char* Avc_ct_type[]=
{
"Progressive",
"Interlaced",
"Unknown",
"Reserved",
};
//---------------------------------------------------------------------------
static const int8u Avc_SubWidthC[]=
{
1,
2,
2,
1,
};
//---------------------------------------------------------------------------
static const int8u Avc_SubHeightC[]=
{
1,
2,
1,
1,
};
//---------------------------------------------------------------------------
const char* Avc_user_data_DTG1_active_format[]=
{
//1st value is for 4:3, 2nd is for 16:9
"", //Undefined
"Reserved",
"Not recommended",
"Not recommended",
"Aspect ratio greater than 16:9", //Use GA94
"Reserved",
"Reserved",
"Reserved",
"4:3 full frame image / 16:9 full frame image",
"4:3 full frame image / 4:3 pillarbox image",
"16:9 letterbox image / 16:9 full frame image",
"14:9 letterbox image / 14:9 pillarbox image",
"Reserved",
"4:3 full frame image, alternative 14:9 center / 4:3 pillarbox image, alternative 14:9 center",
"16:9 letterbox image, alternative 14:9 center / 16:9 full frame image, alternative 14:9 center",
"16:9 letterbox image, alternative 4:3 center / 16:9 full frame image, alternative 4:3 center",
};
//---------------------------------------------------------------------------
const char* Mpegv_colour_primaries(int8u colour_primaries);
const char* Mpegv_transfer_characteristics(int8u transfer_characteristics);
const char* Mpegv_matrix_coefficients(int8u matrix_coefficients);
const char* Mpegv_matrix_coefficients_ColorSpace(int8u matrix_coefficients);
//---------------------------------------------------------------------------
static const char* Avc_ChromaSubsampling_format_idc(int8u chroma_format_idc)
{
switch (chroma_format_idc)
{
case 1: return "4:2:0";
case 2: return "4:2:2";
case 3: return "4:4:4";
default: return "";
}
}
//---------------------------------------------------------------------------
static const char* Avc_ChromaSubsampling_format_idc_ColorSpace(int8u chroma_format_idc)
{
switch (chroma_format_idc)
{
case 0: return "Y";
case 1: return "YUV";
case 2: return "YUV";
default: return "";
}
}
//---------------------------------------------------------------------------
const char* Avc_user_data_GA94_cc_type(int8u cc_type)
{
switch (cc_type)
{
case 0 : return "CEA-608 line 21 field 1 closed captions"; //closed caption 3 if this is second field
case 1 : return "CEA-608 line 21 field 2 closed captions"; //closed caption 4 if this is second field
case 2 : return "DTVCC Channel Packet Data";
case 3 : return "DTVCC Channel Packet Start";
default : return "";
}
}
//---------------------------------------------------------------------------
int32u Avc_MaxDpbMbs(int8u level)
{
switch (level)
{
case 10 : return 1485;
case 11 : return 3000;
case 12 : return 6000;
case 13 :
case 20 : return 11880;
case 21 : return 19800;
case 22 : return 20250;
case 30 : return 40500;
case 31 : return 108000;
case 32 : return 216000;
case 40 :
case 41 : return 245760;
case 42 : return 522240;
case 50 : return 589824;
case 51 : return 983040;
default : return 0;
}
}
//---------------------------------------------------------------------------
namespace AVC_Intra_Headers
{
//720p50
static const size_t __720p50__50_Size = 4 * 0x10 + 0xA;
static const int8u __720p50__50[__720p50__50_Size] = { 0x00, 0x00, 0x01, 0x67, 0x6E, 0x10, 0x20, 0xA6, 0xD4, 0x20, 0x32, 0x33, 0x0C, 0x71, 0x18, 0x88,
0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8C, 0x44, 0x30, 0x21, 0x02, 0x56, 0x4E, 0x6F, 0x37, 0xCD,
0xF9, 0xBF, 0x81, 0x6B, 0xF3, 0x7C, 0xDE, 0x6E, 0x6C, 0xD3, 0x3C, 0x0F, 0x01, 0x6E, 0xFF, 0xC0,
0x00, 0xC0, 0x01, 0x38, 0xC0, 0x40, 0x40, 0x50, 0x00, 0x00, 0x03, 0x00, 0x10, 0x00, 0x00, 0x06,
0x48, 0x40, 0x00, 0x00, 0x01, 0x68, 0xEE, 0x31, 0x12, 0x11 };
static const size_t __720p50_100_Size = 5 * 0x10 + 0x2;
static const int8u __720p50_100[__720p50_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x29, 0xB6, 0xD4, 0x20, 0x2A, 0x33, 0x1D, 0xC7, 0x62, 0xA1,
0x08, 0x40, 0x54, 0x66, 0x3B, 0x8E, 0xC5, 0x42, 0x02, 0x10, 0x25, 0x64, 0x2C, 0x89, 0xE8, 0x85,
0xE4, 0x21, 0x4B, 0x90, 0x83, 0x06, 0x95, 0xD1, 0x06, 0x46, 0x97, 0x20, 0xC8, 0xD7, 0x43, 0x08,
0x11, 0xC2, 0x1E, 0x4C, 0x91, 0x0F, 0x01, 0x40, 0x16, 0xEC, 0x07, 0x8C, 0x04, 0x04, 0x05, 0x00,
0x00, 0x03, 0x00, 0x01, 0x00, 0x00, 0x03, 0x00, 0x64, 0x84, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x31,
0x12, 0x11 };
//720p60
static const size_t __720p60__50_Size = 4 * 0x10 + 0xB;
static const int8u __720p60__50[__720p60__50_Size] = { 0x00, 0x00, 0x01, 0x67, 0x6E, 0x10, 0x20, 0xA6, 0xD4, 0x20, 0x32, 0x33, 0x0C, 0x71, 0x18, 0x88,
0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8C, 0x44, 0x30, 0x21, 0x02, 0x56, 0x4E, 0x6F, 0x37, 0xCD,
0xF9, 0xBF, 0x81, 0x6B, 0xF3, 0x7C, 0xDE, 0x6E, 0x6C, 0xD3, 0x3C, 0x0F, 0x01, 0x6E, 0xFF, 0xC0,
0x00, 0xC0, 0x01, 0x38, 0xC0, 0x40, 0x40, 0x50, 0x00, 0x00, 0x3E, 0x90, 0x00, 0x1D, 0x4C, 0x08,
0x40, 0x00, 0x00, 0x00, 0x00, 0x01, 0x68, 0xEE, 0x31, 0x12, 0x11 };
static const size_t __720p60_100_Size = 5 * 0x10 + 0x1;
static const int8u __720p60_100[__720p60_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x29, 0xB6, 0xD4, 0x20, 0x2A, 0x33, 0x1D, 0xC7, 0x62, 0xA1,
0x08, 0x40, 0x54, 0x66, 0x3B, 0x8E, 0xC5, 0x42, 0x02, 0x10, 0x25, 0x64, 0x2C, 0x89, 0xE8, 0x85,
0xE4, 0x21, 0x4B, 0x90, 0x83, 0x06, 0x95, 0xD1, 0x06, 0x46, 0x97, 0x20, 0xC8, 0xD7, 0x43, 0x08,
0x11, 0xC2, 0x1E, 0x4C, 0x91, 0x0F, 0x01, 0x40, 0x16, 0xEC, 0x07, 0x8C, 0x04, 0x04, 0x05, 0x00,
0x00, 0x03, 0x03, 0xE9, 0x00, 0x01, 0xD4, 0xC0, 0x84, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x31, 0x12,
0x11 };
//1080i50
static const size_t _1080i50__50_Size = 5 * 0x10 + 0xE;
static const int8u _1080i50__50[_1080i50__50_Size] = { 0x00, 0x00, 0x01, 0x67, 0x6E, 0x10, 0x28, 0xA6, 0xD4, 0x20, 0x32, 0x33, 0x0C, 0x71, 0x18, 0x88,
0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8C, 0x44, 0x30, 0x21, 0x02, 0x56, 0x4E, 0x6E, 0x61, 0x87,
0x3E, 0x73, 0x4D, 0x98, 0x0C, 0x03, 0x06, 0x9C, 0x0B, 0x73, 0xE6, 0xC0, 0xB5, 0x18, 0x63, 0x0D,
0x39, 0xE0, 0x5B, 0x02, 0xD4, 0xC6, 0x19, 0x1A, 0x79, 0x8C, 0x32, 0x34, 0x24, 0xF0, 0x16, 0x81,
0x13, 0xF7, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x71, 0x80, 0x80, 0x80, 0xA0, 0x00, 0x00, 0x03, 0x00,
0x20, 0x00, 0x00, 0x06, 0x50, 0x80, 0x00, 0x00, 0x01, 0x68, 0xEE, 0x31, 0x12, 0x11 };
static const size_t _1080i50_100_Size = 5 * 0x10 + 0xF;
static const int8u _1080i50_100[_1080i50_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x29, 0xB6, 0xD4, 0x20, 0x22, 0x33, 0x19, 0xC6, 0x63, 0x23,
0x21, 0x01, 0x11, 0x98, 0xCE, 0x33, 0x19, 0x18, 0x21, 0x03, 0x3A, 0x46, 0x65, 0x6A, 0x65, 0x24,
0xAD, 0xE9, 0x12, 0x32, 0x14, 0x1A, 0x26, 0x34, 0xAD, 0xA4, 0x41, 0x82, 0x23, 0x01, 0x50, 0x2B,
0x1A, 0x24, 0x69, 0x48, 0x30, 0x40, 0x2E, 0x11, 0x12, 0x08, 0xC6, 0x8C, 0x04, 0x41, 0x28, 0x4C,
0x34, 0xF0, 0x1E, 0x01, 0x13, 0xF2, 0xE0, 0x3C, 0x60, 0x20, 0x20, 0x28, 0x00, 0x00, 0x03, 0x00,
0x08, 0x00, 0x00, 0x03, 0x01, 0x94, 0x20, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x33, 0x48, 0xD0 };
//1080i60
static const size_t _1080i60__50_Size = 5 * 0x10 + 0xD;
static const int8u _1080i60__50[_1080i60__50_Size] = { 0x00, 0x00, 0x01, 0x67, 0x6E, 0x10, 0x28, 0xA6, 0xD4, 0x20, 0x32, 0x33, 0x0C, 0x71, 0x18, 0x88,
0x62, 0x10, 0x19, 0x19, 0x86, 0x38, 0x8C, 0x44, 0x30, 0x21, 0x02, 0x56, 0x4E, 0x6E, 0x61, 0x87,
0x3E, 0x73, 0x4D, 0x98, 0x0C, 0x03, 0x06, 0x9C, 0x0B, 0x73, 0xE6, 0xC0, 0xB5, 0x18, 0x63, 0x0D,
0x39, 0xE0, 0x5B, 0x02, 0xD4, 0xC6, 0x19, 0x1A, 0x79, 0x8C, 0x32, 0x34, 0x24, 0xF0, 0x16, 0x81,
0x13, 0xF7, 0xFF, 0x80, 0x01, 0x80, 0x02, 0x71, 0x80, 0x80, 0x80, 0xA0, 0x00, 0x00, 0x7D, 0x20,
0x00, 0x1D, 0x4C, 0x10, 0x80, 0x00, 0x00, 0x01, 0x68, 0xEE, 0x31, 0x12, 0x11 };
static const size_t _1080i60_100_Size = 5 * 0x10 + 0xD;
static const int8u _1080i60_100[_1080i60_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x29, 0xB6, 0xD4, 0x20, 0x22, 0x33, 0x19, 0xC6, 0x63, 0x23,
0x21, 0x01, 0x11, 0x98, 0xCE, 0x33, 0x19, 0x18, 0x21, 0x03, 0x3A, 0x46, 0x65, 0x6A, 0x65, 0x24,
0xAD, 0xE9, 0x12, 0x32, 0x14, 0x1A, 0x26, 0x34, 0xAD, 0xA4, 0x41, 0x82, 0x23, 0x01, 0x50, 0x2B,
0x1A, 0x24, 0x69, 0x48, 0x30, 0x40, 0x2E, 0x11, 0x12, 0x08, 0xC6, 0x8C, 0x04, 0x41, 0x28, 0x4C,
0x34, 0xF0, 0x1E, 0x01, 0x13, 0xF2, 0xE0, 0x3C, 0x60, 0x20, 0x20, 0x28, 0x00, 0x00, 0x1F, 0x48,
0x00, 0x07, 0x53, 0x04, 0x20, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x33, 0x48, 0xD0 };
//1080p50
static const size_t _1080p50_100_Size = 4 * 0x10 + 0xA;
static const int8u _1080p50_100[_1080p50_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x2A, 0xB6, 0xD4, 0x20, 0x22, 0x33, 0x19, 0xC6, 0x63, 0x23,
0x21, 0x01, 0x11, 0x98, 0xCE, 0x33, 0x19, 0x18, 0x21, 0x02, 0x56, 0xB9, 0x3D, 0x7D, 0x7E, 0x4F,
0xE3, 0x3F, 0x11, 0xF1, 0x9E, 0x08, 0xB8, 0x8C, 0x54, 0x43, 0xC0, 0x78, 0x02, 0x27, 0xE2, 0x70,
0x1E, 0x30, 0x10, 0x10, 0x14, 0x00, 0x00, 0x03, 0x00, 0x04, 0x00, 0x00, 0x03, 0x01, 0x92, 0x10,
0x00, 0x00, 0x00, 0x00, 0x01, 0x68, 0xCE, 0x33, 0x48, 0xD0 };
//1080p60
static const size_t _1080p60_100_Size = 4 * 0x10 + 0x8;
static const int8u _1080p60_100[_1080p60_100_Size] = { 0x00, 0x00, 0x01, 0x67, 0x7A, 0x10, 0x2A, 0xB6, 0xD4, 0x20, 0x22, 0x33, 0x19, 0xC6, 0x63, 0x23,
0x21, 0x01, 0x11, 0x98, 0xCE, 0x33, 0x19, 0x18, 0x21, 0x02, 0x56, 0xB9, 0x3D, 0x7D, 0x7E, 0x4F,
0xE3, 0x3F, 0x11, 0xF1, 0x9E, 0x08, 0xB8, 0x8C, 0x54, 0x43, 0xC0, 0x78, 0x02, 0x27, 0xE2, 0x70,
0x1E, 0x30, 0x10, 0x10, 0x14, 0x00, 0x00, 0x0F, 0xA4, 0x00, 0x07, 0x53, 0x02, 0x10, 0x00, 0x00,
0x00, 0x00, 0x01, 0x68, 0xCE, 0x33, 0x48, 0xD0 };
};
//---------------------------------------------------------------------------
// Some DV Metadata info: http://www.freepatentsonline.com/20050076039.pdf
static const char* MDPM(int8u ID)
{
switch (ID)
{
case 0x18: return "Date/Time"; // Is "Text header" in doc?
case 0x19: return "Date/Time (continue 1)"; // Is "Text" in doc?
case 0x70: return "Consumer Camera 1";
case 0x71: return "Consumer Camera 2";
case 0x73: return "Lens";
case 0x7F: return "Camera shutter";
case 0xA1: return "Iris (F)";
case 0xE0: return "Make Model";
case 0xE1: return "Rec Info";
case 0xE4: return "Model Name";
case 0xE5: return "Model Name (continue 1)";
case 0xE6: return "Model Name (continue 1)";
default : return "";
}
}
//---------------------------------------------------------------------------
static const char* MDPM_MakeName(int16u Value)
{
switch (Value)
{
case 0x0103: return "Panasonic";
case 0x0108: return "Sony";
case 0x1011: return "Canon";
case 0x1104: return "JVC";
default : return "";
}
}
//---------------------------------------------------------------------------
// From DV
extern const char* Dv_consumer_camera_1_ae_mode[];
extern const char* Dv_consumer_camera_1_wb_mode[];
extern const char* Dv_consumer_camera_1_white_balance(int8u white_balance);
extern const char* Dv_consumer_camera_1_fcm[];
//***************************************************************************
// Constructor/Destructor
//***************************************************************************
//---------------------------------------------------------------------------
File_Avc::File_Avc()
#if MEDIAINFO_DUPLICATE
:File__Duplicate()
#endif //MEDIAINFO_DUPLICATE
{
//Config
#if MEDIAINFO_EVENTS
ParserIDs[0]=MediaInfo_Parser_Avc;
StreamIDs_Width[0]=0;
#endif //MEDIAINFO_EVENTS
#if MEDIAINFO_TRACE
Trace_Layers_Update(8); //Stream
#endif //MEDIAINFO_TRACE
MustSynchronize=true;
Buffer_TotalBytes_FirstSynched_Max=64*1024;
PTS_DTS_Needed=true;
StreamSource=IsStream;
Frame_Count_NotParsedIncluded=0;
//In
Frame_Count_Valid=0;
FrameIsAlwaysComplete=false;
MustParse_SPS_PPS=false;
SizedBlocks=false;
//Temporal references
TemporalReferences_DelayedElement=NULL;
//Temp
preferred_transfer_characteristics=2;
//Text
#if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
GA94_03_Parser=NULL;
#endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
}
//---------------------------------------------------------------------------
File_Avc::~File_Avc()
{
Clean_Temp_References();
#if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
delete GA94_03_Parser; //GA94_03_Parser=NULL;
#endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
Clean_Seq_Parameter();
}
//---------------------------------------------------------------------------
void File_Avc::Clean_Temp_References()
{
for (size_t Pos = 0; Pos<TemporalReferences.size(); Pos++)
delete TemporalReferences[Pos]; //TemporalReferences[Pos]=NULL;
TemporalReferences.clear();
}
//---------------------------------------------------------------------------
void File_Avc::Clean_Seq_Parameter()
{
for (size_t Pos = 0; Pos<seq_parameter_sets.size(); Pos++)
delete seq_parameter_sets[Pos]; //TemporalReferences[Pos]=NULL;
seq_parameter_sets.clear();
for (size_t Pos = 0; Pos<subset_seq_parameter_sets.size(); Pos++)
delete subset_seq_parameter_sets[Pos]; //subset_seq_parameter_sets[Pos]=NULL;
subset_seq_parameter_sets.clear();
for (size_t Pos = 0; Pos<pic_parameter_sets.size(); Pos++)
delete pic_parameter_sets[Pos]; //pic_parameter_sets[Pos]=NULL;
pic_parameter_sets.clear();
}
//***************************************************************************
// AVC-Intra hardcoded headers
//***************************************************************************
//---------------------------------------------------------------------------
File_Avc::avcintra_header File_Avc::AVC_Intra_Headers_Data(int32u CodecID)
{
switch (CodecID)
{
case 0x61693132: //ai12
case 0x61693232: //ai22
return avcintra_header(AVC_Intra_Headers::_1080p50_100, AVC_Intra_Headers::_1080p50_100_Size); // AVC-Intra 1080p50 class 100/200
case 0x61693133: //ai13
case 0x61693233: //ai23
return avcintra_header(AVC_Intra_Headers::_1080p60_100, AVC_Intra_Headers::_1080p60_100_Size); // AVC-Intra 1080p60 class 100/200
case 0x61693135: //ai15
case 0x61693235: //ai25
return avcintra_header(AVC_Intra_Headers::_1080i50_100, AVC_Intra_Headers::_1080i50_100_Size); // AVC-Intra 1080i50 class 100/200
case 0x61693136: //ai16
case 0x61693236: //ai26
return avcintra_header(AVC_Intra_Headers::_1080i60_100, AVC_Intra_Headers::_1080i60_100_Size); // AVC-Intra 1080i60 class 100/200
case 0x61693170: //ai1p
case 0x61693270: //ai2p
return avcintra_header(AVC_Intra_Headers::__720p60_100, AVC_Intra_Headers::__720p60_100_Size); // AVC-Intra 720p60 class 100/200
case 0x61693171: //ai1q
case 0x61693271: //ai2q
return avcintra_header(AVC_Intra_Headers::__720p50_100, AVC_Intra_Headers::__720p50_100_Size); // AVC-Intra 720p50 class 100/200
//case 0x61693532: //ai52
// return avcintra_header(NULL, 0); // AVC-Intra 1080p25 class 50 (not supported)
//case 0x61693533: //ai53
// return avcintra_header(NULL, 0); // AVC-Intra 1080p30 class 50 (not supported)
case 0x61693535: //ai55
return avcintra_header(AVC_Intra_Headers::_1080i50__50, AVC_Intra_Headers::_1080i50__50_Size); // AVC-Intra 1080i50 class 50
case 0x61693536: //ai56
return avcintra_header(AVC_Intra_Headers::_1080i60__50, AVC_Intra_Headers::_1080i60__50_Size); // AVC-Intra 1080i60 class 50
case 0x61693570: //ai5p
return avcintra_header(AVC_Intra_Headers::__720p60__50, AVC_Intra_Headers::__720p60__50_Size); // AVC-Intra 720p60 class 50
case 0x61693571: //ai5q
return avcintra_header(AVC_Intra_Headers::__720p50__50, AVC_Intra_Headers::__720p50__50_Size); // AVC-Intra 720p50 class 50
default :
return avcintra_header(NULL, 0);
}
}
//---------------------------------------------------------------------------
int32u File_Avc::AVC_Intra_CodecID_FromMeta(int32u Height, int32u Fields, int32u SampleDuration, int32u TimeScale, int32u SizePerFrame)
{
// Computing bitrate
int64u BitRate=((int64u)SizePerFrame)*8*TimeScale/SampleDuration;
int64u SampleRate=float64_int64s(((float64)TimeScale)/SampleDuration);
int32u Class=BitRate<=75000000?50:100; //Arbitrary choosen. TODO: check real maximumm bitrate, check class 200
switch (Class)
{
case 100 :
switch (Height)
{
case 1080 :
switch (Fields)
{
case 1:
switch (SampleRate)
{
case 50: return 0x61693132; //ai12
case 60: return 0x61693133; //ai13
default: return 0x4156696E; //AVin (neutral)
}
case 2:
switch (SampleRate)
{
case 25: return 0x61693135; //ai15 //TODO: check more files in order to know if it should be 1 or 2 fields per sample
case 30: return 0x61693136; //ai16 //TODO: check more files in order to know if it should be 1 or 2 fields per sample
case 50: return 0x61693135; //ai15 //TODO: check more files in order to know if it should be 1 or 2 fields per sample
case 60: return 0x61693136; //ai16 //TODO: check more files in order to know if it should be 1 or 2 fields per sample
default: return 0x4156696E; //AVin (neutral)
}
default: return 0x4156696E; //AVin (neutral)
}
case 720 :
switch (Fields)
{
case 1:
switch (SampleRate)
{
case 50: return 0x61693170; //ai1p
case 60: return 0x61693171; //ai1q
default: return 0x4156696E; //AVin (neutral)
}
default: return 0x4156696E; //AVin (neutral)
}
default : return 0x4156696E; //AVin (neutral)
}
case 50 :
switch (Height)
{
case 1080 :
switch (Fields)
{
case 1:
switch (SampleRate)
{
case 25: return 0x61693532; //ai52
case 30: return 0x61693533; //ai53
default: return 0x4156696E; //AVin (neutral)
}
case 2:
switch (SampleRate)
{
case 25: return 0x61693535; //ai55 //TODO: check more files in order to know if it should be 1 or 2 fields per sample
case 30: return 0x61693536; //ai56 //TODO: check more files in order to know if it should be 1 or 2 fields per sample
case 50: return 0x61693535; //ai55 //TODO: check more files in order to know if it should be 1 or 2 fields per sample
case 60: return 0x61693536; //ai56 //TODO: check more files in order to know if it should be 1 or 2 fields per sample
default: return 0x4156696E; //AVin (neutral)
}
default: return 0x4156696E; //AVin (neutral)
}
case 720 :
switch (Fields)
{
case 1:
switch (SampleRate)
{
case 50: return 0x61693570; //ai5p
case 60: return 0x61693571; //ai5q
default: return 0x4156696E; //AVin (neutral)
}
default: return 0x4156696E; //AVin (neutral)
}
default : return 0x4156696E; //AVin (neutral)
}
default: return 0x4156696E; //AVin (neutral)
}
}
//***************************************************************************
// Streams management
//***************************************************************************
//---------------------------------------------------------------------------
void File_Avc::Streams_Fill()
{
for (std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item=seq_parameter_sets.begin(); seq_parameter_set_Item!=seq_parameter_sets.end(); ++seq_parameter_set_Item)
if ((*seq_parameter_set_Item))
Streams_Fill(seq_parameter_set_Item);
for (std::vector<seq_parameter_set_struct*>::iterator subset_seq_parameter_set_Item=subset_seq_parameter_sets.begin(); subset_seq_parameter_set_Item!=subset_seq_parameter_sets.end(); ++subset_seq_parameter_set_Item)
if ((*subset_seq_parameter_set_Item))
{
if (seq_parameter_sets.empty())
Streams_Fill(subset_seq_parameter_set_Item);
else
Streams_Fill_subset(subset_seq_parameter_set_Item);
Fill(Stream_Video, 0, Video_MultiView_Count, (*subset_seq_parameter_set_Item)->num_views_minus1+1);
}
#if MEDIAINFO_ADVANCED2
for (size_t Pos = 0; Pos<Dump_SPS.size(); Pos++)
Fill(Stream_Video, 0, "Dump_seq_parameter_set", Dump_SPS[Pos].c_str());
for (size_t Pos = 0; Pos<Dump_PPS.size(); Pos++)
Fill(Stream_Video, 0, "Dump_pic_parameter_set", Dump_PPS[Pos].c_str());
#endif //MEDIAINFO_ADVANCED2
}
//---------------------------------------------------------------------------
void File_Avc::Streams_Fill(std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item)
{
if (Count_Get(Stream_Video))
return;
Stream_Prepare(Stream_Video);
Fill(Stream_Video, 0, Video_Format, "AVC");
Fill(Stream_Video, 0, Video_Codec, "AVC");
//Calculating - Pixels
int32u Width =((*seq_parameter_set_Item)->pic_width_in_mbs_minus1 +1)*16;
int32u Height=((*seq_parameter_set_Item)->pic_height_in_map_units_minus1+1)*16*(2-(*seq_parameter_set_Item)->frame_mbs_only_flag);
int8u chromaArrayType = (*seq_parameter_set_Item)->ChromaArrayType();
if (chromaArrayType >= 4)
chromaArrayType = 0;
int32u CropUnitX=Avc_SubWidthC [chromaArrayType];
int32u CropUnitY=Avc_SubHeightC[chromaArrayType]*(2-(*seq_parameter_set_Item)->frame_mbs_only_flag);
Width -=((*seq_parameter_set_Item)->frame_crop_left_offset+(*seq_parameter_set_Item)->frame_crop_right_offset )*CropUnitX;
Height-=((*seq_parameter_set_Item)->frame_crop_top_offset +(*seq_parameter_set_Item)->frame_crop_bottom_offset)*CropUnitY;
//From vui_parameters
float64 PixelAspectRatio=1;
if ((*seq_parameter_set_Item)->vui_parameters)
{
if ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_info_present_flag)
{
if ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_idc<Avc_PixelAspectRatio_Size)
PixelAspectRatio=Avc_PixelAspectRatio[(*seq_parameter_set_Item)->vui_parameters->aspect_ratio_idc];
else if ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_idc==0xFF && (*seq_parameter_set_Item)->vui_parameters->sar_height)
PixelAspectRatio=((float64)(*seq_parameter_set_Item)->vui_parameters->sar_width)/(*seq_parameter_set_Item)->vui_parameters->sar_height;
}
if ((*seq_parameter_set_Item)->vui_parameters->timing_info_present_flag)
{
if (!(*seq_parameter_set_Item)->vui_parameters->fixed_frame_rate_flag)
Fill(Stream_Video, StreamPos_Last, Video_FrameRate_Mode, "VFR");
else if ((*seq_parameter_set_Item)->vui_parameters->timing_info_present_flag && (*seq_parameter_set_Item)->vui_parameters->time_scale && (*seq_parameter_set_Item)->vui_parameters->num_units_in_tick)
Fill(Stream_Video, StreamPos_Last, Video_FrameRate, (float64)(*seq_parameter_set_Item)->vui_parameters->time_scale/(*seq_parameter_set_Item)->vui_parameters->num_units_in_tick/((*seq_parameter_set_Item)->frame_mbs_only_flag?2:(((*seq_parameter_set_Item)->pic_order_cnt_type==2 && Structure_Frame/2>Structure_Field)?1:2))/FrameRate_Divider);
}
//Colour description
if (preferred_transfer_characteristics!=2)
Fill(Stream_Video, 0, Video_transfer_characteristics, Mpegv_transfer_characteristics(preferred_transfer_characteristics));
if ((*seq_parameter_set_Item)->vui_parameters->video_signal_type_present_flag)
{
Fill(Stream_Video, 0, Video_Standard, Avc_video_format[(*seq_parameter_set_Item)->vui_parameters->video_format]);
Fill(Stream_Video, 0, Video_colour_range, Avc_video_full_range[(*seq_parameter_set_Item)->vui_parameters->video_full_range_flag]);
if ((*seq_parameter_set_Item)->vui_parameters->colour_description_present_flag)
{
Fill(Stream_Video, 0, Video_colour_description_present, "Yes");
Fill(Stream_Video, 0, Video_colour_primaries, Mpegv_colour_primaries((*seq_parameter_set_Item)->vui_parameters->colour_primaries));
Fill(Stream_Video, 0, Video_transfer_characteristics, Mpegv_transfer_characteristics((*seq_parameter_set_Item)->vui_parameters->transfer_characteristics));
Fill(Stream_Video, 0, Video_matrix_coefficients, Mpegv_matrix_coefficients((*seq_parameter_set_Item)->vui_parameters->matrix_coefficients));
if ((*seq_parameter_set_Item)->vui_parameters->matrix_coefficients!=2)
Fill(Stream_Video, 0, Video_ColorSpace, Mpegv_matrix_coefficients_ColorSpace((*seq_parameter_set_Item)->vui_parameters->matrix_coefficients), Unlimited, true, true);
}
}
//hrd_parameter_sets
int64u bit_rate_value=(int64u)-1;
bool bit_rate_value_IsValid=true;
bool cbr_flag=false;
bool cbr_flag_IsSet=false;
bool cbr_flag_IsValid=true;
seq_parameter_set_struct::vui_parameters_struct::xxl* NAL=(*seq_parameter_set_Item)->vui_parameters->NAL;
if (NAL)
for (size_t Pos=0; Pos<NAL->SchedSel.size(); Pos++)
{
if (NAL->SchedSel[Pos].cpb_size_value!=(int32u)-1)
Fill(Stream_Video, 0, Video_BufferSize, NAL->SchedSel[Pos].cpb_size_value);
if (bit_rate_value!=(int64u)-1 && bit_rate_value!=NAL->SchedSel[Pos].bit_rate_value)
bit_rate_value_IsValid=false;
if (bit_rate_value==(int64u)-1)
bit_rate_value=NAL->SchedSel[Pos].bit_rate_value;
if (cbr_flag_IsSet==true && cbr_flag!=NAL->SchedSel[Pos].cbr_flag)
cbr_flag_IsValid=false;
if (cbr_flag_IsSet==0)
{
cbr_flag=NAL->SchedSel[Pos].cbr_flag;
cbr_flag_IsSet=true;
}
}
seq_parameter_set_struct::vui_parameters_struct::xxl* VCL=(*seq_parameter_set_Item)->vui_parameters->VCL;
if (VCL)
for (size_t Pos=0; Pos<VCL->SchedSel.size(); Pos++)
{
Fill(Stream_Video, 0, Video_BufferSize, VCL->SchedSel[Pos].cpb_size_value);
if (bit_rate_value!=(int64u)-1 && bit_rate_value!=VCL->SchedSel[Pos].bit_rate_value)
bit_rate_value_IsValid=false;
if (bit_rate_value==(int64u)-1)
bit_rate_value=VCL->SchedSel[Pos].bit_rate_value;
if (cbr_flag_IsSet==true && cbr_flag!=VCL->SchedSel[Pos].cbr_flag)
cbr_flag_IsValid=false;
if (cbr_flag_IsSet==0)
{
cbr_flag=VCL->SchedSel[Pos].cbr_flag;
cbr_flag_IsSet=true;
}
}
if (cbr_flag_IsSet && cbr_flag_IsValid)
{
Fill(Stream_Video, 0, Video_BitRate_Mode, cbr_flag?"CBR":"VBR");
if (bit_rate_value!=(int64u)-1 && bit_rate_value_IsValid)
Fill(Stream_Video, 0, cbr_flag?Video_BitRate_Nominal:Video_BitRate_Maximum, bit_rate_value);
}
}
Ztring Profile=Ztring().From_UTF8(Avc_profile_idc((*seq_parameter_set_Item)->profile_idc));
switch ((*seq_parameter_set_Item)->profile_idc)
{
case 44 : // CAVLC 4:4:4 Intra
case 100 : // High
case 110 : // High 10
case 122 : // High 4:2:2"
case 244 : // High 4:4:4 Predictive
if ((*seq_parameter_set_Item)->constraint_set3_flag)
Profile+=__T(" Intra");
}
Profile+=__T("@L")+Ztring().From_Number(((float)(*seq_parameter_set_Item)->level_idc)/10, ((*seq_parameter_set_Item)->level_idc%10)?1:0);
Fill(Stream_Video, 0, Video_Format_Profile, Profile);
Fill(Stream_Video, 0, Video_Codec_Profile, Profile);
Fill(Stream_Video, StreamPos_Last, Video_Width, Width);
Fill(Stream_Video, StreamPos_Last, Video_Height, Height);
if ((*seq_parameter_set_Item)->frame_crop_left_offset || (*seq_parameter_set_Item)->frame_crop_right_offset)
Fill(Stream_Video, StreamPos_Last, Video_Stored_Width, ((*seq_parameter_set_Item)->pic_width_in_mbs_minus1 +1)*16);
if ((*seq_parameter_set_Item)->frame_crop_top_offset || (*seq_parameter_set_Item)->frame_crop_bottom_offset)
Fill(Stream_Video, StreamPos_Last, Video_Stored_Height, ((*seq_parameter_set_Item)->pic_height_in_map_units_minus1+1)*16*(2-(*seq_parameter_set_Item)->frame_mbs_only_flag));
Fill(Stream_Video, 0, Video_PixelAspectRatio, PixelAspectRatio, 3, true);
if(Height)
Fill(Stream_Video, 0, Video_DisplayAspectRatio, Width*PixelAspectRatio/Height, 3, true); //More precise
if (FrameRate_Divider==2)
{
Fill(Stream_Video, StreamPos_Last, Video_Format_Settings_FrameMode, "Frame doubling");
Fill(Stream_Video, StreamPos_Last, Video_Format_Settings, "Frame doubling");
}
if (FrameRate_Divider==3)
{
Fill(Stream_Video, StreamPos_Last, Video_Format_Settings_FrameMode, "Frame tripling");
Fill(Stream_Video, StreamPos_Last, Video_Format_Settings, "Frame tripling");
}
//Interlacement
if ((*seq_parameter_set_Item)->mb_adaptive_frame_field_flag && Structure_Frame>0) //Interlaced macro-block
{
Fill(Stream_Video, 0, Video_ScanType, "MBAFF");
Fill(Stream_Video, 0, Video_Interlacement, "MBAFF");
}
else if ((*seq_parameter_set_Item)->frame_mbs_only_flag || (Structure_Frame>0 && Structure_Field==0)) //No interlaced frame
{
switch ((*seq_parameter_set_Item)->pic_struct_FirstDetected)
{
case 3 :
Fill(Stream_Video, 0, Video_ScanType, "Interlaced");
Fill(Stream_Video, 0, Video_Interlacement, "TFF");
Fill(Stream_Video, 0, Video_Format_Settings_PictureStructure, "Frame");
Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "InterleavedFields");
break;
case 4 :
Fill(Stream_Video, 0, Video_ScanType, "Interlaced");
Fill(Stream_Video, 0, Video_Interlacement, "BFF");
Fill(Stream_Video, 0, Video_Format_Settings_PictureStructure, "Frame");
Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "InterleavedFields");
break;
default :
Fill(Stream_Video, 0, Video_ScanType, "Progressive");
Fill(Stream_Video, 0, Video_Interlacement, "PPF");
}
}
else if (Structure_Field>0)
{
Fill(Stream_Video, 0, Video_ScanType, "Interlaced");
Fill(Stream_Video, 0, Video_Interlacement, "Interlaced");
}
std::string ScanOrders, PictureTypes(PictureTypes_PreviousFrames);
ScanOrders.reserve(TemporalReferences.size());
for (size_t Pos=0; Pos<TemporalReferences.size(); Pos++)
if (TemporalReferences[Pos])
{
ScanOrders+=TemporalReferences[Pos]->IsTop?'T':'B';
if ((Pos%2)==0)
PictureTypes+=Avc_slice_type[TemporalReferences[Pos]->slice_type];
}
else if (!PictureTypes.empty()) //Only if stream already started
{
ScanOrders+=' ';
if ((Pos%2)==0)
PictureTypes+=' ';
}
Fill(Stream_Video, 0, Video_ScanOrder, ScanOrder_Detect(ScanOrders));
{ //Legacy
string Result=ScanOrder_Detect(ScanOrders);
if (!Result.empty())
{
Fill(Stream_Video, 0, Video_Interlacement, Result, true, true);
Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "SeparatedFields", Unlimited, true, true);
}
else
{
switch ((*seq_parameter_set_Item)->pic_struct_FirstDetected)
{
case 1 :
Fill(Stream_Video, 0, Video_ScanOrder, (string) "TFF");
Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "SeparatedFields", Unlimited, true, true);
break;
case 2 :
Fill(Stream_Video, 0, Video_ScanOrder, (string) "BFF");
Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "SeparatedFields", Unlimited, true, true);
break;
case 3 :
Fill(Stream_Video, 0, Video_ScanOrder, (string) "TFF");
Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "InterleavedFields", Unlimited, true, true);
break;
case 4 :
Fill(Stream_Video, 0, Video_ScanOrder, (string) "BFF");
Fill(Stream_Video, 0, Video_ScanType_StoreMethod, "InterleavedFields", Unlimited, true, true);
break;
default : ;
}
}
}
Fill(Stream_Video, 0, Video_Format_Settings_GOP, GOP_Detect(PictureTypes));
Fill(Stream_General, 0, General_Encoded_Library, Encoded_Library);
Fill(Stream_General, 0, General_Encoded_Library_Name, Encoded_Library_Name);
Fill(Stream_General, 0, General_Encoded_Library_Version, Encoded_Library_Version);
Fill(Stream_General, 0, General_Encoded_Library_Settings, Encoded_Library_Settings);
Fill(Stream_Video, 0, Video_Encoded_Library, Encoded_Library);
Fill(Stream_Video, 0, Video_Encoded_Library_Name, Encoded_Library_Name);
Fill(Stream_Video, 0, Video_Encoded_Library_Version, Encoded_Library_Version);
Fill(Stream_Video, 0, Video_Encoded_Library_Settings, Encoded_Library_Settings);
if (Retrieve_Const(Stream_Video, 0, Video_BitRate_Nominal).empty()) // SPS has priority over other metadata
Fill(Stream_Video, 0, Video_BitRate_Nominal, BitRate_Nominal);
Fill(Stream_Video, 0, Video_MuxingMode, MuxingMode);
for (std::vector<pic_parameter_set_struct*>::iterator pic_parameter_set_Item=pic_parameter_sets.begin(); pic_parameter_set_Item!=pic_parameter_sets.end(); ++pic_parameter_set_Item)
if (*pic_parameter_set_Item && (*pic_parameter_set_Item)->seq_parameter_set_id==seq_parameter_set_Item-(seq_parameter_sets.empty()?subset_seq_parameter_sets.begin():seq_parameter_sets.begin()))
{
if ((*pic_parameter_set_Item)->entropy_coding_mode_flag)
{
Fill(Stream_Video, 0, Video_Format_Settings, "CABAC");
Fill(Stream_Video, 0, Video_Format_Settings_CABAC, "Yes");
Fill(Stream_Video, 0, Video_Codec_Settings, "CABAC");
Fill(Stream_Video, 0, Video_Codec_Settings_CABAC, "Yes");
}
else
{
Fill(Stream_Video, 0, Video_Format_Settings_CABAC, "No");
Fill(Stream_Video, 0, Video_Codec_Settings_CABAC, "No");
}
break; //TODO: currently, testing only the first pic_parameter_set
}
if ((*seq_parameter_set_Item)->max_num_ref_frames>0)
{
Fill(Stream_Video, 0, Video_Format_Settings, Ztring::ToZtring((*seq_parameter_set_Item)->max_num_ref_frames)+__T(" Ref Frames"));
Fill(Stream_Video, 0, Video_Codec_Settings, Ztring::ToZtring((*seq_parameter_set_Item)->max_num_ref_frames)+__T(" Ref Frames"));
Fill(Stream_Video, 0, Video_Format_Settings_RefFrames, (*seq_parameter_set_Item)->max_num_ref_frames);
Fill(Stream_Video, 0, Video_Codec_Settings_RefFrames, (*seq_parameter_set_Item)->max_num_ref_frames);
}
if (Retrieve(Stream_Video, 0, Video_ColorSpace).empty())
Fill(Stream_Video, 0, Video_ColorSpace, Avc_ChromaSubsampling_format_idc_ColorSpace((*seq_parameter_set_Item)->chroma_format_idc));
Fill(Stream_Video, 0, Video_ChromaSubsampling, Avc_ChromaSubsampling_format_idc((*seq_parameter_set_Item)->chroma_format_idc));
if ((*seq_parameter_set_Item)->bit_depth_luma_minus8==(*seq_parameter_set_Item)->bit_depth_chroma_minus8)
Fill(Stream_Video, 0, Video_BitDepth, (*seq_parameter_set_Item)->bit_depth_luma_minus8+8);
hdr::iterator EtsiTs103433 = HDR.find(HdrFormat_EtsiTs103433);
if (EtsiTs103433 != HDR.end())
{
for (std::map<video, Ztring>::iterator Item = EtsiTs103433->second.begin(); Item != EtsiTs103433->second.end(); ++Item)
{
Fill(Stream_Video, 0, Item->first, Item->second);
}
}
hdr::iterator SmpteSt209440 = HDR.find(HdrFormat_SmpteSt209440);
if (SmpteSt209440 != HDR.end())
{
for (std::map<video, Ztring>::iterator Item = SmpteSt209440->second.begin(); Item != SmpteSt209440->second.end(); ++Item)
{
switch (Item->first)
{
case Video_MasteringDisplay_ColorPrimaries:
case Video_MasteringDisplay_Luminance:
if (Retrieve_Const(Stream_Video, 0, Item->first) == Item->second)
break;
// Fallthrough
default:
Fill(Stream_Video, 0, Item->first, Item->second);
}
}
}
hdr::iterator SmpteSt2086 = HDR.find(HdrFormat_SmpteSt2086);
if (SmpteSt2086 != HDR.end())
{
for (std::map<video, Ztring>::iterator Item = SmpteSt2086->second.begin(); Item != SmpteSt2086->second.end(); ++Item)
{
bool Ignore;
switch (Item->first)
{
case Video_HDR_Format:
Ignore = !Retrieve_Const(Stream_Video, 0, Item->first).empty();
break;
case Video_MasteringDisplay_ColorPrimaries:
case Video_MasteringDisplay_Luminance:
Ignore = Retrieve_Const(Stream_Video, 0, Item->first) == Item->second;
break;
}
if (!Ignore)
Fill(Stream_Video, 0, Item->first, Item->second);
}
}
if (maximum_content_light_level)
Fill(Stream_Video, 0, "MaxCLL", Ztring::ToZtring(maximum_content_light_level) + __T(" cd/m2"));
if (maximum_frame_average_light_level)
Fill(Stream_Video, 0, "MaxFALL", Ztring::ToZtring(maximum_frame_average_light_level) + __T(" cd/m2"));
}
//---------------------------------------------------------------------------
void File_Avc::Streams_Fill_subset(const std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item)
{
Ztring Profile=Ztring().From_UTF8(Avc_profile_idc((*seq_parameter_set_Item)->profile_idc))+__T("@L")+Ztring().From_Number(((float)(*seq_parameter_set_Item)->level_idc)/10, 1);
Ztring Profile_Base=Retrieve(Stream_Video, 0, Video_Format_Profile);
Fill(Stream_Video, 0, Video_Format_Profile, Profile, true);
if (!Profile_Base.empty())
Fill(Stream_Video, 0, Video_Format_Profile, Profile_Base);
}
//---------------------------------------------------------------------------
void File_Avc::Streams_Finish()
{
if (PTS_End!=(int64u)-1 && (IsSub || File_Offset+Buffer_Offset+Element_Size==File_Size))
{
if (PTS_End>PTS_Begin)
Fill(Stream_Video, 0, Video_Duration, float64_int64s(((float64)(PTS_End-PTS_Begin))/1000000));
}
//GA94 captions
#if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
if (GA94_03_Parser && GA94_03_Parser->Status[IsAccepted])
{
Clear(Stream_Text);
Finish(GA94_03_Parser);
Merge(*GA94_03_Parser);
Ztring LawRating=GA94_03_Parser->Retrieve(Stream_General, 0, General_LawRating);
if (!LawRating.empty())
Fill(Stream_General, 0, General_LawRating, LawRating, true);
Ztring Title=GA94_03_Parser->Retrieve(Stream_General, 0, General_Title);
if (!Title.empty() && Retrieve(Stream_General, 0, General_Title).empty())
Fill(Stream_General, 0, General_Title, Title);
for (size_t Pos=0; Pos<Count_Get(Stream_Text); Pos++)
{
Ztring MuxingMode=Retrieve(Stream_Text, Pos, "MuxingMode");
Fill(Stream_Text, Pos, "MuxingMode", __T("SCTE 128 / ")+MuxingMode, true);
}
}
#endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
#if MEDIAINFO_IBIUSAGE
if (seq_parameter_sets.size()==1 && (*seq_parameter_sets.begin())->vui_parameters && (*seq_parameter_sets.begin())->vui_parameters->timing_info_present_flag && (*seq_parameter_sets.begin())->vui_parameters->fixed_frame_rate_flag)
Ibi_Stream_Finish((*seq_parameter_sets.begin())->vui_parameters->time_scale, (*seq_parameter_sets.begin())->vui_parameters->num_units_in_tick);
#endif //MEDIAINFO_IBIUSAGE
}
//***************************************************************************
// Buffer - File header
//***************************************************************************
//---------------------------------------------------------------------------
bool File_Avc::FileHeader_Begin()
{
if (!File__Analyze::FileHeader_Begin_0x000001())
return false;
if (!MustSynchronize)
{
Synched_Init();
Buffer_TotalBytes_FirstSynched=0;
File_Offset_FirstSynched=File_Offset;
}
//All should be OK
return true;
}
//***************************************************************************
// Buffer - Synchro
//***************************************************************************
//---------------------------------------------------------------------------
bool File_Avc::Synchronize()
{
//Synchronizing
size_t Buffer_Offset_Min=Buffer_Offset;
while(Buffer_Offset+4<=Buffer_Size && (Buffer[Buffer_Offset ]!=0x00
|| Buffer[Buffer_Offset+1]!=0x00
|| Buffer[Buffer_Offset+2]!=0x01))
{
Buffer_Offset+=2;
while(Buffer_Offset<Buffer_Size && Buffer[Buffer_Offset]!=0x00)
Buffer_Offset+=2;
if (Buffer_Offset>=Buffer_Size || Buffer[Buffer_Offset-1]==0x00)
Buffer_Offset--;
}
if (Buffer_Offset>Buffer_Offset_Min && Buffer[Buffer_Offset-1]==0x00)
Buffer_Offset--;
//Parsing last bytes if needed
if (Buffer_Offset+4==Buffer_Size && (Buffer[Buffer_Offset ]!=0x00
|| Buffer[Buffer_Offset+1]!=0x00
|| Buffer[Buffer_Offset+2]!=0x00
|| Buffer[Buffer_Offset+3]!=0x01))
Buffer_Offset++;
if (Buffer_Offset+3==Buffer_Size && (Buffer[Buffer_Offset ]!=0x00
|| Buffer[Buffer_Offset+1]!=0x00
|| Buffer[Buffer_Offset+2]!=0x01))
Buffer_Offset++;
if (Buffer_Offset+2==Buffer_Size && (Buffer[Buffer_Offset ]!=0x00
|| Buffer[Buffer_Offset+1]!=0x00))
Buffer_Offset++;
if (Buffer_Offset+1==Buffer_Size && Buffer[Buffer_Offset ]!=0x00)
Buffer_Offset++;
if (Buffer_Offset+4>Buffer_Size)
return false;
//Synched is OK
Synched=true;
return true;
}
//---------------------------------------------------------------------------
bool File_Avc::Synched_Test()
{
//Must have enough buffer for having header
if (Buffer_Offset+6>Buffer_Size)
return false;
//Quick test of synchro
if (Buffer[Buffer_Offset ]!=0x00
|| Buffer[Buffer_Offset+1]!=0x00
|| (Buffer[Buffer_Offset+2]!=0x01 && (Buffer[Buffer_Offset+2]!=0x00 || Buffer[Buffer_Offset+3]!=0x01)))
{
Synched=false;
return true;
}
//Quick search
if (!Header_Parser_QuickSearch())
return false;
#if MEDIAINFO_IBIUSAGE
bool zero_byte=Buffer[Buffer_Offset+2]==0x00;
bool RandomAccess=(Buffer[Buffer_Offset+(zero_byte?4:3)]&0x1F)==0x07 || ((Buffer[Buffer_Offset+(zero_byte?4:3)]&0x1F)==0x09 && ((Buffer[Buffer_Offset+(zero_byte?5:4)]&0xE0)==0x00 || (Buffer[Buffer_Offset+(zero_byte?5:4)]&0xE0)==0xA0)); //seq_parameter_set or access_unit_delimiter with value=0 or 5 (3 bits)
if (RandomAccess)
Ibi_Add();
#endif //MEDIAINFO_IBIUSAGE
//We continue
return true;
}
//***************************************************************************
// Buffer - Demux
//***************************************************************************
//---------------------------------------------------------------------------
#if MEDIAINFO_DEMUX
void File_Avc::Data_Parse_Iso14496()
{
if (Demux_Avc_Transcode_Iso14496_15_to_Iso14496_10)
{
if (Element_Code==0x07)
{
std::vector<seq_parameter_set_struct*>::iterator Data_Item=seq_parameter_sets.begin();
if (Data_Item!=seq_parameter_sets.end() && (*Data_Item))
{
(*Data_Item)->Init_Iso14496_10(0x67, Buffer+Buffer_Offset, Element_Size);
}
}
if (Element_Code==0x08)
{
std::vector<pic_parameter_set_struct*>::iterator Data_Item=pic_parameter_sets.begin();
if (Data_Item!=pic_parameter_sets.end() && (*Data_Item))
{
(*Data_Item)->Init_Iso14496_10(0x68, Buffer+Buffer_Offset, Element_Size);
}
}
if (Element_Code==0x0F)
{
std::vector<seq_parameter_set_struct*>::iterator Data_Item=subset_seq_parameter_sets.begin();
if (Data_Item!=subset_seq_parameter_sets.end() && (*Data_Item))
{
SizeOfNALU_Minus1=0;
(*Data_Item)->Init_Iso14496_10(0x6F, Buffer+Buffer_Offset, Element_Size);
}
}
}
}
//---------------------------------------------------------------------------
bool File_Avc::Demux_UnpacketizeContainer_Test()
{
const int8u* Buffer_Temp=NULL;
size_t Buffer_Temp_Size=0;
bool RandomAccess=true; //Default, in case of problem
if ((MustParse_SPS_PPS || SizedBlocks) && Demux_Avc_Transcode_Iso14496_15_to_Iso14496_10)
{
if (MustParse_SPS_PPS)
return true; //Wait for SPS and PPS
//Random access check
RandomAccess=false;
//Computing final size
size_t TranscodedBuffer_Size=0;
size_t Buffer_Offset_Save=Buffer_Offset;
while (Buffer_Offset+SizeOfNALU_Minus1+1+1<=Buffer_Size)
{
size_t Size;
if (Buffer_Offset+SizeOfNALU_Minus1>Buffer_Size)
{
Size=0;
Buffer_Offset=Buffer_Size;
}
else
switch (SizeOfNALU_Minus1)
{
case 0: Size=Buffer[Buffer_Offset];
TranscodedBuffer_Size+=2;
break;
case 1: Size=BigEndian2int16u(Buffer+Buffer_Offset);
TranscodedBuffer_Size++;
break;
case 2: Size=BigEndian2int24u(Buffer+Buffer_Offset);
break;
case 3: Size=BigEndian2int32u(Buffer+Buffer_Offset);
TranscodedBuffer_Size--;
break;
default: return true; //Problem
}
Size+=SizeOfNALU_Minus1+1;
//Coherency checking
if (Size==0 || Buffer_Offset+Size>Buffer_Size || (Buffer_Offset+Size!=Buffer_Size && Buffer_Offset+Size+SizeOfNALU_Minus1+1>Buffer_Size))
Size=Buffer_Size-Buffer_Offset;
//Random access check
if (!RandomAccess && Buffer_Offset+SizeOfNALU_Minus1+1<Buffer_Size && (Buffer[Buffer_Offset+SizeOfNALU_Minus1+1]&0x1F) && (Buffer[Buffer_Offset+SizeOfNALU_Minus1+1]&0x1F)<=5) //Is a slice
{
int32u slice_type;
Element_Offset=SizeOfNALU_Minus1+1+1;
Element_Size=Size;
BS_Begin();
Skip_UE("first_mb_in_slice");
Get_UE (slice_type, "slice_type");
BS_End();
Element_Offset=0;
switch (slice_type)
{
case 2 :
case 7 :
RandomAccess=true;
}
}
TranscodedBuffer_Size+=Size;
Buffer_Offset+=Size;
}
Buffer_Offset=Buffer_Offset_Save;
//Adding SPS/PPS sizes
if (RandomAccess)
{
for (seq_parameter_set_structs::iterator Data_Item=seq_parameter_sets.begin(); Data_Item!=seq_parameter_sets.end(); ++Data_Item)
TranscodedBuffer_Size+=(*Data_Item)->Iso14496_10_Buffer_Size;
for (seq_parameter_set_structs::iterator Data_Item=subset_seq_parameter_sets.begin(); Data_Item!=subset_seq_parameter_sets.end(); ++Data_Item)
TranscodedBuffer_Size+=(*Data_Item)->Iso14496_10_Buffer_Size;
for (pic_parameter_set_structs::iterator Data_Item=pic_parameter_sets.begin(); Data_Item!=pic_parameter_sets.end(); ++Data_Item)
TranscodedBuffer_Size+=(*Data_Item)->Iso14496_10_Buffer_Size;
}
//Copying
int8u* TranscodedBuffer=new int8u[TranscodedBuffer_Size+100];
size_t TranscodedBuffer_Pos=0;
if (RandomAccess)
{
for (seq_parameter_set_structs::iterator Data_Item=seq_parameter_sets.begin(); Data_Item!=seq_parameter_sets.end(); ++Data_Item)
{
std::memcpy(TranscodedBuffer+TranscodedBuffer_Pos, (*Data_Item)->Iso14496_10_Buffer, (*Data_Item)->Iso14496_10_Buffer_Size);
TranscodedBuffer_Pos+=(*Data_Item)->Iso14496_10_Buffer_Size;
}
for (seq_parameter_set_structs::iterator Data_Item=subset_seq_parameter_sets.begin(); Data_Item!=subset_seq_parameter_sets.end(); ++Data_Item)
{
std::memcpy(TranscodedBuffer+TranscodedBuffer_Pos, (*Data_Item)->Iso14496_10_Buffer, (*Data_Item)->Iso14496_10_Buffer_Size);
TranscodedBuffer_Pos+=(*Data_Item)->Iso14496_10_Buffer_Size;
}
for (pic_parameter_set_structs::iterator Data_Item=pic_parameter_sets.begin(); Data_Item!=pic_parameter_sets.end(); ++Data_Item)
{
std::memcpy(TranscodedBuffer+TranscodedBuffer_Pos, (*Data_Item)->Iso14496_10_Buffer, (*Data_Item)->Iso14496_10_Buffer_Size);
TranscodedBuffer_Pos+=(*Data_Item)->Iso14496_10_Buffer_Size;
}
}
while (Buffer_Offset<Buffer_Size)
{
//Sync layer
TranscodedBuffer[TranscodedBuffer_Pos]=0x00;
TranscodedBuffer_Pos++;
TranscodedBuffer[TranscodedBuffer_Pos]=0x00;
TranscodedBuffer_Pos++;
TranscodedBuffer[TranscodedBuffer_Pos]=0x01;
TranscodedBuffer_Pos++;
//Block
size_t Size;
switch (SizeOfNALU_Minus1)
{
case 0: Size=Buffer[Buffer_Offset];
Buffer_Offset++;
break;
case 1: Size=BigEndian2int16u(Buffer+Buffer_Offset);
Buffer_Offset+=2;
break;
case 2: Size=BigEndian2int24u(Buffer+Buffer_Offset);
Buffer_Offset+=3;
break;
case 3: Size=BigEndian2int32u(Buffer+Buffer_Offset);
Buffer_Offset+=4;
break;
default: //Problem
delete [] TranscodedBuffer;
return false;
}
//Coherency checking
if (Size==0 || Buffer_Offset+Size>Buffer_Size || (Buffer_Offset+Size!=Buffer_Size && Buffer_Offset+Size+SizeOfNALU_Minus1+1>Buffer_Size))
Size=Buffer_Size-Buffer_Offset;
std::memcpy(TranscodedBuffer+TranscodedBuffer_Pos, Buffer+Buffer_Offset, Size);
TranscodedBuffer_Pos+=Size;
Buffer_Offset+=Size;
}
Buffer_Offset=0;
Buffer_Temp=Buffer;
Buffer=TranscodedBuffer;
Buffer_Temp_Size=Buffer_Size;
Buffer_Size=TranscodedBuffer_Size;
Demux_Offset=Buffer_Size;
}
else
{
bool zero_byte=Buffer[Buffer_Offset+2]==0x00;
if (!(((Buffer[Buffer_Offset+(zero_byte?4:3)]&0x1B)==0x01 && (Buffer[Buffer_Offset+(zero_byte?5:4)]&0x80)!=0x80)
|| (Buffer[Buffer_Offset+(zero_byte?4:3)]&0x1F)==0x0C))
{
if (Demux_Offset==0)
{
Demux_Offset=Buffer_Offset;
Demux_IntermediateItemFound=false;
}
while (Demux_Offset+6<=Buffer_Size)
{
//Synchronizing
while(Demux_Offset+6<=Buffer_Size && (Buffer[Demux_Offset ]!=0x00
|| Buffer[Demux_Offset+1]!=0x00
|| Buffer[Demux_Offset+2]!=0x01))
{
Demux_Offset+=2;
while(Demux_Offset<Buffer_Size && Buffer[Buffer_Offset]!=0x00)
Demux_Offset+=2;
if (Demux_Offset>=Buffer_Size || Buffer[Demux_Offset-1]==0x00)
Demux_Offset--;
}
if (Demux_Offset+6>Buffer_Size)
{
if (Config->IsFinishing)
Demux_Offset=Buffer_Size;
break;
}
zero_byte=Buffer[Demux_Offset+2]==0x00;
if (Demux_IntermediateItemFound)
{
if (!(((Buffer[Demux_Offset+(zero_byte?4:3)]&0x1B)==0x01 && (Buffer[Demux_Offset+(zero_byte?5:4)]&0x80)!=0x80)
|| (Buffer[Demux_Offset+(zero_byte?4:3)]&0x1F)==0x0C))
break;
}
else
{
if ((Buffer[Demux_Offset+(zero_byte?4:3)]&0x1B)==0x01 && (Buffer[Demux_Offset+(zero_byte?5:4)]&0x80)==0x80)
Demux_IntermediateItemFound=true;
}
Demux_Offset++;
}
if (Demux_Offset+6>Buffer_Size && !FrameIsAlwaysComplete && !Config->IsFinishing)
return false; //No complete frame
if (Demux_Offset && Buffer[Demux_Offset-1]==0x00)
Demux_Offset--;
zero_byte=Buffer[Buffer_Offset+2]==0x00;
size_t Buffer_Offset_Random=Buffer_Offset;
if ((Buffer[Buffer_Offset_Random+(zero_byte?4:3)]&0x1F)==0x09)
{
Buffer_Offset_Random++;
if (zero_byte)
Buffer_Offset_Random++;
while(Buffer_Offset_Random+6<=Buffer_Size && (Buffer[Buffer_Offset_Random ]!=0x00
|| Buffer[Buffer_Offset_Random+1]!=0x00
|| Buffer[Buffer_Offset_Random+2]!=0x01))
Buffer_Offset_Random++;
zero_byte=Buffer[Buffer_Offset_Random+2]==0x00;
}
RandomAccess=Buffer_Offset_Random+6<=Buffer_Size && (Buffer[Buffer_Offset_Random+(zero_byte?4:3)]&0x1F)==0x07; //seq_parameter_set
}
}
if (!Status[IsAccepted])
{
if (Config->Demux_EventWasSent)
return false;
File_Avc* MI=new File_Avc;
Element_Code=(int64u)-1;
Open_Buffer_Init(MI);
#ifdef MEDIAINFO_EVENTS
MediaInfo_Config_PerPackage* Config_PerPackage_Temp=MI->Config->Config_PerPackage;
MI->Config->Config_PerPackage=NULL;
#endif //MEDIAINFO_EVENTS
Open_Buffer_Continue(MI, Buffer, Buffer_Size);
#ifdef MEDIAINFO_EVENTS
MI->Config->Config_PerPackage=Config_PerPackage_Temp;
#endif //MEDIAINFO_EVENTS
bool IsOk=MI->Status[IsAccepted];
delete MI;
if (!IsOk)
return false;
}
if (IFrame_Count || RandomAccess)
{
bool Frame_Count_NotParsedIncluded_PlusOne=false;
int64u PTS_Temp=FrameInfo.PTS;
if (!IsSub)
FrameInfo.PTS=(int64u)-1;
if (Frame_Count_NotParsedIncluded!=(int64u)-1 && Interlaced_Top!=Interlaced_Bottom)
{
Frame_Count_NotParsedIncluded--;
Frame_Count_NotParsedIncluded_PlusOne=true;
}
Demux_UnpacketizeContainer_Demux(RandomAccess);
if (!IsSub)
FrameInfo.PTS=PTS_Temp;
if (Frame_Count_NotParsedIncluded_PlusOne)
Frame_Count_NotParsedIncluded++;
}
else
Demux_UnpacketizeContainer_Demux_Clear();
if (Buffer_Temp)
{
Demux_TotalBytes-=Buffer_Size;
Demux_TotalBytes+=Buffer_Temp_Size;
delete[] Buffer;
Buffer=Buffer_Temp;
Buffer_Size=Buffer_Temp_Size;
}
return true;
}
#endif //MEDIAINFO_DEMUX
//---------------------------------------------------------------------------
void File_Avc::Synched_Init()
{
if (!Frame_Count_Valid)
Frame_Count_Valid=Config->ParseSpeed>=0.3?512:2;
//FrameInfo
PTS_End=0;
if (!IsSub)
FrameInfo.DTS=0; //No DTS in container
DTS_Begin=FrameInfo.DTS;
DTS_End=FrameInfo.DTS;
//Temporal references
TemporalReferences_DelayedElement=NULL;
TemporalReferences_Min=0;
TemporalReferences_Max=0;
TemporalReferences_Reserved=0;
TemporalReferences_Offset=0;
TemporalReferences_Offset_pic_order_cnt_lsb_Last=0;
TemporalReferences_pic_order_cnt_Min=0;
//Text
#if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
GA94_03_IsPresent=false;
#endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
//File specific
SizeOfNALU_Minus1=(int8u)-1;
//Status
IFrame_Count=0;
prevPicOrderCntMsb=0;
prevPicOrderCntLsb=(int32u)-1;
prevTopFieldOrderCnt=(int32u)-1;
prevFrameNum=(int32u)-1;
prevFrameNumOffset=(int32u)-1;
//Count of a Packets
Block_Count=0;
Interlaced_Top=0;
Interlaced_Bottom=0;
Structure_Field=0;
Structure_Frame=0;
//Temp
FrameRate_Divider=1;
FirstPFrameInGop_IsParsed=false;
Config_IsRepeated=false;
tc=0;
maximum_content_light_level=0;
maximum_frame_average_light_level=0;
//Default values
Streams.resize(0x100);
Streams[0x06].Searching_Payload=true; //sei
Streams[0x07].Searching_Payload=true; //seq_parameter_set
Streams[0x09].Searching_Payload=true; //access_unit_delimiter
Streams[0x0F].Searching_Payload=true; //subset_seq_parameter_set
for (int8u Pos=0xFF; Pos>=0xB9; Pos--)
Streams[Pos].Searching_Payload=true; //Testing MPEG-PS
//Options
Option_Manage();
//Specific cases
#if MEDIAINFO_EVENTS
if (Config->ParseUndecodableFrames_Get())
{
Accept(); //In some case, we must accept the stream very quickly and before the sequence header is detected
Streams[0x01].Searching_Payload=true; //slice_header
Streams[0x05].Searching_Payload=true; //slice_header
}
#endif //MEDIAINFO_EVENTS
#if MEDIAINFO_DEMUX
Demux_Avc_Transcode_Iso14496_15_to_Iso14496_10=Config->Demux_Avc_Transcode_Iso14496_15_to_Iso14496_10_Get();
#endif //MEDIAINFO_DEMUX
}
//***************************************************************************
// Buffer - Global
//***************************************************************************
//---------------------------------------------------------------------------
#if MEDIAINFO_ADVANCED2
void File_Avc::Read_Buffer_SegmentChange()
{
}
#endif //MEDIAINFO_ADVANCED2
//---------------------------------------------------------------------------
void File_Avc::Read_Buffer_Unsynched()
{
//Temporal references
Clean_Temp_References();
delete TemporalReferences_DelayedElement; TemporalReferences_DelayedElement=NULL;
TemporalReferences_Min=0;
TemporalReferences_Max=0;
TemporalReferences_Reserved=0;
TemporalReferences_Offset=0;
TemporalReferences_Offset_pic_order_cnt_lsb_Last=0;
TemporalReferences_pic_order_cnt_Min=0;
//Text
#if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
if (GA94_03_Parser)
GA94_03_Parser->Open_Buffer_Unsynch();
#endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
//parameter_sets
if (SizedBlocks || !Config_IsRepeated) //If sized blocks, it is not a broadcasted stream so SPS/PPS are only in container header, we must not disable them.
{
//Rebuilding immediatly TemporalReferences
seq_parameter_set_structs* _seq_parameter_sets=!seq_parameter_sets.empty()?&seq_parameter_sets:&subset_seq_parameter_sets; //Some MVC streams have no seq_parameter_sets. TODO: better management of temporal references
for (std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item=(*_seq_parameter_sets).begin(); seq_parameter_set_Item!=(*_seq_parameter_sets).end(); ++seq_parameter_set_Item)
if ((*seq_parameter_set_Item))
{
size_t MaxNumber;
switch ((*seq_parameter_set_Item)->pic_order_cnt_type)
{
case 0 : MaxNumber=(*seq_parameter_set_Item)->MaxPicOrderCntLsb; break;
case 2 : MaxNumber=(*seq_parameter_set_Item)->MaxFrameNum*2; break;
default: Trusted_IsNot("Not supported"); return;
}
TemporalReferences.resize(4*MaxNumber);
TemporalReferences_Reserved=MaxNumber;
}
}
else
{
Clean_Seq_Parameter();
}
//Status
Interlaced_Top=0;
Interlaced_Bottom=0;
prevPicOrderCntMsb=0;
prevPicOrderCntLsb=(int32u)-1;
prevTopFieldOrderCnt=(int32u)-1;
prevFrameNum=(int32u)-1;
prevFrameNumOffset=(int32u)-1;
//Temp
FrameRate_Divider=1;
FirstPFrameInGop_IsParsed=false;
tc=0;
//Impossible to know TimeStamps now
PTS_End=0;
DTS_End=0;
}
//***************************************************************************
// Buffer - Per element
//***************************************************************************
//---------------------------------------------------------------------------
void File_Avc::Header_Parse()
{
//Specific case
if (MustParse_SPS_PPS)
{
Header_Fill_Size(Element_Size);
Header_Fill_Code((int64u)-1, "Specific");
return;
}
//Parsing
int8u nal_unit_type;
if (!SizedBlocks)
{
if (Buffer[Buffer_Offset+2]==0x00)
Skip_B1( "zero_byte");
Skip_B3( "start_code_prefix_one_3bytes");
BS_Begin();
Mark_0 ();
Get_S1 ( 2, nal_ref_idc, "nal_ref_idc");
Get_S1 ( 5, nal_unit_type, "nal_unit_type");
BS_End();
if (!Header_Parser_Fill_Size())
{
Element_WaitForMoreData();
return;
}
}
else
{
int64u Size;
switch (SizeOfNALU_Minus1)
{
case 0: {
int8u Size_;
Get_B1 (Size_, "size");
Size=Size_;
}
break;
case 1: {
int16u Size_;
Get_B2 (Size_, "size");
Size=Size_;
}
break;
case 2: {
int32u Size_;
Get_B3 (Size_, "size");
Size=Size_;
}
break;
case 3: {
int32u Size_;
Get_B4 (Size_, "size");
Size=Size_;
}
break;
}
Size+=Element_Offset;
if (Size==Element_Offset || Buffer_Offset+Size>Buffer_Size) //If Size is 0 or Size biger than sample size, it is not normal, we skip the complete frame
Size=Buffer_Size-Buffer_Offset;
Header_Fill_Size(Size);
BS_Begin();
Mark_0 ();
Get_S1 ( 2, nal_ref_idc, "nal_ref_idc");
Get_S1 ( 5, nal_unit_type, "nal_unit_type");
BS_End();
}
//Filling
#if MEDIAINFO_TRACE
if (Trace_Activated)
Header_Fill_Code(nal_unit_type, Ztring().From_CC1(nal_unit_type));
else
#endif //MEDIAINFO_TRACE
Header_Fill_Code(nal_unit_type);
}
//---------------------------------------------------------------------------
bool File_Avc::Header_Parser_Fill_Size()
{
//Look for next Sync word
if (Buffer_Offset_Temp==0) //Buffer_Offset_Temp is not 0 if Header_Parse_Fill_Size() has already parsed first frames
Buffer_Offset_Temp=Buffer_Offset+4;
while (Buffer_Offset_Temp+5<=Buffer_Size
&& CC3(Buffer+Buffer_Offset_Temp)!=0x000001)
{
Buffer_Offset_Temp+=2;
while(Buffer_Offset_Temp<Buffer_Size && Buffer[Buffer_Offset_Temp]!=0x00)
Buffer_Offset_Temp+=2;
if (Buffer_Offset_Temp>=Buffer_Size || Buffer[Buffer_Offset_Temp-1]==0x00)
Buffer_Offset_Temp--;
}
//Must wait more data?
if (Buffer_Offset_Temp+5>Buffer_Size)
{
if (FrameIsAlwaysComplete || Config->IsFinishing)
Buffer_Offset_Temp=Buffer_Size; //We are sure that the next bytes are a start
else
return false;
}
if (Buffer[Buffer_Offset_Temp-1]==0x00)
Buffer_Offset_Temp--;
//OK, we continue
Header_Fill_Size(Buffer_Offset_Temp-Buffer_Offset);
Buffer_Offset_Temp=0;
return true;
}
//---------------------------------------------------------------------------
bool File_Avc::Header_Parser_QuickSearch()
{
while ( Buffer_Offset+6<=Buffer_Size
&& Buffer[Buffer_Offset ]==0x00
&& Buffer[Buffer_Offset+1]==0x00
&& (Buffer[Buffer_Offset+2]==0x01
|| (Buffer[Buffer_Offset+2]==0x00 && Buffer[Buffer_Offset+3]==0x01)))
{
//Getting start_code
int8u start_code;
if (Buffer[Buffer_Offset+2]==0x00)
start_code=CC1(Buffer+Buffer_Offset+4)&0x1F;
else
start_code=CC1(Buffer+Buffer_Offset+3)&0x1F;
//Searching start
if (Streams[start_code].Searching_Payload
|| Streams[start_code].ShouldDuplicate)
return true;
//Synchronizing
Buffer_Offset+=4;
Synched=false;
if (!Synchronize())
{
UnSynched_IsNotJunk=true;
return false;
}
if (Buffer_Offset+6>Buffer_Size)
{
UnSynched_IsNotJunk=true;
return false;
}
}
Trusted_IsNot("AVC, Synchronisation lost");
return Synchronize();
}
//---------------------------------------------------------------------------
void File_Avc::Data_Parse()
{
//Specific case
if (Element_Code==(int64u)-1)
{
SPS_PPS();
return;
}
//Trailing zeroes
int64u Element_Size_SaveBeforeZeroes=Element_Size;
if (Element_Size)
{
while (Element_Size && Buffer[Buffer_Offset+(size_t)Element_Size-1]==0)
Element_Size--;
}
//Dump of the SPS/PPS - Init
#if MEDIAINFO_ADVANCED2
size_t spspps_Size=0;
if (true) //TODO: add an option for activating this extra piece of information in the output
{
switch (Element_Code)
{
case 0x07 : //seq_parameter_set();
spspps_Size = seq_parameter_sets.size();
break;
case 0x08 : //pic_parameter_set();
spspps_Size = pic_parameter_sets.size();
break;
default: ;
}
}
#endif //MEDIAINFO_ADVANCED2
//svc_extension
bool svc_extension_flag=false;
if (Element_Code==0x0E || Element_Code==0x14)
{
BS_Begin();
Get_SB (svc_extension_flag, "svc_extension_flag");
if (svc_extension_flag)
nal_unit_header_svc_extension();
else
nal_unit_header_mvc_extension();
BS_End();
}
//Searching emulation_prevention_three_byte
int8u* Buffer_3Bytes=NULL;
const int8u* Save_Buffer=Buffer;
int64u Save_File_Offset=File_Offset;
size_t Save_Buffer_Offset=Buffer_Offset;
int64u Save_Element_Size=Element_Size;
size_t Element_Offset_3Bytes=(size_t)Element_Offset;
std::vector<size_t> ThreeByte_List;
while (Element_Offset_3Bytes+3<=Element_Size)
{
if (CC3(Buffer+Buffer_Offset+(size_t)Element_Offset_3Bytes)==0x000003)
ThreeByte_List.push_back(Element_Offset_3Bytes+2);
Element_Offset_3Bytes+=2;
while(Element_Offset_3Bytes<Element_Size && Buffer[Buffer_Offset+(size_t)Element_Offset_3Bytes]!=0x00)
Element_Offset_3Bytes+=2;
if (Element_Offset_3Bytes>=Element_Size || Buffer[Buffer_Offset+(size_t)Element_Offset_3Bytes-1]==0x00)
Element_Offset_3Bytes--;
}
if (!ThreeByte_List.empty())
{
//We must change the buffer for keeping out
Element_Size=Save_Element_Size-ThreeByte_List.size();
File_Offset+=Buffer_Offset;
Buffer_Offset=0;
Buffer_3Bytes=new int8u[(size_t)Element_Size];
for (size_t Pos=0; Pos<=ThreeByte_List.size(); Pos++)
{
size_t Pos0=(Pos==ThreeByte_List.size())?(size_t)Save_Element_Size:(ThreeByte_List[Pos]);
size_t Pos1=(Pos==0)?0:(ThreeByte_List[Pos-1]+1);
size_t Buffer_3bytes_Begin=Pos1-Pos;
size_t Save_Buffer_Begin =Pos1;
size_t Size= Pos0-Pos1;
std::memcpy(Buffer_3Bytes+Buffer_3bytes_Begin, Save_Buffer+Save_Buffer_Offset+Save_Buffer_Begin, Size);
}
Buffer=Buffer_3Bytes;
}
//Parsing
switch (Element_Code)
{
case 0x00 : Element_Name("unspecified"); Skip_XX(Element_Size-Element_Offset, "Data"); break;
case 0x01 : slice_layer_without_partitioning_non_IDR(); break;
case 0x02 : Element_Name("slice_data_partition_a_layer"); Skip_XX(Element_Size-Element_Offset, "Data"); break;
case 0x03 : Element_Name("slice_data_partition_b_layer"); Skip_XX(Element_Size-Element_Offset, "Data"); break;
case 0x04 : Element_Name("slice_data_partition_c_layer"); Skip_XX(Element_Size-Element_Offset, "Data"); break;
case 0x05 : slice_layer_without_partitioning_IDR(); break;
case 0x06 : sei(); break;
case 0x07 : seq_parameter_set(); break;
case 0x08 : pic_parameter_set(); break;
case 0x09 : access_unit_delimiter(); break;
case 0x0A : Element_Name("end_of_seq"); Skip_XX(Element_Size-Element_Offset, "Data"); break;
case 0x0B : Element_Name("end_of_stream"); Skip_XX(Element_Size-Element_Offset, "Data"); break;
case 0x0C : filler_data(); break;
case 0x0D : Element_Name("seq_parameter_set_extension"); Skip_XX(Element_Size-Element_Offset, "Data"); break;
case 0x0E : prefix_nal_unit(svc_extension_flag); break;
case 0x0F : subset_seq_parameter_set(); break;
case 0x13 : Element_Name("slice_layer_without_partitioning"); Skip_XX(Element_Size-Element_Offset, "Data"); break;
case 0x14 : slice_layer_extension(svc_extension_flag); break;
default :
if (Element_Code<0x18)
Element_Name("reserved");
else
Element_Name("unspecified");
Skip_XX(Element_Size-Element_Offset, "Data");
}
if (!ThreeByte_List.empty())
{
//We must change the buffer for keeping out
Element_Size=Save_Element_Size;
File_Offset=Save_File_Offset;
Buffer_Offset=Save_Buffer_Offset;
delete[] Buffer; Buffer=Save_Buffer;
Buffer_3Bytes=NULL; //Same as Buffer...
Element_Offset+=ThreeByte_List.size();
}
//Duplicate
#if MEDIAINFO_DUPLICATE
if (!Streams.empty() && Streams[(size_t)Element_Code].ShouldDuplicate)
File__Duplicate_Write(Element_Code);
#endif //MEDIAINFO_DUPLICATE
#if MEDIAINFO_DEMUX
Data_Parse_Iso14496();
#endif //MEDIAINFO_DEMUX
//Dump of the SPS/PPS - Fill
#if MEDIAINFO_ADVANCED2
if (false) //TODO: add an option for activating this extra piece of information in the output
{
switch (Element_Code)
{
case 0x07 : //seq_parameter_set();
if (spspps_Size != seq_parameter_sets.size() && !Status[IsFilled])
{
std::string Data_Raw((const char*)(Buffer+(size_t)(Buffer_Offset-1)), (size_t)(Element_Size+1)); //Including the last byte in the header
Dump_SPS.push_back(Base64::encode(Data_Raw));
}
break;
case 0x08 : //pic_parameter_set();
if (spspps_Size != pic_parameter_sets.size() && !Status[IsFilled])
{
std::string Data_Raw((const char*)(Buffer+(size_t)(Buffer_Offset-1)), (size_t)(Element_Size+1)); //Including the last byte in the header
Dump_PPS.push_back(Base64::encode(Data_Raw));
}
break;
default: ;
}
}
#endif //MEDIAINFO_ADVANCED2
#if MEDIAINFO_DEMUX
Data_Parse_Iso14496();
#endif //MEDIAINFO_DEMUX
//Trailing zeroes
Element_Size=Element_Size_SaveBeforeZeroes;
}
//***************************************************************************
// Elements
//***************************************************************************
//---------------------------------------------------------------------------
// Packet "01"
void File_Avc::slice_layer_without_partitioning_non_IDR()
{
Element_Name("slice_layer_without_partitioning (non-IDR)");
//Parsing
BS_Begin();
slice_header();
slice_data(true);
BS_End();
}
//---------------------------------------------------------------------------
// Packet "05"
void File_Avc::slice_layer_without_partitioning_IDR()
{
Element_Name("slice_layer_without_partitioning (IDR)");
//Parsing
BS_Begin();
slice_header();
slice_data(true);
BS_End();
FILLING_BEGIN_PRECISE();
//NextCode
for (int8u Pos=0x01; Pos<=0x05; Pos++)
NextCode_Add(Pos);
FILLING_END();
}
//---------------------------------------------------------------------------
//
void File_Avc::slice_header()
{
//Encryption management
if (CA_system_ID_MustSkipSlices)
{
//Is not decodable
Skip_BS(Data_BS_Remain(), "Data");
Finish("AVC");
return;
}
Element_Begin1("slice_header");
//Parsing
int32u slice_type, pic_order_cnt_lsb=(int32u)-1;
int32u first_mb_in_slice, pic_parameter_set_id, frame_num, num_ref_idx_l0_active_minus1, num_ref_idx_l1_active_minus1, disable_deblocking_filter_idc;
int32s delta_pic_order_cnt_bottom=0;
bool field_pic_flag=false, bottom_field_flag=false;
Get_UE (first_mb_in_slice, "first_mb_in_slice");
Get_UE (slice_type, "slice_type"); Param_Info1C((slice_type<10), Avc_slice_type[slice_type]);
#if MEDIAINFO_EVENTS
if (!first_mb_in_slice)
{
switch(Element_Code)
{
case 5 : // This is an IDR frame
if (Config->Config_PerPackage) // First slice of an IDR frame
{
// IDR
Config->Config_PerPackage->FrameForAlignment(this, true);
Config->Config_PerPackage->IsClosedGOP(this);
}
break;
default : ; // This is not an IDR frame
}
EVENT_BEGIN (Video, SliceInfo, 0)
Event.FieldPosition=Field_Count;
Event.SlicePosition=Element_IsOK()?first_mb_in_slice:(int64u)-1;
switch (slice_type)
{
case 0 :
case 3 :
case 5 :
case 8 :
Event.SliceType=1; break;
case 1 :
case 6 :
Event.SliceType=2; break;
case 2 :
case 4 :
case 7 :
case 9 :
Event.SliceType=0; break;
default:
Event.SliceType=(int8u)-1;
}
Event.Flags=0;
EVENT_END ()
}
#endif //MEDIAINFO_EVENTS
if (slice_type>=10)
{
Skip_BS(Data_BS_Remain(), "Data");
Element_End0();
return;
}
Get_UE (pic_parameter_set_id, "pic_parameter_set_id");
std::vector<pic_parameter_set_struct*>::iterator pic_parameter_set_Item;
if (pic_parameter_set_id>=pic_parameter_sets.size() || (*(pic_parameter_set_Item=pic_parameter_sets.begin()+pic_parameter_set_id))==NULL)
{
//Not yet present
Skip_BS(Data_BS_Remain(), "Data (pic_parameter_set is missing)");
Element_End0();
return;
}
std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item;
if ((*pic_parameter_set_Item)->seq_parameter_set_id>=seq_parameter_sets.size() || (*(seq_parameter_set_Item=seq_parameter_sets.begin()+(*pic_parameter_set_Item)->seq_parameter_set_id))==NULL)
{
if ((*pic_parameter_set_Item)->seq_parameter_set_id>=subset_seq_parameter_sets.size() || (*(seq_parameter_set_Item=subset_seq_parameter_sets.begin()+(*pic_parameter_set_Item)->seq_parameter_set_id))==NULL)
{
//Not yet present
Skip_BS(Data_BS_Remain(), "Data (seq_parameter_set is missing)");
Element_End0();
return;
}
}
if ((*seq_parameter_set_Item)->separate_colour_plane_flag==1)
Skip_S1(2, "color_plane_id");
num_ref_idx_l0_active_minus1=(*pic_parameter_set_Item)->num_ref_idx_l0_default_active_minus1; //Default
num_ref_idx_l1_active_minus1=(*pic_parameter_set_Item)->num_ref_idx_l1_default_active_minus1; //Default
Get_BS ((*seq_parameter_set_Item)->log2_max_frame_num_minus4+4, frame_num, "frame_num");
if (!(*seq_parameter_set_Item)->frame_mbs_only_flag)
{
TEST_SB_GET(field_pic_flag, "field_pic_flag");
Get_SB (bottom_field_flag, "bottom_field_flag");
TEST_SB_END();
}
if (Element_Code==5) //IdrPicFlag
Skip_UE( "idr_pic_id");
if ((*seq_parameter_set_Item)->pic_order_cnt_type==0)
{
Get_BS ((*seq_parameter_set_Item)->log2_max_pic_order_cnt_lsb_minus4+4, pic_order_cnt_lsb, "pic_order_cnt_lsb");
if ((*pic_parameter_set_Item)->bottom_field_pic_order_in_frame_present_flag && !field_pic_flag)
Get_SE (delta_pic_order_cnt_bottom, "delta_pic_order_cnt_bottom");
}
if ((*seq_parameter_set_Item)->pic_order_cnt_type==1 && !(*seq_parameter_set_Item)->delta_pic_order_always_zero_flag )
{
Skip_SE( "delta_pic_order_cnt[0]");
if((*pic_parameter_set_Item)->bottom_field_pic_order_in_frame_present_flag && !field_pic_flag)
Skip_SE( "delta_pic_order_cnt[1]");
}
if((*pic_parameter_set_Item)->redundant_pic_cnt_present_flag)
Skip_UE( "redundant_pic_cnt");
if (slice_type==1 || slice_type==6) //B-Frame
Skip_SB( "direct_spatial_mv_pred_flag");
switch (slice_type)
{
case 0 : //P-Frame
case 1 : //B-Frame
case 3 : //SP-Frame
case 5 : //P-Frame
case 6 : //B-Frame
case 8 : //SP-Frame
TEST_SB_SKIP( "num_ref_idx_active_override_flag");
Get_UE (num_ref_idx_l0_active_minus1, "num_ref_idx_l0_active_minus1");
switch (slice_type)
{
case 1 : //B-Frame
case 6 : //B-Frame
Get_UE (num_ref_idx_l1_active_minus1, "num_ref_idx_l1_active_minus1");
break;
default: ;
}
TEST_SB_END();
break;
default: ;
}
ref_pic_list_modification(slice_type, Element_Code==20); //nal_unit_type==20 --> ref_pic_list_mvc_modification()
if (((*pic_parameter_set_Item)->weighted_pred_flag && (slice_type==0 || slice_type==3 || slice_type==5 || slice_type==8))
|| ((*pic_parameter_set_Item)->weighted_bipred_idc==1 && (slice_type==1 || slice_type==6)))
pred_weight_table(slice_type, num_ref_idx_l0_active_minus1, num_ref_idx_l1_active_minus1, (*seq_parameter_set_Item)->ChromaArrayType());
std::vector<int8u> memory_management_control_operations;
if (nal_ref_idc)
dec_ref_pic_marking(memory_management_control_operations);
if ((*pic_parameter_set_Item)->entropy_coding_mode_flag &&
(slice_type!=2 && slice_type!=7 && //I-Frames
slice_type!=4 && slice_type!=9)) //SI-Frames
Skip_UE( "cabac_init_idc");
Skip_SE( "slice_qp_delta");
switch (slice_type)
{
case 3 : //SP-Frame
case 4 : //SI-Frame
case 8 : //SP-Frame
case 9 : //SI-Frame
switch (slice_type)
{
case 3 : //SP-Frame
case 8 : //SP-Frame
Skip_SB( "sp_for_switch_flag");
break;
default: ;
}
Skip_SE ( "slice_qs_delta");
break;
default: ;
}
if ((*pic_parameter_set_Item)->deblocking_filter_control_present_flag)
{
Get_UE(disable_deblocking_filter_idc, "disable_deblocking_filter_idc");
if (disable_deblocking_filter_idc!=1)
{
Skip_SE( "slice_alpha_c0_offset_div2");
Skip_SE( "slice_beta_offset_div2");
}
}
Element_End0();
FILLING_BEGIN();
//Count of I-Frames
if (first_mb_in_slice==0 && Element_Code!=20 && (slice_type==2 || slice_type==7)) //Not slice_layer_extension, I-Frame
IFrame_Count++;
//pic_struct
if (field_pic_flag && (*seq_parameter_set_Item)->pic_struct_FirstDetected==(int8u)-1)
(*seq_parameter_set_Item)->pic_struct_FirstDetected=bottom_field_flag?2:1; //2=BFF, 1=TFF
//Saving some info
int32s TemporalReferences_Offset_pic_order_cnt_lsb_Diff=0;
if ((*seq_parameter_set_Item)->pic_order_cnt_type!=1 && first_mb_in_slice==0 && (Element_Code!=0x14 || seq_parameter_sets.empty())) //Not slice_layer_extension except if MVC only
{
if (field_pic_flag)
{
Structure_Field++;
if (bottom_field_flag)
Interlaced_Bottom++;
else
Interlaced_Top++;
}
else
Structure_Frame++;
//Frame order detection
int64s pic_order_cnt=0;
switch ((*seq_parameter_set_Item)->pic_order_cnt_type)
{
case 0 :
{
if (Element_Code==5) //IDR
{
prevPicOrderCntMsb=0;
prevPicOrderCntLsb=0;
TemporalReferences_Offset=TemporalReferences_Max;
if (TemporalReferences_Offset%2)
TemporalReferences_Offset++;
TemporalReferences_pic_order_cnt_Min=0;
}
else
{
const bool Has5 = std::find(memory_management_control_operations.begin(), memory_management_control_operations.end(), 5) != memory_management_control_operations.end();
if (Has5)
{
prevPicOrderCntMsb=0;
if (bottom_field_flag)
prevPicOrderCntLsb=0;
else
prevPicOrderCntLsb=prevTopFieldOrderCnt;
}
}
int32s PicOrderCntMsb;
if (prevPicOrderCntLsb==(int32u)-1)
{
PicOrderCntMsb=0;
if ((int32u)(2*((*seq_parameter_set_Item)->max_num_ref_frames+3))<pic_order_cnt_lsb)
TemporalReferences_Min=pic_order_cnt_lsb-2*((*seq_parameter_set_Item)->max_num_ref_frames+3);
}
else if (pic_order_cnt_lsb<prevPicOrderCntLsb && prevPicOrderCntLsb-pic_order_cnt_lsb>=(*seq_parameter_set_Item)->MaxPicOrderCntLsb/2)
PicOrderCntMsb=prevPicOrderCntMsb+(*seq_parameter_set_Item)->MaxPicOrderCntLsb;
else if (pic_order_cnt_lsb>prevPicOrderCntLsb && pic_order_cnt_lsb-prevPicOrderCntLsb>(*seq_parameter_set_Item)->MaxPicOrderCntLsb/2)
PicOrderCntMsb=prevPicOrderCntMsb-(*seq_parameter_set_Item)->MaxPicOrderCntLsb;
else
PicOrderCntMsb=prevPicOrderCntMsb;
int32s TopFieldOrderCnt=PicOrderCntMsb+pic_order_cnt_lsb;
int32s BottomFieldOrderCnt;
if (field_pic_flag)
BottomFieldOrderCnt=TopFieldOrderCnt+delta_pic_order_cnt_bottom;
else
BottomFieldOrderCnt=PicOrderCntMsb+pic_order_cnt_lsb;
prevPicOrderCntMsb=PicOrderCntMsb;
prevPicOrderCntLsb=pic_order_cnt_lsb;
prevTopFieldOrderCnt=TopFieldOrderCnt;
pic_order_cnt=bottom_field_flag?BottomFieldOrderCnt:TopFieldOrderCnt;
}
break;
case 2 :
{
const bool Has5 = std::find(memory_management_control_operations.begin(), memory_management_control_operations.end(),5) != memory_management_control_operations.end();
if (Has5)
prevFrameNumOffset=0;
int32u FrameNumOffset;
if (Element_Code==5) //IdrPicFlag
{
TemporalReferences_Offset=TemporalReferences_Max;
if (TemporalReferences_Offset%2)
TemporalReferences_Offset++;
FrameNumOffset=0;
}
else if (prevFrameNumOffset==(int32u)-1)
FrameNumOffset=0;
else if (prevFrameNum>frame_num)
FrameNumOffset=prevFrameNumOffset+(*seq_parameter_set_Item)->MaxFrameNum;
else
FrameNumOffset=prevFrameNumOffset;
int32u tempPicOrderCnt;
if (Element_Code==5) //IdrPicFlag
tempPicOrderCnt=0;
else
{
tempPicOrderCnt=2*(FrameNumOffset+frame_num);
if (!nal_ref_idc && tempPicOrderCnt) //Note: if nal_ref_idc is 0, tempPicOrderCnt is not expected to be 0 but it may be the case with invalid streams
tempPicOrderCnt--;
}
pic_order_cnt=tempPicOrderCnt;
prevFrameNum=frame_num;
prevFrameNumOffset=FrameNumOffset;
pic_order_cnt_lsb=frame_num;
}
break;
default: ;
}
if (pic_order_cnt<TemporalReferences_pic_order_cnt_Min)
{
if (pic_order_cnt<0)
{
size_t Base=(size_t)(TemporalReferences_Offset+TemporalReferences_pic_order_cnt_Min);
size_t ToInsert=(size_t)(TemporalReferences_pic_order_cnt_Min-pic_order_cnt);
if (Base+ToInsert>=4*TemporalReferences_Reserved || Base>=4*TemporalReferences_Reserved || ToInsert+TemporalReferences_Max>=4*TemporalReferences_Reserved || TemporalReferences_Max>=4*TemporalReferences_Reserved || TemporalReferences_Max-Base>=4*TemporalReferences_Reserved)
{
Trusted_IsNot("Problem in temporal references");
return;
}
Element_Info1(__T("Offset of ")+Ztring::ToZtring(ToInsert));
TemporalReferences.insert(TemporalReferences.begin()+Base, ToInsert, NULL);
TemporalReferences_Offset+=ToInsert;
TemporalReferences_Offset_pic_order_cnt_lsb_Last += ToInsert;
TemporalReferences_Max+=ToInsert;
TemporalReferences_pic_order_cnt_Min=pic_order_cnt;
}
else if (TemporalReferences_Min>(size_t)(TemporalReferences_Offset+pic_order_cnt))
TemporalReferences_Min=(size_t)(TemporalReferences_Offset+pic_order_cnt);
}
if (pic_order_cnt<0 && TemporalReferences_Offset<(size_t)(-pic_order_cnt)) //Found in playreadyEncryptedBlowUp.ts without encryption test
{
Trusted_IsNot("Problem in temporal references");
return;
}
if ((size_t)(TemporalReferences_Offset+pic_order_cnt)>=3*TemporalReferences_Reserved)
{
size_t Offset=TemporalReferences_Max-TemporalReferences_Offset;
if (Offset%2)
Offset++;
if (Offset>=TemporalReferences_Reserved && pic_order_cnt>=(int64s)TemporalReferences_Reserved)
{
TemporalReferences_Offset+=TemporalReferences_Reserved;
pic_order_cnt-=TemporalReferences_Reserved;
TemporalReferences_pic_order_cnt_Min-=TemporalReferences_Reserved/2;
switch ((*seq_parameter_set_Item)->pic_order_cnt_type)
{
case 0 :
prevPicOrderCntMsb-=(int32u)TemporalReferences_Reserved;
break;
case 2 :
prevFrameNumOffset-=(int32u)TemporalReferences_Reserved/2;
break;
default:;
}
}
while (TemporalReferences_Offset+pic_order_cnt>=3*TemporalReferences_Reserved)
{
for (size_t Pos=0; Pos<TemporalReferences_Reserved; Pos++)
{
if (TemporalReferences[Pos])
{
if ((Pos%2)==0)
PictureTypes_PreviousFrames+=Avc_slice_type[TemporalReferences[Pos]->slice_type];
delete TemporalReferences[Pos];
TemporalReferences[Pos] = NULL;
}
else if (!PictureTypes_PreviousFrames.empty()) //Only if stream already started
{
if ((Pos%2)==0)
PictureTypes_PreviousFrames+=' ';
}
}
if (PictureTypes_PreviousFrames.size()>=8*TemporalReferences.size())
PictureTypes_PreviousFrames.erase(PictureTypes_PreviousFrames.begin(), PictureTypes_PreviousFrames.begin()+PictureTypes_PreviousFrames.size()-TemporalReferences.size());
TemporalReferences.erase(TemporalReferences.begin(), TemporalReferences.begin()+TemporalReferences_Reserved);
TemporalReferences.resize(4*TemporalReferences_Reserved);
if (TemporalReferences_Reserved<TemporalReferences_Offset)
TemporalReferences_Offset-=TemporalReferences_Reserved;
else
TemporalReferences_Offset=0;
if (TemporalReferences_Reserved<TemporalReferences_Min)
TemporalReferences_Min-=TemporalReferences_Reserved;
else
TemporalReferences_Min=0;
if (TemporalReferences_Reserved<TemporalReferences_Max)
TemporalReferences_Max-=TemporalReferences_Reserved;
else
TemporalReferences_Max=0;
if (TemporalReferences_Reserved<TemporalReferences_Offset_pic_order_cnt_lsb_Last)
TemporalReferences_Offset_pic_order_cnt_lsb_Last-=TemporalReferences_Reserved;
else
TemporalReferences_Offset_pic_order_cnt_lsb_Last=0;
}
}
TemporalReferences_Offset_pic_order_cnt_lsb_Diff=(int32s)((int32s)(TemporalReferences_Offset+pic_order_cnt)-TemporalReferences_Offset_pic_order_cnt_lsb_Last);
TemporalReferences_Offset_pic_order_cnt_lsb_Last=(size_t)(TemporalReferences_Offset+pic_order_cnt);
if (field_pic_flag && (*seq_parameter_set_Item)->pic_order_cnt_type==2 && TemporalReferences_Offset_pic_order_cnt_lsb_Last<TemporalReferences.size() && TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last])
TemporalReferences_Offset_pic_order_cnt_lsb_Last++;
if (TemporalReferences_Max<=TemporalReferences_Offset_pic_order_cnt_lsb_Last)
TemporalReferences_Max=TemporalReferences_Offset_pic_order_cnt_lsb_Last+((*seq_parameter_set_Item)->frame_mbs_only_flag?2:1);
if (TemporalReferences_Min>TemporalReferences_Offset_pic_order_cnt_lsb_Last)
TemporalReferences_Min=TemporalReferences_Offset_pic_order_cnt_lsb_Last;
if (TemporalReferences_DelayedElement)
{
delete TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]; TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]=TemporalReferences_DelayedElement;
}
if (TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]==NULL)
TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]=new temporal_reference();
TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]->frame_num=frame_num;
TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]->slice_type=(int8u)slice_type;
TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]->IsTop=!bottom_field_flag;
TemporalReferences[TemporalReferences_Offset_pic_order_cnt_lsb_Last]->IsField=field_pic_flag;
if (TemporalReferences_DelayedElement)
{
TemporalReferences_DelayedElement=NULL;
sei_message_user_data_registered_itu_t_t35_GA94_03_Delayed((*pic_parameter_set_Item)->seq_parameter_set_id);
}
}
if ((*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->timing_info_present_flag && (*seq_parameter_set_Item)->vui_parameters->num_units_in_tick)
tc=float64_int64s(((float64)1000000000)/((float64)(*seq_parameter_set_Item)->vui_parameters->time_scale/(*seq_parameter_set_Item)->vui_parameters->num_units_in_tick/((*seq_parameter_set_Item)->pic_order_cnt_type==2?1:2)/FrameRate_Divider)/((!(*seq_parameter_set_Item)->frame_mbs_only_flag && field_pic_flag)?2:1));
if (first_mb_in_slice==0)
{
if (Frame_Count==0)
{
if (FrameInfo.PTS==(int64u)-1)
FrameInfo.PTS=FrameInfo.DTS+tc*(TemporalReferences_Offset_pic_order_cnt_lsb_Diff?2:1)*((!(*seq_parameter_set_Item)->frame_mbs_only_flag && field_pic_flag)?2:1); //No PTS in container
PTS_Begin=FrameInfo.PTS;
}
#if MEDIAINFO_ADVANCED2
if (PTS_Begin_Segment==(int64u)-1 && File_Offset>=Config->File_Current_Offset)
{
PTS_Begin_Segment=FrameInfo.PTS;
}
#endif //MEDIAINFO_ADVANCED2
if (slice_type==2 || slice_type==7) //IFrame
FirstPFrameInGop_IsParsed=false;
}
else
{
if (FrameInfo.PTS!=(int64u)-1)
FrameInfo.PTS-=tc;
if (FrameInfo.DTS!=(int64u)-1)
FrameInfo.DTS-=tc;
}
//Frame pos
if (Frame_Count!=(int64u)-1 && Frame_Count && ((!(*seq_parameter_set_Item)->frame_mbs_only_flag && Interlaced_Top==Interlaced_Bottom && field_pic_flag) || first_mb_in_slice!=0 || (Element_Code==0x14 && !seq_parameter_sets.empty())))
{
Frame_Count--;
if (IFrame_Count && Frame_Count_NotParsedIncluded!=(int64u)-1)
Frame_Count_NotParsedIncluded--;
Frame_Count_InThisBlock--;
}
else if (first_mb_in_slice==0)
{
if ((*seq_parameter_set_Item)->pic_order_cnt_type!=1 && (Element_Code!=0x14 || seq_parameter_sets.empty())) //Not slice_layer_extension except if MVC only
{
if ((!IsSub || Frame_Count_InThisBlock) && TemporalReferences_Offset_pic_order_cnt_lsb_Diff && TemporalReferences_Offset_pic_order_cnt_lsb_Diff!=2)
FrameInfo.PTS+=(TemporalReferences_Offset_pic_order_cnt_lsb_Diff-(field_pic_flag?1:2))/((!(*seq_parameter_set_Item)->frame_mbs_only_flag && field_pic_flag)?1:2)*(int64s)tc;
}
if (!FirstPFrameInGop_IsParsed && (slice_type==0 || slice_type==5)) //P-Frame
{
FirstPFrameInGop_IsParsed=true;
//Testing if we have enough to test GOP
if (Frame_Count<=Frame_Count_Valid)
{
std::string PictureTypes(PictureTypes_PreviousFrames);
PictureTypes.reserve(TemporalReferences.size());
for (size_t Pos=0; Pos<TemporalReferences.size(); Pos++)
if (TemporalReferences[Pos])
{
if ((Pos%2)==0)
PictureTypes+=Avc_slice_type[TemporalReferences[Pos]->slice_type];
}
else if (!PictureTypes.empty()) //Only if stream already started
{
if ((Pos%2)==0)
PictureTypes+=' ';
}
#if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
if (!GOP_Detect(PictureTypes).empty() && !GA94_03_IsPresent)
Frame_Count_Valid=Frame_Count; //We have enough frames
#endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
}
}
}
#if MEDIAINFO_TRACE
if (Trace_Activated)
{
Element_Info1(TemporalReferences_Offset_pic_order_cnt_lsb_Last);
Element_Info1((((*seq_parameter_set_Item)->frame_mbs_only_flag || !field_pic_flag)?__T("Frame "):(bottom_field_flag?__T("Field (Bottom) "):__T("Field (Top) ")))+Ztring::ToZtring(Frame_Count));
if (slice_type<9)
Element_Info1(__T("slice_type ")+Ztring().From_UTF8(Avc_slice_type[slice_type]));
Element_Info1(__T("frame_num ")+Ztring::ToZtring(frame_num));
if ((*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->fixed_frame_rate_flag)
{
if (FrameInfo.PCR!=(int64u)-1)
Element_Info1(__T("PCR ")+Ztring().Duration_From_Milliseconds(float64_int64s(((float64)FrameInfo.PCR)/1000000)));
if (FrameInfo.DTS!=(int64u)-1)
Element_Info1(__T("DTS ")+Ztring().Duration_From_Milliseconds(float64_int64s(((float64)FrameInfo.DTS)/1000000)));
if (FrameInfo.PTS!=(int64u)-1)
Element_Info1(__T("PTS ")+Ztring().Duration_From_Milliseconds(float64_int64s(((float64)FrameInfo.PTS)/1000000)));
}
if ((*seq_parameter_set_Item)->pic_order_cnt_type==0)
Element_Info1(__T("pic_order_cnt_lsb ")+Ztring::ToZtring(pic_order_cnt_lsb));
if (first_mb_in_slice)
Element_Info1(__T("first_mb_in_slice ")+Ztring::ToZtring(first_mb_in_slice));
}
#endif //MEDIAINFO_TRACE
//Counting
if (Frame_Count!=(int64u)-1)
{
if (File_Offset+Buffer_Offset+Element_Size==File_Size)
Frame_Count_Valid=Frame_Count; //Finish frames in case of there are less than Frame_Count_Valid frames
Frame_Count++;
if (IFrame_Count && Frame_Count_NotParsedIncluded!=(int64u)-1)
Frame_Count_NotParsedIncluded++;
Frame_Count_InThisBlock++;
}
if ((*seq_parameter_set_Item)->pic_order_cnt_type==0 && field_pic_flag)
{
Field_Count++;
Field_Count_InThisBlock++;
}
if (FrameInfo.PTS!=(int64u)-1)
FrameInfo.PTS+=tc;
if (FrameInfo.DTS!=(int64u)-1)
FrameInfo.DTS+=tc;
if (FrameInfo.PTS!=(int64u)-1 && (FrameInfo.PTS>PTS_End || (PTS_End>1000000000 && FrameInfo.PTS<=PTS_End-1000000000))) //More than current PTS_End or less than current PTS_End minus 1 second (there is a problem?)
PTS_End=FrameInfo.PTS;
#if MEDIAINFO_DUPLICATE
if (Streams[(size_t)Element_Code].ShouldDuplicate)
File__Duplicate_Write(Element_Code, (*seq_parameter_set_Item)->pic_order_cnt_type==0?pic_order_cnt_lsb:frame_num);
#endif //MEDIAINFO_DUPLICATE
//Filling only if not already done
if (Frame_Count==1 && !Status[IsAccepted])
Accept("AVC");
if (!Status[IsFilled])
{
#if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
if (!GA94_03_IsPresent && IFrame_Count>=8)
Frame_Count_Valid=Frame_Count; //We have enough frames
#endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
if (Frame_Count>=Frame_Count_Valid)
{
Fill("AVC");
if (!IsSub && !Streams[(size_t)Element_Code].ShouldDuplicate && Config->ParseSpeed<1.0)
Finish("AVC");
}
}
FILLING_END();
}
//---------------------------------------------------------------------------
//
void File_Avc::slice_data(bool AllCategories)
{
Element_Begin1("slice_data");
Skip_BS(Data_BS_Remain(), "(ToDo)");
Element_End0();
}
//---------------------------------------------------------------------------
//
void File_Avc::ref_pic_list_modification(int32u slice_type, bool mvc)
{
if ((slice_type%5)!=2 && (slice_type%5)!=4)
{
TEST_SB_SKIP( "ref_pic_list_modification_flag_l0");
int32u modification_of_pic_nums_idc;
do
{
Get_UE (modification_of_pic_nums_idc, "modification_of_pic_nums_idc");
if (modification_of_pic_nums_idc<2)
Skip_UE( "abs_diff_pic_num_minus1");
else if (modification_of_pic_nums_idc==2)
Skip_UE( "long_term_pic_num");
else if (mvc && (modification_of_pic_nums_idc==4 || modification_of_pic_nums_idc==5)) //ref_pic_list_mvc_modification only
Skip_UE( "abs_diff_view_idx_minus1");
else if (modification_of_pic_nums_idc!=3)
{
Trusted_IsNot("ref_pic_list_modification_flag_l0");
Skip_BS(Data_BS_Remain(), "(Remaining bits)");
}
}
while (modification_of_pic_nums_idc!=3 && Data_BS_Remain());
TEST_SB_END();
}
if ((slice_type%5)==1)
{
TEST_SB_SKIP( "ref_pic_list_modification_flag_l1");
int32u modification_of_pic_nums_idc;
do
{
Get_UE (modification_of_pic_nums_idc, "modification_of_pic_nums_idc");
if (modification_of_pic_nums_idc<2)
Skip_UE( "abs_diff_pic_num_minus1");
else if (modification_of_pic_nums_idc==2)
Skip_UE( "long_term_pic_num");
else if (mvc && (modification_of_pic_nums_idc==4 || modification_of_pic_nums_idc==5)) //ref_pic_list_mvc_modification only
Skip_UE( "abs_diff_view_idx_minus1");
else if (modification_of_pic_nums_idc!=3)
{
Trusted_IsNot("ref_pic_list_modification_flag_l1");
Skip_BS(Data_BS_Remain(), "(Remaining bits)");
}
}
while (modification_of_pic_nums_idc!=3 && Data_BS_Remain());
TEST_SB_END();
}
}
//---------------------------------------------------------------------------
//
void File_Avc::pred_weight_table(int32u slice_type, int32u num_ref_idx_l0_active_minus1, int32u num_ref_idx_l1_active_minus1, int8u ChromaArrayType)
{
// 7.3.3.2 Prediction weight table syntax
Skip_UE( "luma_log2_weight_denom");
if (ChromaArrayType)
Skip_UE( "chroma_log2_weight_denom");
for(int32u i=0; i<=num_ref_idx_l0_active_minus1; i++)
{
TEST_SB_SKIP( "luma_weight_l0_flag");
Skip_SE( "luma_weight_l0");
Skip_SE( "luma_offset_l0");
TEST_SB_END();
if (ChromaArrayType)
{
TEST_SB_SKIP( "chroma_weight_l0_flag");
Skip_SE( "chroma_weight_l0");
Skip_SE( "chroma_offset_l0");
Skip_SE( "chroma_weight_l0");
Skip_SE( "chroma_offset_l0");
TEST_SB_END();
}
}
if (slice_type % 5 == 1)
{
for (int32u i = 0; i <= num_ref_idx_l1_active_minus1; i++)
{
TEST_SB_SKIP("luma_weight_l1_flag");
Skip_SE("luma_weight_l1");
Skip_SE("luma_offset_l1");
TEST_SB_END();
if (ChromaArrayType)
{
TEST_SB_SKIP("chroma_weight_l1_flag");
Skip_SE("chroma_weight_l1");
Skip_SE("chroma_offset_l1");
Skip_SE("chroma_weight_l1");
Skip_SE("chroma_offset_l1");
TEST_SB_END();
}
}
}
}
//---------------------------------------------------------------------------
//
void File_Avc::dec_ref_pic_marking(std::vector<int8u> &memory_management_control_operations)
{
if (Element_Code==5) //IdrPicFlag
{
Skip_SB( "no_output_of_prior_pics_flag");
Skip_SB( "long_term_reference_flag");
}
else
{
TEST_SB_SKIP( "adaptive_ref_pic_marking_mode_flag");
int32u memory_management_control_operation;
do
{
Get_UE (memory_management_control_operation, "memory_management_control_operation");
switch (memory_management_control_operation)
{
case 1 :
Skip_UE( "difference_of_pic_nums_minus1");
break;
case 2 :
Skip_UE( "long_term_pic_num");
break;
case 3 :
Skip_UE( "difference_of_pic_nums_minus1");
//break; 3 --> difference_of_pic_nums_minus1 then long_term_frame_idx
case 6 :
Skip_UE( "long_term_frame_idx");
break;
case 4 :
Skip_UE( "max_long_term_frame_idx_plus1");
break;
}
memory_management_control_operations.push_back((int8u)memory_management_control_operation);
}
while (Data_BS_Remain() && memory_management_control_operation);
TEST_SB_END()
}
}
//---------------------------------------------------------------------------
// Packet "06"
void File_Avc::sei()
{
Element_Name("sei");
//Parsing
int32u seq_parameter_set_id=(int32u)-1;
while(Element_Offset+1<Element_Size)
{
Element_Begin1("sei message");
sei_message(seq_parameter_set_id);
Element_End0();
}
BS_Begin();
Mark_1( );
BS_End();
}
//---------------------------------------------------------------------------
void File_Avc::sei_message(int32u &seq_parameter_set_id)
{
//Parsing
int32u payloadType=0, payloadSize=0;
int8u payload_type_byte, payload_size_byte;
Element_Begin1("sei message header");
do
{
Get_B1 (payload_type_byte, "payload_type_byte");
payloadType+=payload_type_byte;
}
while(payload_type_byte==0xFF);
do
{
Get_B1 (payload_size_byte, "payload_size_byte");
payloadSize+=payload_size_byte;
}
while(payload_size_byte==0xFF);
Element_End0();
int64u Element_Offset_Save=Element_Offset+payloadSize;
if (Element_Offset_Save>Element_Size)
{
Trusted_IsNot("Wrong size");
Skip_XX(Element_Size-Element_Offset, "unknown");
return;
}
int64u Element_Size_Save=Element_Size;
Element_Size=Element_Offset_Save;
switch (payloadType)
{
case 0 : sei_message_buffering_period(seq_parameter_set_id); break;
case 1 : sei_message_pic_timing(payloadSize, seq_parameter_set_id); break;
case 4 : sei_message_user_data_registered_itu_t_t35(); break;
case 5 : sei_message_user_data_unregistered(payloadSize); break;
case 6 : sei_message_recovery_point(); break;
case 32 : sei_message_mainconcept(payloadSize); break;
case 147: sei_alternative_transfer_characteristics(); break;
case 137: sei_message_mastering_display_colour_volume(); break;
case 144: sei_message_light_level(); break;
default :
Element_Info1("unknown");
Skip_XX(payloadSize, "data");
}
Element_Offset=Element_Offset_Save; //Positionning in the right place.
Element_Size=Element_Size_Save; //Positionning in the right place.
}
//---------------------------------------------------------------------------
// SEI - 0
void File_Avc::sei_message_buffering_period(int32u &seq_parameter_set_id)
{
Element_Info1("buffering_period");
//Parsing
if (Element_Offset==Element_Size)
return; //Nothing to do
BS_Begin();
Get_UE (seq_parameter_set_id, "seq_parameter_set_id");
std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item;
if (seq_parameter_set_id>=seq_parameter_sets.size() || (*(seq_parameter_set_Item=seq_parameter_sets.begin()+seq_parameter_set_id))==NULL)
{
//Not yet present
Skip_BS(Data_BS_Remain(), "Data (seq_parameter_set is missing)");
BS_End();
return;
}
if ((*seq_parameter_set_Item)->NalHrdBpPresentFlag())
sei_message_buffering_period_xxl((*seq_parameter_set_Item)->vui_parameters->NAL);
if ((*seq_parameter_set_Item)->VclHrdBpPresentFlag())
sei_message_buffering_period_xxl((*seq_parameter_set_Item)->vui_parameters->VCL);
BS_End();
}
void File_Avc::sei_message_buffering_period_xxl(seq_parameter_set_struct::vui_parameters_struct::xxl* xxl)
{
if (xxl==NULL)
return;
for (int32u SchedSelIdx=0; SchedSelIdx<xxl->SchedSel.size(); SchedSelIdx++)
{
//Get_S4 (xxl->initial_cpb_removal_delay_length_minus1+1, xxl->SchedSel[SchedSelIdx].initial_cpb_removal_delay, "initial_cpb_removal_delay"); Param_Info2(xxl->SchedSel[SchedSelIdx].initial_cpb_removal_delay/90, " ms");
//Get_S4 (xxl->initial_cpb_removal_delay_length_minus1+1, xxl->SchedSel[SchedSelIdx].initial_cpb_removal_delay_offset, "initial_cpb_removal_delay_offset"); Param_Info2(xxl->SchedSel[SchedSelIdx].initial_cpb_removal_delay_offset/90, " ms");
Info_S4 (xxl->initial_cpb_removal_delay_length_minus1+1, initial_cpb_removal_delay, "initial_cpb_removal_delay"); Param_Info2(initial_cpb_removal_delay/90, " ms");
Info_S4 (xxl->initial_cpb_removal_delay_length_minus1+1, initial_cpb_removal_delay_offset, "initial_cpb_removal_delay_offset"); Param_Info2(initial_cpb_removal_delay_offset/90, " ms");
}
}
//---------------------------------------------------------------------------
// SEI - 1
void File_Avc::sei_message_pic_timing(int32u /*payloadSize*/, int32u seq_parameter_set_id)
{
Element_Info1("pic_timing");
//Testing if we can parsing it now. TODO: handle case seq_parameter_set_id is unknown (buffering of message, decoding in slice parsing)
if (seq_parameter_set_id==(int32u)-1 && seq_parameter_sets.size()==1)
seq_parameter_set_id=0;
std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item;
if (seq_parameter_set_id>=seq_parameter_sets.size() || (*(seq_parameter_set_Item=seq_parameter_sets.begin()+seq_parameter_set_id))==NULL)
{
//Not yet present
Skip_BS(Data_BS_Remain(), "Data (seq_parameter_set is missing)");
return;
}
//Parsing
int8u pic_struct=(int8u)-1;
BS_Begin();
if ((*seq_parameter_set_Item)->CpbDpbDelaysPresentFlag())
{
int8u cpb_removal_delay_length_minus1=(*seq_parameter_set_Item)->vui_parameters->NAL?(*seq_parameter_set_Item)->vui_parameters->NAL->cpb_removal_delay_length_minus1:(*seq_parameter_set_Item)->vui_parameters->VCL->cpb_removal_delay_length_minus1; //Spec is not precise, I am not sure
int8u dpb_output_delay_length_minus1=(*seq_parameter_set_Item)->vui_parameters->NAL?(*seq_parameter_set_Item)->vui_parameters->NAL->dpb_output_delay_length_minus1:(*seq_parameter_set_Item)->vui_parameters->VCL->dpb_output_delay_length_minus1; //Spec is not precise, I am not sure
Skip_S4(cpb_removal_delay_length_minus1+1, "cpb_removal_delay");
Skip_S4(dpb_output_delay_length_minus1+1, "dpb_output_delay");
}
if ((*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->pic_struct_present_flag)
{
Get_S1 (4, pic_struct, "pic_struct");
switch (pic_struct)
{
case 0 :
case 1 :
case 2 :
case 3 :
case 4 :
case 5 :
case 6 : FrameRate_Divider=1; break;
case 7 : FrameRate_Divider=2; break;
case 8 : FrameRate_Divider=3; break;
default : Param_Info1("Reserved"); return; //NumClockTS is unknown
}
Param_Info1(Avc_pic_struct[pic_struct]);
int8u NumClockTS=Avc_NumClockTS[pic_struct];
int8u seconds_value=0, minutes_value=0, hours_value=0; //Here because theses values can be reused in later ClockTSs.
for (int8u i=0; i<NumClockTS; i++)
{
Element_Begin1("ClockTS");
TEST_SB_SKIP( "clock_timestamp_flag");
Ztring TimeStamp;
int32u time_offset=0;
int8u n_frames;
bool full_timestamp_flag, nuit_field_based_flag;
Info_S1(2, ct_type, "ct_type"); Param_Info1(Avc_ct_type[ct_type]);
Get_SB ( nuit_field_based_flag, "nuit_field_based_flag");
Skip_S1(5, "counting_type");
Get_SB ( full_timestamp_flag, "full_timestamp_flag");
Skip_SB( "discontinuity_flag");
Skip_SB( "cnt_dropped_flag");
Get_S1 (8, n_frames, "n_frames");
if (full_timestamp_flag)
{
Get_S1 (6, seconds_value, "seconds_value");
Get_S1 (6, minutes_value, "minutes_value");
Get_S1 (5, hours_value, "hours_value");
}
else
{
TEST_SB_SKIP( "seconds_flag");
Get_S1 (6, seconds_value, "seconds_value");
TEST_SB_SKIP( "minutes_flag");
Get_S1 (6, minutes_value, "minutes_value");
TEST_SB_SKIP( "hours_flag");
Get_S1 (5, hours_value, "hours_value");
TEST_SB_END();
TEST_SB_END();
TEST_SB_END();
}
TimeStamp=Ztring::ToZtring(hours_value)+__T(':')+Ztring::ToZtring(minutes_value)+__T(':')+Ztring::ToZtring(seconds_value);
if ((*seq_parameter_set_Item)->CpbDpbDelaysPresentFlag())
{
int8u time_offset_length=(*seq_parameter_set_Item)->vui_parameters->NAL?(*seq_parameter_set_Item)->vui_parameters->NAL->time_offset_length:(*seq_parameter_set_Item)->vui_parameters->VCL->time_offset_length; //Spec is not precise, I am not sure
if (time_offset_length)
Get_S4 (time_offset_length, time_offset, "time_offset");
}
if ((*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->timing_info_present_flag && (*seq_parameter_set_Item)->vui_parameters->time_scale)
{
float32 Milliseconds=((float32)(n_frames*((*seq_parameter_set_Item)->vui_parameters->num_units_in_tick*(1+(nuit_field_based_flag?1:0)))+time_offset))/(*seq_parameter_set_Item)->vui_parameters->time_scale;
TimeStamp+=__T('.');
TimeStamp+=Ztring::ToZtring(Milliseconds);
}
Element_Info1(TimeStamp);
TEST_SB_END();
Element_End0();
}
}
BS_End();
FILLING_BEGIN_PRECISE();
if ((*seq_parameter_set_Item)->pic_struct_FirstDetected==(int8u)-1 && (*seq_parameter_set_Item)->vui_parameters && (*seq_parameter_set_Item)->vui_parameters->pic_struct_present_flag)
(*seq_parameter_set_Item)->pic_struct_FirstDetected=pic_struct;
FILLING_END();
}
//---------------------------------------------------------------------------
// SEI - 5
void File_Avc::sei_message_user_data_registered_itu_t_t35()
{
Element_Info1("user_data_registered_itu_t_t35");
//Parsing
int8u itu_t_t35_country_code;
Get_B1 (itu_t_t35_country_code, "itu_t_t35_country_code");
if (itu_t_t35_country_code==0xFF)
Skip_B1( "itu_t_t35_country_code_extension_byte");
if (itu_t_t35_country_code!=0xB5 || Element_Offset+2>=Element_Size)
{
if (Element_Size-Element_Offset)
Skip_XX(Element_Size-Element_Offset, "Unknown");
return;
}
//United-States
int16u id;
Get_B2 (id, "id?");
if (id!=0x0031 || Element_Offset+4>=Element_Size)
{
if (Element_Size-Element_Offset)
Skip_XX(Element_Size-Element_Offset, "Unknown");
return;
}
int32u Identifier;
Peek_B4(Identifier);
switch (Identifier)
{
case 0x44544731 : sei_message_user_data_registered_itu_t_t35_DTG1(); return;
case 0x47413934 : sei_message_user_data_registered_itu_t_t35_GA94(); return;
default : if (Element_Size-Element_Offset)
Skip_XX(Element_Size-Element_Offset, "Unknown");
}
}
//---------------------------------------------------------------------------
// SEI - 5 - DTG1
void File_Avc::sei_message_user_data_registered_itu_t_t35_DTG1()
{
Element_Info1("Active Format Description");
//Parsing
bool active_format_flag;
Skip_C4( "afd_identifier");
BS_Begin();
Mark_0();
Get_SB (active_format_flag, "active_format_flag");
Mark_0_NoTrustError();
Mark_0_NoTrustError();
Mark_0_NoTrustError();
Mark_0_NoTrustError();
Mark_0_NoTrustError();
Mark_1_NoTrustError();
if (active_format_flag)
{
Mark_1_NoTrustError();
Mark_1_NoTrustError();
Mark_1_NoTrustError();
Mark_1_NoTrustError();
Info_S1(4, active_format, "active_format"); Param_Info1(Avc_user_data_DTG1_active_format[active_format]);
}
BS_End();
}
//---------------------------------------------------------------------------
// SEI - 5 - GA94
void File_Avc::sei_message_user_data_registered_itu_t_t35_GA94()
{
//Parsing
int8u user_data_type_code;
Skip_B4( "GA94_identifier");
Get_B1 (user_data_type_code, "user_data_type_code");
switch (user_data_type_code)
{
case 0x03 : sei_message_user_data_registered_itu_t_t35_GA94_03(); break;
case 0x06 : sei_message_user_data_registered_itu_t_t35_GA94_06(); break;
default : Skip_XX(Element_Size-Element_Offset, "GA94_reserved_user_data");
}
}
//---------------------------------------------------------------------------
// SEI - 5 - GA94 - 0x03
void File_Avc::sei_message_user_data_registered_itu_t_t35_GA94_03()
{
#if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
GA94_03_IsPresent=true;
MustExtendParsingDuration=true;
Buffer_TotalBytes_Fill_Max=(int64u)-1; //Disabling this feature for this format, this is done in the parser
Element_Info1("DTVCC Transport");
//Coherency
delete TemporalReferences_DelayedElement; TemporalReferences_DelayedElement=new temporal_reference();
TemporalReferences_DelayedElement->GA94_03=new buffer_data(Buffer+Buffer_Offset+(size_t)Element_Offset,(size_t)(Element_Size-Element_Offset));
//Parsing
Skip_XX(Element_Size-Element_Offset, "CC data");
#else //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
Skip_XX(Element_Size-Element_Offset, "DTVCC Transport data");
#endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
}
void File_Avc::sei_message_user_data_registered_itu_t_t35_GA94_03_Delayed(int32u seq_parameter_set_id)
{
// Skipping missing frames
if (TemporalReferences_Max-TemporalReferences_Min>(size_t)(4*(seq_parameter_sets[seq_parameter_set_id]->max_num_ref_frames+3))) // max_num_ref_frames ref frame maximum
{
size_t TemporalReferences_Min_New=TemporalReferences_Max-4*(seq_parameter_sets[seq_parameter_set_id]->max_num_ref_frames+3);
while (TemporalReferences_Min_New>TemporalReferences_Min && TemporalReferences[TemporalReferences_Min_New-1])
TemporalReferences_Min_New--;
TemporalReferences_Min=TemporalReferences_Min_New;
while (TemporalReferences[TemporalReferences_Min]==NULL)
TemporalReferences_Min++;
}
// Parsing captions
while (TemporalReferences[TemporalReferences_Min] && TemporalReferences_Min+2*seq_parameter_sets[seq_parameter_set_id]->max_num_ref_frames<TemporalReferences_Max)
{
#if defined(MEDIAINFO_DTVCCTRANSPORT_YES)
Element_Begin1("Reordered DTVCC Transport");
//Parsing
#if MEDIAINFO_DEMUX
int64u Element_Code_Old=Element_Code;
Element_Code=0x4741393400000003LL;
#endif //MEDIAINFO_DEMUX
if (GA94_03_Parser==NULL)
{
GA94_03_Parser=new File_DtvccTransport;
Open_Buffer_Init(GA94_03_Parser);
((File_DtvccTransport*)GA94_03_Parser)->Format=File_DtvccTransport::Format_A53_4_GA94_03;
}
if (((File_DtvccTransport*)GA94_03_Parser)->AspectRatio==0)
{
float64 PixelAspectRatio=1;
std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item=seq_parameter_sets.begin();
for (; seq_parameter_set_Item!=seq_parameter_sets.end(); ++seq_parameter_set_Item)
if ((*seq_parameter_set_Item))
break;
if (seq_parameter_set_Item!=seq_parameter_sets.end())
{
if (((*seq_parameter_set_Item)->vui_parameters) && ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_info_present_flag))
{
if ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_idc<Avc_PixelAspectRatio_Size)
PixelAspectRatio=Avc_PixelAspectRatio[(*seq_parameter_set_Item)->vui_parameters->aspect_ratio_idc];
else if ((*seq_parameter_set_Item)->vui_parameters->aspect_ratio_idc==0xFF && (*seq_parameter_set_Item)->vui_parameters->sar_height)
PixelAspectRatio=((float64)(*seq_parameter_set_Item)->vui_parameters->sar_width)/(*seq_parameter_set_Item)->vui_parameters->sar_height;
}
const int32u Width =((*seq_parameter_set_Item)->pic_width_in_mbs_minus1 +1)*16;
const int32u Height=((*seq_parameter_set_Item)->pic_height_in_map_units_minus1+1)*16*(2-(*seq_parameter_set_Item)->frame_mbs_only_flag);
if(Height)
((File_DtvccTransport*)GA94_03_Parser)->AspectRatio=Width*PixelAspectRatio/Height;
}
}
if (GA94_03_Parser->PTS_DTS_Needed)
{
GA94_03_Parser->FrameInfo.PCR=FrameInfo.PCR;
GA94_03_Parser->FrameInfo.PTS=FrameInfo.PTS;
GA94_03_Parser->FrameInfo.DTS=FrameInfo.DTS;
}
#if MEDIAINFO_DEMUX
if (TemporalReferences[TemporalReferences_Min]->GA94_03)
{
int8u Demux_Level_Save=Demux_Level;
Demux_Level=8; //Ancillary
Demux(TemporalReferences[TemporalReferences_Min]->GA94_03->Data, TemporalReferences[TemporalReferences_Min]->GA94_03->Size, ContentType_MainStream);
Demux_Level=Demux_Level_Save;
}
Element_Code=Element_Code_Old;
#endif //MEDIAINFO_DEMUX
if (TemporalReferences[TemporalReferences_Min]->GA94_03)
{
#if defined(MEDIAINFO_EIA608_YES) || defined(MEDIAINFO_EIA708_YES)
GA94_03_Parser->ServiceDescriptors=ServiceDescriptors;
#endif
Open_Buffer_Continue(GA94_03_Parser, TemporalReferences[TemporalReferences_Min]->GA94_03->Data, TemporalReferences[TemporalReferences_Min]->GA94_03->Size);
}
Element_End0();
#endif //defined(MEDIAINFO_DTVCCTRANSPORT_YES)
TemporalReferences_Min+=((seq_parameter_sets[seq_parameter_set_id]->frame_mbs_only_flag | !TemporalReferences[TemporalReferences_Min]->IsField)?2:1);
}
}
//---------------------------------------------------------------------------
// SEI - 5 - GA94 - 0x03
void File_Avc::sei_message_user_data_registered_itu_t_t35_GA94_06()
{
Element_Info1("Bar data");
//Parsing
bool top_bar_flag, bottom_bar_flag, left_bar_flag, right_bar_flag;
BS_Begin();
Get_SB (top_bar_flag, "top_bar_flag");
Get_SB (bottom_bar_flag, "bottom_bar_flag");
Get_SB (left_bar_flag, "left_bar_flag");
Get_SB (right_bar_flag, "right_bar_flag");
Mark_1_NoTrustError();
Mark_1_NoTrustError();
Mark_1_NoTrustError();
Mark_1_NoTrustError();
BS_End();
if (top_bar_flag)
{
Mark_1();
Mark_1();
Skip_S2(14, "line_number_end_of_top_bar");
}
if (bottom_bar_flag)
{
Mark_1();
Mark_1();
Skip_S2(14, "line_number_start_of_bottom_bar");
}
if (left_bar_flag)
{
Mark_1();
Mark_1();
Skip_S2(14, "pixel_number_end_of_left_bar");
}
if (right_bar_flag)
{
Mark_1();
Mark_1();
Skip_S2(14, "pixel_number_start_of_right_bar");
}
Mark_1();
Mark_1();
Mark_1();
Mark_1();
Mark_1();
Mark_1();
Mark_1();
Mark_1();
BS_End();
if (Element_Size-Element_Offset)
Skip_XX(Element_Size-Element_Offset, "additional_bar_data");
}
//---------------------------------------------------------------------------
// SEI - 5
void File_Avc::sei_message_user_data_unregistered(int32u payloadSize)
{
Element_Info1("user_data_unregistered");
//Parsing
int128u uuid_iso_iec_11578;
Get_UUID(uuid_iso_iec_11578, "uuid_iso_iec_11578");
switch (uuid_iso_iec_11578.hi)
{
case 0xDC45E9BDE6D948B7LL : Element_Info1("x264");
sei_message_user_data_unregistered_x264(payloadSize-16); break;
case 0xFB574A60AC924E68LL : Element_Info1("eavc");
sei_message_user_data_unregistered_x264(payloadSize-16); break;
case 0x17EE8C60F84D11D9LL : Element_Info1("Blu-ray");
sei_message_user_data_unregistered_bluray(payloadSize-16); break;
default :
Element_Info1("unknown");
Skip_XX(payloadSize-16, "data");
}
}
//---------------------------------------------------------------------------
// SEI - 5 - x264
void File_Avc::sei_message_user_data_unregistered_x264(int32u payloadSize)
{
//Parsing
string Data;
Peek_String(payloadSize, Data);
if (Data.size()!=payloadSize && Data.size()+1!=payloadSize)
{
Skip_XX(payloadSize, "Unknown");
return; //This is not a text string
}
size_t Data_Pos_Before=0;
size_t Loop=0;
do
{
size_t Data_Pos=Data.find(" - ", Data_Pos_Before);
if (Data_Pos==std::string::npos)
Data_Pos=Data.size();
if (Data.find("options: ", Data_Pos_Before)==Data_Pos_Before)
{
Element_Begin1("options");
size_t Options_Pos_Before=Data_Pos_Before;
Encoded_Library_Settings.clear();
do
{
size_t Options_Pos=Data.find(__T(' '), Options_Pos_Before);
if (Options_Pos==std::string::npos)
Options_Pos=Data.size();
string option;
Get_String (Options_Pos-Options_Pos_Before, option, "option");
Options_Pos_Before=Options_Pos;
do
{
string Separator;
Peek_String(1, Separator);
if (Separator==" ")
{
Skip_UTF8(1, "separator");
Options_Pos_Before+=1;
}
else
break;
}
while (Options_Pos_Before!=Data.size());
//Filling
if (option!="options:")
{
if (!Encoded_Library_Settings.empty())
Encoded_Library_Settings+=__T(" / ");
Encoded_Library_Settings+=Ztring().From_UTF8(option.c_str());
if (option.find("bitrate=")==0)
BitRate_Nominal.From_UTF8(option.substr(8)+"000"); //After "bitrate="
}
}
while (Options_Pos_Before!=Data.size());
Element_End0();
}
else
{
string Value;
Get_String(Data_Pos-Data_Pos_Before, Value, "data");
//Saving
if (Loop==0)
{
//Cleaning a little the value
while (!Value.empty() && Value[0]<0x30)
Value.erase(Value.begin());
while (!Value.empty() && Value[Value.size()-1]<0x30)
Value.erase(Value.end()-1);
Encoded_Library.From_UTF8(Value.c_str());
}
if (Loop==1 && Encoded_Library.find(__T("x264"))==0)
{
Encoded_Library+=__T(" - ");
Encoded_Library+=Ztring().From_UTF8(Value.c_str());
}
}
Data_Pos_Before=Data_Pos;
if (Data_Pos_Before+3<=Data.size())
{
Skip_UTF8(3, "separator");
Data_Pos_Before+=3;
}
Loop++;
}
while (Data_Pos_Before!=Data.size());
//Encoded_Library
if (Encoded_Library.find(__T("eavc "))==0)
{
Encoded_Library_Name=__T("eavc");
Encoded_Library_Version=Encoded_Library.SubString(__T("eavc "), __T(""));
}
else if (Encoded_Library.find(__T("x264 - "))==0)
{
Encoded_Library_Name=__T("x264");
Encoded_Library_Version=Encoded_Library.SubString(__T("x264 - "), __T(""));
}
else if (Encoded_Library.find(__T("SUPER(C) by eRightSoft "))==0)
{
Encoded_Library_Name=__T("SUPER(C) by eRightSoft");
Encoded_Library_Date=Ztring(__T("UTC "))+Encoded_Library.SubString(__T("2000-"), __T(" "));
}
else
Encoded_Library_Name=Encoded_Library;
}
//---------------------------------------------------------------------------
// SEI - 5 - x264
void File_Avc::sei_message_user_data_unregistered_bluray(int32u payloadSize)
{
if (payloadSize<4)
{
Skip_XX(payloadSize, "Unknown");
return;
}
int32u Identifier;
Get_B4 (Identifier, "Identifier");
switch (Identifier)
{
case 0x47413934 : sei_message_user_data_registered_itu_t_t35_GA94_03(); return;
case 0x4D44504D : sei_message_user_data_unregistered_bluray_MDPM(Element_Size-Element_Offset); return;
default : Skip_XX(Element_Size-Element_Offset, "Unknown");
}
}
//---------------------------------------------------------------------------
// SEI - 5 - bluray - MDPM
void File_Avc::sei_message_user_data_unregistered_bluray_MDPM(int32u payloadSize)
{
if (payloadSize<1)
{
Skip_XX(payloadSize, "Unknown");
return;
}
Element_Info1("Modified Digital Video Pack Metadata");
Skip_B1( "Count");
payloadSize--;
string DateTime0, DateTime1, DateTime2, Model0, Model1, Model2;
int16u MakeName=(int16u)-1;
Ztring IrisFNumber;
while (payloadSize >= 5)
{
Element_Begin0();
int8u ID;
Get_B1(ID, "ID"); Element_Name(MDPM(ID));
switch (ID)
{
case 0x18:
{
int16u Year;
int8u MM, Zone_Hours;
bool Zone_Sign, Zone_Minutes;
BS_Begin();
Mark_0();
Skip_SB( "DST flag");
Get_SB (Zone_Sign, "Time zone sign");
Get_S1 (4, Zone_Hours, "Time zone hours");
Get_SB (Zone_Minutes, "Time zone half-hour flag");
BS_End();
Get_B2 (Year, "Year");
Get_B1 (MM, "Month");
DateTime0+='0'+(Year>>12);
DateTime0+='0'+((Year&0xF00)>>8);
DateTime0+='0'+((Year&0xF0)>>4);
DateTime0+='0'+(Year&0xF);
DateTime0+='-';
DateTime0+='0'+((MM&0xF0)>>4);
DateTime0+='0'+(MM&0xF);
DateTime0+='-';
Element_Info1(DateTime0);
DateTime2+=Zone_Sign?'-':'+';
DateTime2+='0'+Zone_Hours/10;
DateTime2+='0'+Zone_Hours%10;
DateTime2+=':';
DateTime2+=Zone_Minutes?'3':'0';
DateTime2+='0';
Element_Info1(DateTime2);
}
break;
case 0x19:
{
int8u DD, hh, mm, ss;
Get_B1 (DD, "Day");
Get_B1 (hh, "Hour");
Get_B1 (mm, "Minute");
Get_B1 (ss, "Second");
DateTime1+='0'+(DD>>4);
DateTime1+='0'+(DD&0xF);
DateTime1+=' ';
DateTime1+='0'+(hh>>4);
DateTime1+='0'+(hh&0xF);
DateTime1+=':';
DateTime1+='0'+(mm>>4);
DateTime1+='0'+(mm&0xF);
DateTime1+=':';
DateTime1+='0'+(ss>>4);
DateTime1+='0'+(ss&0xF);
Element_Info1(DateTime1);
}
break;
case 0x70:
consumer_camera_1();
break;
case 0x71:
consumer_camera_2();
break;
case 0xA1:
{
int16u D, N;
Get_B2 (D, "D");
Get_B2 (N, "N");
IrisFNumber.From_Number(((float64)D)/N, 6);
Element_Info1(IrisFNumber);
}
break;
case 0xE0:
{
Get_B2 (MakeName, "Name");
Skip_B2( "Category");
Element_Info1(MDPM_MakeName(MakeName));
}
break;
case 0xE4:
Get_String(4, Model0, "Data"); Element_Info1(Model0);
break;
case 0xE5:
Get_String(4, Model1, "Data"); Element_Info1(Model1);
break;
case 0xE6:
Get_String(4, Model2, "Data");
Model2.erase(Model2.find_last_not_of('\0')+1);
Element_Info1(Model2);
break;
default: Skip_B4("Data");
}
Element_End0();
payloadSize -= 5;
}
if (payloadSize)
Skip_XX(payloadSize, "Unknown");
FILLING_BEGIN();
if (!Frame_Count && !seq_parameter_sets.empty() && !pic_parameter_sets.empty())
{
if (!DateTime0.empty() && !DateTime1.empty())
Fill(Stream_General, 0, General_Recorded_Date, DateTime0+DateTime1+DateTime2);
if (MDPM_MakeName(MakeName)[0] || !Model0.empty())
{
string Model;
if (MDPM_MakeName(MakeName)[0])
{
Model=MDPM_MakeName(MakeName);
Fill(Stream_General, 0, General_Encoded_Application_CompanyName, Model);
if (!Model0.empty())
Model+=' ';
}
Fill(Stream_General, 0, General_Encoded_Application, Model+Model0+Model1+Model2);
Fill(Stream_General, 0, General_Encoded_Application_Name, Model0+Model1+Model2);
}
Fill(Stream_Video, 0, "IrisFNumber", IrisFNumber);
}
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Avc::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();
/* TODO: need some tweaking
FILLING_BEGIN();
if (!Frame_Count)
{
Ztring Settings;
if (ae_mode<0x0F) Settings+=__T("ae mode=")+Ztring(Dv_consumer_camera_1_ae_mode[ae_mode])+__T(", ");
if (wb_mode<0x08) Settings+=__T("wb mode=")+Ztring(Dv_consumer_camera_1_wb_mode[wb_mode])+__T(", ");
if (wb_mode<0x1F) Settings+=__T("white balance=")+Ztring(Dv_consumer_camera_1_white_balance(white_balance))+__T(", ");
Settings+=__T("fcm=")+Ztring(Dv_consumer_camera_1_fcm[fcm]);
Fill(Stream_Video, 0, "Camera_Settings", Settings);
}
FILLING_END();
*/
}
//---------------------------------------------------------------------------
void File_Avc::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();
}
//---------------------------------------------------------------------------
void File_Avc::sei_message_mastering_display_colour_volume()
{
Element_Info1("mastering_display_colour_volume");
std::map<video, Ztring>& SmpteSt2086 = HDR[HdrFormat_SmpteSt2086];
Ztring& HDR_Format = SmpteSt2086[Video_HDR_Format];
if (HDR_Format.empty())
{
HDR_Format = __T("SMPTE ST 2086");
SmpteSt2086[Video_HDR_Format_Compatibility] = "HDR10";
}
Get_MasteringDisplayColorVolume(SmpteSt2086[Video_MasteringDisplay_ColorPrimaries], SmpteSt2086[Video_MasteringDisplay_Luminance]);
}
//---------------------------------------------------------------------------
void File_Avc::sei_message_light_level()
{
Element_Info1("light_level");
//Parsing
Get_B2(maximum_content_light_level, "maximum_content_light_level");
Get_B2(maximum_frame_average_light_level, "maximum_frame_average_light_level");
}
//---------------------------------------------------------------------------
// SEI - 6
void File_Avc::sei_message_recovery_point()
{
Element_Info1("recovery_point");
//Parsing
BS_Begin();
Skip_UE( "recovery_frame_cnt");
Skip_SB( "exact_match_flag");
Skip_SB( "broken_link_flag");
Skip_S1(2, "changing_slice_group_idc");
BS_End();
}
//---------------------------------------------------------------------------
// SEI - 32
void File_Avc::sei_message_mainconcept(int32u payloadSize)
{
Element_Info1("MainConcept text");
//Parsing
string Text;
Get_String(payloadSize, Text, "text");
if (Text.find("produced by MainConcept H.264/AVC Codec v")!=std::string::npos)
{
Encoded_Library=Ztring().From_UTF8(Text).SubString(__T("produced by "), __T(" MainConcept AG"));
Encoded_Library_Name=__T("MainConcept H.264/AVC Codec");
Encoded_Library_Version= Ztring().From_UTF8(Text).SubString(__T("produced by MainConcept H.264/AVC Codec v"), __T(" (c) "));
Encoded_Library_Date=MediaInfoLib::Config.Library_Get(InfoLibrary_Format_MainConcept_Avc, Encoded_Library_Version, InfoLibrary_Date);
}
}
//---------------------------------------------------------------------------
void File_Avc::sei_alternative_transfer_characteristics()
{
Element_Info1("alternative_transfer_characteristics");
//Parsing
Get_B1(preferred_transfer_characteristics, "preferred_transfer_characteristics"); Param_Info1(Mpegv_transfer_characteristics(preferred_transfer_characteristics));
}
//---------------------------------------------------------------------------
// Packet "07"
void File_Avc::seq_parameter_set()
{
Element_Name("seq_parameter_set");
//parsing
int32u seq_parameter_set_id;
seq_parameter_set_struct* Data_Item_New=seq_parameter_set_data(seq_parameter_set_id);
if (!Data_Item_New)
return;
Mark_1( );
size_t BS_bits=Data_BS_Remain()%8;
while (BS_bits)
{
Mark_0( );
BS_bits--;
}
BS_End();
//Hack for 00003.m2ts: There is a trailing 0x89, why?
if (Element_Offset+1==Element_Size)
{
int8u ToTest;
Peek_B1(ToTest);
if (ToTest==0x98)
Skip_B1( "Unknown");
}
//Hack for : There is a trailing data, why?
if (Element_Offset+4==Element_Size)
{
int32u ToTest;
Peek_B4(ToTest);
if (ToTest==0xE30633C0)
Skip_B4( "Unknown");
}
//NULL bytes
while (Element_Offset<Element_Size)
{
int8u Null;
Get_B1 (Null, "NULL byte");
if (Null)
Trusted_IsNot("Should be NULL byte");
}
FILLING_BEGIN_PRECISE();
//NextCode
NextCode_Clear();
NextCode_Add(0x08);
//Add
seq_parameter_set_data_Add(seq_parameter_sets, seq_parameter_set_id, Data_Item_New);
//Autorisation of other streams
Streams[0x08].Searching_Payload=true; //pic_parameter_set
if (Streams[0x07].ShouldDuplicate)
Streams[0x08].ShouldDuplicate=true; //pic_parameter_set
Streams[0x0A].Searching_Payload=true; //end_of_seq
if (Streams[0x07].ShouldDuplicate)
Streams[0x0A].ShouldDuplicate=true; //end_of_seq
Streams[0x0B].Searching_Payload=true; //end_of_stream
if (Streams[0x07].ShouldDuplicate)
Streams[0x0B].ShouldDuplicate=true; //end_of_stream
FILLING_ELSE();
delete Data_Item_New;
FILLING_END();
}
void File_Avc::seq_parameter_set_data_Add(std::vector<seq_parameter_set_struct*> &Data, const int32u Data_id, seq_parameter_set_struct* Data_Item_New)
{
//Creating Data
if (Data_id>=Data.size())
Data.resize(Data_id+1);
else
FirstPFrameInGop_IsParsed=true;
std::vector<seq_parameter_set_struct*>::iterator Data_Item=Data.begin()+Data_id;
delete *Data_Item; *Data_Item=Data_Item_New;
//Computing values (for speed)
size_t MaxNumber;
switch (Data_Item_New->pic_order_cnt_type)
{
case 0 :
MaxNumber=Data_Item_New->MaxPicOrderCntLsb;
break;
case 1 :
case 2 :
MaxNumber=Data_Item_New->MaxFrameNum*2;
break;
default:
MaxNumber = 0;
}
if (MaxNumber>TemporalReferences_Reserved)
{
TemporalReferences.resize(4*MaxNumber);
TemporalReferences_Reserved=MaxNumber;
}
}
//---------------------------------------------------------------------------
// Packet "08"
void File_Avc::pic_parameter_set()
{
Element_Name("pic_parameter_set");
//Parsing
int32u pic_parameter_set_id, seq_parameter_set_id, num_slice_groups_minus1, num_ref_idx_l0_default_active_minus1, num_ref_idx_l1_default_active_minus1, slice_group_map_type=0;
int8u weighted_bipred_idc=0;
bool entropy_coding_mode_flag,bottom_field_pic_order_in_frame_present_flag, redundant_pic_cnt_present_flag, weighted_pred_flag, deblocking_filter_control_present_flag;
BS_Begin();
Get_UE (pic_parameter_set_id, "pic_parameter_set_id");
Get_UE (seq_parameter_set_id, "seq_parameter_set_id");
std::vector<seq_parameter_set_struct*>::iterator seq_parameter_set_Item;
if (seq_parameter_set_id>=seq_parameter_sets.size() || (*(seq_parameter_set_Item=seq_parameter_sets.begin()+seq_parameter_set_id))==NULL)
{
if (seq_parameter_set_id>=subset_seq_parameter_sets.size() || (*(seq_parameter_set_Item=subset_seq_parameter_sets.begin()+seq_parameter_set_id))==NULL)
{
//Not yet present
Skip_BS(Data_BS_Remain(), "Data (seq_parameter_set is missing)");
return;
}
}
Get_SB (entropy_coding_mode_flag, "entropy_coding_mode_flag");
Get_SB (bottom_field_pic_order_in_frame_present_flag, "bottom_field_pic_order_in_frame_present_flag");
Get_UE (num_slice_groups_minus1, "num_slice_groups_minus1");
if (num_slice_groups_minus1>7)
{
Trusted_IsNot("num_slice_groups_minus1 too high");
num_slice_groups_minus1=0;
}
if (num_slice_groups_minus1>0)
{
Get_UE (slice_group_map_type, "slice_group_map_type");
if (slice_group_map_type==0)
{
for (int32u Pos=0; Pos<=num_slice_groups_minus1; Pos++)
Skip_UE( "run_length_minus1");
}
else if (slice_group_map_type==2)
{
for (int32u Pos=0; Pos<num_slice_groups_minus1; Pos++)
{
Skip_UE( "top_left");
Skip_UE( "bottom_right");
}
}
else if (slice_group_map_type==3
|| slice_group_map_type==4
|| slice_group_map_type==5)
{
Skip_SB( "slice_group_change_direction_flag");
Skip_UE( "slice_group_change_rate_minus1");
}
else if (slice_group_map_type==6)
{
int32u pic_size_in_map_units_minus1;
Get_UE (pic_size_in_map_units_minus1, "pic_size_in_map_units_minus1");
if(pic_size_in_map_units_minus1>((*seq_parameter_set_Item)->pic_width_in_mbs_minus1+1)*((*seq_parameter_set_Item)->pic_height_in_map_units_minus1+1))
{
Trusted_IsNot("pic_size_in_map_units_minus1 too high");
return;
}
#if defined (__mips__) || defined (__mipsel__)
int32u slice_group_id_Size=(int32u)(std::ceil(std::log((double)(num_slice_groups_minus1+1))/std::log((double)10))); //std::log is natural logarithm
#else
int32u slice_group_id_Size=(int32u)(std::ceil(std::log((float32)(num_slice_groups_minus1+1))/std::log((float32)10))); //std::log is natural logarithm
#endif
for (int32u Pos=0; Pos<=pic_size_in_map_units_minus1; Pos++)
Skip_BS(slice_group_id_Size, "slice_group_id");
}
}
Get_UE (num_ref_idx_l0_default_active_minus1, "num_ref_idx_l0_default_active_minus1");
Get_UE (num_ref_idx_l1_default_active_minus1, "num_ref_idx_l1_default_active_minus1");
Get_SB (weighted_pred_flag, "weighted_pred_flag");
Get_S1 (2, weighted_bipred_idc, "weighted_bipred_idc");
Skip_SE( "pic_init_qp_minus26");
Skip_SE( "pic_init_qs_minus26");
Skip_SE( "chroma_qp_index_offset");
Get_SB (deblocking_filter_control_present_flag, "deblocking_filter_control_present_flag");
Skip_SB( "constrained_intra_pred_flag");
Get_SB (redundant_pic_cnt_present_flag, "redundant_pic_cnt_present_flag");
bool more_rbsp_data=false;
if (Element_Size)
{
int64u Offset=Element_Size-1;
while (Offset && Buffer[Buffer_Offset+(size_t)Offset]==0x00) //Searching if there are NULL bytes at the end of the data
Offset--;
size_t Bit_Pos=7;
while (Bit_Pos && !(Buffer[Buffer_Offset+(size_t)Offset]&(1<<(7-Bit_Pos))))
Bit_Pos--;
if (Data_BS_Remain()>1+(7-Bit_Pos)+(Element_Size-Offset-1)*8)
more_rbsp_data=true;
}
if (more_rbsp_data)
{
bool transform_8x8_mode_flag;
Get_SB (transform_8x8_mode_flag, "transform_8x8_mode_flag");
TEST_SB_SKIP( "pic_scaling_matrix_present_flag");
for (int8u Pos=0; Pos<6+(transform_8x8_mode_flag?((*seq_parameter_set_Item)->chroma_format_idc!=3?2:6):0); Pos++ )
{
TEST_SB_SKIP( "pic_scaling_list_present_flag");
scaling_list(Pos<6?16:64);
TEST_SB_END();
}
TEST_SB_END();
Skip_SE( "second_chroma_qp_index_offset");
}
Mark_1( );
BS_End();
while (Element_Offset<Element_Size) //Not always removed from the stream, ie in MPEG-4
{
int8u Padding;
Peek_B1(Padding);
if (!Padding)
Skip_B1( "Padding");
else
break;
}
FILLING_BEGIN_PRECISE();
//Integrity
if (pic_parameter_set_id>=256)
{
Trusted_IsNot("pic_parameter_set_id not valid");
return; //Problem, not valid
}
if (seq_parameter_set_id>=32)
{
Trusted_IsNot("seq_parameter_set_id not valid");
return; //Problem, not valid
}
//NextCode
NextCode_Clear();
NextCode_Add(0x05);
NextCode_Add(0x06);
if (!subset_seq_parameter_sets.empty())
NextCode_Add(0x14); //slice_layer_extension
//Filling
if (pic_parameter_set_id>=pic_parameter_sets.size())
pic_parameter_sets.resize(pic_parameter_set_id+1);
std::vector<pic_parameter_set_struct*>::iterator pic_parameter_sets_Item=pic_parameter_sets.begin()+pic_parameter_set_id;
delete *pic_parameter_sets_Item; *pic_parameter_sets_Item = new pic_parameter_set_struct(
(int8u)seq_parameter_set_id,
(int8u)num_ref_idx_l0_default_active_minus1,
(int8u)num_ref_idx_l1_default_active_minus1,
weighted_bipred_idc,
num_slice_groups_minus1,
slice_group_map_type,
entropy_coding_mode_flag,
bottom_field_pic_order_in_frame_present_flag,
weighted_pred_flag,
redundant_pic_cnt_present_flag,
deblocking_filter_control_present_flag
);
//Autorisation of other streams
if (!seq_parameter_sets.empty())
{
for (int8u Pos=0x01; Pos<=0x06; Pos++)
{
Streams[Pos].Searching_Payload=true; //Coded slice...
if (Streams[0x08].ShouldDuplicate)
Streams[Pos].ShouldDuplicate=true;
}
}
if (!subset_seq_parameter_sets.empty())
{
Streams[0x14].Searching_Payload=true; //slice_layer_extension
if (Streams[0x08].ShouldDuplicate)
Streams[0x14].ShouldDuplicate=true; //slice_layer_extension
}
//Setting as OK
if (!Status[IsAccepted])
Accept("AVC");
FILLING_END();
}
//---------------------------------------------------------------------------
// Packet "09"
void File_Avc::access_unit_delimiter()
{
Element_Name("access_unit_delimiter");
int8u primary_pic_type;
BS_Begin();
Get_S1 ( 3, primary_pic_type, "primary_pic_type"); Param_Info1(Avc_primary_pic_type[primary_pic_type]);
Mark_1_NoTrustError( ); //Found 1 file without this bit
BS_End();
}
//---------------------------------------------------------------------------
// Packet "09"
void File_Avc::filler_data()
{
Element_Name("filler_data");
while (Element_Offset<Element_Size)
{
int8u FF;
Peek_B1(FF);
if (FF!=0xFF)
break;
Element_Offset++;
}
BS_Begin();
Mark_1( );
BS_End();
}
//---------------------------------------------------------------------------
// Packet "0E"
void File_Avc::prefix_nal_unit(bool svc_extension_flag)
{
Element_Name("prefix_nal_unit");
//Parsing
if (svc_extension_flag)
{
Skip_XX(Element_Size-Element_Offset, "prefix_nal_unit_svc");
}
}
//---------------------------------------------------------------------------
// Packet "0F"
void File_Avc::subset_seq_parameter_set()
{
Element_Name("subset_seq_parameter_set");
//Parsing
int32u subset_seq_parameter_set_id;
seq_parameter_set_struct* Data_Item_New=seq_parameter_set_data(subset_seq_parameter_set_id);
if (!Data_Item_New)
return;
if (Data_Item_New->profile_idc==83 || Data_Item_New->profile_idc==86)
{
//bool svc_vui_parameters_present_flag;
seq_parameter_set_svc_extension();
/* The rest is not yet implemented
Get_SB (svc_vui_parameters_present_flag, "svc_vui_parameters_present_flag");
if (svc_vui_parameters_present_flag)
svc_vui_parameters_extension();
*/
}
else if (Data_Item_New->profile_idc==118 || Data_Item_New->profile_idc==128)
{
//bool mvc_vui_parameters_present_flag, additional_extension2_flag;
Mark_1();
seq_parameter_set_mvc_extension(Data_Item_New);
/* The rest is not yet implemented
Get_SB (mvc_vui_parameters_present_flag, "mvc_vui_parameters_present_flag");
if (mvc_vui_parameters_present_flag)
mvc_vui_parameters_extension();
Get_SB (additional_extension2_flag, "additional_extension2_flag");
if (additional_extension2_flag)
{
//Not handled, should skip all bits except 1
BS_End();
return;
}
*/
}
/* The rest is not yet implemented
Mark_1( );
*/
BS_End();
FILLING_BEGIN();
//NextCode
NextCode_Clear();
NextCode_Add(0x08);
//Add
seq_parameter_set_data_Add(subset_seq_parameter_sets, subset_seq_parameter_set_id, Data_Item_New);
//Autorisation of other streams
Streams[0x08].Searching_Payload=true; //pic_parameter_set
if (Streams[0x0F].ShouldDuplicate)
Streams[0x08].ShouldDuplicate=true; //pic_parameter_set
Streams[0x0A].Searching_Payload=true; //end_of_seq
if (Streams[0x0F].ShouldDuplicate)
Streams[0x0A].ShouldDuplicate=true; //end_of_seq
Streams[0x0B].Searching_Payload=true; //end_of_stream
if (Streams[0x0F].ShouldDuplicate)
Streams[0x0B].ShouldDuplicate=true; //end_of_stream
FILLING_END();
}
//---------------------------------------------------------------------------
// Packet "14"
void File_Avc::slice_layer_extension(bool svc_extension_flag)
{
Element_Name("slice_layer_extension");
//Parsing
if (svc_extension_flag)
{
Skip_XX(Element_Size-Element_Offset, "slice_header_in_scalable_extension + slice_data_in_scalable_extension");
}
else
{
BS_Begin();
slice_header();
slice_data(true);
BS_End();
}
}
//***************************************************************************
// SubElements
//***************************************************************************
//---------------------------------------------------------------------------
File_Avc::seq_parameter_set_struct* File_Avc::seq_parameter_set_data(int32u &Data_id)
{
//Parsing
seq_parameter_set_struct::vui_parameters_struct* vui_parameters_Item=NULL;
int32u chroma_format_idc=1, bit_depth_luma_minus8=0, bit_depth_chroma_minus8=0, log2_max_frame_num_minus4, pic_order_cnt_type, log2_max_pic_order_cnt_lsb_minus4=(int32u)-1, max_num_ref_frames, pic_width_in_mbs_minus1, pic_height_in_map_units_minus1, frame_crop_left_offset=0, frame_crop_right_offset=0, frame_crop_top_offset=0, frame_crop_bottom_offset=0;
int8u profile_idc, level_idc;
bool constraint_set3_flag, separate_colour_plane_flag=false, delta_pic_order_always_zero_flag=false, frame_mbs_only_flag, mb_adaptive_frame_field_flag=false;
Get_B1 (profile_idc, "profile_idc");
BS_Begin();
Element_Begin1("constraints");
Skip_SB( "constraint_set0_flag");
Skip_SB( "constraint_set1_flag");
Skip_SB( "constraint_set2_flag");
Get_SB (constraint_set3_flag, "constraint_set3_flag");
Skip_SB( "constraint_set4_flag");
Skip_SB( "constraint_set5_flag");
Skip_BS(2, "reserved_zero_2bits");
Element_End0();
Get_S1 ( 8, level_idc, "level_idc");
Get_UE ( Data_id, "seq_parameter_set_id");
switch (profile_idc)
{
case 100 :
case 110 :
case 122 :
case 244 :
case 44 :
case 83 :
case 86 :
case 118 :
case 128 : //High profiles
case 138 :
Element_Begin1("high profile specific");
Get_UE (chroma_format_idc, "chroma_format_idc"); Param_Info1C((chroma_format_idc<3), Avc_ChromaSubsampling_format_idc(chroma_format_idc));
if (chroma_format_idc==3)
Get_SB (separate_colour_plane_flag, "separate_colour_plane_flag");
Get_UE (bit_depth_luma_minus8, "bit_depth_luma_minus8");
Get_UE (bit_depth_chroma_minus8, "bit_depth_chroma_minus8");
Skip_SB( "qpprime_y_zero_transform_bypass_flag");
TEST_SB_SKIP( "seq_scaling_matrix_present_flag");
for (int32u Pos=0; Pos<(int32u)((chroma_format_idc!=3) ? 8 : 12); Pos++)
{
TEST_SB_SKIP( "seq_scaling_list_present_flag");
scaling_list(Pos<6?16:64);
TEST_SB_END();
}
TEST_SB_END();
Element_End0();
break;
default : ;
}
Get_UE (log2_max_frame_num_minus4, "log2_max_frame_num_minus4");
Get_UE (pic_order_cnt_type, "pic_order_cnt_type");
if (pic_order_cnt_type==0)
Get_UE (log2_max_pic_order_cnt_lsb_minus4, "log2_max_pic_order_cnt_lsb_minus4");
else if (pic_order_cnt_type==1)
{
int32u num_ref_frames_in_pic_order_cnt_cycle;
Get_SB (delta_pic_order_always_zero_flag, "delta_pic_order_always_zero_flag");
Skip_SE( "offset_for_non_ref_pic");
Skip_SE( "offset_for_top_to_bottom_field");
Get_UE (num_ref_frames_in_pic_order_cnt_cycle, "num_ref_frames_in_pic_order_cnt_cycle");
if (num_ref_frames_in_pic_order_cnt_cycle>=256)
{
Trusted_IsNot("num_ref_frames_in_pic_order_cnt_cycle too high");
return NULL;
}
for(int32u Pos=0; Pos<num_ref_frames_in_pic_order_cnt_cycle; Pos++)
Skip_SE( "offset_for_ref_frame");
}
else if (pic_order_cnt_type > 2)
{
Trusted_IsNot("pic_order_cnt_type not supported");
return NULL;
}
Get_UE (max_num_ref_frames, "max_num_ref_frames");
Skip_SB( "gaps_in_frame_num_value_allowed_flag");
Get_UE (pic_width_in_mbs_minus1, "pic_width_in_mbs_minus1");
Get_UE (pic_height_in_map_units_minus1, "pic_height_in_map_units_minus1");
Get_SB (frame_mbs_only_flag, "frame_mbs_only_flag");
if (!frame_mbs_only_flag)
Get_SB (mb_adaptive_frame_field_flag, "mb_adaptive_frame_field_flag");
Skip_SB( "direct_8x8_inference_flag");
TEST_SB_SKIP( "frame_cropping_flag");
Get_UE (frame_crop_left_offset, "frame_crop_left_offset");
Get_UE (frame_crop_right_offset, "frame_crop_right_offset");
Get_UE (frame_crop_top_offset, "frame_crop_top_offset");
Get_UE (frame_crop_bottom_offset, "frame_crop_bottom_offset");
TEST_SB_END();
TEST_SB_SKIP( "vui_parameters_present_flag");
vui_parameters(vui_parameters_Item);
TEST_SB_END();
FILLING_BEGIN();
//Integrity
if (Data_id>=32)
{
Trusted_IsNot("seq_parameter_set_id not valid");
delete (seq_parameter_set_struct::vui_parameters_struct*)vui_parameters_Item;
return NULL; //Problem, not valid
}
if (pic_order_cnt_type==0 && log2_max_pic_order_cnt_lsb_minus4>12)
{
Trusted_IsNot("log2_max_pic_order_cnt_lsb_minus4 not valid");
delete (seq_parameter_set_struct::vui_parameters_struct*)vui_parameters_Item;
return NULL; //Problem, not valid
}
if (log2_max_frame_num_minus4>12)
{
Trusted_IsNot("log2_max_frame_num_minus4 not valid");
delete (seq_parameter_set_struct::vui_parameters_struct*)vui_parameters_Item;
return NULL; //Problem, not valid
}
//Creating Data
return new seq_parameter_set_struct(
vui_parameters_Item,
pic_width_in_mbs_minus1,
pic_height_in_map_units_minus1,
frame_crop_left_offset,
frame_crop_right_offset,
frame_crop_top_offset,
frame_crop_bottom_offset,
(int8u)chroma_format_idc,
profile_idc,
level_idc,
(int8u)bit_depth_luma_minus8,
(int8u)bit_depth_chroma_minus8,
(int8u)log2_max_frame_num_minus4,
(int8u)pic_order_cnt_type,
(int8u)log2_max_pic_order_cnt_lsb_minus4,
(int8u)max_num_ref_frames,
constraint_set3_flag,
separate_colour_plane_flag,
delta_pic_order_always_zero_flag,
frame_mbs_only_flag,
mb_adaptive_frame_field_flag
);
FILLING_ELSE();
delete vui_parameters_Item; //vui_parameters_Item=NULL;
return NULL;
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Avc::scaling_list(int32u ScalingList_Size)
{
//From http://mpeg4ip.cvs.sourceforge.net/mpeg4ip/mpeg4ip/util/h264/main.cpp?revision=1.17&view=markup
int32u lastScale=8, nextScale=8;
for (int32u Pos=0; Pos<ScalingList_Size; Pos++)
{
if (nextScale!=0)
{
int32s delta_scale;
Get_SE (delta_scale, "scale_delta");
nextScale=(lastScale+delta_scale+256)%256;
}
if (nextScale)
lastScale=nextScale;
}
}
//---------------------------------------------------------------------------
void File_Avc::vui_parameters(seq_parameter_set_struct::vui_parameters_struct* &vui_parameters_Item_)
{
//Parsing
seq_parameter_set_struct::vui_parameters_struct::xxl *NAL=NULL, *VCL=NULL;
int32u num_units_in_tick=(int32u)-1, time_scale=(int32u)-1;
int16u sar_width=(int16u)-1, sar_height=(int16u)-1;
int8u aspect_ratio_idc=0, video_format=5, video_full_range_flag = 0, colour_primaries=2, transfer_characteristics=2, matrix_coefficients=2;
bool aspect_ratio_info_present_flag, video_signal_type_present_flag, colour_description_present_flag=false, timing_info_present_flag, fixed_frame_rate_flag=false, nal_hrd_parameters_present_flag, vcl_hrd_parameters_present_flag, pic_struct_present_flag;
TEST_SB_GET (aspect_ratio_info_present_flag, "aspect_ratio_info_present_flag");
Get_S1 (8, aspect_ratio_idc, "aspect_ratio_idc"); Param_Info1C((aspect_ratio_idc<Avc_PixelAspectRatio_Size), Avc_PixelAspectRatio[aspect_ratio_idc]);
if (aspect_ratio_idc==0xFF)
{
Get_S2 (16, sar_width, "sar_width");
Get_S2 (16, sar_height, "sar_height");
}
TEST_SB_END();
TEST_SB_SKIP( "overscan_info_present_flag");
Skip_SB( "overscan_appropriate_flag");
TEST_SB_END();
TEST_SB_GET (video_signal_type_present_flag, "video_signal_type_present_flag");
Get_S1 (3, video_format, "video_format"); Param_Info1(Avc_video_format[video_format]);
Get_S1 (1, video_full_range_flag, "video_full_range_flag"); Param_Info1(Avc_video_full_range[video_full_range_flag]);
TEST_SB_GET (colour_description_present_flag, "colour_description_present_flag");
Get_S1 (8, colour_primaries, "colour_primaries"); Param_Info1(Mpegv_colour_primaries(colour_primaries));
Get_S1 (8, transfer_characteristics, "transfer_characteristics"); Param_Info1(Mpegv_transfer_characteristics(transfer_characteristics));
Get_S1 (8, matrix_coefficients, "matrix_coefficients"); Param_Info1(Mpegv_matrix_coefficients(matrix_coefficients));
TEST_SB_END();
TEST_SB_END();
TEST_SB_SKIP( "chroma_loc_info_present_flag");
Skip_UE( "chroma_sample_loc_type_top_field");
Skip_UE( "chroma_sample_loc_type_bottom_field");
TEST_SB_END();
TEST_SB_GET (timing_info_present_flag, "timing_info_present_flag");
Get_S4 (32, num_units_in_tick, "num_units_in_tick");
Get_S4 (32, time_scale, "time_scale");
Get_SB ( fixed_frame_rate_flag, "fixed_frame_rate_flag");
TEST_SB_END();
TEST_SB_GET (nal_hrd_parameters_present_flag, "nal_hrd_parameters_present_flag");
hrd_parameters(NAL);
TEST_SB_END();
TEST_SB_GET (vcl_hrd_parameters_present_flag, "vcl_hrd_parameters_present_flag");
hrd_parameters(VCL);
TEST_SB_END();
if (nal_hrd_parameters_present_flag || vcl_hrd_parameters_present_flag)
Skip_SB( "low_delay_hrd_flag");
Get_SB ( pic_struct_present_flag, "pic_struct_present_flag");
TEST_SB_SKIP( "bitstream_restriction_flag");
int32u max_num_reorder_frames;
Skip_SB( "motion_vectors_over_pic_boundaries_flag");
Skip_UE( "max_bytes_per_pic_denom");
Skip_UE( "max_bits_per_mb_denom");
Skip_UE( "log2_max_mv_length_horizontal");
Skip_UE( "log2_max_mv_length_vertical");
Get_UE (max_num_reorder_frames, "max_num_reorder_frames");
Skip_UE( "max_dec_frame_buffering");
TEST_SB_END();
FILLING_BEGIN();
vui_parameters_Item_=new seq_parameter_set_struct::vui_parameters_struct(
NAL,
VCL,
num_units_in_tick,
time_scale,
sar_width,
sar_height,
aspect_ratio_idc,
video_format,
video_full_range_flag,
colour_primaries,
transfer_characteristics,
matrix_coefficients,
aspect_ratio_info_present_flag,
video_signal_type_present_flag,
colour_description_present_flag,
timing_info_present_flag,
fixed_frame_rate_flag,
pic_struct_present_flag
);
FILLING_ELSE();
delete NAL; NAL=NULL;
delete VCL; VCL=NULL;
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Avc::hrd_parameters(seq_parameter_set_struct::vui_parameters_struct::xxl* &hrd_parameters_Item_)
{
//Parsing
int32u cpb_cnt_minus1;
int8u bit_rate_scale, cpb_size_scale, initial_cpb_removal_delay_length_minus1, cpb_removal_delay_length_minus1, dpb_output_delay_length_minus1, time_offset_length;
Get_UE ( cpb_cnt_minus1, "cpb_cnt_minus1");
Get_S1 (4, bit_rate_scale, "bit_rate_scale");
Get_S1 (4, cpb_size_scale, "cpb_size_scale");
if (cpb_cnt_minus1>31)
{
Trusted_IsNot("cpb_cnt_minus1 too high");
cpb_cnt_minus1=0;
}
vector<seq_parameter_set_struct::vui_parameters_struct::xxl::xxl_data> SchedSel;
SchedSel.reserve(cpb_cnt_minus1+1);
for (int8u SchedSelIdx = 0; SchedSelIdx <= cpb_cnt_minus1; ++SchedSelIdx)
{
Element_Begin1("ShedSel");
int64u bit_rate_value, cpb_size_value;
int32u bit_rate_value_minus1, cpb_size_value_minus1;
bool cbr_flag;
Get_UE (bit_rate_value_minus1, "bit_rate_value_minus1");
bit_rate_value=(int64u)((bit_rate_value_minus1+1)*pow(2.0, 6+bit_rate_scale)); Param_Info2(bit_rate_value, " bps");
Get_UE (cpb_size_value_minus1, "cpb_size_value_minus1");
cpb_size_value=(int64u)((cpb_size_value_minus1+1)*pow(2.0, 4+cpb_size_scale)); Param_Info2(cpb_size_value, " bits");
Get_SB (cbr_flag, "cbr_flag");
Element_End0();
FILLING_BEGIN();
SchedSel.push_back(seq_parameter_set_struct::vui_parameters_struct::xxl::xxl_data(
bit_rate_value,
cpb_size_value,
cbr_flag
));
FILLING_END();
}
Get_S1 (5, initial_cpb_removal_delay_length_minus1, "initial_cpb_removal_delay_length_minus1");
Get_S1 (5, cpb_removal_delay_length_minus1, "cpb_removal_delay_length_minus1");
Get_S1 (5, dpb_output_delay_length_minus1, "dpb_output_delay_length_minus1");
Get_S1 (5, time_offset_length, "time_offset_length");
//Validity test
if (!Element_IsOK() || (SchedSel.size() == 1 && SchedSel[0].bit_rate_value == 64))
{
return; //We do not trust this kind of data
}
//Filling
hrd_parameters_Item_=new seq_parameter_set_struct::vui_parameters_struct::xxl(
SchedSel,
initial_cpb_removal_delay_length_minus1,
cpb_removal_delay_length_minus1,
dpb_output_delay_length_minus1,
time_offset_length
);
}
//---------------------------------------------------------------------------
void File_Avc::nal_unit_header_svc_extension()
{
//Parsing
Element_Begin1("nal_unit_header_svc_extension");
Skip_SB( "idr_flag");
Skip_S1( 6, "priority_id");
Skip_SB( "no_inter_layer_pred_flag");
Skip_S1( 3, "dependency_id");
Skip_S1( 4, "quality_id");
Skip_S1( 3, "temporal_id");
Skip_SB( "use_ref_base_pic_flag");
Skip_SB( "discardable_flag");
Skip_SB( "output_flag");
Skip_S1( 2, "reserved_three_2bits");
Element_End0();
}
//---------------------------------------------------------------------------
void File_Avc::nal_unit_header_mvc_extension()
{
//Parsing
Element_Begin1("nal_unit_header_mvc_extension");
Skip_SB( "non_idr_flag");
Skip_S1( 6, "priority_id");
Skip_S1(10, "view_id");
Skip_S1( 3, "temporal_id");
Skip_SB( "anchor_pic_flag");
Skip_SB( "inter_view_flag");
Skip_SB( "reserved_one_bit");
Element_End0();
}
//---------------------------------------------------------------------------
void File_Avc::seq_parameter_set_svc_extension()
{
//Parsing
Element_Begin1("seq_parameter_set_svc_extension");
//Skip_SB( "");
Element_End0();
}
//---------------------------------------------------------------------------
void File_Avc::svc_vui_parameters_extension()
{
//Parsing
Element_Begin1("svc_vui_parameters_extension");
//Skip_SB( "");
Element_End0();
}
//---------------------------------------------------------------------------
void File_Avc::seq_parameter_set_mvc_extension(seq_parameter_set_struct* Data_Item)
{
//Parsing
Element_Begin1("seq_parameter_set_mvc_extension");
int32u num_views_minus1;
Get_UE (num_views_minus1, "num_views_minus1");
//(Not implemented)
Element_End0();
FILLING_BEGIN();
Data_Item->num_views_minus1 = (int16u)num_views_minus1;
FILLING_END();
}
//---------------------------------------------------------------------------
void File_Avc::mvc_vui_parameters_extension()
{
//Parsing
Element_Begin1("mvc_vui_parameters_extension");
Skip_SB( "");
Element_End0();
}
//***************************************************************************
// Specific
//***************************************************************************
//---------------------------------------------------------------------------
void File_Avc::SPS_PPS()
{
//Parsing
int8u Profile, Level, seq_parameter_set_count, pic_parameter_set_count;
if (SizedBlocks)
Skip_B1( "configurationVersion");
Get_B1 (Profile, "AVCProfileIndication");
Skip_B1( "profile_compatibility");
Get_B1 (Level, "AVCLevelIndication");
BS_Begin();
Skip_S1(6, "reserved");
Get_S1 (2, SizeOfNALU_Minus1, "lengthSizeMinusOne");
Skip_S1(3, "reserved");
Get_S1 (5, seq_parameter_set_count, "numOfSequenceParameterSets");
BS_End();
for (int8u Pos=0; Pos<seq_parameter_set_count; Pos++)
{
Element_Begin1("seq_parameter_set");
int16u Size;
Get_B2 (Size, "sequenceParameterSetLength");
BS_Begin();
Mark_0 ();
Skip_S1( 2, "nal_ref_idc");
Skip_S1( 5, "nal_unit_type");
BS_End();
if (Element_Offset+Size-1>Element_Size)
{
Trusted_IsNot("Size is wrong");
break; //There is an error
}
int64u Element_Offset_Save=Element_Offset;
int64u Element_Size_Save=Element_Size;
Buffer_Offset+=(size_t)Element_Offset_Save;
Element_Offset=0;
Element_Size=Size-(Size?1:0);
Element_Code=0x07; //seq_parameter_set
Data_Parse();
Buffer_Offset-=(size_t)Element_Offset_Save;
Element_Offset=Element_Offset_Save+Size-1;
Element_Size=Element_Size_Save;
Element_End0();
}
Get_B1 (pic_parameter_set_count, "numOfPictureParameterSets");
for (int8u Pos=0; Pos<pic_parameter_set_count; Pos++)
{
Element_Begin1("pic_parameter_set");
int16u Size;
Get_B2 (Size, "pictureParameterSetLength");
BS_Begin();
Mark_0 ();
Skip_S1( 2, "nal_ref_idc");
Skip_S1( 5, "nal_unit_type");
BS_End();
int64u Element_Offset_Save=Element_Offset;
int64u Element_Size_Save=Element_Size;
Buffer_Offset+=(size_t)Element_Offset_Save;
Element_Offset=0;
Element_Size=Size-1;
if (Element_Size>Element_Size_Save-Element_Offset_Save)
break; //There is an error
Element_Code=0x08; //pic_parameter_set
Data_Parse();
Buffer_Offset-=(size_t)Element_Offset_Save;
Element_Offset=Element_Offset_Save+Size-1;
Element_Size=Element_Size_Save;
Element_End0();
}
if (Element_Offset<Element_Size)
{
switch (Profile)
{
case 100:
case 110:
case 122:
case 144:
{
int8u numOfSequenceParameterSetExt;
BS_Begin();
Skip_S1( 6, "reserved");
Skip_S1( 2, "chroma_format");
Skip_S1( 5, "reserved");
Skip_S1( 3, "bit_depth_luma_minus8");
Skip_S1( 5, "reserved");
Skip_S1( 3, "bit_depth_chroma_minus8");
BS_End();
Get_B1 (numOfSequenceParameterSetExt, "numOfSequenceParameterSetExt");
for (int8u Pos=0; Pos<numOfSequenceParameterSetExt; Pos++)
{
Element_Begin1("sequenceParameterSetExtNALUnit");
int16u Size;
Get_B2 (Size, "sequenceParameterSetExtLength");
BS_Begin();
Mark_0 ();
Skip_S1( 2, "nal_ref_idc");
Skip_S1( 5, "nal_unit_type");
BS_End();
int64u Element_Offset_Save=Element_Offset;
int64u Element_Size_Save=Element_Size;
Buffer_Offset+=(size_t)Element_Offset_Save;
Element_Offset=0;
Element_Size=Size-1;
if (Element_Size>Element_Size_Save-Element_Offset_Save)
break; //There is an error
Element_Code=0x0F; //subset_seq_parameter_set
Data_Parse();
Buffer_Offset-=(size_t)Element_Offset_Save;
Element_Offset=Element_Offset_Save+Size-1;
Element_Size=Element_Size_Save;
Element_End0();
}
}
default:;
}
}
if (Element_Offset<Element_Size)
Skip_XX(Element_Size-Element_Offset, "Padding?");
//Filling
FILLING_BEGIN_PRECISE();
//Detection of some bugs in the file
if (!seq_parameter_sets.empty() && seq_parameter_sets[0] && (Profile!=seq_parameter_sets[0]->profile_idc || Level!=seq_parameter_sets[0]->level_idc))
MuxingMode=Ztring("Container profile=")+Ztring().From_UTF8(Avc_profile_idc(Profile))+__T("@")+Ztring().From_Number(((float)Level)/10, 1);
MustParse_SPS_PPS=false;
if (!Status[IsAccepted])
Accept("AVC");
FILLING_END();
}
//***************************************************************************
// Helpers
//***************************************************************************
//---------------------------------------------------------------------------
std::string File_Avc::GOP_Detect (std::string PictureTypes)
{
//Finding a string without blanks
size_t PictureTypes_Limit=PictureTypes.find(' ');
if (PictureTypes_Limit!=string::npos)
{
if (PictureTypes_Limit>PictureTypes.size()/2)
PictureTypes.resize(PictureTypes_Limit);
else
{
//Trim
size_t TrimPos;
TrimPos=PictureTypes.find_first_not_of(' ');
if (TrimPos!=string::npos)
PictureTypes.erase(0, TrimPos);
TrimPos=PictureTypes.find_last_not_of(' ');
if (TrimPos!=string::npos)
PictureTypes.erase(TrimPos+1);
//Finding the longest string
ZtringList List; List.Separator_Set(0, __T(" "));
List.Write(Ztring().From_UTF8(PictureTypes));
size_t MaxLength=0;
size_t MaxLength_Pos=0;
for (size_t Pos=0; Pos<List.size(); Pos++)
if (List[Pos].size()>MaxLength)
{
MaxLength=List[Pos].size();
MaxLength_Pos=Pos;
}
PictureTypes=List[MaxLength_Pos].To_UTF8();
}
}
//Creating all GOP values
std::vector<Ztring> GOPs;
size_t GOP_Frame_Count=0;
size_t GOP_BFrames_Max=0;
size_t I_Pos1=PictureTypes.find('I');
while (I_Pos1!=std::string::npos)
{
size_t I_Pos2=PictureTypes.find('I', I_Pos1+1);
if (I_Pos2!=std::string::npos)
{
std::vector<size_t> P_Positions;
size_t P_Position=I_Pos1;
do
{
P_Position=PictureTypes.find('P', P_Position+1);
if (P_Position<I_Pos2)
P_Positions.push_back(P_Position);
}
while (P_Position<I_Pos2);
if (P_Positions.size()>1 && P_Positions[0]>I_Pos1+1 && P_Positions[P_Positions.size()-1]==I_Pos2-1)
P_Positions.resize(P_Positions.size()-1); //Removing last P-Frame for next test, this is often a terminating P-Frame replacing a B-Frame
Ztring GOP;
bool IsOK=true;
if (!P_Positions.empty())
{
size_t Delta=P_Positions[0]-I_Pos1;
for (size_t Pos=1; Pos<P_Positions.size(); Pos++)
if (P_Positions[Pos]-P_Positions[Pos-1]!=Delta)
{
IsOK=false;
break;
}
if (IsOK)
{
GOP+=__T("M=")+Ztring::ToZtring(P_Positions[0]-I_Pos1)+__T(", ");
if (P_Positions[0]-I_Pos1>GOP_BFrames_Max)
GOP_BFrames_Max=P_Positions[0]-I_Pos1;
}
}
if (IsOK)
{
GOP+=__T("N=")+Ztring::ToZtring(I_Pos2-I_Pos1);
GOPs.push_back(GOP);
}
else
GOPs.push_back(Ztring()); //There is a problem, blank
GOP_Frame_Count+=I_Pos2-I_Pos1;
}
I_Pos1=I_Pos2;
}
//Some clean up
if (GOP_Frame_Count+GOP_BFrames_Max>Frame_Count && !GOPs.empty())
GOPs.resize(GOPs.size()-1); //Removing the last one, there may have uncomplete B-frame filling
if (GOPs.size()>4)
GOPs.erase(GOPs.begin()); //Removing the first one, it is sometime different and we have enough to deal with
//Filling
if (GOPs.size()>=4)
{
bool IsOK=true;
for (size_t Pos=1; Pos<GOPs.size(); Pos++)
if (GOPs[Pos]!=GOPs[0])
{
IsOK=false;
break;
}
if (IsOK)
return GOPs[0].To_UTF8();
}
return string();
}
//---------------------------------------------------------------------------
std::string File_Avc::ScanOrder_Detect (std::string ScanOrders)
{
//Finding a string without blanks
size_t ScanOrders_Limit=ScanOrders.find(' ');
if (ScanOrders_Limit!=string::npos)
{
if (ScanOrders_Limit>ScanOrders.size()/2)
ScanOrders.resize(ScanOrders_Limit);
else
{
//Trim
size_t TrimPos;
TrimPos=ScanOrders.find_first_not_of(' ');
if (TrimPos!=string::npos)
ScanOrders.erase(0, TrimPos);
TrimPos=ScanOrders.find_last_not_of(' ');
if (TrimPos!=string::npos)
ScanOrders.erase(TrimPos+1);
//Finding the longest string
ZtringList List; List.Separator_Set(0, __T(" "));
List.Write(Ztring().From_UTF8(ScanOrders));
size_t MaxLength=0;
size_t MaxLength_Pos=0;
for (size_t Pos=0; Pos<List.size(); Pos++)
if (List[Pos].size()>MaxLength)
{
MaxLength=List[Pos].size();
MaxLength_Pos=Pos;
}
ScanOrders=List[MaxLength_Pos].To_UTF8();
}
}
//Filling
if (ScanOrders.find("TBTBTBTB")==0)
return ("TFF");
if (ScanOrders.find("BTBTBTBT")==0)
return ("BFF");
return string();
}
} //NameSpace
#endif //MEDIAINFO_AVC_YES
↑ V1020 The function exited without calling the 'BS_End' function. Check lines: 2820, 2798.
↑ V1020 The function exited without calling the 'BS_End' function. Check lines: 3666, 3656.
↑ V1020 The function exited without calling the 'BS_End' function. Check lines: 3707, 3656.
↑ V1020 The function exited without calling the 'Element_End' function. Check lines: 4474, 4365.
↑ V1020 The function exited without calling the 'Element_End' function. Check lines: 4474, 4393.
↑ V1020 The function exited without calling the 'Element_End' function. Check lines: 4474, 4436.
↑ V1037 Two or more case-branches perform the same actions. Check lines: 3142, 3144
↑ V796 It is possible that 'break' statement is missing in switch statement.
↑ V1037 Two or more case-branches perform the same actions. Check lines: 274, 275
↑ V1037 Two or more case-branches perform the same actions. Check lines: 413, 414
↑ V1037 Two or more case-branches perform the same actions. Check lines: 580, 582
↑ V1037 Two or more case-branches perform the same actions. Check lines: 581, 583
↑ V1037 Two or more case-branches perform the same actions. Check lines: 618, 620
↑ V1037 Two or more case-branches perform the same actions. Check lines: 619, 621
↑ V524 It is odd that the body of 'svc_vui_parameters_extension' function is fully equivalent to the body of 'seq_parameter_set_svc_extension' function.
↑ V525 The code contains the collection of similar blocks. Check items '6', '6', '5' in lines 2842, 2843, 2844.
↑ V525 The code contains the collection of similar blocks. Check items 'sei_message_user_data_unregistered_x264', 'sei_message_user_data_unregistered_x264', 'sei_message_user_data_unregistered_bluray' in lines 3143, 3145, 3147.
↑ V525 The code contains the collection of similar blocks. Check items '3', '4', '3' in lines 4276, 4277, 4278.
↑ V525 The code contains the collection of similar blocks. Check items '6', '2', '5', '3', '5', '3' in lines 4426, 4427, 4428, 4429, 4430, 4431.
↑ V550 An odd precise comparison. It's probably better to use a comparison with defined precision: fabs(A - B) < Epsilon.
↑ V688 The 'MuxingMode' 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: maximum_content_light_level, maximum_frame_average_light_level, TemporalReferences_Min, TemporalReferences_Max, TemporalReferences_Reserved, TemporalReferences_Offset, ...
↑ V793 It is odd that the result of the 'Element_Size - Element_Offset' statement is a part of the condition. Perhaps, this statement should have been compared with something else.
↑ V793 It is odd that the result of the 'Element_Size - Element_Offset' statement is a part of the condition. Perhaps, this statement should have been compared with something else.
↑ V793 It is odd that the result of the 'Element_Size - Element_Offset' statement is a part of the condition. Perhaps, this statement should have been compared with something else.
↑ V793 It is odd that the result of the 'Element_Size - Element_Offset' statement is a part of the condition. Perhaps, this statement should have been compared with something else.
↑ V823 Decreased performance. Object may be created in-place in the 'SchedSel' container. Consider replacing methods: 'push_back' -> 'emplace_back'.
↑ V823 Decreased performance. Object may be created in-place in the 'GOPs' container. Consider replacing methods: 'push_back' -> 'emplace_back'.
↑ V826 Consider replacing the 'GOPs' std::vector with std::deque. Overall efficiency of operations will increase.
↑ V807 Decreased performance. Consider creating a reference to avoid using the 'NAL->SchedSel[Pos]' expression repeatedly.
↑ V807 Decreased performance. Consider creating a reference to avoid using the 'VCL->SchedSel[Pos]' expression repeatedly.