/***************************************************************** | | AP4 - hvcC Atoms | | Copyright 2002-2016 Axiomatic Systems, LLC | | | This file is part of Bento4/AP4 (MP4 Atom Processing Library). | | Unless you have obtained Bento4 under a difference license, | this version of Bento4 is Bento4|GPL. | Bento4|GPL is free software; you can redistribute it and/or modify | it under the terms of the GNU General Public License as published by | the Free Software Foundation; either version 2, or (at your option) | any later version. | | Bento4|GPL is distributed in the hope that it will be useful, | but WITHOUT ANY WARRANTY; without even the implied warranty of | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | GNU General Public License for more details. | | You should have received a copy of the GNU General Public License | along with Bento4|GPL; see the file COPYING. If not, write to the | Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA | 02111-1307, USA. | ****************************************************************/ /*---------------------------------------------------------------------- | includes +---------------------------------------------------------------------*/ #include "Ap4HvccAtom.h" #include "Ap4AtomFactory.h" #include "Ap4Utils.h" #include "Ap4Types.h" #include "Ap4HevcParser.h" /*---------------------------------------------------------------------- | dynamic cast support +---------------------------------------------------------------------*/ AP4_DEFINE_DYNAMIC_CAST_ANCHOR(AP4_HvccAtom) /*---------------------------------------------------------------------- | AP4_HvccAtom::GetProfileName +---------------------------------------------------------------------*/ const char* AP4_HvccAtom::GetProfileName(AP4_UI08 profile_space, AP4_UI08 profile) { if (profile_space != 0) { return NULL; } switch (profile) { case AP4_HEVC_PROFILE_MAIN: return "Main"; case AP4_HEVC_PROFILE_MAIN_10: return "Main 10"; case AP4_HEVC_PROFILE_MAIN_STILL_PICTURE: return "Main Still Picture"; case AP4_HEVC_PROFILE_REXT: return "Rext"; } return NULL; } /*---------------------------------------------------------------------- | AP4_HvccAtom::GetChromaFormatName +---------------------------------------------------------------------*/ const char* AP4_HvccAtom::GetChromaFormatName(AP4_UI08 chroma_format) { switch (chroma_format) { case AP4_HEVC_CHROMA_FORMAT_MONOCHROME: return "Monochrome"; case AP4_HEVC_CHROMA_FORMAT_420: return "4:2:0"; case AP4_HEVC_CHROMA_FORMAT_422: return "4:2:2"; case AP4_HEVC_CHROMA_FORMAT_444: return "4:4:4"; } return NULL; } /*---------------------------------------------------------------------- | AP4_HvccAtom::Create +---------------------------------------------------------------------*/ AP4_HvccAtom* AP4_HvccAtom::Create(AP4_Size size, AP4_ByteStream& stream) { // read the raw bytes in a buffer unsigned int payload_size = size-AP4_ATOM_HEADER_SIZE; AP4_DataBuffer payload_data(payload_size); AP4_Result result = stream.Read(payload_data.UseData(), payload_size); if (AP4_FAILED(result)) return NULL; return new AP4_HvccAtom(size, payload_data.GetData()); } /*---------------------------------------------------------------------- | AP4_HvccAtom::AP4_HvccAtom +---------------------------------------------------------------------*/ AP4_HvccAtom::AP4_HvccAtom() : AP4_Atom(AP4_ATOM_TYPE_HVCC, AP4_ATOM_HEADER_SIZE), m_ConfigurationVersion(1), m_GeneralProfileSpace(0), m_GeneralTierFlag(0), m_GeneralProfile(0), m_GeneralProfileCompatibilityFlags(0), m_GeneralConstraintIndicatorFlags(0), m_GeneralLevel(0), m_Reserved1(0), m_MinSpatialSegmentation(0), m_Reserved2(0), m_ParallelismType(0), m_Reserved3(0), m_ChromaFormat(0), m_Reserved4(0), m_LumaBitDepth(8), m_Reserved5(0), m_ChromaBitDepth(8), m_AverageFrameRate(0), m_ConstantFrameRate(0), m_NumTemporalLayers(0), m_TemporalIdNested(0), m_NaluLengthSize(4) { UpdateRawBytes(); m_Size32 += m_RawBytes.GetDataSize(); } /*---------------------------------------------------------------------- | AP4_HvccAtom::AP4_HvccAtom +---------------------------------------------------------------------*/ AP4_HvccAtom::AP4_HvccAtom(const AP4_HvccAtom& other) : AP4_Atom(AP4_ATOM_TYPE_HVCC, other.m_Size32), m_ConfigurationVersion(other.m_ConfigurationVersion), m_GeneralProfileSpace(other.m_GeneralProfileSpace), m_GeneralTierFlag(other.m_GeneralTierFlag), m_GeneralProfile(other.m_GeneralProfile), m_GeneralProfileCompatibilityFlags(other.m_GeneralProfileCompatibilityFlags), m_GeneralConstraintIndicatorFlags(other.m_GeneralConstraintIndicatorFlags), m_GeneralLevel(other.m_GeneralLevel), m_Reserved1(other.m_Reserved1), m_MinSpatialSegmentation(other.m_MinSpatialSegmentation), m_Reserved2(other.m_Reserved2), m_ParallelismType(other.m_ParallelismType), m_Reserved3(other.m_Reserved3), m_ChromaFormat(other.m_ChromaFormat), m_Reserved4(other.m_Reserved4), m_LumaBitDepth(other.m_LumaBitDepth), m_Reserved5(other.m_Reserved5), m_ChromaBitDepth(other.m_ChromaBitDepth), m_AverageFrameRate(other.m_AverageFrameRate), m_ConstantFrameRate(other.m_ConstantFrameRate), m_NumTemporalLayers(other.m_NumTemporalLayers), m_TemporalIdNested(other.m_TemporalIdNested), m_NaluLengthSize(other.m_NaluLengthSize), m_RawBytes(other.m_RawBytes) { // deep copy of the parameters unsigned int i = 0; for (i=0; i& video_parameters, AP4_UI08 video_parameters_completeness, const AP4_Array& sequence_parameters, AP4_UI08 sequence_parameters_completeness, const AP4_Array& picture_parameters, AP4_UI08 picture_parameters_completeness) : AP4_Atom(AP4_ATOM_TYPE_HVCC, AP4_ATOM_HEADER_SIZE), m_ConfigurationVersion(1), m_GeneralProfileSpace(general_profile_space), m_GeneralTierFlag(general_tier_flag), m_GeneralProfile(general_profile), m_GeneralProfileCompatibilityFlags(general_profile_compatibility_flags), m_GeneralConstraintIndicatorFlags(general_constraint_indicator_flags), m_GeneralLevel(general_level), m_Reserved1(0), m_MinSpatialSegmentation(min_spatial_segmentation), m_Reserved2(0), m_ParallelismType(parallelism_type), m_Reserved3(0), m_ChromaFormat(chroma_format), m_Reserved4(0), m_LumaBitDepth(luma_bit_depth), m_Reserved5(0), m_ChromaBitDepth(chroma_bit_depth), m_AverageFrameRate(average_frame_rate), m_ConstantFrameRate(constant_frame_rate), m_NumTemporalLayers(num_temporal_layers), m_TemporalIdNested(temporal_id_nested), m_NaluLengthSize(nalu_length_size) { // deep copy of the parameters AP4_HvccAtom::Sequence vps_sequence; vps_sequence.m_NaluType = AP4_HEVC_NALU_TYPE_VPS_NUT; vps_sequence.m_ArrayCompleteness = video_parameters_completeness; for (unsigned int i=0; i>6) & 0x03; m_GeneralTierFlag = (payload[1]>>5) & 0x01; m_GeneralProfile = (payload[1] ) & 0x1F; m_GeneralProfileCompatibilityFlags = AP4_BytesToUInt32BE(&payload[2]); m_GeneralConstraintIndicatorFlags = (((AP4_UI64)AP4_BytesToUInt32BE(&payload[6]))<<16) | AP4_BytesToUInt16BE(&payload[10]); m_GeneralLevel = payload[12]; m_Reserved1 = (payload[13]>>4) & 0x0F; m_MinSpatialSegmentation = AP4_BytesToUInt16BE(&payload[13]) & 0x0FFF; m_Reserved2 = (payload[15]>>2) & 0x3F; m_ParallelismType = payload[15] & 0x03; m_Reserved3 = (payload[16]>>2) & 0x3F; m_ChromaFormat = payload[16] & 0x03; m_Reserved4 = (payload[17]>>3) & 0x1F; m_LumaBitDepth = 8+(payload[17] & 0x07); m_Reserved5 = (payload[18]>>3) & 0x1F; m_ChromaBitDepth = 8+(payload[18] & 0x07); m_AverageFrameRate = AP4_BytesToUInt16BE(&payload[19]); m_ConstantFrameRate = (payload[21]>>6) & 0x03; m_NumTemporalLayers = (payload[21]>>3) & 0x07; m_TemporalIdNested = (payload[21]>>2) & 0x01; m_NaluLengthSize = 1+(payload[21] & 0x03); AP4_UI08 num_seq = payload[22]; m_Sequences.SetItemCount(num_seq); unsigned int cursor = 23; for (unsigned int i=0; i payload_size) break; seq.m_ArrayCompleteness = (payload[cursor] >> 7) & 0x01; seq.m_Reserved = (payload[cursor] >> 6) & 0x01; seq.m_NaluType = payload[cursor] & 0x3F; cursor += 1; if (cursor+2 > payload_size) break; AP4_UI16 nalu_count = AP4_BytesToUInt16BE(&payload[cursor]); seq.m_Nalus.SetItemCount(nalu_count); cursor += 2; for (unsigned int j=0; j payload_size) break; unsigned int nalu_length = AP4_BytesToUInt16BE(&payload[cursor]); cursor += 2; if (cursor + nalu_length > payload_size) break; seq.m_Nalus[j].SetData(&payload[cursor], nalu_length); cursor += nalu_length; } } } /*---------------------------------------------------------------------- | AP4_HvccAtom::UpdateRawBytes +---------------------------------------------------------------------*/ void AP4_HvccAtom::UpdateRawBytes() { AP4_BitWriter bits(23); bits.Write(m_ConfigurationVersion, 8); bits.Write(m_GeneralProfileSpace, 2); bits.Write(m_GeneralTierFlag, 1); bits.Write(m_GeneralProfile, 5); bits.Write(m_GeneralProfileCompatibilityFlags, 32); bits.Write((AP4_UI32)(m_GeneralConstraintIndicatorFlags>>32), 16); bits.Write((AP4_UI32)(m_GeneralConstraintIndicatorFlags), 32); bits.Write(m_GeneralLevel, 8); bits.Write(0xFF, 4); bits.Write(m_MinSpatialSegmentation, 12); bits.Write(0xFF, 6); bits.Write(m_ParallelismType, 2); bits.Write(0xFF, 6); bits.Write(m_ChromaFormat, 2); bits.Write(0xFF, 5); bits.Write(m_LumaBitDepth >= 8 ? m_LumaBitDepth - 8 : 0, 3); bits.Write(0xFF, 5); bits.Write(m_ChromaBitDepth >= 8 ? m_ChromaBitDepth - 8 : 0, 3); bits.Write(m_AverageFrameRate, 16); bits.Write(m_ConstantFrameRate, 2); bits.Write(m_NumTemporalLayers, 3); bits.Write(m_TemporalIdNested, 1); bits.Write(m_NaluLengthSize > 0 ? m_NaluLengthSize - 1 : 0, 2); bits.Write(m_Sequences.ItemCount(), 8); m_RawBytes.SetData(bits.GetData(), 23); for (unsigned int i=0; i