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

多媒体编程

开发平台:

Visual C++

  1. /*****************************************************************
  2. |
  3. |    AP4 - Atom Factory
  4. |
  5. |    Copyright 2002 Gilles Boccon-Gibod
  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 "Ap4.h"
  32. #include "Ap4AtomFactory.h"
  33. #include "Ap4SampleEntry.h"
  34. #include "Ap4IsmaCryp.h"
  35. #include "Ap4UrlAtom.h"
  36. #include "Ap4MoovAtom.h"
  37. #include "Ap4MvhdAtom.h"
  38. #include "Ap4TrakAtom.h"
  39. #include "Ap4HdlrAtom.h"
  40. #include "Ap4DrefAtom.h"
  41. #include "Ap4TkhdAtom.h"
  42. #include "Ap4MdhdAtom.h"
  43. #include "Ap4StsdAtom.h"
  44. #include "Ap4StscAtom.h"
  45. #include "Ap4StcoAtom.h"
  46. #include "Ap4Co64Atom.h"
  47. #include "Ap4StszAtom.h"
  48. #include "Ap4EsdsAtom.h"
  49. #include "Ap4SttsAtom.h"
  50. #include "Ap4CttsAtom.h"
  51. #include "Ap4StssAtom.h"
  52. #include "Ap4FtypAtom.h"
  53. #include "Ap4VmhdAtom.h"
  54. #include "Ap4SmhdAtom.h"
  55. #include "Ap4NmhdAtom.h"
  56. #include "Ap4HmhdAtom.h"
  57. #include "Ap4SchmAtom.h"
  58. #include "Ap4FrmaAtom.h"
  59. #include "Ap4TimsAtom.h"
  60. #include "Ap4RtpAtom.h"
  61. #include "Ap4SdpAtom.h"
  62. #include "Ap4IkmsAtom.h"
  63. #include "Ap4IsfmAtom.h"
  64. #include "Ap4TrefTypeAtom.h"
  65. #include "Ap4AvcCAtom.h"
  66. #include "Ap4FtabAtom.h"
  67. #include "Ap4ChplAtom.h"
  68. #include "Ap4DataAtom.h"
  69. /*----------------------------------------------------------------------
  70. |       class variables
  71. +---------------------------------------------------------------------*/
  72. AP4_AtomFactory AP4_AtomFactory::DefaultFactory;
  73. /*----------------------------------------------------------------------
  74. |       AP4_AtomFactory::AddTypeHandler
  75. +---------------------------------------------------------------------*/
  76. AP4_Result
  77. AP4_AtomFactory::AddTypeHandler(TypeHandler* handler)
  78. {
  79.     return m_TypeHandlers.Add(handler);
  80. }
  81. /*----------------------------------------------------------------------
  82. |       AP4_AtomFactory::RemoveTypeHandler
  83. +---------------------------------------------------------------------*/
  84. AP4_Result
  85. AP4_AtomFactory::RemoveTypeHandler(TypeHandler* handler)
  86. {
  87.     return m_TypeHandlers.Remove(handler);
  88. }
  89. /*----------------------------------------------------------------------
  90. |       AP4_AtomFactory::CreateAtomFromStream
  91. +---------------------------------------------------------------------*/
  92. AP4_Result
  93. AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream, 
  94.                                       AP4_Atom*&      atom)
  95. {
  96.     AP4_Size bytes_available = 0;
  97.     if (AP4_FAILED(stream.GetSize(bytes_available)) ||
  98.         bytes_available == 0) {
  99.         bytes_available = (AP4_Size)((unsigned long)(-1));
  100.     }
  101.     return CreateAtomFromStream(stream, bytes_available, atom);
  102. }
  103. /*----------------------------------------------------------------------
  104. |       AP4_AtomFactory::CreateAtomFromStream
  105. +---------------------------------------------------------------------*/
  106. AP4_Result
  107. AP4_AtomFactory::CreateAtomFromStream(AP4_ByteStream& stream, 
  108.                                       AP4_Size&       bytes_available,
  109.                                       AP4_Atom*&      atom)
  110. {
  111.     AP4_Result result;
  112.     // NULL by default
  113.     atom = NULL;
  114.     // check that there are enough bytes for at least a header
  115.     if (bytes_available < 8) return AP4_ERROR_EOS;
  116.     // remember current stream offset
  117.     AP4_Offset start;
  118.     stream.Tell(start);
  119.     // read atom size
  120.     AP4_UI32 size;
  121.     result = stream.ReadUI32(size);
  122.     if (AP4_FAILED(result)) {
  123.         stream.Seek(start);
  124.         return result;
  125.     }
  126.     if (size == 0) {
  127.         // atom extends to end of file
  128.         AP4_Size streamSize = 0;
  129.         stream.GetSize(streamSize);
  130.         if (streamSize >= start) {
  131.             size = streamSize - start;
  132.         }
  133.     }
  134.     // check the size (we don't handle extended size yet)
  135.     if (size != 1 && size < 8 || size > bytes_available) {
  136.         stream.Seek(start);
  137.         return AP4_ERROR_INVALID_FORMAT;
  138.     }
  139.     // read atom type
  140.     AP4_Atom::Type type;
  141.     result = stream.ReadUI32(type);
  142.     if (AP4_FAILED(result)) {
  143.         stream.Seek(start);
  144.         return result;
  145.     }
  146. if (size == 1)
  147. {
  148. AP4_UI32 size_high;
  149. result = stream.ReadUI32(size_high);
  150. if (AP4_FAILED(result) || size_high) {
  151. stream.Seek(start);
  152. return AP4_ERROR_INVALID_FORMAT;
  153. }
  154. result = stream.ReadUI32(size);
  155. if (AP4_FAILED(result)) {
  156. stream.Seek(start);
  157. return result;
  158. }
  159. }
  160.     // create the atom
  161.     switch (type) {
  162.       case AP4_ATOM_TYPE_MOOV:
  163.         atom = new AP4_MoovAtom(size, stream, *this);
  164.         break;
  165.       case AP4_ATOM_TYPE_MVHD:
  166.         atom = new AP4_MvhdAtom(size, stream);
  167.         break;
  168.       case AP4_ATOM_TYPE_TRAK:
  169.         atom = new AP4_TrakAtom(size, stream, *this);
  170.         break;
  171.       case AP4_ATOM_TYPE_HDLR:
  172.         atom = new AP4_HdlrAtom(size, stream);
  173.         break;
  174.       case AP4_ATOM_TYPE_DREF:
  175.         atom = new AP4_DrefAtom(size, stream, *this);
  176.         break;
  177.       case AP4_ATOM_TYPE_URL:
  178.         atom = new AP4_UrlAtom(size, stream);
  179.         break;
  180.       case AP4_ATOM_TYPE_TKHD:
  181.         atom = new AP4_TkhdAtom(size, stream);
  182.         break;
  183.       case AP4_ATOM_TYPE_MDHD:
  184.         atom = new AP4_MdhdAtom(size, stream);
  185.         break;
  186.       case AP4_ATOM_TYPE_STSD:
  187.         atom = new AP4_StsdAtom(size, stream, *this);
  188.         break;
  189.       case AP4_ATOM_TYPE_STSC:
  190.         atom = new AP4_StscAtom(size, stream);
  191.         break;
  192.       case AP4_ATOM_TYPE_STCO:
  193.         atom = new AP4_StcoAtom(size, stream);
  194.         break;
  195.       case AP4_ATOM_TYPE_CO64:
  196.         atom = new AP4_Co64Atom(size, stream);
  197.         break;
  198.       case AP4_ATOM_TYPE_STSZ:
  199.         atom = new AP4_StszAtom(size, stream);
  200.         break;
  201.       case AP4_ATOM_TYPE_STTS:
  202.         atom = new AP4_SttsAtom(size, stream);
  203.         break;
  204.       case AP4_ATOM_TYPE_CTTS:
  205.         atom = new AP4_CttsAtom(size, stream);
  206.         break;
  207.       case AP4_ATOM_TYPE_STSS:
  208.         atom = new AP4_StssAtom(size, stream);
  209.         break;
  210.       case AP4_ATOM_TYPE_MP4S:
  211.         atom = new AP4_Mp4sSampleEntry(size, stream, *this);
  212.         break;
  213.       case AP4_ATOM_TYPE_MP4A:
  214.         atom = new AP4_Mp4aSampleEntry(size, stream, *this);
  215.         break;
  216.       case AP4_ATOM_TYPE_MP4V:
  217.         atom = new AP4_Mp4vSampleEntry(size, stream, *this);
  218.         break;
  219.       case AP4_ATOM_TYPE_AVC1:
  220.         atom = new AP4_Avc1SampleEntry(size, stream, *this);
  221.         break;
  222.       case AP4_ATOM_TYPE_ENCA:
  223.         atom = new AP4_EncaSampleEntry(size, stream, *this);
  224.         break;
  225.       case AP4_ATOM_TYPE_ENCV:
  226.         atom = new AP4_EncvSampleEntry(size, stream, *this);
  227.         break;
  228.       case AP4_ATOM_TYPE_ESDS:
  229.         atom = new AP4_EsdsAtom(size, stream);
  230.         break;
  231.       case AP4_ATOM_TYPE_VMHD:
  232.         atom = new AP4_VmhdAtom(size, stream);
  233.         break;
  234.       case AP4_ATOM_TYPE_SMHD:
  235.         atom = new AP4_SmhdAtom(size, stream);
  236.         break;
  237.       case AP4_ATOM_TYPE_NMHD:
  238.         atom = new AP4_NmhdAtom(size, stream);
  239.         break;
  240.       case AP4_ATOM_TYPE_HMHD:
  241.         atom = new AP4_HmhdAtom(size, stream);
  242.         break;
  243.       case AP4_ATOM_TYPE_FRMA:
  244.         atom = new AP4_FrmaAtom(size, stream);
  245.         break;
  246.       case AP4_ATOM_TYPE_SCHM:
  247.           atom = new AP4_SchmAtom(size, stream);
  248.           break;
  249.       case AP4_ATOM_TYPE_FTYP:
  250.         atom = new AP4_FtypAtom(size, stream);
  251.         break;
  252.           
  253.       case AP4_ATOM_TYPE_RTP:
  254.         if (m_Context == AP4_ATOM_TYPE_HNTI) {
  255.             atom = new AP4_RtpAtom(size, stream);
  256.         } else {
  257.             atom = new AP4_RtpHintSampleEntry(size, stream, *this);
  258.         }
  259.         break;
  260.       
  261.       case AP4_ATOM_TYPE_TIMS:
  262.         atom = new AP4_TimsAtom(size, stream);
  263.         break;
  264.  
  265.       case AP4_ATOM_TYPE_SDP:
  266.         atom = new AP4_SdpAtom(size, stream);
  267.         break;
  268.       case AP4_ATOM_TYPE_IKMS:
  269.         atom = new AP4_IkmsAtom(size, stream);
  270.         break;
  271.       case AP4_ATOM_TYPE_ISFM:
  272.         atom = new AP4_IsfmAtom(size, stream);
  273.         break;
  274.       case AP4_ATOM_TYPE_HINT:
  275.         atom = new AP4_TrefTypeAtom(type, size, stream);
  276.         break;
  277.       // container atoms
  278.       case AP4_ATOM_TYPE_TREF:
  279.       case AP4_ATOM_TYPE_HNTI:
  280.       case AP4_ATOM_TYPE_STBL:
  281.       case AP4_ATOM_TYPE_MDIA:
  282.       case AP4_ATOM_TYPE_DINF:
  283.       case AP4_ATOM_TYPE_MINF:
  284.       case AP4_ATOM_TYPE_SCHI:
  285.       case AP4_ATOM_TYPE_SINF:
  286.       case AP4_ATOM_TYPE_UDTA:
  287.       case AP4_ATOM_TYPE_ILST:
  288.   case AP4_ATOM_TYPE_NAM:
  289.   case AP4_ATOM_TYPE_ART:
  290.       case AP4_ATOM_TYPE_WRT:
  291.       case AP4_ATOM_TYPE_ALB:
  292.       case AP4_ATOM_TYPE_DAY:
  293.       case AP4_ATOM_TYPE_TOO:
  294.       case AP4_ATOM_TYPE_CMT:
  295.       case AP4_ATOM_TYPE_GEN:
  296.   case AP4_ATOM_TYPE_TRKN:
  297.   case AP4_ATOM_TYPE_EDTS: {
  298.           AP4_UI32 context = m_Context;
  299.           m_Context = type; // set the context for the children
  300.           atom = new AP4_ContainerAtom(type, size, false, stream, *this);
  301.           m_Context = context; // restore the previous context
  302.           break;
  303.       }
  304.       // full container atoms
  305.       case AP4_ATOM_TYPE_META:
  306.         atom = new AP4_ContainerAtom(type, size, true, stream, *this);
  307.         break;
  308.       // other
  309.       case AP4_ATOM_TYPE_AVCC:
  310.         atom = new AP4_AvcCAtom(size, stream);
  311.         break;
  312.       case AP4_ATOM_TYPE_TEXT:
  313.         atom = new AP4_TextSampleEntry(size, stream, *this);
  314.         break;
  315.       case AP4_ATOM_TYPE_TX3G:
  316.         atom = new AP4_Tx3gSampleEntry(size, stream, *this);
  317.         break;
  318.       case AP4_ATOM_TYPE_FTAB:
  319.         atom = new AP4_FtabAtom(size, stream);
  320.         break;
  321.       case AP4_ATOM_TYPE_S263:
  322.         atom = new AP4_VisualSampleEntry(AP4_ATOM_TYPE_S263, size, stream, *this); // TODO
  323.         break;
  324.   case AP4_ATOM_TYPE_SAMR:
  325.         atom = new AP4_AudioSampleEntry(AP4_ATOM_TYPE_SAMR, size, stream, *this); // TODO
  326.         break;
  327.       case AP4_ATOM_TYPE_CHPL:
  328.         atom = new AP4_ChplAtom(size, stream);
  329.         break;
  330.   case AP4_ATOM_TYPE_DATA:
  331.         atom = new AP4_DataAtom(size, stream);
  332.         break;
  333.       default:
  334.         // try all the external type handlers
  335.         {
  336.             atom = NULL;
  337.             AP4_List<TypeHandler>::Item* handler_item = m_TypeHandlers.FirstItem();
  338.             while (handler_item) {
  339.                 TypeHandler* handler = handler_item->GetData();
  340.                 if (AP4_SUCCEEDED(handler->CreateAtom(type, size, stream, atom))) {
  341.                     break;
  342.                 }
  343.                 handler_item = handler_item->GetNext();
  344.             }
  345.             if (atom == NULL) {
  346.                 // no custom handlers, create a generic atom
  347.                 atom = new AP4_UnknownAtom(type, size, false, stream);
  348.             }
  349.             break;
  350.         }
  351.     }
  352.     // skip to the end of the atom
  353.     bytes_available -= size;
  354.     result = stream.Seek(start+size);
  355.     if (AP4_FAILED(result)) {
  356.         delete atom;
  357.         atom = NULL;
  358.     }
  359.     return result;
  360. }