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 __MP4_PROPERTY_INCLUDED__ 23 #define __MP4_PROPERTY_INCLUDED__ 24 25 // forward declarations 26 class MP4Atom; 27 28 class MP4Descriptor; 29 MP4ARRAY_DECL(MP4Descriptor, MP4Descriptor*); 30 31 enum MP4PropertyType { 32 Integer8Property, 33 Integer16Property, 34 Integer24Property, 35 Integer32Property, 36 Integer64Property, 37 Float32Property, 38 StringProperty, 39 BytesProperty, 40 TableProperty, 41 DescriptorProperty, 42 }; 43 44 class MP4Property { 45 public: 46 MP4Property(const char *name = NULL); 47 ~MP4Property()48 virtual ~MP4Property() { } 49 GetParentAtom()50 MP4Atom* GetParentAtom() { 51 return m_pParentAtom; 52 } SetParentAtom(MP4Atom * pParentAtom)53 virtual void SetParentAtom(MP4Atom* pParentAtom) { 54 m_pParentAtom = pParentAtom; 55 } 56 GetName()57 const char *GetName() { 58 return m_name; 59 } 60 61 virtual MP4PropertyType GetType() = 0; 62 IsReadOnly()63 bool IsReadOnly() { 64 return m_readOnly; 65 } 66 void SetReadOnly(bool value = true) { 67 m_readOnly = value; 68 } 69 IsImplicit()70 bool IsImplicit() { 71 return m_implicit; 72 } 73 void SetImplicit(bool value = true) { 74 m_implicit = value; 75 } 76 77 virtual u_int32_t GetCount() = 0; 78 virtual void SetCount(u_int32_t count) = 0; 79 Generate()80 virtual void Generate() { /* default is a no-op */ }; 81 82 virtual void Read(MP4File* pFile, u_int32_t index = 0) = 0; 83 84 virtual void Write(MP4File* pFile, u_int32_t index = 0) = 0; 85 86 virtual void Dump(FILE* pFile, u_int8_t indent, 87 bool dumpImplicits, u_int32_t index = 0) = 0; 88 89 virtual bool FindProperty(const char* name, 90 MP4Property** ppProperty, u_int32_t* pIndex = NULL); 91 92 protected: 93 MP4Atom* m_pParentAtom; 94 const char* m_name; 95 bool m_readOnly; 96 bool m_implicit; 97 }; 98 99 MP4ARRAY_DECL(MP4Property, MP4Property*); 100 101 class MP4IntegerProperty : public MP4Property { 102 protected: MP4IntegerProperty(char * name)103 MP4IntegerProperty(char* name) 104 : MP4Property(name) { }; 105 106 public: 107 u_int64_t GetValue(u_int32_t index = 0); 108 109 void SetValue(u_int64_t value, u_int32_t index = 0); 110 111 void InsertValue(u_int64_t value, u_int32_t index = 0); 112 113 void DeleteValue(u_int32_t index = 0); 114 115 void IncrementValue(int32_t increment = 1, u_int32_t index = 0); 116 }; 117 118 #define MP4INTEGER_PROPERTY_DECL2(isize, xsize) \ 119 class MP4Integer##xsize##Property : public MP4IntegerProperty { \ 120 public: \ 121 MP4Integer##xsize##Property(char* name) \ 122 : MP4IntegerProperty(name) { \ 123 SetCount(1); \ 124 m_values[0] = 0; \ 125 } \ 126 \ 127 MP4PropertyType GetType() { \ 128 return Integer##xsize##Property; \ 129 } \ 130 \ 131 u_int32_t GetCount() { \ 132 return m_values.Size(); \ 133 } \ 134 void SetCount(u_int32_t count) { \ 135 m_values.Resize(count); \ 136 } \ 137 \ 138 u_int##isize##_t GetValue(u_int32_t index = 0) { \ 139 return m_values[index]; \ 140 } \ 141 \ 142 void SetValue(u_int##isize##_t value, u_int32_t index = 0) { \ 143 if (m_readOnly) { \ 144 throw new MP4Error(EACCES, "property is read-only", m_name); \ 145 } \ 146 m_values[index] = value; \ 147 } \ 148 void AddValue(u_int##isize##_t value) { \ 149 m_values.Add(value); \ 150 } \ 151 void InsertValue(u_int##isize##_t value, u_int32_t index) { \ 152 m_values.Insert(value, index); \ 153 } \ 154 void DeleteValue(u_int32_t index) { \ 155 m_values.Delete(index); \ 156 } \ 157 void IncrementValue(int32_t increment = 1, u_int32_t index = 0) { \ 158 m_values[index] += increment; \ 159 } \ 160 void Read(MP4File* pFile, u_int32_t index = 0) { \ 161 if (m_implicit) { \ 162 return; \ 163 } \ 164 m_values[index] = pFile->ReadUInt##xsize(); \ 165 } \ 166 \ 167 void Write(MP4File* pFile, u_int32_t index = 0) { \ 168 if (m_implicit) { \ 169 return; \ 170 } \ 171 pFile->WriteUInt##xsize(m_values[index]); \ 172 } \ 173 void Dump(FILE* pFile, u_int8_t indent, \ 174 bool dumpImplicits, u_int32_t index = 0); \ 175 \ 176 protected: \ 177 MP4Integer##isize##Array m_values; \ 178 }; 179 180 #define MP4INTEGER_PROPERTY_DECL(size) \ 181 MP4INTEGER_PROPERTY_DECL2(size, size) 182 183 MP4INTEGER_PROPERTY_DECL(8); 184 MP4INTEGER_PROPERTY_DECL(16); 185 MP4INTEGER_PROPERTY_DECL2(32, 24); 186 MP4INTEGER_PROPERTY_DECL(32); 187 MP4INTEGER_PROPERTY_DECL(64); 188 189 class MP4BitfieldProperty : public MP4Integer64Property { 190 public: MP4BitfieldProperty(char * name,u_int8_t numBits)191 MP4BitfieldProperty(char* name, u_int8_t numBits) 192 : MP4Integer64Property(name) { 193 ASSERT(numBits != 0); 194 ASSERT(numBits <= 64); 195 m_numBits = numBits; 196 } 197 GetNumBits()198 u_int8_t GetNumBits() { 199 return m_numBits; 200 } SetNumBits(u_int8_t numBits)201 void SetNumBits(u_int8_t numBits) { 202 m_numBits = numBits; 203 } 204 205 void Read(MP4File* pFile, u_int32_t index = 0); 206 void Write(MP4File* pFile, u_int32_t index = 0); 207 void Dump(FILE* pFile, u_int8_t indent, 208 bool dumpImplicits, u_int32_t index = 0); 209 210 protected: 211 u_int8_t m_numBits; 212 }; 213 214 class MP4Float32Property : public MP4Property { 215 public: MP4Float32Property(char * name)216 MP4Float32Property(char* name) 217 : MP4Property(name) { 218 m_useFixed16Format = false; 219 m_useFixed32Format = false; 220 SetCount(1); 221 m_values[0] = 0.0; 222 } 223 GetType()224 MP4PropertyType GetType() { 225 return Float32Property; 226 } 227 GetCount()228 u_int32_t GetCount() { 229 return m_values.Size(); 230 } SetCount(u_int32_t count)231 void SetCount(u_int32_t count) { 232 m_values.Resize(count); 233 } 234 235 float GetValue(u_int32_t index = 0) { 236 return m_values[index]; 237 } 238 239 void SetValue(float value, u_int32_t index = 0) { 240 if (m_readOnly) { 241 throw new MP4Error(EACCES, "property is read-only", m_name); 242 } 243 m_values[index] = value; 244 } 245 AddValue(float value)246 void AddValue(float value) { 247 m_values.Add(value); 248 } 249 InsertValue(float value,u_int32_t index)250 void InsertValue(float value, u_int32_t index) { 251 m_values.Insert(value, index); 252 } 253 IsFixed16Format()254 bool IsFixed16Format() { 255 return m_useFixed16Format; 256 } 257 258 void SetFixed16Format(bool useFixed16Format = true) { 259 m_useFixed16Format = useFixed16Format; 260 } 261 IsFixed32Format()262 bool IsFixed32Format() { 263 return m_useFixed32Format; 264 } 265 266 void SetFixed32Format(bool useFixed32Format = true) { 267 m_useFixed32Format = useFixed32Format; 268 } 269 270 void Read(MP4File* pFile, u_int32_t index = 0); 271 void Write(MP4File* pFile, u_int32_t index = 0); 272 void Dump(FILE* pFile, u_int8_t indent, 273 bool dumpImplicits, u_int32_t index = 0); 274 275 protected: 276 bool m_useFixed16Format; 277 bool m_useFixed32Format; 278 MP4Float32Array m_values; 279 }; 280 281 class MP4StringProperty : public MP4Property { 282 public: 283 MP4StringProperty(char* name, 284 bool useCountedFormat = false, bool useUnicode = false); 285 286 ~MP4StringProperty(); 287 GetType()288 MP4PropertyType GetType() { 289 return StringProperty; 290 } 291 GetCount()292 u_int32_t GetCount() { 293 return m_values.Size(); 294 } 295 296 void SetCount(u_int32_t count); 297 298 const char* GetValue(u_int32_t index = 0) { 299 return m_values[index]; 300 } 301 302 void SetValue(const char* value, u_int32_t index = 0); 303 AddValue(const char * value)304 void AddValue(const char* value) { 305 u_int32_t count = GetCount(); 306 SetCount(count + 1); 307 SetValue(value, count); 308 } 309 IsCountedFormat()310 bool IsCountedFormat() { 311 return m_useCountedFormat; 312 } 313 SetCountedFormat(bool useCountedFormat)314 void SetCountedFormat(bool useCountedFormat) { 315 m_useCountedFormat = useCountedFormat; 316 } 317 IsExpandedCountedFormat()318 bool IsExpandedCountedFormat() { 319 return m_useExpandedCount; 320 } 321 SetExpandedCountedFormat(bool useExpandedCount)322 void SetExpandedCountedFormat(bool useExpandedCount) { 323 m_useExpandedCount = useExpandedCount; 324 } 325 IsUnicode()326 bool IsUnicode() { 327 return m_useUnicode; 328 } 329 SetUnicode(bool useUnicode)330 void SetUnicode(bool useUnicode) { 331 m_useUnicode = useUnicode; 332 } 333 GetFixedLength()334 u_int32_t GetFixedLength() { 335 return m_fixedLength; 336 } 337 SetFixedLength(u_int32_t fixedLength)338 void SetFixedLength(u_int32_t fixedLength) { 339 m_fixedLength = fixedLength; 340 } 341 342 void Read(MP4File* pFile, u_int32_t index = 0); 343 void Write(MP4File* pFile, u_int32_t index = 0); 344 void Dump(FILE* pFile, u_int8_t indent, 345 bool dumpImplicits, u_int32_t index = 0); 346 347 protected: 348 bool m_useCountedFormat; 349 bool m_useExpandedCount; 350 bool m_useUnicode; 351 u_int32_t m_fixedLength; 352 353 MP4StringArray m_values; 354 }; 355 356 class MP4BytesProperty : public MP4Property { 357 public: 358 MP4BytesProperty(char* name, u_int32_t valueSize = 0, 359 u_int32_t defaultValueSize = 0); 360 361 ~MP4BytesProperty(); 362 GetType()363 MP4PropertyType GetType() { 364 return BytesProperty; 365 } 366 GetCount()367 u_int32_t GetCount() { 368 return m_values.Size(); 369 } 370 371 void SetCount(u_int32_t count); 372 373 void GetValue(u_int8_t** ppValue, u_int32_t* pValueSize, 374 u_int32_t index = 0) { 375 // N.B. caller must free memory 376 *ppValue = (u_int8_t*)MP4Malloc(m_valueSizes[index]); 377 memcpy(*ppValue, m_values[index], m_valueSizes[index]); 378 *pValueSize = m_valueSizes[index]; 379 } 380 381 void CopyValue(u_int8_t* pValue, u_int32_t index = 0) { 382 // N.B. caller takes responsbility for valid pointer 383 // and sufficient memory at the destination 384 memcpy(pValue, m_values[index], m_valueSizes[index]); 385 } 386 387 void SetValue(const u_int8_t* pValue, u_int32_t valueSize, 388 u_int32_t index = 0); 389 AddValue(const u_int8_t * pValue,u_int32_t valueSize)390 void AddValue(const u_int8_t* pValue, u_int32_t valueSize) { 391 u_int32_t count = GetCount(); 392 SetCount(count + 1); 393 SetValue(pValue, valueSize, count); 394 } 395 396 u_int32_t GetValueSize(u_int32_t valueSize, u_int32_t index = 0) { 397 return m_valueSizes[index]; 398 } 399 400 void SetValueSize(u_int32_t valueSize, u_int32_t index = 0); 401 GetFixedSize()402 u_int32_t GetFixedSize() { 403 return m_fixedValueSize; 404 } 405 406 void SetFixedSize(u_int32_t fixedSize); 407 408 void Read(MP4File* pFile, u_int32_t index = 0); 409 void Write(MP4File* pFile, u_int32_t index = 0); 410 void Dump(FILE* pFile, u_int8_t indent, 411 bool dumpImplicits, u_int32_t index = 0); 412 413 protected: 414 u_int32_t m_fixedValueSize; 415 u_int32_t m_defaultValueSize; 416 MP4Integer32Array m_valueSizes; 417 MP4BytesArray m_values; 418 }; 419 420 class MP4TableProperty : public MP4Property { 421 public: 422 MP4TableProperty(char* name, MP4IntegerProperty* pCountProperty); 423 424 ~MP4TableProperty(); 425 GetType()426 MP4PropertyType GetType() { 427 return TableProperty; 428 } 429 SetParentAtom(MP4Atom * pParentAtom)430 void SetParentAtom(MP4Atom* pParentAtom) { 431 m_pParentAtom = pParentAtom; 432 for (u_int32_t i = 0; i < m_pProperties.Size(); i++) { 433 m_pProperties[i]->SetParentAtom(pParentAtom); 434 } 435 } 436 437 void AddProperty(MP4Property* pProperty); 438 GetProperty(u_int32_t index)439 MP4Property* GetProperty(u_int32_t index) { 440 return m_pProperties[index]; 441 } 442 GetCount()443 virtual u_int32_t GetCount() { 444 return m_pCountProperty->GetValue(); 445 } SetCount(u_int32_t count)446 virtual void SetCount(u_int32_t count) { 447 m_pCountProperty->SetValue(count); 448 } 449 450 void Read(MP4File* pFile, u_int32_t index = 0); 451 void Write(MP4File* pFile, u_int32_t index = 0); 452 void Dump(FILE* pFile, u_int8_t indent, 453 bool dumpImplicits, u_int32_t index = 0); 454 455 bool FindProperty(const char* name, 456 MP4Property** ppProperty, u_int32_t* pIndex = NULL); 457 458 protected: 459 virtual void ReadEntry(MP4File* pFile, u_int32_t index); 460 virtual void WriteEntry(MP4File* pFile, u_int32_t index); 461 462 bool FindContainedProperty(const char* name, 463 MP4Property** ppProperty, u_int32_t* pIndex); 464 465 protected: 466 MP4IntegerProperty* m_pCountProperty; 467 MP4PropertyArray m_pProperties; 468 }; 469 470 class MP4DescriptorProperty : public MP4Property { 471 public: 472 MP4DescriptorProperty(char* name = NULL, 473 u_int8_t tagsStart = 0, u_int8_t tagsEnd = 0, 474 bool mandatory = false, bool onlyOne = false); 475 476 ~MP4DescriptorProperty(); 477 GetType()478 MP4PropertyType GetType() { 479 return DescriptorProperty; 480 } 481 482 void SetParentAtom(MP4Atom* pParentAtom); 483 SetSizeLimit(u_int64_t sizeLimit)484 void SetSizeLimit(u_int64_t sizeLimit) { 485 m_sizeLimit = sizeLimit; 486 } 487 GetCount()488 u_int32_t GetCount() { 489 return m_pDescriptors.Size(); 490 } SetCount(u_int32_t count)491 void SetCount(u_int32_t count) { 492 m_pDescriptors.Resize(count); 493 } 494 495 void SetTags(u_int8_t tagsStart, u_int8_t tagsEnd = 0) { 496 m_tagsStart = tagsStart; 497 m_tagsEnd = tagsEnd ? tagsEnd : tagsStart; 498 } 499 500 MP4Descriptor* AddDescriptor(u_int8_t tag); 501 AppendDescriptor(MP4Descriptor * pDescriptor)502 void AppendDescriptor(MP4Descriptor* pDescriptor) { 503 m_pDescriptors.Add(pDescriptor); 504 } 505 506 void DeleteDescriptor(u_int32_t index); 507 508 void Generate(); 509 void Read(MP4File* pFile, u_int32_t index = 0); 510 void Write(MP4File* pFile, u_int32_t index = 0); 511 void Dump(FILE* pFile, u_int8_t indent, 512 bool dumpImplicits, u_int32_t index = 0); 513 514 bool FindProperty(const char* name, 515 MP4Property** ppProperty, u_int32_t* pIndex = NULL); 516 517 protected: 518 virtual MP4Descriptor* CreateDescriptor(u_int8_t tag); 519 520 bool FindContainedProperty(const char* name, 521 MP4Property** ppProperty, u_int32_t* pIndex); 522 523 protected: 524 u_int8_t m_tagsStart; 525 u_int8_t m_tagsEnd; 526 u_int64_t m_sizeLimit; 527 bool m_mandatory; 528 bool m_onlyOne; 529 MP4DescriptorArray m_pDescriptors; 530 }; 531 532 class MP4QosQualifierProperty : public MP4DescriptorProperty { 533 public: 534 MP4QosQualifierProperty(char* name = NULL, 535 u_int8_t tagsStart = 0, u_int8_t tagsEnd = 0, 536 bool mandatory = false, bool onlyOne = false) : MP4DescriptorProperty(name,tagsStart,tagsEnd,mandatory,onlyOne)537 MP4DescriptorProperty(name, tagsStart, tagsEnd, mandatory, onlyOne) { } 538 539 protected: 540 MP4Descriptor* CreateDescriptor(u_int8_t tag); 541 }; 542 543 #endif /* __MP4_PROPERTY_INCLUDED__ */ 544