/* * The contents of this file are subject to the Mozilla Public * License Version 1.1 (the "License"); you may not use this file * except in compliance with the License. You may obtain a copy of * the License at http://www.mozilla.org/MPL/ * * Software distributed under the License is distributed on an "AS * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or * implied. See the License for the specific language governing * rights and limitations under the License. * * The Original Code is MPEG4IP. * * The Initial Developer of the Original Code is Cisco Systems Inc. * Portions created by Cisco Systems Inc. are * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. * * Contributor(s): * Dave Mackie dmackie@cisco.com */ #ifndef MP4V2_IMPL_MP4PROPERTY_H #define MP4V2_IMPL_MP4PROPERTY_H namespace mp4v2 { namespace impl { /////////////////////////////////////////////////////////////////////////////// // forward declarations class MP4Atom; class MP4Descriptor; MP4ARRAY_DECL(MP4Descriptor, MP4Descriptor*); enum MP4PropertyType { Integer8Property, Integer16Property, Integer24Property, Integer32Property, Integer64Property, Float32Property, StringProperty, BytesProperty, TableProperty, DescriptorProperty, LanguageCodeProperty, BasicTypeProperty, }; class MP4Property { public: MP4Property(MP4Atom& parentAtom, const char *name = NULL); virtual ~MP4Property() { } MP4Atom& GetParentAtom() { return m_parentAtom; } const char *GetName() { return m_name; } virtual MP4PropertyType GetType() = 0; bool IsReadOnly() { return m_readOnly; } void SetReadOnly(bool value = true) { m_readOnly = value; } bool IsImplicit() { return m_implicit; } void SetImplicit(bool value = true) { m_implicit = value; } virtual uint32_t GetCount() = 0; virtual void SetCount(uint32_t count) = 0; virtual void Generate() { /* default is a no-op */ }; virtual void Read(MP4File& file, uint32_t index = 0) = 0; virtual void Write(MP4File& file, uint32_t index = 0) = 0; virtual void Dump(uint8_t indent, bool dumpImplicits, uint32_t index = 0) = 0; virtual bool FindProperty(const char* name, MP4Property** ppProperty, uint32_t* pIndex = NULL); protected: MP4Atom& m_parentAtom; const char* m_name; bool m_readOnly; bool m_implicit; private: MP4Property(); MP4Property ( const MP4Property &src ); MP4Property &operator= ( const MP4Property &src ); }; MP4ARRAY_DECL(MP4Property, MP4Property*); class MP4IntegerProperty : public MP4Property { protected: MP4IntegerProperty(MP4Atom& parentAtom, const char* name) : MP4Property(parentAtom, name) { }; public: uint64_t GetValue(uint32_t index = 0); void SetValue(uint64_t value, uint32_t index = 0); void InsertValue(uint64_t value, uint32_t index = 0); void DeleteValue(uint32_t index = 0); void IncrementValue(int32_t increment = 1, uint32_t index = 0); private: MP4IntegerProperty(); MP4IntegerProperty ( const MP4IntegerProperty &src ); MP4IntegerProperty &operator= ( const MP4IntegerProperty &src ); }; #define MP4INTEGER_PROPERTY_DECL2(isize, xsize) \ class MP4Integer##xsize##Property : public MP4IntegerProperty { \ public: \ MP4Integer##xsize##Property(MP4Atom& parentAtom, const char* name) \ : MP4IntegerProperty(parentAtom, name) { \ SetCount(1); \ m_values[0] = 0; \ } \ \ MP4PropertyType GetType() { \ return Integer##xsize##Property; \ } \ \ uint32_t GetCount() { \ return m_values.Size(); \ } \ void SetCount(uint32_t count) { \ m_values.Resize(count); \ } \ \ uint##isize##_t GetValue(uint32_t index = 0) { \ return m_values[index]; \ } \ \ void SetValue(uint##isize##_t value, uint32_t index = 0) { \ if (m_readOnly) { \ ostringstream msg; \ msg << "property is read-only: " << m_name; \ throw new PlatformException(msg.str().c_str(), EACCES, __FILE__, __LINE__, __FUNCTION__); \ } \ m_values[index] = value; \ } \ void AddValue(uint##isize##_t value) { \ m_values.Add(value); \ } \ void InsertValue(uint##isize##_t value, uint32_t index) { \ m_values.Insert(value, index); \ } \ void DeleteValue(uint32_t index) { \ m_values.Delete(index); \ } \ void IncrementValue(int32_t increment = 1, uint32_t index = 0) { \ m_values[index] += increment; \ } \ void Read(MP4File& file, uint32_t index = 0) { \ if (m_implicit) { \ return; \ } \ m_values[index] = file.ReadUInt##xsize(); \ } \ \ void Write(MP4File& file, uint32_t index = 0) { \ if (m_implicit) { \ return; \ } \ file.WriteUInt##xsize(m_values[index]); \ } \ void Dump(uint8_t indent, \ bool dumpImplicits, uint32_t index = 0); \ \ protected: \ MP4Integer##isize##Array m_values; \ private: \ MP4Integer##xsize##Property(); \ MP4Integer##xsize##Property ( const MP4Integer##xsize##Property &src ); \ MP4Integer##xsize##Property &operator= ( const MP4Integer##xsize##Property &src ); \ }; #define MP4INTEGER_PROPERTY_DECL(size) \ MP4INTEGER_PROPERTY_DECL2(size, size) MP4INTEGER_PROPERTY_DECL(8); MP4INTEGER_PROPERTY_DECL(16); MP4INTEGER_PROPERTY_DECL2(32, 24); MP4INTEGER_PROPERTY_DECL(32); MP4INTEGER_PROPERTY_DECL(64); class MP4BitfieldProperty : public MP4Integer64Property { public: MP4BitfieldProperty(MP4Atom& parentAtom, const char* name, uint8_t numBits) : MP4Integer64Property(parentAtom, name) { ASSERT(numBits != 0); ASSERT(numBits <= 64); m_numBits = numBits; } uint8_t GetNumBits() { return m_numBits; } void SetNumBits(uint8_t numBits) { m_numBits = numBits; } void Read(MP4File& file, uint32_t index = 0); void Write(MP4File& file, uint32_t index = 0); void Dump(uint8_t indent, bool dumpImplicits, uint32_t index = 0); protected: uint8_t m_numBits; private: MP4BitfieldProperty(); MP4BitfieldProperty ( const MP4BitfieldProperty &src ); MP4BitfieldProperty &operator= ( const MP4BitfieldProperty &src ); }; class MP4Float32Property : public MP4Property { public: MP4Float32Property(MP4Atom& parentAtom, const char* name) : MP4Property(parentAtom, name) { m_useFixed16Format = false; m_useFixed32Format = false; SetCount(1); m_values[0] = 0.0; } MP4PropertyType GetType() { return Float32Property; } uint32_t GetCount() { return m_values.Size(); } void SetCount(uint32_t count) { m_values.Resize(count); } float GetValue(uint32_t index = 0) { return m_values[index]; } void SetValue(float value, uint32_t index = 0) { if (m_readOnly) { ostringstream msg; msg << "property is read-only: " << m_name; throw new PlatformException(msg.str().c_str(), EACCES, __FILE__, __LINE__, __FUNCTION__); } m_values[index] = value; } void AddValue(float value) { m_values.Add(value); } void InsertValue(float value, uint32_t index) { m_values.Insert(value, index); } bool IsFixed16Format() { return m_useFixed16Format; } void SetFixed16Format(bool useFixed16Format = true) { m_useFixed16Format = useFixed16Format; } bool IsFixed32Format() { return m_useFixed32Format; } void SetFixed32Format(bool useFixed32Format = true) { m_useFixed32Format = useFixed32Format; } void Read(MP4File& file, uint32_t index = 0); void Write(MP4File& file, uint32_t index = 0); void Dump(uint8_t indent, bool dumpImplicits, uint32_t index = 0); protected: bool m_useFixed16Format; bool m_useFixed32Format; MP4Float32Array m_values; private: MP4Float32Property(); MP4Float32Property ( const MP4Float32Property &src ); MP4Float32Property &operator= ( const MP4Float32Property &src ); }; class MP4StringProperty : public MP4Property { public: MP4StringProperty(MP4Atom& parentAtom, const char* name, bool useCountedFormat = false, bool useUnicode = false, bool arrayMode = false); ~MP4StringProperty(); MP4PropertyType GetType() { return StringProperty; } uint32_t GetCount() { return m_values.Size(); } void SetCount(uint32_t count); const char* GetValue(uint32_t index = 0) { return m_values[index]; } void SetValue(const char* value, uint32_t index = 0); void AddValue(const char* value) { uint32_t count = GetCount(); SetCount(count + 1); SetValue(value, count); } bool IsCountedFormat() { return m_useCountedFormat; } void SetCountedFormat(bool useCountedFormat) { m_useCountedFormat = useCountedFormat; } bool IsExpandedCountedFormat() { return m_useExpandedCount; } void SetExpandedCountedFormat(bool useExpandedCount) { m_useExpandedCount = useExpandedCount; } bool IsUnicode() { return m_useUnicode; } void SetUnicode(bool useUnicode) { m_useUnicode = useUnicode; } uint32_t GetFixedLength() { return m_fixedLength; } void SetFixedLength(uint32_t fixedLength) { m_fixedLength = fixedLength; } void Read(MP4File& file, uint32_t index = 0); void Write(MP4File& file, uint32_t index = 0); void Dump(uint8_t indent, bool dumpImplicits, uint32_t index = 0); protected: bool m_arrayMode; // during read/write ignore index and read/write full array bool m_useCountedFormat; bool m_useExpandedCount; bool m_useUnicode; uint32_t m_fixedLength; MP4StringArray m_values; private: MP4StringProperty(); MP4StringProperty ( const MP4StringProperty &src ); MP4StringProperty &operator= ( const MP4StringProperty &src ); }; class MP4BytesProperty : public MP4Property { public: MP4BytesProperty(MP4Atom& parentAtom, const char* name, uint32_t valueSize = 0, uint32_t defaultValueSize = 0); ~MP4BytesProperty(); MP4PropertyType GetType() { return BytesProperty; } uint32_t GetCount() { return m_values.Size(); } void SetCount(uint32_t count); void GetValue(uint8_t** ppValue, uint32_t* pValueSize, uint32_t index = 0) { // N.B. caller must free memory *ppValue = (uint8_t*)MP4Malloc(m_valueSizes[index]); memcpy(*ppValue, m_values[index], m_valueSizes[index]); *pValueSize = m_valueSizes[index]; } char* GetValueStringAlloc( uint32_t index = 0 ) { char* buf = (char*)MP4Malloc( m_valueSizes[index] + 1 ); memcpy( buf, m_values[index], m_valueSizes[index] ); buf[m_valueSizes[index]] = '\0'; return buf; } bool CompareToString( const string& s, uint32_t index = 0 ) { return string( (const char*)m_values[index], m_valueSizes[index] ) != s; } void CopyValue(uint8_t* pValue, uint32_t index = 0) { // N.B. caller takes responsbility for valid pointer // and sufficient memory at the destination memcpy(pValue, m_values[index], m_valueSizes[index]); } void SetValue(const uint8_t* pValue, uint32_t valueSize, uint32_t index = 0); void AddValue(const uint8_t* pValue, uint32_t valueSize) { uint32_t count = GetCount(); SetCount(count + 1); SetValue(pValue, valueSize, count); } uint32_t GetValueSize( uint32_t index = 0 ) { return m_valueSizes[index]; } void SetValueSize(uint32_t valueSize, uint32_t index = 0); uint32_t GetFixedSize() { return m_fixedValueSize; } void SetFixedSize(uint32_t fixedSize); void Read(MP4File& file, uint32_t index = 0); void Write(MP4File& file, uint32_t index = 0); void Dump(uint8_t indent, bool dumpImplicits, uint32_t index = 0); protected: uint32_t m_fixedValueSize; uint32_t m_defaultValueSize; MP4Integer32Array m_valueSizes; MP4BytesArray m_values; private: MP4BytesProperty(); MP4BytesProperty ( const MP4BytesProperty &src ); MP4BytesProperty &operator= ( const MP4BytesProperty &src ); }; class MP4TableProperty : public MP4Property { public: MP4TableProperty(MP4Atom& parentAtom, const char* name, MP4IntegerProperty* pCountProperty); ~MP4TableProperty(); MP4PropertyType GetType() { return TableProperty; } void AddProperty(MP4Property* pProperty); MP4Property* GetProperty(uint32_t index) { return m_pProperties[index]; } virtual uint32_t GetCount() { return m_pCountProperty->GetValue(); } virtual void SetCount(uint32_t count) { m_pCountProperty->SetValue(count); } void Read(MP4File& file, uint32_t index = 0); void Write(MP4File& file, uint32_t index = 0); void Dump(uint8_t indent, bool dumpImplicits, uint32_t index = 0); bool FindProperty(const char* name, MP4Property** ppProperty, uint32_t* pIndex = NULL); protected: virtual void ReadEntry(MP4File& file, uint32_t index); virtual void WriteEntry(MP4File& file, uint32_t index); bool FindContainedProperty(const char* name, MP4Property** ppProperty, uint32_t* pIndex); protected: MP4IntegerProperty* m_pCountProperty; MP4PropertyArray m_pProperties; private: MP4TableProperty(); MP4TableProperty ( const MP4TableProperty &src ); MP4TableProperty &operator= ( const MP4TableProperty &src ); }; class MP4DescriptorProperty : public MP4Property { public: MP4DescriptorProperty(MP4Atom& parentAtom, const char* name = NULL, uint8_t tagsStart = 0, uint8_t tagsEnd = 0, bool mandatory = false, bool onlyOne = false); ~MP4DescriptorProperty(); MP4PropertyType GetType() { return DescriptorProperty; } void SetParentAtom(MP4Atom* pParentAtom); void SetSizeLimit(uint64_t sizeLimit) { m_sizeLimit = sizeLimit; } uint32_t GetCount() { return m_pDescriptors.Size(); } void SetCount(uint32_t count) { m_pDescriptors.Resize(count); } void SetTags(uint8_t tagsStart, uint8_t tagsEnd = 0) { m_tagsStart = tagsStart; m_tagsEnd = tagsEnd ? tagsEnd : tagsStart; } MP4Descriptor* AddDescriptor(uint8_t tag); void AppendDescriptor(MP4Descriptor* pDescriptor) { m_pDescriptors.Add(pDescriptor); } void DeleteDescriptor(uint32_t index); void Generate(); void Read(MP4File& file, uint32_t index = 0); void Write(MP4File& file, uint32_t index = 0); void Dump(uint8_t indent, bool dumpImplicits, uint32_t index = 0); bool FindProperty(const char* name, MP4Property** ppProperty, uint32_t* pIndex = NULL); protected: virtual MP4Descriptor* CreateDescriptor(MP4Atom& parentAtom, uint8_t tag); bool FindContainedProperty(const char* name, MP4Property** ppProperty, uint32_t* pIndex); protected: uint8_t m_tagsStart; uint8_t m_tagsEnd; uint64_t m_sizeLimit; bool m_mandatory; bool m_onlyOne; MP4DescriptorArray m_pDescriptors; private: MP4DescriptorProperty(); MP4DescriptorProperty ( const MP4DescriptorProperty &src ); MP4DescriptorProperty &operator= ( const MP4DescriptorProperty &src ); }; class MP4QosQualifierProperty : public MP4DescriptorProperty { public: MP4QosQualifierProperty(MP4Atom& parentAtom, const char* name = NULL, uint8_t tagsStart = 0, uint8_t tagsEnd = 0, bool mandatory = false, bool onlyOne = false) : MP4DescriptorProperty(parentAtom, name, tagsStart, tagsEnd, mandatory, onlyOne) { } protected: MP4Descriptor* CreateDescriptor(MP4Atom& parentAtom, uint8_t tag); private: MP4QosQualifierProperty(); MP4QosQualifierProperty ( const MP4QosQualifierProperty &src ); MP4QosQualifierProperty &operator= ( const MP4QosQualifierProperty &src ); }; /////////////////////////////////////////////////////////////////////////////// /// ISO-639-2/T language code. /// Language codes are 3-alpha (always lowercase) codes which are then /// offset using 0x60 and packed as 5-bit values into 16-bits, most /// significant bit is zero-padding. class MP4LanguageCodeProperty : public MP4Property { private: bmff::LanguageCode _value; public: explicit MP4LanguageCodeProperty( MP4Atom& parentAtom, const char* , bmff::LanguageCode = bmff::ILC_UND ); MP4LanguageCodeProperty( MP4Atom& parentAtom, const char* , const string& ); MP4PropertyType GetType(); uint32_t GetCount(); void SetCount( uint32_t ); void Read( MP4File&, uint32_t = 0 ); void Write( MP4File&, uint32_t = 0 ); void Dump( uint8_t, bool, uint32_t = 0 ); bmff::LanguageCode GetValue(); void SetValue( bmff::LanguageCode ); private: MP4LanguageCodeProperty(); MP4LanguageCodeProperty ( const MP4LanguageCodeProperty &src ); MP4LanguageCodeProperty &operator= ( const MP4LanguageCodeProperty &src ); }; /////////////////////////////////////////////////////////////////////////////// class MP4BasicTypeProperty : public MP4Property { private: itmf::BasicType _value; public: explicit MP4BasicTypeProperty( MP4Atom& parentAtom, const char* , itmf::BasicType = itmf::BT_UNDEFINED ); MP4PropertyType GetType(); uint32_t GetCount(); void SetCount( uint32_t ); void Read( MP4File&, uint32_t = 0 ); void Write( MP4File&, uint32_t = 0 ); void Dump( uint8_t, bool, uint32_t = 0 ); itmf::BasicType GetValue(); void SetValue( itmf::BasicType ); private: MP4BasicTypeProperty(); MP4BasicTypeProperty ( const MP4BasicTypeProperty &src ); MP4BasicTypeProperty &operator= ( const MP4BasicTypeProperty &src ); }; /////////////////////////////////////////////////////////////////////////////// }} // namespace mp4v2::impl #endif // MP4V2_IMPL_MP4PROPERTY_H