1 /* 2 * The contents of this file are subject to the Mozilla Public 3 * License Version 1.1 (the "License"); you may not use this file 4 * except in compliance with the License. You may obtain a copy of 5 * the License at http://www.mozilla.org/MPL/ 6 * 7 * Software distributed under the License is distributed on an "AS 8 * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or 9 * implied. See the License for the specific language governing 10 * rights and limitations under the License. 11 * 12 * The Original Code is MPEG4IP. 13 * 14 * The Initial Developer of the Original Code is Cisco Systems Inc. 15 * Portions created by Cisco Systems Inc. are 16 * Copyright (C) Cisco Systems Inc. 2001. All Rights Reserved. 17 * 18 * Contributor(s): 19 * Dave Mackie dmackie@cisco.com 20 */ 21 22 #ifndef MP4V2_IMPL_MP4PROPERTY_H 23 #define MP4V2_IMPL_MP4PROPERTY_H 24 25 namespace mp4v2 { namespace impl { 26 27 /////////////////////////////////////////////////////////////////////////////// 28 29 // forward declarations 30 class MP4Atom; 31 32 class MP4Descriptor; 33 MP4ARRAY_DECL(MP4Descriptor, MP4Descriptor*); 34 35 enum MP4PropertyType { 36 Integer8Property, 37 Integer16Property, 38 Integer24Property, 39 Integer32Property, 40 Integer64Property, 41 Float32Property, 42 StringProperty, 43 BytesProperty, 44 TableProperty, 45 DescriptorProperty, 46 LanguageCodeProperty, 47 BasicTypeProperty, 48 }; 49 50 class MP4Property { 51 public: 52 MP4Property(MP4Atom& parentAtom, const char *name = NULL); 53 ~MP4Property()54 virtual ~MP4Property() { } 55 GetParentAtom()56 MP4Atom& GetParentAtom() { 57 return m_parentAtom; 58 } 59 GetName()60 const char *GetName() { 61 return m_name; 62 } 63 64 virtual MP4PropertyType GetType() = 0; 65 IsReadOnly()66 bool IsReadOnly() { 67 return m_readOnly; 68 } 69 void SetReadOnly(bool value = true) { 70 m_readOnly = value; 71 } 72 IsImplicit()73 bool IsImplicit() { 74 return m_implicit; 75 } 76 void SetImplicit(bool value = true) { 77 m_implicit = value; 78 } 79 80 virtual uint32_t GetCount() = 0; 81 virtual void SetCount(uint32_t count) = 0; 82 Generate()83 virtual void Generate() { /* default is a no-op */ }; 84 85 virtual void Read(MP4File& file, uint32_t index = 0) = 0; 86 87 virtual void Write(MP4File& file, uint32_t index = 0) = 0; 88 89 virtual void Dump(uint8_t indent, 90 bool dumpImplicits, uint32_t index = 0) = 0; 91 92 virtual bool FindProperty(const char* name, 93 MP4Property** ppProperty, uint32_t* pIndex = NULL); 94 95 protected: 96 MP4Atom& m_parentAtom; 97 const char* m_name; 98 bool m_readOnly; 99 bool m_implicit; 100 101 private: 102 MP4Property(); 103 MP4Property ( const MP4Property &src ); 104 MP4Property &operator= ( const MP4Property &src ); 105 }; 106 107 MP4ARRAY_DECL(MP4Property, MP4Property*); 108 109 class MP4IntegerProperty : public MP4Property { 110 protected: MP4IntegerProperty(MP4Atom & parentAtom,const char * name)111 MP4IntegerProperty(MP4Atom& parentAtom, const char* name) 112 : MP4Property(parentAtom, name) { }; 113 114 public: 115 uint64_t GetValue(uint32_t index = 0); 116 117 void SetValue(uint64_t value, uint32_t index = 0); 118 119 void InsertValue(uint64_t value, uint32_t index = 0); 120 121 void DeleteValue(uint32_t index = 0); 122 123 void IncrementValue(int32_t increment = 1, uint32_t index = 0); 124 125 private: 126 MP4IntegerProperty(); 127 MP4IntegerProperty ( const MP4IntegerProperty &src ); 128 MP4IntegerProperty &operator= ( const MP4IntegerProperty &src ); 129 }; 130 131 #define MP4INTEGER_PROPERTY_DECL2(isize, xsize) \ 132 class MP4Integer##xsize##Property : public MP4IntegerProperty { \ 133 public: \ 134 MP4Integer##xsize##Property(MP4Atom& parentAtom, const char* name) \ 135 : MP4IntegerProperty(parentAtom, name) { \ 136 SetCount(1); \ 137 m_values[0] = 0; \ 138 } \ 139 \ 140 MP4PropertyType GetType() { \ 141 return Integer##xsize##Property; \ 142 } \ 143 \ 144 uint32_t GetCount() { \ 145 return m_values.Size(); \ 146 } \ 147 void SetCount(uint32_t count) { \ 148 m_values.Resize(count); \ 149 } \ 150 \ 151 uint##isize##_t GetValue(uint32_t index = 0) { \ 152 return m_values[index]; \ 153 } \ 154 \ 155 void SetValue(uint##isize##_t value, uint32_t index = 0) { \ 156 if (m_readOnly) { \ 157 ostringstream msg; \ 158 msg << "property is read-only: " << m_name; \ 159 throw new PlatformException(msg.str().c_str(), EACCES, __FILE__, __LINE__, __FUNCTION__); \ 160 } \ 161 m_values[index] = value; \ 162 } \ 163 void AddValue(uint##isize##_t value) { \ 164 m_values.Add(value); \ 165 } \ 166 void InsertValue(uint##isize##_t value, uint32_t index) { \ 167 m_values.Insert(value, index); \ 168 } \ 169 void DeleteValue(uint32_t index) { \ 170 m_values.Delete(index); \ 171 } \ 172 void IncrementValue(int32_t increment = 1, uint32_t index = 0) { \ 173 m_values[index] += increment; \ 174 } \ 175 void Read(MP4File& file, uint32_t index = 0) { \ 176 if (m_implicit) { \ 177 return; \ 178 } \ 179 m_values[index] = file.ReadUInt##xsize(); \ 180 } \ 181 \ 182 void Write(MP4File& file, uint32_t index = 0) { \ 183 if (m_implicit) { \ 184 return; \ 185 } \ 186 file.WriteUInt##xsize(m_values[index]); \ 187 } \ 188 void Dump(uint8_t indent, \ 189 bool dumpImplicits, uint32_t index = 0); \ 190 \ 191 protected: \ 192 MP4Integer##isize##Array m_values; \ 193 private: \ 194 MP4Integer##xsize##Property(); \ 195 MP4Integer##xsize##Property ( const MP4Integer##xsize##Property &src ); \ 196 MP4Integer##xsize##Property &operator= ( const MP4Integer##xsize##Property &src ); \ 197 }; 198 199 #define MP4INTEGER_PROPERTY_DECL(size) \ 200 MP4INTEGER_PROPERTY_DECL2(size, size) 201 202 MP4INTEGER_PROPERTY_DECL(8); 203 MP4INTEGER_PROPERTY_DECL(16); 204 MP4INTEGER_PROPERTY_DECL2(32, 24); 205 MP4INTEGER_PROPERTY_DECL(32); 206 MP4INTEGER_PROPERTY_DECL(64); 207 208 class MP4BitfieldProperty : public MP4Integer64Property { 209 public: MP4BitfieldProperty(MP4Atom & parentAtom,const char * name,uint8_t numBits)210 MP4BitfieldProperty(MP4Atom& parentAtom, const char* name, uint8_t numBits) 211 : MP4Integer64Property(parentAtom, name) { 212 ASSERT(numBits != 0); 213 ASSERT(numBits <= 64); 214 m_numBits = numBits; 215 } 216 GetNumBits()217 uint8_t GetNumBits() { 218 return m_numBits; 219 } SetNumBits(uint8_t numBits)220 void SetNumBits(uint8_t numBits) { 221 m_numBits = numBits; 222 } 223 224 void Read(MP4File& file, uint32_t index = 0); 225 void Write(MP4File& file, uint32_t index = 0); 226 void Dump(uint8_t indent, 227 bool dumpImplicits, uint32_t index = 0); 228 229 protected: 230 uint8_t m_numBits; 231 232 private: 233 MP4BitfieldProperty(); 234 MP4BitfieldProperty ( const MP4BitfieldProperty &src ); 235 MP4BitfieldProperty &operator= ( const MP4BitfieldProperty &src ); 236 }; 237 238 class MP4Float32Property : public MP4Property { 239 public: MP4Float32Property(MP4Atom & parentAtom,const char * name)240 MP4Float32Property(MP4Atom& parentAtom, const char* name) 241 : MP4Property(parentAtom, name) { 242 m_useFixed16Format = false; 243 m_useFixed32Format = false; 244 SetCount(1); 245 m_values[0] = 0.0; 246 } 247 GetType()248 MP4PropertyType GetType() { 249 return Float32Property; 250 } 251 GetCount()252 uint32_t GetCount() { 253 return m_values.Size(); 254 } SetCount(uint32_t count)255 void SetCount(uint32_t count) { 256 m_values.Resize(count); 257 } 258 259 float GetValue(uint32_t index = 0) { 260 return m_values[index]; 261 } 262 263 void SetValue(float value, uint32_t index = 0) { 264 if (m_readOnly) { 265 ostringstream msg; 266 msg << "property is read-only: " << m_name; 267 throw new PlatformException(msg.str().c_str(), EACCES, __FILE__, __LINE__, __FUNCTION__); 268 } 269 m_values[index] = value; 270 } 271 AddValue(float value)272 void AddValue(float value) { 273 m_values.Add(value); 274 } 275 InsertValue(float value,uint32_t index)276 void InsertValue(float value, uint32_t index) { 277 m_values.Insert(value, index); 278 } 279 IsFixed16Format()280 bool IsFixed16Format() { 281 return m_useFixed16Format; 282 } 283 284 void SetFixed16Format(bool useFixed16Format = true) { 285 m_useFixed16Format = useFixed16Format; 286 } 287 IsFixed32Format()288 bool IsFixed32Format() { 289 return m_useFixed32Format; 290 } 291 292 void SetFixed32Format(bool useFixed32Format = true) { 293 m_useFixed32Format = useFixed32Format; 294 } 295 296 void Read(MP4File& file, uint32_t index = 0); 297 void Write(MP4File& file, uint32_t index = 0); 298 void Dump(uint8_t indent, 299 bool dumpImplicits, uint32_t index = 0); 300 301 protected: 302 bool m_useFixed16Format; 303 bool m_useFixed32Format; 304 MP4Float32Array m_values; 305 306 private: 307 MP4Float32Property(); 308 MP4Float32Property ( const MP4Float32Property &src ); 309 MP4Float32Property &operator= ( const MP4Float32Property &src ); 310 }; 311 312 class MP4StringProperty : public MP4Property { 313 public: 314 MP4StringProperty(MP4Atom& parentAtom, const char* name, 315 bool useCountedFormat = false, bool useUnicode = false, bool arrayMode = false); 316 317 ~MP4StringProperty(); 318 GetType()319 MP4PropertyType GetType() { 320 return StringProperty; 321 } 322 GetCount()323 uint32_t GetCount() { 324 return m_values.Size(); 325 } 326 327 void SetCount(uint32_t count); 328 329 const char* GetValue(uint32_t index = 0) { 330 return m_values[index]; 331 } 332 333 void SetValue(const char* value, uint32_t index = 0); 334 AddValue(const char * value)335 void AddValue(const char* value) { 336 uint32_t count = GetCount(); 337 SetCount(count + 1); 338 SetValue(value, count); 339 } 340 IsCountedFormat()341 bool IsCountedFormat() { 342 return m_useCountedFormat; 343 } 344 SetCountedFormat(bool useCountedFormat)345 void SetCountedFormat(bool useCountedFormat) { 346 m_useCountedFormat = useCountedFormat; 347 } 348 IsExpandedCountedFormat()349 bool IsExpandedCountedFormat() { 350 return m_useExpandedCount; 351 } 352 SetExpandedCountedFormat(bool useExpandedCount)353 void SetExpandedCountedFormat(bool useExpandedCount) { 354 m_useExpandedCount = useExpandedCount; 355 } 356 IsUnicode()357 bool IsUnicode() { 358 return m_useUnicode; 359 } 360 SetUnicode(bool useUnicode)361 void SetUnicode(bool useUnicode) { 362 m_useUnicode = useUnicode; 363 } 364 GetFixedLength()365 uint32_t GetFixedLength() { 366 return m_fixedLength; 367 } 368 SetFixedLength(uint32_t fixedLength)369 void SetFixedLength(uint32_t fixedLength) { 370 m_fixedLength = fixedLength; 371 } 372 373 void Read(MP4File& file, uint32_t index = 0); 374 void Write(MP4File& file, uint32_t index = 0); 375 void Dump(uint8_t indent, 376 bool dumpImplicits, uint32_t index = 0); 377 378 protected: 379 bool m_arrayMode; // during read/write ignore index and read/write full array 380 bool m_useCountedFormat; 381 bool m_useExpandedCount; 382 bool m_useUnicode; 383 uint32_t m_fixedLength; 384 385 MP4StringArray m_values; 386 387 private: 388 MP4StringProperty(); 389 MP4StringProperty ( const MP4StringProperty &src ); 390 MP4StringProperty &operator= ( const MP4StringProperty &src ); 391 }; 392 393 class MP4BytesProperty : public MP4Property { 394 public: 395 MP4BytesProperty(MP4Atom& parentAtom, const char* name, uint32_t valueSize = 0, 396 uint32_t defaultValueSize = 0); 397 398 ~MP4BytesProperty(); 399 GetType()400 MP4PropertyType GetType() { 401 return BytesProperty; 402 } 403 GetCount()404 uint32_t GetCount() { 405 return m_values.Size(); 406 } 407 408 void SetCount(uint32_t count); 409 410 void GetValue(uint8_t** ppValue, uint32_t* pValueSize, 411 uint32_t index = 0) { 412 // N.B. caller must free memory 413 *ppValue = (uint8_t*)MP4Malloc(m_valueSizes[index]); 414 memcpy(*ppValue, m_values[index], m_valueSizes[index]); 415 *pValueSize = m_valueSizes[index]; 416 } 417 418 char* GetValueStringAlloc( uint32_t index = 0 ) { 419 char* buf = (char*)MP4Malloc( m_valueSizes[index] + 1 ); 420 memcpy( buf, m_values[index], m_valueSizes[index] ); 421 buf[m_valueSizes[index]] = '\0'; 422 return buf; 423 } 424 425 bool CompareToString( const string& s, uint32_t index = 0 ) { 426 return string( (const char*)m_values[index], m_valueSizes[index] ) != s; 427 } 428 429 void CopyValue(uint8_t* pValue, uint32_t index = 0) { 430 // N.B. caller takes responsbility for valid pointer 431 // and sufficient memory at the destination 432 memcpy(pValue, m_values[index], m_valueSizes[index]); 433 } 434 435 void SetValue(const uint8_t* pValue, uint32_t valueSize, 436 uint32_t index = 0); 437 AddValue(const uint8_t * pValue,uint32_t valueSize)438 void AddValue(const uint8_t* pValue, uint32_t valueSize) { 439 uint32_t count = GetCount(); 440 SetCount(count + 1); 441 SetValue(pValue, valueSize, count); 442 } 443 444 uint32_t GetValueSize( uint32_t index = 0 ) { 445 return m_valueSizes[index]; 446 } 447 448 void SetValueSize(uint32_t valueSize, uint32_t index = 0); 449 GetFixedSize()450 uint32_t GetFixedSize() { 451 return m_fixedValueSize; 452 } 453 454 void SetFixedSize(uint32_t fixedSize); 455 456 void Read(MP4File& file, uint32_t index = 0); 457 void Write(MP4File& file, uint32_t index = 0); 458 void Dump(uint8_t indent, 459 bool dumpImplicits, uint32_t index = 0); 460 461 protected: 462 uint32_t m_fixedValueSize; 463 uint32_t m_defaultValueSize; 464 MP4Integer32Array m_valueSizes; 465 MP4BytesArray m_values; 466 467 private: 468 MP4BytesProperty(); 469 MP4BytesProperty ( const MP4BytesProperty &src ); 470 MP4BytesProperty &operator= ( const MP4BytesProperty &src ); 471 }; 472 473 class MP4TableProperty : public MP4Property { 474 public: 475 MP4TableProperty(MP4Atom& parentAtom, const char* name, MP4IntegerProperty* pCountProperty); 476 477 ~MP4TableProperty(); 478 GetType()479 MP4PropertyType GetType() { 480 return TableProperty; 481 } 482 483 void AddProperty(MP4Property* pProperty); 484 GetProperty(uint32_t index)485 MP4Property* GetProperty(uint32_t index) { 486 return m_pProperties[index]; 487 } 488 GetCount()489 virtual uint32_t GetCount() { 490 return m_pCountProperty->GetValue(); 491 } SetCount(uint32_t count)492 virtual void SetCount(uint32_t count) { 493 m_pCountProperty->SetValue(count); 494 } 495 496 void Read(MP4File& file, uint32_t index = 0); 497 void Write(MP4File& file, uint32_t index = 0); 498 void Dump(uint8_t indent, 499 bool dumpImplicits, uint32_t index = 0); 500 501 bool FindProperty(const char* name, 502 MP4Property** ppProperty, uint32_t* pIndex = NULL); 503 504 protected: 505 virtual void ReadEntry(MP4File& file, uint32_t index); 506 virtual void WriteEntry(MP4File& file, uint32_t index); 507 508 bool FindContainedProperty(const char* name, 509 MP4Property** ppProperty, uint32_t* pIndex); 510 511 protected: 512 MP4IntegerProperty* m_pCountProperty; 513 MP4PropertyArray m_pProperties; 514 515 private: 516 MP4TableProperty(); 517 MP4TableProperty ( const MP4TableProperty &src ); 518 MP4TableProperty &operator= ( const MP4TableProperty &src ); 519 }; 520 521 class MP4DescriptorProperty : public MP4Property { 522 public: 523 MP4DescriptorProperty(MP4Atom& parentAtom, const char* name = NULL, 524 uint8_t tagsStart = 0, uint8_t tagsEnd = 0, 525 bool mandatory = false, bool onlyOne = false); 526 527 ~MP4DescriptorProperty(); 528 GetType()529 MP4PropertyType GetType() { 530 return DescriptorProperty; 531 } 532 533 void SetParentAtom(MP4Atom* pParentAtom); 534 SetSizeLimit(uint64_t sizeLimit)535 void SetSizeLimit(uint64_t sizeLimit) { 536 m_sizeLimit = sizeLimit; 537 } 538 GetCount()539 uint32_t GetCount() { 540 return m_pDescriptors.Size(); 541 } SetCount(uint32_t count)542 void SetCount(uint32_t count) { 543 m_pDescriptors.Resize(count); 544 } 545 546 void SetTags(uint8_t tagsStart, uint8_t tagsEnd = 0) { 547 m_tagsStart = tagsStart; 548 m_tagsEnd = tagsEnd ? tagsEnd : tagsStart; 549 } 550 551 MP4Descriptor* AddDescriptor(uint8_t tag); 552 AppendDescriptor(MP4Descriptor * pDescriptor)553 void AppendDescriptor(MP4Descriptor* pDescriptor) { 554 m_pDescriptors.Add(pDescriptor); 555 } 556 557 void DeleteDescriptor(uint32_t index); 558 559 void Generate(); 560 void Read(MP4File& file, uint32_t index = 0); 561 void Write(MP4File& file, uint32_t index = 0); 562 void Dump(uint8_t indent, 563 bool dumpImplicits, uint32_t index = 0); 564 565 bool FindProperty(const char* name, 566 MP4Property** ppProperty, uint32_t* pIndex = NULL); 567 568 protected: 569 virtual MP4Descriptor* CreateDescriptor(MP4Atom& parentAtom, uint8_t tag); 570 571 bool FindContainedProperty(const char* name, 572 MP4Property** ppProperty, uint32_t* pIndex); 573 574 protected: 575 uint8_t m_tagsStart; 576 uint8_t m_tagsEnd; 577 uint64_t m_sizeLimit; 578 bool m_mandatory; 579 bool m_onlyOne; 580 MP4DescriptorArray m_pDescriptors; 581 582 private: 583 MP4DescriptorProperty(); 584 MP4DescriptorProperty ( const MP4DescriptorProperty &src ); 585 MP4DescriptorProperty &operator= ( const MP4DescriptorProperty &src ); 586 }; 587 588 class MP4QosQualifierProperty : public MP4DescriptorProperty { 589 public: 590 MP4QosQualifierProperty(MP4Atom& parentAtom, const char* name = NULL, 591 uint8_t tagsStart = 0, uint8_t tagsEnd = 0, 592 bool mandatory = false, bool onlyOne = false) : MP4DescriptorProperty(parentAtom,name,tagsStart,tagsEnd,mandatory,onlyOne)593 MP4DescriptorProperty(parentAtom, name, tagsStart, tagsEnd, mandatory, onlyOne) { } 594 595 protected: 596 MP4Descriptor* CreateDescriptor(MP4Atom& parentAtom, uint8_t tag); 597 598 private: 599 MP4QosQualifierProperty(); 600 MP4QosQualifierProperty ( const MP4QosQualifierProperty &src ); 601 MP4QosQualifierProperty &operator= ( const MP4QosQualifierProperty &src ); 602 }; 603 604 /////////////////////////////////////////////////////////////////////////////// 605 606 /// ISO-639-2/T language code. 607 /// Language codes are 3-alpha (always lowercase) codes which are then 608 /// offset using 0x60 and packed as 5-bit values into 16-bits, most 609 /// significant bit is zero-padding. 610 611 class MP4LanguageCodeProperty : public MP4Property { 612 private: 613 bmff::LanguageCode _value; 614 615 public: 616 explicit MP4LanguageCodeProperty( MP4Atom& parentAtom, const char* , bmff::LanguageCode = bmff::ILC_UND ); 617 MP4LanguageCodeProperty( MP4Atom& parentAtom, const char* , const string& ); 618 619 MP4PropertyType GetType(); 620 uint32_t GetCount(); 621 void SetCount( uint32_t ); 622 void Read( MP4File&, uint32_t = 0 ); 623 void Write( MP4File&, uint32_t = 0 ); 624 void Dump( uint8_t, bool, uint32_t = 0 ); 625 626 bmff::LanguageCode GetValue(); 627 void SetValue( bmff::LanguageCode ); 628 629 private: 630 MP4LanguageCodeProperty(); 631 MP4LanguageCodeProperty ( const MP4LanguageCodeProperty &src ); 632 MP4LanguageCodeProperty &operator= ( const MP4LanguageCodeProperty &src ); 633 }; 634 635 /////////////////////////////////////////////////////////////////////////////// 636 637 class MP4BasicTypeProperty : public MP4Property { 638 private: 639 itmf::BasicType _value; 640 641 public: 642 explicit MP4BasicTypeProperty( MP4Atom& parentAtom, const char* , itmf::BasicType = itmf::BT_UNDEFINED ); 643 644 MP4PropertyType GetType(); 645 uint32_t GetCount(); 646 void SetCount( uint32_t ); 647 void Read( MP4File&, uint32_t = 0 ); 648 void Write( MP4File&, uint32_t = 0 ); 649 void Dump( uint8_t, bool, uint32_t = 0 ); 650 itmf::BasicType GetValue(); 651 void SetValue( itmf::BasicType ); 652 653 private: 654 MP4BasicTypeProperty(); 655 MP4BasicTypeProperty ( const MP4BasicTypeProperty &src ); 656 MP4BasicTypeProperty &operator= ( const MP4BasicTypeProperty &src ); 657 }; 658 659 /////////////////////////////////////////////////////////////////////////////// 660 661 }} // namespace mp4v2::impl 662 663 #endif // MP4V2_IMPL_MP4PROPERTY_H 664