Ap4RtpHint.cpp
上传用户:xjjlds
上传日期:2015-12-05
资源大小:22823k
文件大小:21k
源码类别:

多媒体编程

开发平台:

Visual C++

  1. /*****************************************************************
  2. |
  3. |    AP4 - RTP Hint Objects
  4. |
  5. |    Copyright 2002-2005 Gilles Boccon-Gibod & Julien Boeuf
  6. |
  7. |
  8. |    This file is part of Bento4/AP4 (MP4 Atom Processing Library).
  9. |
  10. |    Unless you have obtained Bento4 under a difference license,
  11. |    this version of Bento4 is Bento4|GPL.
  12. |    Bento4|GPL is free software; you can redistribute it and/or modify
  13. |    it under the terms of the GNU General Public License as published by
  14. |    the Free Software Foundation; either version 2, or (at your option)
  15. |    any later version.
  16. |
  17. |    Bento4|GPL is distributed in the hope that it will be useful,
  18. |    but WITHOUT ANY WARRANTY; without even the implied warranty of
  19. |    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  20. |    GNU General Public License for more details.
  21. |
  22. |    You should have received a copy of the GNU General Public License
  23. |    along with Bento4|GPL; see the file COPYING.  If not, write to the
  24. |    Free Software Foundation, 59 Temple Place - Suite 330, Boston, MA
  25. |    02111-1307, USA.
  26. |
  27. ****************************************************************/
  28. /*----------------------------------------------------------------------
  29. |       includes
  30. +---------------------------------------------------------------------*/
  31. #include "Ap4RtpHint.h"
  32. #include "Ap4ByteStream.h"
  33. #include "Ap4Atom.h"
  34. /*----------------------------------------------------------------------
  35. |       AP4_RtpSampleData::~AP4_RtpSampleData
  36. +---------------------------------------------------------------------*/
  37. AP4_RtpSampleData::~AP4_RtpSampleData()
  38. {
  39.     AP4_List<AP4_RtpPacket>::Item* it = m_Packets.FirstItem();
  40.     while (it != NULL) {
  41.         it->GetData()->Release();
  42.         it = it->GetNext();
  43.     }
  44. }
  45. /*----------------------------------------------------------------------
  46. |       AP4_RtpSampleData::AP4_RtpSampleData
  47. +---------------------------------------------------------------------*/
  48. AP4_RtpSampleData::AP4_RtpSampleData(AP4_ByteStream& stream, AP4_Size size)
  49. {
  50.     // save the start position
  51.     AP4_Offset start, extra_data_start;
  52.     stream.Tell(start);
  53.     AP4_UI16 packet_count;
  54.     stream.ReadUI16(packet_count);
  55.     
  56.     AP4_UI16 reserved;
  57.     stream.ReadUI16(reserved); // later, check that reserved is 0
  58.     // packets
  59.     for (AP4_UI16 i=0; i<packet_count; i++) {
  60.         AP4_RtpPacket* packet = new AP4_RtpPacket(stream);
  61.         m_Packets.Add(packet);
  62.     }
  63.     // extra data
  64.     stream.Tell(extra_data_start);
  65.     AP4_Size extra_data_size = size - (extra_data_start-start);
  66.     if (extra_data_size != 0) {
  67.         m_ExtraData.SetDataSize(extra_data_size);
  68.         stream.Read(m_ExtraData.UseData(), extra_data_size);
  69.     }
  70. }
  71. /*----------------------------------------------------------------------
  72. |       AP4_RtpSampleData::GetSize
  73. +---------------------------------------------------------------------*/
  74. AP4_Size
  75. AP4_RtpSampleData::GetSize()
  76. {
  77.     // packet count and reserved
  78.     AP4_Size result = 4;
  79.     // packets
  80.     AP4_List<AP4_RtpPacket>::Item* it = m_Packets.FirstItem();
  81.     while (it != NULL) {
  82.         result = it->GetData()->GetSize();
  83.         it = it->GetNext();
  84.     }
  85.     // extra data
  86.     result += m_ExtraData.GetDataSize();
  87.     return result;
  88. }
  89. /*----------------------------------------------------------------------
  90. |       AP4_RtpSampleData::ToByteStream
  91. +---------------------------------------------------------------------*/
  92. AP4_ByteStream*
  93. AP4_RtpSampleData::ToByteStream()
  94. {
  95.     // refresh the size
  96.     AP4_Size size = GetSize();
  97.     // create a memory stream
  98.     AP4_MemoryByteStream* stream = new AP4_MemoryByteStream(size);
  99.     // write in it
  100.     AP4_Result result = stream->WriteUI16(static_cast<AP4_UI16>(m_Packets.ItemCount()));
  101.     if (AP4_FAILED(result)) goto bail;
  102.     result = stream->WriteUI16(0); // reserved
  103.     if (AP4_FAILED(result)) goto bail;
  104.     {
  105. AP4_List<AP4_RtpPacket>::Item* it = m_Packets.FirstItem();
  106. while (it != NULL) {
  107. result = it->GetData()->Write(*stream);
  108. if (AP4_FAILED(result)) goto bail;
  109. it = it->GetNext();
  110. }
  111. }
  112.     result = stream->Write(m_ExtraData.GetData(), m_ExtraData.GetDataSize());
  113.     if (AP4_FAILED(result)) goto bail;
  114.     // return
  115.     return stream;
  116. bail:
  117.     stream->Release();
  118.     return NULL;
  119. }
  120. /*----------------------------------------------------------------------
  121. |       AP4_RtpSampleData::AddPacket
  122. +---------------------------------------------------------------------*/
  123. AP4_Result
  124. AP4_RtpSampleData::AddPacket(AP4_RtpPacket* packet)
  125. {
  126.     packet->AddReference();
  127.     return m_Packets.Add(packet);
  128. }
  129. /*----------------------------------------------------------------------
  130. |       AP4_RtpPacket::AP4_RtpPacket
  131. +---------------------------------------------------------------------*/
  132. AP4_RtpPacket::AP4_RtpPacket(AP4_Integer relative_time, 
  133.                              bool p_bit, 
  134.                              bool x_bit, 
  135.                              bool m_bit, 
  136.                              AP4_UI08 payload_type, 
  137.                              AP4_UI16 sequence_seed, 
  138.                              AP4_Integer time_stamp_offset /* = 0 */,
  139.                              bool bframe_flag /* = false */, 
  140.                              bool repeat_flag /* = false */) :
  141.     m_ReferenceCount(1),
  142.     m_RelativeTime(relative_time),
  143.     m_PBit(p_bit),
  144.     m_XBit(x_bit),
  145.     m_MBit(m_bit),
  146.     m_PayloadType(payload_type),
  147.     m_SequenceSeed(sequence_seed),
  148.     m_TimeStampOffset(time_stamp_offset),
  149.     m_BFrameFlag(bframe_flag),
  150.     m_RepeatFlag(repeat_flag)
  151. {}
  152. /*----------------------------------------------------------------------
  153. |       AP4_RtpPacket::AP4_RtpPacket
  154. +---------------------------------------------------------------------*/
  155. AP4_RtpPacket::AP4_RtpPacket(AP4_ByteStream& stream) :
  156.     m_ReferenceCount(1),
  157.     m_TimeStampOffset(0)
  158. {
  159.     AP4_UI08 octet;
  160.     // relative time
  161.     AP4_UI32 relative_time;
  162.     stream.ReadUI32(relative_time);
  163.     m_RelativeTime = relative_time;
  164.     // pbit and xbit
  165.     stream.ReadUI08(octet);
  166.     m_PBit = (octet & 0x20) != 0;
  167.     m_XBit = (octet & 0x10) != 0;
  168.     // mbit and payload type
  169.     stream.ReadUI08(octet);
  170.     m_MBit = (octet & 0x80) != 0;
  171.     m_PayloadType = octet & 0x7F;
  172.     // sequence seed
  173.     stream.ReadUI16(m_SequenceSeed);
  174.     // extra, bframe and repeat flags
  175.     stream.ReadUI08(octet);
  176.     stream.ReadUI08(octet); // repeat on purpose
  177.     bool extra_flag = (octet & 0x04) != 0;
  178.     // bframe and repeat flags
  179.     m_BFrameFlag = (octet & 0x02) != 0;
  180.     m_RepeatFlag = (octet & 0x01) != 0;
  181.     // constructor count
  182.     AP4_UI16 constructor_count;
  183.     stream.ReadUI16(constructor_count);
  184.     // parse the packet extra data
  185.     if (extra_flag) {
  186.         // read the length
  187.         AP4_UI32 extra_length;
  188.         stream.ReadUI32(extra_length);
  189.         // check it 
  190.         if (extra_length < 4) 
  191.             throw AP4_Exception(AP4_ERROR_INVALID_RTP_PACKET_EXTRA_DATA);
  192.         // now read the entries
  193.         extra_length -= 4;
  194.         while (extra_length > 0) {
  195.             AP4_UI32 entry_length;
  196.             AP4_UI32 entry_tag;
  197.             stream.ReadUI32(entry_length);
  198.             stream.ReadUI32(entry_tag);
  199.             // check the entry
  200.             if (entry_length < 8) {
  201.                 throw AP4_Exception(AP4_ERROR_INVALID_RTP_PACKET_EXTRA_DATA);
  202.             }
  203.             // parse the single entry that's currently defined in the spec
  204.             if (entry_tag == AP4_ATOM_TYPE('r','t','p','o') && entry_length == 12) {
  205.                 AP4_UI32 time_stamp_offset;
  206.                 stream.ReadUI32(time_stamp_offset);
  207.                 m_TimeStampOffset = time_stamp_offset;
  208.             } else {
  209.                 // ignore it
  210.                 AP4_Offset cur_pos;
  211.                 stream.Tell(cur_pos);
  212.                 stream.Seek(cur_pos + entry_length - 8); // 8 = length + tag
  213.             }
  214.             extra_length -= entry_length;
  215.         }
  216.     }
  217.     // constructors
  218.     for (AP4_UI16 i=0; i<constructor_count; i++) {
  219.         AP4_RtpConstructor* constructor = NULL;
  220.         AP4_RtpConstructorFactory::CreateConstructorFromStream(stream, constructor);
  221.         m_Constructors.Add(constructor);
  222.     }
  223. }
  224. /*----------------------------------------------------------------------
  225. |       AP4_RtpPacket::AP4_RtpPacket
  226. +---------------------------------------------------------------------*/
  227. AP4_RtpPacket::~AP4_RtpPacket()
  228. {
  229.     AP4_List<AP4_RtpConstructor>::Item* it = m_Constructors.FirstItem();
  230.     while (it != NULL) {
  231.         it->GetData()->Release();
  232.         it = it->GetNext();
  233.     }
  234. }
  235. /*----------------------------------------------------------------------
  236. |       AP4_RtpPacket::AddReference
  237. +---------------------------------------------------------------------*/
  238. void
  239. AP4_RtpPacket::AddReference()
  240. {
  241.     m_ReferenceCount++;
  242. }
  243. /*----------------------------------------------------------------------
  244. |       AP4_RtpPacket::Release
  245. +---------------------------------------------------------------------*/
  246. void
  247. AP4_RtpPacket::Release()
  248. {
  249.     if (--m_ReferenceCount == 0) {
  250.         delete this;
  251.     }
  252. }
  253. /*----------------------------------------------------------------------
  254. |       AP4_RtpPacket::GetSize
  255. +---------------------------------------------------------------------*/
  256. AP4_Size
  257. AP4_RtpPacket::GetSize()
  258. {
  259.     AP4_Size result = 12 + (m_TimeStampOffset != 0)?16:0; 
  260.     result += m_Constructors.ItemCount() * AP4_RTP_CONSTRUCTOR_SIZE;
  261.     return result;
  262. }
  263. /*----------------------------------------------------------------------
  264. |       AP4_RtpPacket::Write
  265. +---------------------------------------------------------------------*/
  266. AP4_Result
  267. AP4_RtpPacket::Write(AP4_ByteStream& stream) 
  268. {
  269.     // check the payload type
  270.     if (m_PayloadType > 128) return AP4_FAILURE;
  271.     // now write
  272.     AP4_Result result = stream.WriteUI32(m_RelativeTime);
  273.     if (AP4_FAILED(result)) return result;
  274.     result = stream.WriteUI08(0x80 | m_PBit << 5 | m_XBit << 4);
  275.     if (AP4_FAILED(result)) return result;
  276.     result = stream.WriteUI08(m_MBit << 7 | m_PayloadType);
  277.     if (AP4_FAILED(result)) return result;
  278.     result = stream.WriteUI16(m_SequenceSeed);
  279.     if (AP4_FAILED(result)) return result;
  280.     result = stream.WriteUI08(0);
  281.     if (AP4_FAILED(result)) return result;
  282.     // deal with extra flag
  283.     bool extra_flag = m_TimeStampOffset != 0;
  284.     result = stream.WriteUI08(0x00 | extra_flag << 2 
  285.                                    | m_BFrameFlag << 1 
  286.                                    | m_RepeatFlag << 0);
  287.     if (AP4_FAILED(result)) return result;
  288.     // constructor count
  289.     result = stream.WriteUI16(static_cast<AP4_UI16>(m_Constructors.ItemCount()));
  290.     // write extra data
  291.     if (extra_flag) {
  292.         // extra_length
  293.         result = stream.WriteUI32(16); // 4 (extra_length) + 12 (rtpo atom)
  294.         if (AP4_FAILED(result)) return result;
  295.         // rtpo atom
  296.         result = stream.WriteUI32(12); // size
  297.         if (AP4_FAILED(result)) return result;
  298.         result = stream.WriteUI32(AP4_ATOM_TYPE('r','t','p','o'));
  299.         if (AP4_FAILED(result)) return result;
  300.         result = stream.WriteUI32(m_TimeStampOffset);
  301.         if (AP4_FAILED(result)) return result;
  302.     }
  303.     // constructors
  304.     AP4_List<AP4_RtpConstructor>::Item* it = m_Constructors.FirstItem();
  305.     while (it != NULL) {
  306.         result = it->GetData()->Write(stream);
  307.         if (AP4_FAILED(result)) return result;
  308.         it = it->GetNext();
  309.     }
  310.     return result;
  311. }
  312. /*----------------------------------------------------------------------
  313. |       AP4_RtpPacket::AddConstructor
  314. +---------------------------------------------------------------------*/
  315. AP4_Result
  316. AP4_RtpPacket::AddConstructor(AP4_RtpConstructor* constructor) 
  317. {
  318.     constructor->AddReference();
  319.     return m_Constructors.Add(constructor);
  320. }
  321. /*----------------------------------------------------------------------
  322. |       AP4_RtpConstructor::GetConstructedDataSize
  323. +---------------------------------------------------------------------*/
  324. AP4_Size
  325. AP4_RtpPacket::GetConstructedDataSize()
  326. {
  327.     // header + ssrc
  328.     AP4_Size size = 12;
  329.     // constructed data from constructors
  330.     AP4_List<AP4_RtpConstructor>::Item* constructors_it 
  331.         = m_Constructors.FirstItem();
  332.     while (constructors_it != NULL) {
  333.         size += constructors_it->GetData()->GetConstructedDataSize();
  334.         constructors_it = constructors_it->GetNext();
  335.     }
  336.     return size;
  337. }
  338. /*----------------------------------------------------------------------
  339. |       AP4_RtpConstructor::AddReference
  340. +---------------------------------------------------------------------*/
  341. void
  342. AP4_RtpConstructor::AddReference()
  343. {
  344.     m_ReferenceCount++;
  345. }
  346. /*----------------------------------------------------------------------
  347. |       AP4_RtpConstructor::Release
  348. +---------------------------------------------------------------------*/
  349. void
  350. AP4_RtpConstructor::Release()
  351. {
  352.     if (--m_ReferenceCount == 0) {
  353.         delete this;
  354.     }
  355. }
  356. /*----------------------------------------------------------------------
  357. |       AP4_RtpConstructor::Write
  358. +---------------------------------------------------------------------*/
  359. AP4_Result
  360. AP4_RtpConstructor::Write(AP4_ByteStream& stream)
  361. {
  362.     AP4_Result result = stream.WriteUI08(m_Type);
  363.     if (AP4_FAILED(result)) return result;
  364.     return DoWrite(stream);
  365. }
  366. /*----------------------------------------------------------------------
  367. |       AP4_NoopRtpConstructor::AP4_NoopRtpConstructor
  368. +---------------------------------------------------------------------*/
  369. AP4_NoopRtpConstructor::AP4_NoopRtpConstructor(AP4_ByteStream& stream) :
  370.     AP4_RtpConstructor(AP4_RTP_CONSTRUCTOR_TYPE_NOOP)
  371. {
  372.     AP4_Offset cur_offset;
  373.     stream.Tell(cur_offset);
  374.     stream.Seek(cur_offset+15);
  375. }
  376. /*----------------------------------------------------------------------
  377. |       AP4_NoopRtpConstructor::DoWrite
  378. +---------------------------------------------------------------------*/
  379. AP4_Result
  380. AP4_NoopRtpConstructor::DoWrite(AP4_ByteStream& stream)
  381. {
  382.     AP4_UI08 pad[15];
  383.     return stream.Write(pad, sizeof(pad));
  384. }
  385. /*----------------------------------------------------------------------
  386. |       AP4_ImmediateRtpConstructor::AP4_ImmediateRtpConstructor
  387. +---------------------------------------------------------------------*/
  388. AP4_ImmediateRtpConstructor::AP4_ImmediateRtpConstructor(const AP4_DataBuffer& data) :
  389.     AP4_RtpConstructor(AP4_RTP_CONSTRUCTOR_TYPE_IMMEDIATE),
  390.     m_Data(data)
  391. {}
  392. /*----------------------------------------------------------------------
  393. |       AP4_ImmediateRtpConstructor::AP4_ImmediateRtpConstructor
  394. +---------------------------------------------------------------------*/
  395. AP4_ImmediateRtpConstructor::AP4_ImmediateRtpConstructor(AP4_ByteStream& stream) :
  396.     AP4_RtpConstructor(AP4_RTP_CONSTRUCTOR_TYPE_IMMEDIATE)
  397. {
  398.     AP4_Offset cur_offset;
  399.     stream.Tell(cur_offset);
  400.     // data
  401.     AP4_UI08 data_size;
  402.     stream.ReadUI08(data_size);
  403.     m_Data.SetDataSize(data_size);
  404.     stream.Read(m_Data.UseData(), data_size);
  405.     // reposition the stream
  406.     stream.Seek(cur_offset+15);
  407. }
  408. /*----------------------------------------------------------------------
  409. |       AP4_ImmediateRtpConstructor::DoWrite
  410. +---------------------------------------------------------------------*/
  411. AP4_Result
  412. AP4_ImmediateRtpConstructor::DoWrite(AP4_ByteStream& stream)
  413. {
  414.     // first check that the data is not too large
  415.     if (m_Data.GetDataSize() > 14) return AP4_FAILURE;
  416.     // now write
  417.     AP4_Result result = stream.WriteUI08(static_cast<AP4_UI08>(m_Data.GetDataSize()));
  418.     if (AP4_FAILED(result)) return result;
  419.     result = stream.Write(m_Data.GetData(), m_Data.GetDataSize());
  420.     if (AP4_FAILED(result)) return result;
  421.     // pad
  422.     AP4_Byte pad[14];
  423.     return stream.Write(pad, sizeof(pad)-m_Data.GetDataSize());
  424. }
  425. /*----------------------------------------------------------------------
  426. |       AP4_SampleRtpConstructor::AP4_SampleRtpConstructor
  427. +---------------------------------------------------------------------*/
  428. AP4_SampleRtpConstructor::AP4_SampleRtpConstructor(AP4_UI08 track_ref_index, 
  429.                                                    AP4_UI16 length, 
  430.                                                    AP4_UI32 sample_num, 
  431.                                                    AP4_UI32 sample_offset) :
  432.     AP4_RtpConstructor(AP4_RTP_CONSTRUCTOR_TYPE_SAMPLE),
  433.     m_TrackRefIndex(track_ref_index),
  434.     m_Length(length),
  435.     m_SampleNum(sample_num),
  436.     m_SampleOffset(sample_offset)
  437. {}
  438. /*----------------------------------------------------------------------
  439. |       AP4_SampleRtpConstructor::AP4_SampleRtpConstructor
  440. +---------------------------------------------------------------------*/
  441. AP4_SampleRtpConstructor::AP4_SampleRtpConstructor(AP4_ByteStream& stream) :
  442.     AP4_RtpConstructor(AP4_RTP_CONSTRUCTOR_TYPE_SAMPLE)
  443. {
  444.     // offset
  445.     AP4_Offset cur_offset;
  446.     stream.Tell(cur_offset);
  447.     // data
  448.     stream.ReadUI08(m_TrackRefIndex);
  449.     stream.ReadUI16(m_Length);
  450.     stream.ReadUI32(m_SampleNum);
  451.     stream.ReadUI32(m_SampleOffset);
  452.     // reposition the stream
  453.     stream.Seek(cur_offset+15);
  454. }
  455. /*----------------------------------------------------------------------
  456. |       AP4_SampleRtpConstructor::DoWrite
  457. +---------------------------------------------------------------------*/
  458. AP4_Result
  459. AP4_SampleRtpConstructor::DoWrite(AP4_ByteStream& stream)
  460. {
  461.     AP4_Result result = stream.WriteUI08(m_TrackRefIndex);
  462.     if (AP4_FAILED(result)) return result;
  463.     result = stream.WriteUI16(m_Length);
  464.     if (AP4_FAILED(result)) return result;
  465.     result = stream.WriteUI32(m_SampleNum);
  466.     if (AP4_FAILED(result)) return result;
  467.     result = stream.WriteUI32(m_SampleOffset);
  468.     if (AP4_FAILED(result)) return result;
  469.     result = stream.WriteUI16(1); // bytes per block
  470.     if (AP4_FAILED(result)) return result;
  471.     return stream.WriteUI16(1); // samples per block
  472. }
  473. /*----------------------------------------------------------------------
  474. |       AP4_SampleDescRtpConstructor::AP4_SampleDescRtpConstructor
  475. +---------------------------------------------------------------------*/
  476. AP4_SampleDescRtpConstructor::AP4_SampleDescRtpConstructor(AP4_UI08 track_ref_index, 
  477.                                                            AP4_UI16 length, 
  478.                                                            AP4_UI32 sample_desc_index, 
  479.                                                            AP4_UI32 sample_desc_offset) :
  480.     AP4_RtpConstructor(AP4_RTP_CONSTRUCTOR_TYPE_SAMPLE_DESC),
  481.     m_TrackRefIndex(track_ref_index),
  482.     m_Length(length),
  483.     m_SampleDescIndex(sample_desc_index),
  484.     m_SampleDescOffset(sample_desc_offset)
  485. {}
  486. /*----------------------------------------------------------------------
  487. |       AP4_SampleDescRtpConstructor::AP4_SampleDescRtpConstructor
  488. +---------------------------------------------------------------------*/
  489. AP4_SampleDescRtpConstructor::AP4_SampleDescRtpConstructor(AP4_ByteStream& stream) :
  490.     AP4_RtpConstructor(AP4_RTP_CONSTRUCTOR_TYPE_SAMPLE_DESC)
  491. {
  492.     // offset
  493.     AP4_Offset cur_offset;
  494.     stream.Tell(cur_offset);
  495.     // data
  496.     stream.ReadUI08(m_TrackRefIndex);
  497.     stream.ReadUI16(m_Length);
  498.     stream.ReadUI32(m_SampleDescIndex);
  499.     stream.ReadUI32(m_SampleDescOffset);
  500.     // reposition the stream
  501.     stream.Seek(cur_offset+15);
  502. }
  503. /*----------------------------------------------------------------------
  504. |       AP4_SampleDescRtpConstructor::DoWrite
  505. +---------------------------------------------------------------------*/
  506. AP4_Result
  507. AP4_SampleDescRtpConstructor::DoWrite(AP4_ByteStream& stream)
  508. {
  509.     AP4_Result result = stream.WriteUI08(m_TrackRefIndex);
  510.     if (AP4_FAILED(result)) return result;
  511.     result = stream.WriteUI16(m_Length);
  512.     if (AP4_FAILED(result)) return result;
  513.     result = stream.WriteUI32(m_SampleDescIndex);
  514.     if (AP4_FAILED(result)) return result;
  515.     result = stream.WriteUI32(m_SampleDescOffset);
  516.     if (AP4_FAILED(result)) return result;
  517.     return stream.WriteUI32(0); // reserved
  518. }
  519. /*----------------------------------------------------------------------
  520. |       AP4_RtpConstructorFactory::CreateConstructorFromStream
  521. +---------------------------------------------------------------------*/
  522. AP4_Result
  523. AP4_RtpConstructorFactory::CreateConstructorFromStream(AP4_ByteStream& stream, 
  524.                                                        AP4_RtpConstructor*& constructor)
  525. {
  526.     // read the first byte (type)
  527.     AP4_RtpConstructor::Type type;
  528.     AP4_Result result = stream.ReadUI08(type);
  529.     if (AP4_FAILED(result)) return result;
  530.     switch(type) {
  531.         case AP4_RTP_CONSTRUCTOR_TYPE_NOOP:
  532.             constructor = new AP4_NoopRtpConstructor(stream);
  533.             break;
  534.         case AP4_RTP_CONSTRUCTOR_TYPE_IMMEDIATE:
  535.             constructor = new AP4_ImmediateRtpConstructor(stream);
  536.             break;
  537.         case AP4_RTP_CONSTRUCTOR_TYPE_SAMPLE:
  538.             constructor = new AP4_SampleRtpConstructor(stream);
  539.             break;
  540.         case AP4_RTP_CONSTRUCTOR_TYPE_SAMPLE_DESC:
  541.             constructor = new AP4_SampleDescRtpConstructor(stream);
  542.             break;
  543.         default:
  544.             return AP4_ERROR_INVALID_RTP_CONSTRUCTOR_TYPE;
  545.     }
  546.     return AP4_SUCCESS;
  547. }