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

多媒体编程

开发平台:

Visual C++

  1. /*****************************************************************
  2. |
  3. |    AP4 - MP4 File Processor
  4. |
  5. |    Copyright 2003 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 <stdio.h>
  32. #include <stdlib.h>
  33. #include "Ap4.h"
  34. #include "Ap4FileByteStream.h"
  35. #include "Ap4Processor.h"
  36. #include "Ap4Utils.h"
  37. #include "Ap4ContainerAtom.h"
  38. /*----------------------------------------------------------------------
  39. |       constants
  40. +---------------------------------------------------------------------*/
  41. #define BANNER "MP4 File Editor - Version 0.5an"
  42.                "(c) 2003-2005 Gilles Boccon-Gibod & Julien Boeuf"
  43.  
  44. /*----------------------------------------------------------------------
  45. |       PrintUsageAndExit
  46. +---------------------------------------------------------------------*/
  47. static void
  48. PrintUsageAndExit()
  49. {
  50.     fprintf(stderr, 
  51.             BANNER 
  52.             "nnusage: mp4edit [commands] <input> <output>n"
  53.             "    where commands include one or more of:n"
  54.             "    --insert <atom_name>:<source_file>[:<position>]n"
  55.             "    --remove <atom_name>n"
  56.             "    --replace <atom_name>:<source_file>n");
  57.     exit(1);
  58. }
  59. /*----------------------------------------------------------------------
  60. |       AP4_EditingProcessor
  61. +---------------------------------------------------------------------*/
  62. class AP4_EditingProcessor : public AP4_Processor
  63. {
  64. public:
  65.     // types
  66.     class Command {
  67.     public:
  68.         // types
  69.         typedef enum {
  70.             TYPE_INSERT,
  71.             TYPE_REMOVE,
  72.             TYPE_REPLACE
  73.         } Type;
  74.         // constructor
  75.         Command(Type type, const char* atom_path, 
  76.                            const char* file_path,
  77.                            int         position = -1) :
  78.           m_Type(type), 
  79.           m_AtomPath(atom_path), 
  80.           m_FilePath(file_path),
  81.           m_Position(position) {}
  82.         // members
  83.         Type       m_Type;
  84.         AP4_String m_AtomPath;
  85.         AP4_String m_FilePath;
  86.         int        m_Position;
  87.     };
  88.     // constructor and destructor
  89.     virtual ~AP4_EditingProcessor();
  90.     // methods
  91.     virtual AP4_Result Initialize(AP4_AtomParent& top_level);
  92.     AP4_Result         AddCommand(Command::Type type, 
  93.                                   const char*   atom_path, 
  94.                                   const char*   file_path,
  95.                                   int           position = -1);
  96. private:
  97.     // methods
  98.     AP4_Result InsertAtom(const char*     file_path, 
  99.                           AP4_AtomParent* container,
  100.                           int             position);
  101.     AP4_Result DoRemove(Command* command, AP4_AtomParent& top_level);
  102.     AP4_Result DoInsert(Command* command, AP4_AtomParent& top_level);
  103.     AP4_Result DoReplace(Command* command, AP4_AtomParent& top_level);
  104.     // members
  105.     AP4_List<Command> m_Commands;
  106.     AP4_AtomParent    m_TopLevelParent;
  107. };
  108. /*----------------------------------------------------------------------
  109. |       AP4_EditingProcessor::~AP4_EditingProcessor
  110. +---------------------------------------------------------------------*/
  111. AP4_EditingProcessor::~AP4_EditingProcessor()
  112. {
  113.     m_Commands.DeleteReferences();
  114. }
  115. /*----------------------------------------------------------------------
  116. |       AP4_EditingProcessor::AddCommand
  117. +---------------------------------------------------------------------*/
  118. AP4_Result
  119. AP4_EditingProcessor::AddCommand(Command::Type type, 
  120.                                  const char*   atom_path, 
  121.                                  const char*   file_path,
  122.                                  int           position)
  123. {
  124.     return m_Commands.Add(new Command(type, atom_path, file_path, position));
  125. }
  126. /*----------------------------------------------------------------------
  127. |       AP4_EditingProcessor::Initialize
  128. +---------------------------------------------------------------------*/
  129. AP4_Result
  130. AP4_EditingProcessor::Initialize(AP4_AtomParent& top_level)
  131. {
  132.     AP4_Result result;
  133.     AP4_List<Command>::Item* command_item = m_Commands.FirstItem();
  134.     while (command_item) {
  135.         Command* command = command_item->GetData();
  136.         switch (command->m_Type) {
  137.           case Command::TYPE_REMOVE:
  138.             result = DoRemove(command, top_level);
  139.             if (AP4_FAILED(result)) return result;
  140.             break;
  141.           case Command::TYPE_INSERT:
  142.             result = DoInsert(command, top_level);
  143.             if (AP4_FAILED(result)) return result;
  144.             break;
  145.           case Command::TYPE_REPLACE:
  146.             result = DoReplace(command, top_level);
  147.             if (AP4_FAILED(result)) return result;
  148.             break;
  149.         }
  150.         command_item = command_item->GetNext();
  151.     }
  152.     return AP4_SUCCESS;
  153. }
  154. /*----------------------------------------------------------------------
  155. |       AP4_EditingProcessor::DoRemove
  156. +---------------------------------------------------------------------*/
  157. AP4_Result
  158. AP4_EditingProcessor::DoRemove(Command* command, AP4_AtomParent& top_level)
  159. {
  160.     AP4_Atom* atom = top_level.FindChild(command->m_AtomPath.c_str());
  161.     if (atom == NULL) {
  162.         fprintf(stderr, "ERROR: atom '%s' not foundn", command->m_AtomPath.c_str());
  163.         return AP4_FAILURE;
  164.     } else {
  165.         atom->Detach();
  166.         delete atom;
  167.         return AP4_SUCCESS;
  168.     }
  169. }
  170. /*----------------------------------------------------------------------
  171. |       AP4_EditingProcessor::InsertAtom
  172. +---------------------------------------------------------------------*/
  173. AP4_Result
  174. AP4_EditingProcessor::InsertAtom(const char*     file_path, 
  175.                                  AP4_AtomParent* container,
  176.                                  int             position)
  177. {
  178.     // read the atom to insert
  179.     AP4_Atom* child = NULL;
  180.     AP4_ByteStream* input;
  181.     try {
  182.         input = new AP4_FileByteStream(file_path,
  183.             AP4_FileByteStream::STREAM_MODE_READ);
  184.     } catch (AP4_Exception) {
  185.         fprintf(stderr, "ERROR: cannot open atom file (%s)n", file_path);
  186.         return AP4_FAILURE;
  187.     }
  188.     AP4_Result result;
  189.     result = AP4_AtomFactory::DefaultFactory.CreateAtomFromStream(*input, child);
  190.     input->Release();
  191.     if (AP4_FAILED(result)) {
  192.         fprintf(stderr, "ERROR: failed to create atomn");
  193.         return AP4_FAILURE;
  194.     } 
  195.     // insert the atom
  196.     result = container->AddChild(child, position);
  197.     if (AP4_FAILED(result)) {
  198.         fprintf(stderr, "ERROR: failed to insert atomn");
  199.         delete child;
  200.         return result;
  201.     }
  202.     return AP4_SUCCESS;
  203. }
  204. /*----------------------------------------------------------------------
  205. |       AP4_EditingProcessor::DoInsert
  206. +---------------------------------------------------------------------*/
  207. AP4_Result
  208. AP4_EditingProcessor::DoInsert(Command* command, AP4_AtomParent& top_level)
  209. {
  210.     AP4_AtomParent* parent = NULL;
  211.     if (command->m_AtomPath.length() == 0) {
  212.         // insert into the toplevel list
  213.         parent = &top_level;
  214.     } else {
  215.         // find the atom to insert into
  216.         AP4_Atom* atom = top_level.FindChild(command->m_AtomPath.c_str(), true);
  217.         if (atom == NULL) {
  218.             fprintf(stderr, "ERROR: atom '%s' not foundn", 
  219.                 command->m_AtomPath.c_str());
  220.             return AP4_FAILURE;
  221.         }
  222.         // check that the atom is a container
  223.         parent = dynamic_cast<AP4_AtomParent*>(atom);
  224.     }
  225.     // check that we have a place to insert into
  226.     if (parent == NULL) {
  227.         fprintf(stderr, "ERROR: atom '%s' is not a containern",
  228.             command->m_AtomPath.c_str());
  229.         return AP4_FAILURE;
  230.     }
  231.     return InsertAtom(command->m_FilePath.c_str(), parent, command->m_Position);
  232. }
  233. /*----------------------------------------------------------------------
  234. |       AP4_EditingProcessor::DoReplace
  235. +---------------------------------------------------------------------*/
  236. AP4_Result
  237. AP4_EditingProcessor::DoReplace(Command* command, AP4_AtomParent& top_level)
  238. {
  239.     // remove the atom
  240.     AP4_Atom* atom = top_level.FindChild(command->m_AtomPath.c_str());
  241.     if (atom == NULL) {
  242.         fprintf(stderr, "ERROR: atom '%s' not foundn", command->m_AtomPath.c_str());
  243.         return AP4_FAILURE;
  244.     } else {
  245.         // find the position of the atom in the parent
  246.         AP4_AtomParent* parent = atom->GetParent();
  247.         int position = 0;
  248.         AP4_List<AP4_Atom>::Item* list_item = parent->GetChildren().FirstItem();
  249.         while (list_item) {
  250.             if (list_item->GetData() == atom) break;
  251.             position++;
  252.             list_item = list_item->GetNext();
  253.         }
  254.         // remove the atom from the parent
  255.         atom->Detach();
  256.         delete atom;
  257.         // insert the replacement
  258.         return InsertAtom(command->m_FilePath.c_str(), parent, position);
  259.     }
  260. }
  261. /*----------------------------------------------------------------------
  262. |       main
  263. +---------------------------------------------------------------------*/
  264. int
  265. main(int argc, char** argv)
  266. {
  267.     if (argc < 3) {
  268.         PrintUsageAndExit();
  269.     }
  270.     
  271.     // create initial objects
  272.     AP4_EditingProcessor processor;
  273.     // parse arguments
  274.     const char* input_filename = NULL;
  275.     const char* output_filename = NULL;
  276.     char* arg;
  277.     while ((arg = *++argv)) {
  278.         if (!strcmp(arg, "--insert")) {
  279.             char* param = *++argv;
  280.             if (param == NULL) {
  281.                 fprintf(stderr, "ERROR: missing argument for --insert commandn");
  282.                 return 1;
  283.             }
  284.             char* atom_path = NULL;
  285.             char* file_path = NULL;
  286.             if (AP4_SUCCEEDED(AP4_SplitArgs(param, atom_path, file_path))) {
  287.                 int position = -1;
  288.                 char* position_str = NULL;
  289.                 if (AP4_SUCCEEDED(AP4_SplitArgs(file_path, file_path, position_str))) {
  290.                     if (position_str) {
  291.                         position = strtoul(position_str, NULL, 10);
  292.                     }
  293.                 }
  294.                 processor.AddCommand(AP4_EditingProcessor::Command::TYPE_INSERT, atom_path, file_path, position);
  295.             } else {
  296.                 fprintf(stderr, "ERROR: invalid format for --insert command argumentn");
  297.                 return 1;
  298.             }
  299.         } else if (!strcmp(arg, "--remove")) {
  300.             char* atom_path = *++argv;
  301.             if (atom_path == NULL) {
  302.                 fprintf(stderr, "ERROR: missing argument for --remove commandn");
  303.                 return 1;
  304.             }
  305.             processor.AddCommand(AP4_EditingProcessor::Command::TYPE_REMOVE, atom_path, "");
  306.         } else if (!strcmp(arg, "--replace")) {
  307.             char* param = *++argv;
  308.             if (param == NULL) {
  309.                 fprintf(stderr, "ERROR: missing argument for --replace commandn");
  310.                 return 1;
  311.             }
  312.             char* atom_path = NULL;
  313.             char* file_path = NULL;
  314.             if (AP4_SUCCEEDED(AP4_SplitArgs(param, atom_path, file_path))) {
  315.                 processor.AddCommand(AP4_EditingProcessor::Command::TYPE_REPLACE, atom_path, file_path);
  316.             } else {
  317.                 fprintf(stderr, "ERROR: invalid format for --replace command argumentn");
  318.                 return 1;
  319.             }
  320.         } else if (input_filename == NULL) {
  321.             input_filename = arg;
  322.         } else if (output_filename == NULL) {
  323.             output_filename = arg;
  324.         } else {
  325.             fprintf(stderr, "ERROR: invalid command line argument (%s)n", arg);
  326.             return 1;
  327.         }
  328.     }
  329.     // check arguments
  330.     if (input_filename == NULL) {
  331.         fprintf(stderr, "ERROR: missing input filenamen");
  332.         return 1;
  333.     }
  334.     if (output_filename == NULL) {
  335.         fprintf(stderr, "ERROR: missing output filenamen");
  336.         return 1;
  337.     }
  338. // create the input stream
  339.     AP4_ByteStream* input = NULL;
  340.     try {
  341.         input = new AP4_FileByteStream(input_filename,
  342.                         AP4_FileByteStream::STREAM_MODE_READ);
  343.     } catch (AP4_Exception) {
  344.         fprintf(stderr, "ERROR: cannot open input file (%s)n", input_filename);
  345.         return 1;
  346.     }
  347. // create the output stream
  348.     AP4_ByteStream* output = NULL;
  349.     try {
  350.         output = new AP4_FileByteStream(output_filename,
  351.                          AP4_FileByteStream::STREAM_MODE_WRITE);
  352.     } catch (AP4_Exception) {
  353.         fprintf(stderr, "ERROR: cannot open output file (%s)n", output_filename);
  354.         input->Release();
  355.         return 1;
  356.     }
  357.     // process!
  358.     processor.Process(*input, *output);
  359.     // cleanup
  360.     input->Release();
  361.     output->Release();
  362.     return 0;
  363. }