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 #include "mp4common.h"
23 
MP4BaseDescriptor(u_int8_t tag)24 MP4BaseDescriptor::MP4BaseDescriptor (u_int8_t tag) : MP4Descriptor(tag)
25 {
26   switch (tag) {
27   case MP4ESIDIncDescrTag:
28     AddProperty( /* 0 */
29 		new MP4Integer32Property("id"));
30     break;
31   case MP4ESIDRefDescrTag:
32     AddProperty( /* 0 */
33 		new MP4Integer16Property("refIndex"));
34     break;
35   case MP4IPIPtrDescrTag:
36     AddProperty( /* 0 */
37 		new MP4Integer16Property("IPIESId"));
38     break;
39   case MP4SupplContentIdDescrTag:
40     AddProperty( /* 0 */
41 		new MP4BytesProperty("languageCode", 3));
42     AddProperty( /* 1 */
43 		new MP4StringProperty("title", Counted));
44     AddProperty( /* 2 */
45 		new MP4StringProperty("value", Counted));
46     break;
47   case MP4IPMPPtrDescrTag:
48     AddProperty( /* 0 */
49 		new MP4Integer8Property("IPMPDescriptorId"));
50     break;
51   case MP4ExtProfileLevelDescrTag:
52     AddProperty( /* 0 */
53 		new MP4Integer8Property("profileLevelIndicationIndex"));
54     AddProperty( /* 1 */
55 		new MP4Integer8Property("ODProfileLevelIndication"));
56     AddProperty( /* 2 */
57 		new MP4Integer8Property("sceneProfileLevelIndication"));
58     AddProperty( /* 3 */
59 		new MP4Integer8Property("audioProfileLevelIndication"));
60     AddProperty( /* 4 */
61 		new MP4Integer8Property("visualProfileLevelIndication"));
62     AddProperty( /* 5 */
63 		new MP4Integer8Property("graphicsProfileLevelIndication"));
64     AddProperty( /* 6 */
65 		new MP4Integer8Property("MPEGJProfileLevelIndication"));
66     break;
67   default:
68     MP4Printf("error in base descriptor - tag %u", tag);
69     break;
70 
71   }
72 }
73 
MP4BytesDescriptor(u_int8_t tag)74 MP4BytesDescriptor::MP4BytesDescriptor (u_int8_t tag) : MP4Descriptor(tag)
75 {
76   m_size_offset = 0;
77   m_bytes_index = 0;
78   if (tag >= MP4ExtDescrTagsStart && tag <= MP4ExtDescrTagsEnd) {
79     AddProperty( /* 0 */
80 		new MP4BytesProperty("data"));
81   } else {
82     switch (tag) {
83     case MP4DecSpecificDescrTag:
84       AddProperty( /* 0 */
85 		  new MP4BytesProperty("info"));
86       // no change to m_size
87       break;
88     case MP4IPMPDescrTag:
89       AddProperty( /* 0 */
90 		  new MP4Integer8Property("IPMPDescriptorId"));
91       AddProperty( /* 1 */
92 		  new MP4Integer16Property("IPMPSType"));
93       AddProperty( /* 2 */
94 		  new MP4BytesProperty("IPMPData"));
95       /* note: if IPMPSType == 0, IPMPData is an URL */
96       m_size_offset = 3;
97       m_bytes_index = 2;
98       break;
99     case MP4RegistrationDescrTag:
100       AddProperty( /* 0 */
101 		  new MP4Integer32Property("formatIdentifier"));
102       AddProperty( /* 1 */
103 		  new MP4BytesProperty("additionalIdentificationInfo"));
104       m_size_offset = 4;
105       m_bytes_index = 1;
106       break;
107     default:
108       MP4Printf("error in bytes descriptor - tag %u", tag);
109       break;
110     }
111   }
112 }
113 
Read(MP4File * pFile)114 void MP4BytesDescriptor::Read(MP4File *pFile)
115 {
116   ReadHeader(pFile);
117 
118   /* byte properties need to know how long they are before reading */
119   ((MP4BytesProperty*)m_pProperties[m_bytes_index])->SetValueSize(m_size - m_size_offset);
120 
121   ReadProperties(pFile);
122 }
MP4IODescriptor()123 MP4IODescriptor::MP4IODescriptor()
124 	: MP4Descriptor(MP4FileIODescrTag)
125 {
126 	/* N.B. other member functions depend on the property indicies */
127 	AddProperty( /* 0 */
128 		new MP4BitfieldProperty("objectDescriptorId", 10));
129 	AddProperty( /* 1 */
130 		new MP4BitfieldProperty("URLFlag", 1));
131 	AddProperty( /* 2 */
132 		new MP4BitfieldProperty("includeInlineProfileLevelFlag", 1));
133 	AddProperty( /* 3 */
134 		new MP4BitfieldProperty("reserved", 4));
135 	AddProperty( /* 4 */
136 		new MP4StringProperty("URL", Counted));
137 	AddProperty( /* 5 */
138 		new MP4Integer8Property("ODProfileLevelId"));
139 	AddProperty( /* 6 */
140 		new MP4Integer8Property("sceneProfileLevelId"));
141 	AddProperty( /* 7 */
142 		new MP4Integer8Property("audioProfileLevelId"));
143 	AddProperty( /* 8 */
144 		new MP4Integer8Property("visualProfileLevelId"));
145 	AddProperty( /* 9 */
146 		new MP4Integer8Property("graphicsProfileLevelId"));
147 	AddProperty( /* 10 */
148 		new MP4DescriptorProperty("esIds",
149 			MP4ESIDIncDescrTag, 0, Required, Many));
150 	AddProperty( /* 11 */
151 		new MP4DescriptorProperty("ociDescr",
152 			MP4OCIDescrTagsStart, MP4OCIDescrTagsEnd, Optional, Many));
153 	AddProperty( /* 12 */
154 		new MP4DescriptorProperty("ipmpDescrPtr",
155 			MP4IPMPPtrDescrTag, 0, Optional, Many));
156 	AddProperty( /* 13 */
157 		new MP4DescriptorProperty("extDescr",
158 			MP4ExtDescrTagsStart, MP4ExtDescrTagsEnd, Optional, Many));
159 
160 	SetReadMutate(2);
161 }
162 
Generate()163 void MP4IODescriptor::Generate()
164 {
165 	((MP4BitfieldProperty*)m_pProperties[0])->SetValue(1);
166 	((MP4BitfieldProperty*)m_pProperties[3])->SetValue(0xF);
167 	for (u_int32_t i = 5; i <= 9; i++) {
168 		((MP4Integer8Property*)m_pProperties[i])->SetValue(0xFF);
169 	}
170 }
171 
Mutate()172 void MP4IODescriptor::Mutate()
173 {
174 	bool urlFlag = ((MP4BitfieldProperty*)m_pProperties[1])->GetValue();
175 
176 	m_pProperties[4]->SetImplicit(!urlFlag);
177 	for (u_int32_t i = 5; i <= 12; i++) {
178 		m_pProperties[i]->SetImplicit(urlFlag);
179 	}
180 }
181 
MP4ODescriptor()182 MP4ODescriptor::MP4ODescriptor()
183 	: MP4Descriptor(MP4FileODescrTag)
184 {
185 	/* N.B. other member functions depend on the property indicies */
186 	AddProperty( /* 0 */
187 		new MP4BitfieldProperty("objectDescriptorId", 10));
188 	AddProperty( /* 1 */
189 		new MP4BitfieldProperty("URLFlag", 1));
190 	AddProperty( /* 2 */
191 		new MP4BitfieldProperty("reserved", 5));
192 	AddProperty( /* 3 */
193 		new MP4StringProperty("URL", Counted));
194 	AddProperty( /* 4 */
195 		new MP4DescriptorProperty("esIds",
196 			MP4ESIDRefDescrTag, 0, Required, Many));
197 	AddProperty( /* 5 */
198 		new MP4DescriptorProperty("ociDescr",
199 			MP4OCIDescrTagsStart, MP4OCIDescrTagsEnd, Optional, Many));
200 	AddProperty( /* 6 */
201 		new MP4DescriptorProperty("ipmpDescrPtr",
202 			MP4IPMPPtrDescrTag, 0, Optional, Many));
203 	AddProperty( /* 7 */
204 		new MP4DescriptorProperty("extDescr",
205 			MP4ExtDescrTagsStart, MP4ExtDescrTagsEnd, Optional, Many));
206 
207 	SetReadMutate(2);
208 }
209 
Generate()210 void MP4ODescriptor::Generate()
211 {
212 	((MP4BitfieldProperty*)m_pProperties[2])->SetValue(0x1F);
213 }
214 
Mutate()215 void MP4ODescriptor::Mutate()
216 {
217 	bool urlFlag = ((MP4BitfieldProperty*)m_pProperties[1])->GetValue();
218 
219 	m_pProperties[3]->SetImplicit(!urlFlag);
220 	for (u_int32_t i = 4; i <= 6; i++) {
221 		m_pProperties[i]->SetImplicit(urlFlag);
222 	}
223 }
224 
MP4ESDescriptor()225 MP4ESDescriptor::MP4ESDescriptor()
226 	: MP4Descriptor(MP4ESDescrTag)
227 {
228 	/* N.B. other class functions depend on the property indicies */
229 	AddProperty( /* 0 */
230 		new MP4Integer16Property("ESID"));
231 	AddProperty( /* 1 */
232 		new MP4BitfieldProperty("streamDependenceFlag", 1));
233 	AddProperty( /* 2 */
234 		new MP4BitfieldProperty("URLFlag", 1));
235 	AddProperty( /* 3 */
236 		new MP4BitfieldProperty("OCRstreamFlag", 1));
237 	AddProperty( /* 4 */
238 		new MP4BitfieldProperty("streamPriority", 5));
239 	AddProperty( /* 5 */
240 		new MP4Integer16Property("dependsOnESID"));
241 	AddProperty( /* 6 */
242 		new MP4StringProperty("URL", Counted));
243 	AddProperty( /* 7 */
244 		new MP4Integer16Property("OCRESID"));
245 	AddProperty( /* 8 */
246 		new MP4DescriptorProperty("decConfigDescr",
247 			MP4DecConfigDescrTag, 0, Required, OnlyOne));
248 	AddProperty( /* 9 */
249 		new MP4DescriptorProperty("slConfigDescr",
250 			MP4SLConfigDescrTag, 0, Required, OnlyOne));
251 	AddProperty( /* 10 */
252 		new MP4DescriptorProperty("ipiPtr",
253 			MP4IPIPtrDescrTag, 0, Optional, OnlyOne));
254 	AddProperty( /* 11 */
255 		new MP4DescriptorProperty("ipIds",
256 			MP4ContentIdDescrTag, MP4SupplContentIdDescrTag, Optional, Many));
257 	AddProperty( /* 12 */
258 		new MP4DescriptorProperty("ipmpDescrPtr",
259 			MP4IPMPPtrDescrTag, 0, Optional, Many));
260 	AddProperty( /* 13 */
261 		new MP4DescriptorProperty("langDescr",
262 			MP4LanguageDescrTag, 0, Optional, Many));
263 	AddProperty( /* 14 */
264 		new MP4DescriptorProperty("qosDescr",
265 			MP4QosDescrTag, 0, Optional, OnlyOne));
266 	AddProperty( /* 15 */
267 		new MP4DescriptorProperty("regDescr",
268 			MP4RegistrationDescrTag, 0, Optional, OnlyOne));
269 	AddProperty( /* 16 */
270 		new MP4DescriptorProperty("extDescr",
271 			MP4ExtDescrTagsStart, MP4ExtDescrTagsEnd, Optional, Many));
272 
273 	SetReadMutate(5);
274 }
275 
Mutate()276 void MP4ESDescriptor::Mutate()
277 {
278 	bool streamDependFlag =
279 		((MP4BitfieldProperty*)m_pProperties[1])->GetValue();
280 	m_pProperties[5]->SetImplicit(!streamDependFlag);
281 
282 	bool urlFlag =
283 		((MP4BitfieldProperty*)m_pProperties[2])->GetValue();
284 	m_pProperties[6]->SetImplicit(!urlFlag);
285 
286 	bool ocrFlag =
287 		((MP4BitfieldProperty*)m_pProperties[3])->GetValue();
288 	m_pProperties[7]->SetImplicit(!ocrFlag);
289 }
290 
MP4DecConfigDescriptor()291 MP4DecConfigDescriptor::MP4DecConfigDescriptor()
292 	: MP4Descriptor(MP4DecConfigDescrTag)
293 {
294 	AddProperty( /* 0 */
295 		new MP4Integer8Property("objectTypeId"));
296 	AddProperty( /* 1 */
297 		new MP4BitfieldProperty("streamType", 6));
298 	AddProperty( /* 2 */
299 		new MP4BitfieldProperty("upStream", 1));
300 	AddProperty( /* 3 */
301 		new MP4BitfieldProperty("reserved", 1));
302 	AddProperty( /* 4 */
303 		new MP4BitfieldProperty("bufferSizeDB", 24));
304 	AddProperty( /* 5 */
305 		new MP4Integer32Property("maxBitrate"));
306 	AddProperty( /* 6 */
307 		new MP4Integer32Property("avgBitrate"));
308 	AddProperty( /* 7 */
309 		new MP4DescriptorProperty("decSpecificInfo",
310 			MP4DecSpecificDescrTag, 0, Optional, OnlyOne));
311 	AddProperty( /* 8 */
312 		new MP4DescriptorProperty("profileLevelIndicationIndexDescr",
313 			MP4ExtProfileLevelDescrTag, 0, Optional, Many));
314 }
315 
Generate()316 void MP4DecConfigDescriptor::Generate()
317 {
318 	((MP4BitfieldProperty*)m_pProperties[3])->SetValue(1);
319 }
320 
MP4SLConfigDescriptor()321 MP4SLConfigDescriptor::MP4SLConfigDescriptor()
322 	: MP4Descriptor(MP4SLConfigDescrTag)
323 {
324 	AddProperty( /* 0 */
325 		new MP4Integer8Property("predefined"));
326 	AddProperty( /* 1 */
327 		new MP4BitfieldProperty("useAccessUnitStartFlag", 1));
328 	AddProperty( /* 2 */
329 		new MP4BitfieldProperty("useAccessUnitEndFlag", 1));
330 	AddProperty( /* 3 */
331 		new MP4BitfieldProperty("useRandomAccessPointFlag", 1));
332 	AddProperty( /* 4 */
333 		new MP4BitfieldProperty("hasRandomAccessUnitsOnlyFlag", 1));
334 	AddProperty( /* 5 */
335 		new MP4BitfieldProperty("usePaddingFlag", 1));
336 	AddProperty( /* 6 */
337 		new MP4BitfieldProperty("useTimeStampsFlag", 1));
338 	AddProperty( /* 7 */
339 		new MP4BitfieldProperty("useIdleFlag", 1));
340 	AddProperty( /* 8 */
341 		new MP4BitfieldProperty("durationFlag", 1));
342 	AddProperty( /* 9 */
343 		new MP4Integer32Property("timeStampResolution"));
344 	AddProperty( /* 10 */
345 		new MP4Integer32Property("OCRResolution"));
346 	AddProperty( /* 11 */
347 		new MP4Integer8Property("timeStampLength"));
348 	AddProperty( /* 12 */
349 		new MP4Integer8Property("OCRLength"));
350 	AddProperty( /* 13 */
351 		new MP4Integer8Property("AULength"));
352 	AddProperty( /* 14 */
353 		new MP4Integer8Property("instantBitrateLength"));
354 	AddProperty( /* 15 */
355 		new MP4BitfieldProperty("degradationPriortyLength", 4));
356 	AddProperty( /* 16 */
357 		new MP4BitfieldProperty("AUSeqNumLength", 5));
358 	AddProperty( /* 17 */
359 		new MP4BitfieldProperty("packetSeqNumLength", 5));
360 	AddProperty( /* 18 */
361 		new MP4BitfieldProperty("reserved", 2));
362 
363 	// if durationFlag
364 	AddProperty( /* 19 */
365 		new MP4Integer32Property("timeScale"));
366 	AddProperty( /* 20 */
367 		new MP4Integer16Property("accessUnitDuration"));
368 	AddProperty( /* 21 */
369 		new MP4Integer16Property("compositionUnitDuration"));
370 
371 	// if !useTimeStampsFlag
372 	AddProperty( /* 22 */
373 		new MP4BitfieldProperty("startDecodingTimeStamp", 64));
374 	AddProperty( /* 23 */
375 		new MP4BitfieldProperty("startCompositionTimeStamp", 64));
376 }
377 
Generate()378 void MP4SLConfigDescriptor::Generate()
379 {
380 	// by default all tracks in an mp4 file
381 	// use predefined SLConfig descriptor == 2
382 	((MP4Integer8Property*)m_pProperties[0])->SetValue(2);
383 
384 	// which implies UseTimestampsFlag = 1
385 	((MP4BitfieldProperty*)m_pProperties[6])->SetValue(1);
386 
387 	// reserved = 3
388 	((MP4BitfieldProperty*)m_pProperties[18])->SetValue(3);
389 }
390 
Read(MP4File * pFile)391 void MP4SLConfigDescriptor::Read(MP4File* pFile)
392 {
393 	ReadHeader(pFile);
394 
395 	// read the first property, 'predefined'
396 	ReadProperties(pFile, 0, 1);
397 
398 	// if predefined == 0
399 	if (((MP4Integer8Property*)m_pProperties[0])->GetValue() == 0) {
400 
401 		/* read the next 18 properties */
402 		ReadProperties(pFile, 1, 18);
403 	}
404 
405 	// now mutate
406 	Mutate();
407 
408 	// and read the remaining properties
409 	ReadProperties(pFile, 19);
410 }
411 
Mutate()412 void MP4SLConfigDescriptor::Mutate()
413 {
414 	u_int32_t i;
415 	u_int8_t predefined =
416 		((MP4Integer8Property*)m_pProperties[0])->GetValue();
417 
418 	if (predefined) {
419 		// properties 1-18 are implicit
420 		for (i = 1; i < m_pProperties.Size(); i++) {
421 			m_pProperties[i]->SetImplicit(true);
422 		}
423 
424 		if (predefined == 1) {
425 			// UseTimestampsFlag = 0
426 			((MP4BitfieldProperty*)m_pProperties[6])->SetValue(0);
427 
428 			// TimestampResolution = 1000
429 			((MP4Integer32Property*)m_pProperties[9])->SetValue(1000);
430 
431 			// TimeStampLength = 32
432 			((MP4Integer8Property*)m_pProperties[11])->SetValue(32);
433 
434 		} else if (predefined == 2) {
435 			// UseTimestampsFlag = 1
436 			((MP4BitfieldProperty*)m_pProperties[6])->SetValue(1);
437 		}
438 	} else {
439 #if 1
440 	  for (i = 1; i <= 18; i++) {
441 	    m_pProperties[i]->SetImplicit(false);
442 	  }
443 	((MP4BitfieldProperty*)m_pProperties[18])->SetValue(3);
444 #endif
445 	}
446 
447 	bool durationFlag =
448 		((MP4BitfieldProperty*)m_pProperties[8])->GetValue();
449 
450 	for (i = 19; i <= 21; i++) {
451 		m_pProperties[i]->SetImplicit(!durationFlag);
452 	}
453 
454 	bool useTimeStampsFlag =
455 		((MP4BitfieldProperty*)m_pProperties[6])->GetValue();
456 
457 	for (i = 22; i <= 23; i++) {
458 		m_pProperties[i]->SetImplicit(useTimeStampsFlag);
459 
460 		u_int8_t timeStampLength = MIN(64,
461 			((MP4Integer8Property*)m_pProperties[11])->GetValue());
462 
463 		((MP4BitfieldProperty*)m_pProperties[i])->SetNumBits(timeStampLength);
464 
465 		// handle a nonsensical situation gracefully
466 		if (timeStampLength == 0) {
467 			m_pProperties[i]->SetImplicit(true);
468 		}
469 	}
470 }
471 
MP4ContentIdDescriptor()472 MP4ContentIdDescriptor::MP4ContentIdDescriptor()
473 	: MP4Descriptor(MP4ContentIdDescrTag)
474 {
475 	AddProperty( /* 0 */
476 		new MP4BitfieldProperty("compatibility", 2));
477 	AddProperty( /* 1 */
478 		new MP4BitfieldProperty("contentTypeFlag", 1));
479 	AddProperty( /* 2 */
480 		new MP4BitfieldProperty("contentIdFlag", 1));
481 	AddProperty( /* 3 */
482 		new MP4BitfieldProperty("protectedContent", 1));
483 	AddProperty( /* 4 */
484 		new MP4BitfieldProperty("reserved", 3));
485 	AddProperty( /* 5 */
486 		new MP4Integer8Property("contentType"));
487 	AddProperty( /* 6 */
488 		new MP4Integer8Property("contentIdType"));
489 	AddProperty( /* 7 */
490 		new MP4BytesProperty("contentId"));
491 }
492 
Read(MP4File * pFile)493 void MP4ContentIdDescriptor::Read(MP4File* pFile)
494 {
495 	ReadHeader(pFile);
496 
497 	/* read the first property, 'compatiblity' */
498 	ReadProperties(pFile, 0, 1);
499 
500 	/* if compatiblity != 0 */
501 	if (((MP4Integer8Property*)m_pProperties[0])->GetValue() != 0) {
502 		/* we don't understand it */
503 		VERBOSE_READ(pFile->GetVerbosity(),
504 			printf("incompatible content id descriptor\n"));
505 		return;
506 	}
507 
508 	/* read the next four properties */
509 	ReadProperties(pFile, 1, 4);
510 
511 	/* which allows us to reconfigure ourselves */
512 	Mutate();
513 
514 	bool contentTypeFlag = ((MP4BitfieldProperty*)m_pProperties[1])->GetValue();
515 
516 	bool contentIdFlag = ((MP4BitfieldProperty*)m_pProperties[2])->GetValue();
517 
518   if (contentIdFlag) {
519 
520     u_int32_t cIdOffset = 2;
521 
522     if (contentTypeFlag) {
523 
524       cIdOffset++;
525 
526     }
527 
528   	((MP4BytesProperty*)m_pProperties[7])->SetValueSize(m_size - cIdOffset);
529 
530   }
531 
532 
533 
534 	/* read the remaining properties */
535 	ReadProperties(pFile, 5);
536 }
537 
Mutate()538 void MP4ContentIdDescriptor::Mutate()
539 {
540 	bool contentTypeFlag = ((MP4BitfieldProperty*)m_pProperties[1])->GetValue();
541 	m_pProperties[5]->SetImplicit(!contentTypeFlag);
542 
543 	bool contentIdFlag = ((MP4BitfieldProperty*)m_pProperties[2])->GetValue();
544 	m_pProperties[6]->SetImplicit(!contentIdFlag);
545 	m_pProperties[7]->SetImplicit(!contentIdFlag);
546 
547 }
548 
CreateDescriptor(u_int8_t tag)549 MP4Descriptor* MP4DescriptorProperty::CreateDescriptor(u_int8_t tag)
550 {
551 	MP4Descriptor* pDescriptor = NULL;
552 
553 	switch (tag) {
554 	case MP4ESDescrTag:
555 		pDescriptor = new MP4ESDescriptor();
556 		break;
557 	case MP4DecConfigDescrTag:
558 		pDescriptor = new MP4DecConfigDescriptor();
559 		break;
560 	case MP4DecSpecificDescrTag:
561 	case MP4IPMPDescrTag:
562 	case MP4RegistrationDescrTag:
563 		pDescriptor = new MP4BytesDescriptor(tag);
564 		break;
565 	case MP4SLConfigDescrTag:
566 		pDescriptor = new MP4SLConfigDescriptor();
567 		break;
568 	case MP4ContentIdDescrTag:
569 		pDescriptor = new MP4ContentIdDescriptor();
570 		break;
571 	case MP4ESIDIncDescrTag:
572 	case MP4ESIDRefDescrTag:
573 	case MP4IPIPtrDescrTag:
574 	case MP4SupplContentIdDescrTag:
575 	case MP4IPMPPtrDescrTag:
576 	case MP4ExtProfileLevelDescrTag:
577 	        pDescriptor = new MP4BaseDescriptor(tag);
578 		break;
579 	case MP4QosDescrTag:
580 		pDescriptor = new MP4QosDescriptorBase(MP4QosDescrTag);
581 		break;
582 	case MP4IODescrTag:
583 	case MP4FileIODescrTag:
584 		pDescriptor = new MP4IODescriptor();
585 		pDescriptor->SetTag(tag);
586 		break;
587 	case MP4ODescrTag:
588 	case MP4FileODescrTag:
589 		pDescriptor = new MP4ODescriptor();
590 		pDescriptor->SetTag(tag);
591 		break;
592 	}
593 
594 	if (pDescriptor == NULL) {
595 		if (tag >= MP4OCIDescrTagsStart && tag <= MP4OCIDescrTagsEnd) {
596 			pDescriptor = CreateOCIDescriptor(tag);
597 		}
598 
599 		if (tag >= MP4ExtDescrTagsStart && tag <= MP4ExtDescrTagsEnd) {
600 			pDescriptor = new MP4BytesDescriptor(tag);
601 		}
602 	}
603 
604 	return pDescriptor;
605 }
606 
607