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

多媒体编程

开发平台:

Visual C++

  1. /*****************************************************************
  2. |
  3. |    AP4 - Atoms 
  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 "Ap4Atom.h"
  33. #include "Ap4Utils.h"
  34. #include "Ap4ContainerAtom.h"
  35. #include "Ap4StsdAtom.h"
  36. #include "Ap4Debug.h"
  37. /*----------------------------------------------------------------------
  38. |       AP4_Atom::AP4_Atom
  39. +---------------------------------------------------------------------*/
  40. AP4_Atom::AP4_Atom(Type type, 
  41.                    bool is_full) : 
  42.     m_Type(type),
  43.     m_Size(is_full ? AP4_FULL_ATOM_HEADER_SIZE : AP4_ATOM_HEADER_SIZE),
  44.     m_IsFull(is_full),
  45.     m_Version(0),
  46.     m_Flags(0),
  47.     m_Parent(NULL)
  48. {
  49. }
  50. /*----------------------------------------------------------------------
  51. |       AP4_Atom::AP4_Atom
  52. +---------------------------------------------------------------------*/
  53. AP4_Atom::AP4_Atom(Type     type, 
  54.                    AP4_Size size,
  55.                    bool     is_full) : 
  56.     m_Type(type),
  57.     m_Size(size),
  58.     m_IsFull(is_full),
  59.     m_Version(0),
  60.     m_Flags(0),
  61.     m_Parent(NULL)
  62. {
  63. }
  64. /*----------------------------------------------------------------------
  65. |       AP4_Atom::AP4_Atom
  66. +---------------------------------------------------------------------*/
  67. AP4_Atom::AP4_Atom(Type            type, 
  68.                    AP4_Size        size,
  69.                    bool            is_full,
  70.                    AP4_ByteStream& stream) : 
  71.     m_Type(type),
  72.     m_Size(size),
  73.     m_IsFull(is_full),
  74.     m_Parent(NULL)
  75. {
  76.     // if this is a full atom, read the version and flags
  77.     if (is_full) {
  78.         AP4_UI32 header;
  79.         stream.ReadUI32(header);
  80.         m_Version = (header>>24)&0xFF;
  81.         m_Flags   = (header&0xFFFFFF);
  82.     } else {
  83.         m_Version = 0;
  84.         m_Flags   = 0;
  85.     }
  86. }
  87. /*----------------------------------------------------------------------
  88. |       AP4_Atom::GetHeaderSize
  89. +---------------------------------------------------------------------*/
  90. AP4_Size
  91. AP4_Atom::GetHeaderSize() 
  92. {
  93.     return m_IsFull ? AP4_FULL_ATOM_HEADER_SIZE : AP4_ATOM_HEADER_SIZE;
  94. }
  95. /*----------------------------------------------------------------------
  96. |       AP4_Atom::WriteHeader
  97. +---------------------------------------------------------------------*/
  98. AP4_Result
  99. AP4_Atom::WriteHeader(AP4_ByteStream& stream)
  100. {
  101.     AP4_Result result;
  102.     // write the size
  103.     result = stream.WriteUI32(m_Size);
  104.     if (AP4_FAILED(result)) return result;
  105.     // write the type
  106.     result = stream.WriteUI32(m_Type);
  107.     if (AP4_FAILED(result)) return result;
  108.     // for full atoms, write version and flags
  109.     if (m_IsFull) {
  110.         result = stream.WriteUI08(m_Version);
  111.         if (AP4_FAILED(result)) return result;
  112.         result = stream.WriteUI24(m_Flags);
  113.         if (AP4_FAILED(result)) return result;
  114.     }
  115.     return AP4_SUCCESS;
  116. }
  117. /*----------------------------------------------------------------------
  118. |       AP4_Atom::Write
  119. +---------------------------------------------------------------------*/
  120. AP4_Result
  121. AP4_Atom::Write(AP4_ByteStream& stream)
  122. {
  123.     AP4_Result result;
  124. #if defined(AP4_DEBUG)
  125.     AP4_Offset before;
  126.     stream.Tell(before);
  127. #endif
  128.     // write the header
  129.     result = WriteHeader(stream);
  130.     if (AP4_FAILED(result)) return result;
  131.     // write the fields
  132.     result = WriteFields(stream);
  133.     if (AP4_FAILED(result)) return result;
  134. #if defined(AP4_DEBUG)
  135.     AP4_Offset after;
  136.     stream.Tell(after);
  137.     AP4_ASSERT(after-before == m_Size);
  138. #endif
  139.     return AP4_SUCCESS;
  140. }
  141. /*----------------------------------------------------------------------
  142. |       AP4_Atom::Inspect
  143. +---------------------------------------------------------------------*/
  144. AP4_Result
  145. AP4_Atom::Inspect(AP4_AtomInspector& inspector)
  146. {
  147.     InspectHeader(inspector);
  148.     InspectFields(inspector);
  149.     inspector.EndElement();
  150.     return AP4_SUCCESS;
  151. }
  152. /*----------------------------------------------------------------------
  153. |       AP4_Atom::InspectHeader
  154. +---------------------------------------------------------------------*/
  155. AP4_Result
  156. AP4_Atom::InspectHeader(AP4_AtomInspector& inspector)
  157. {
  158.     // write atom name
  159.     char name[7];
  160.     name[0] = '[';
  161.     AP4_FormatFourChars(&name[1], m_Type);
  162.     name[5] = ']';
  163.     name[6] = '';
  164.     char size[64];
  165.     AP4_StringFormat(size, sizeof(size), "size=%ld+%ld", GetHeaderSize(), 
  166.         m_Size-GetHeaderSize());
  167.     inspector.StartElement(name, size);
  168.     return AP4_SUCCESS;
  169. }
  170. /*----------------------------------------------------------------------
  171. |       AP4_Atom::Detach
  172. +---------------------------------------------------------------------*/
  173. AP4_Result
  174. AP4_Atom::Detach() 
  175. {
  176.     if (m_Parent) {
  177.         return m_Parent->RemoveChild(this);
  178.     } else {
  179.         return AP4_SUCCESS;
  180.     }
  181. }
  182. /*----------------------------------------------------------------------
  183. |       AP4_UnknownAtom::AP4_UnknownAtom
  184. +---------------------------------------------------------------------*/
  185. AP4_UnknownAtom::AP4_UnknownAtom(Type            type, 
  186.                                  AP4_Size        size,
  187.                                  bool            is_full,
  188.                                  AP4_ByteStream& stream) : 
  189.     AP4_Atom(type, size, is_full, stream),
  190.     m_SourceStream(&stream)
  191. {
  192.     // store source stream offset
  193.     stream.Tell(m_SourceOffset);
  194.     // keep a reference to the source stream
  195.     m_SourceStream->AddReference();
  196. }
  197. /*----------------------------------------------------------------------
  198. |       AP4_UnknownAtom::~AP4_UnknownAtom
  199. +---------------------------------------------------------------------*/
  200. AP4_UnknownAtom::~AP4_UnknownAtom()
  201. {
  202.     // release the source stream reference
  203.     if (m_SourceStream) {
  204.         m_SourceStream->Release();
  205.     }
  206. }
  207. /*----------------------------------------------------------------------
  208. |       AP4_UnknownAtom::WriteFields
  209. +---------------------------------------------------------------------*/
  210. AP4_Result
  211. AP4_UnknownAtom::WriteFields(AP4_ByteStream& stream)
  212. {
  213.     AP4_Result result;
  214.     // check that we have a source stream
  215.     // and a normal size
  216.     if (m_SourceStream == NULL || m_Size < 8) {
  217.         return AP4_FAILURE;
  218.     }
  219.     // seek into the source at the stored offset
  220.     result = m_SourceStream->Seek(m_SourceOffset);
  221.     if (AP4_FAILED(result)) return result;
  222.     // copy the source stream to the output
  223.     result = m_SourceStream->CopyTo(stream, m_Size-GetHeaderSize());
  224.     if (AP4_FAILED(result)) return result;
  225.     return AP4_SUCCESS;
  226. }
  227. /*----------------------------------------------------------------------
  228. |       AP4_AtomParent::~AP4_AtomParent
  229. +---------------------------------------------------------------------*/
  230. AP4_AtomParent::~AP4_AtomParent()
  231. {
  232.     m_Children.DeleteReferences();
  233. }
  234. /*----------------------------------------------------------------------
  235. |       AP4_AtomParent::AddChild
  236. +---------------------------------------------------------------------*/
  237. AP4_Result
  238. AP4_AtomParent::AddChild(AP4_Atom* child, int position)
  239. {
  240.     // check that the child does not already have a parent
  241.     if (child->GetParent() != NULL) return AP4_ERROR_INVALID_PARAMETERS;
  242.     // attach the child
  243.     AP4_Result result;
  244.     if (position == -1) {
  245.         // insert at the tail
  246.         result = m_Children.Add(child);
  247.     } else if (position == 0) {
  248.         // insert at the head
  249.         result = m_Children.Insert(NULL, child);
  250.     } else {
  251.         // insert after <n-1>
  252.         AP4_List<AP4_Atom>::Item* insertion_point = m_Children.FirstItem();
  253.         unsigned int count = position;
  254.         while (insertion_point && --count) {
  255.             insertion_point = insertion_point->GetNext();
  256.         }
  257.         if (insertion_point) {
  258.             result = m_Children.Insert(insertion_point, child);
  259.         } else {
  260.             result = AP4_ERROR_OUT_OF_RANGE;
  261.         }
  262.     }
  263.     if (AP4_FAILED(result)) return result;
  264.     // notify the child of its parent
  265.     child->SetParent(this);
  266.     // get a chance to update
  267.     OnChildAdded(child);
  268.     return AP4_SUCCESS;
  269. }
  270. /*----------------------------------------------------------------------
  271. |       AP4_AtomParent::RemoveChild
  272. +---------------------------------------------------------------------*/
  273. AP4_Result
  274. AP4_AtomParent::RemoveChild(AP4_Atom* child)
  275. {
  276.     // check that this is our child
  277.     if (child->GetParent() != this) return AP4_ERROR_INVALID_PARAMETERS;
  278.     // remove the child
  279.     AP4_Result result = m_Children.Remove(child);
  280.     if (AP4_FAILED(result)) return result;
  281.     // notify that child that it is orphaned
  282.     child->SetParent(NULL);
  283.     // get a chance to update
  284.     OnChildRemoved(child);
  285.     return AP4_SUCCESS;
  286. }
  287. /*----------------------------------------------------------------------
  288. |       AP4_AtomParent::DeleteChild
  289. +---------------------------------------------------------------------*/
  290. AP4_Result
  291. AP4_AtomParent::DeleteChild(AP4_Atom::Type type)
  292. {
  293.     // find the child
  294.     AP4_Atom* child = GetChild(type);
  295.     if (child == NULL) return AP4_FAILURE;
  296.     // remove the child
  297.     AP4_Result result = RemoveChild(child);
  298.     if (AP4_FAILED(result)) return result;
  299.     // delete the child
  300.     delete child;
  301.     return AP4_SUCCESS;
  302. }
  303. /*----------------------------------------------------------------------
  304. |       AP4_AtomParent::GetChild
  305. +---------------------------------------------------------------------*/
  306. AP4_Atom*
  307. AP4_AtomParent::GetChild(AP4_Atom::Type type, AP4_Ordinal index /* = 0 */)
  308. {
  309.     AP4_Atom* atom;
  310.     AP4_Result result = m_Children.Find(AP4_AtomFinder(type, index), atom);
  311.     if (AP4_SUCCEEDED(result)) {
  312.         return atom;
  313.     } else { 
  314.         return NULL;
  315.     }
  316. }
  317. /*----------------------------------------------------------------------
  318. |       AP4_AtomParent::FindChild
  319. +---------------------------------------------------------------------*/
  320. AP4_Atom*
  321. AP4_AtomParent::FindChild(const char* path, 
  322.                           bool        auto_create)
  323. {
  324.     // start from here
  325.     AP4_AtomParent* parent = this;
  326.     // walk the path
  327.     while (path[0] && path[1] && path[2] && path[3]) {
  328.         // we have 4 valid chars
  329.         const char* tail;
  330.         int         index = 0;
  331.         if (path[4] == '') {
  332.             tail = NULL;
  333.         } else if (path[4] == '/') {
  334.             // separator
  335.             tail = &path[5];
  336.         } else if (path[4] == '[') {
  337.             const char* x = &path[5];
  338.             while (*x >= '0' && *x <= '9') {
  339.                 index = 10*index+(*x++ - '0');
  340.             }
  341.             if (x[0] == ']') {
  342.                 if (x[1] == '') {
  343.                     tail = NULL;
  344.                 } else {
  345.                     tail = x+2;
  346.                 }
  347.             } else {
  348.                 // malformed path
  349.                 return NULL;
  350.             }
  351.         } else {
  352.             // malformed path
  353.             return NULL;
  354.         }
  355.         // look for this atom in the current list
  356.         AP4_Atom::Type type = AP4_ATOM_TYPE(path[0], path[1], path[2], path[3]); 
  357.         AP4_Atom* atom = parent->GetChild(type, index);
  358.         if (atom == NULL) {
  359.             // not found
  360.             if (auto_create && (index == 0)) {
  361.                 AP4_ContainerAtom* container = dynamic_cast<AP4_ContainerAtom*>(parent);
  362.                 if (parent) {
  363.                     atom = new AP4_ContainerAtom(type, false);
  364.                     container->AddChild(atom);
  365.                 } else {
  366.                     return NULL;
  367.                 }
  368.             } else {
  369.                 return NULL;
  370.             }
  371.         }
  372.         if (tail) {
  373.             path = tail;
  374.             // if this atom is an atom parent, recurse
  375.             parent = dynamic_cast<AP4_ContainerAtom*>(atom);
  376.             if (parent == NULL) return NULL;
  377.         } else {
  378.             return atom;
  379.         }
  380.     }
  381.     // not found
  382.     return NULL;
  383. }