Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | RSS feed

  1. /*
  2.  * Copyright (c) 2007, Digital Signal Processing Laboratory, Università degli studi di Perugia (UPG), Italy
  3.  * All rights reserved.
  4.  *
  5.  * Redistribution and use in source and binary forms, with or without
  6.  * modification, are permitted provided that the following conditions
  7.  * are met:
  8.  * 1. Redistributions of source code must retain the above copyright
  9.  *    notice, this list of conditions and the following disclaimer.
  10.  * 2. Redistributions in binary form must reproduce the above copyright
  11.  *    notice, this list of conditions and the following disclaimer in the
  12.  *    documentation and/or other materials provided with the distribution.
  13.  *
  14.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
  15.  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
  16.  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
  17.  * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
  18.  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
  19.  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
  20.  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
  21.  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  22.  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
  23.  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  24.  * POSSIBILITY OF SUCH DAMAGE.
  25.  */
  26. /////////////////////////////////////////////////////////////////////////////
  27. // Name:        imagmxf.cpp
  28. // Purpose:     wxImage MXF (Material eXchange Format) JPEG 2000 file format handler
  29. // Author:      Giuseppe Baruffa - based on imagjpeg.cpp, Vaclav Slavik
  30. // RCS-ID:      $Id: imagmxf.cpp,v 0.00 2007/11/19 17:00:00 MW Exp $
  31. // Copyright:   (c) Giuseppe Baruffa
  32. // Licence:     wxWindows licence
  33. /////////////////////////////////////////////////////////////////////////////
  34.  
  35. #ifdef USE_MXF
  36.  
  37. #include "mxflib/mxflib.h"
  38. using namespace mxflib;
  39.  
  40. namespace
  41. {
  42.         //! Structure holding information about the essence in each body stream
  43.         struct EssenceInfo
  44.         {
  45.                 UMIDPtr PackageID;
  46.                 PackagePtr Package;
  47.                 MDObjectPtr Descriptor;
  48.         };
  49.         //! Map of EssenceInfo structures indexed by BodySID
  50.         typedef std::map<UInt32, EssenceInfo> EssenceInfoMap;
  51.  
  52.         //! The map of essence info for this file
  53.         EssenceInfoMap EssenceLookup;
  54. };
  55.  
  56. //! Build an EssenceInfoMap for the essence in a given file
  57. /*! \return True if al OK, else false
  58.  */
  59. bool BuildEssenceInfo(MXFFilePtr &File, EssenceInfoMap &EssenceLookup);
  60.  
  61. // For compilers that support precompilation, includes "wx.h".
  62. #include "wx/wxprec.h"
  63.  
  64. #ifdef __BORLANDC__
  65.     #pragma hdrstop
  66. #endif
  67.  
  68. #if wxUSE_IMAGE && wxUSE_LIBOPENJPEG
  69.  
  70. #include "imagmxf.h"
  71.  
  72. #ifndef WX_PRECOMP
  73.     #include "wx/log.h"
  74.     #include "wx/app.h"
  75.     #include "wx/intl.h"
  76.     #include "wx/bitmap.h"
  77.     #include "wx/module.h"
  78. #endif
  79.  
  80.  
  81. #include "libopenjpeg/openjpeg.h"
  82.  
  83.  
  84. #include "wx/filefn.h"
  85. #include "wx/wfstream.h"
  86.  
  87. // ----------------------------------------------------------------------------
  88. // types
  89. // ----------------------------------------------------------------------------
  90.  
  91.  
  92. //-----------------------------------------------------------------------------
  93. // wxMXFHandler
  94. //-----------------------------------------------------------------------------
  95.  
  96. IMPLEMENT_DYNAMIC_CLASS(wxMXFHandler,wxImageHandler)
  97.  
  98. #if wxUSE_STREAMS
  99.  
  100. #include <stdarg.h>
  101. #define MAX_MESSAGE_LEN 200
  102.  
  103. //------------- MXF Manager
  104.  
  105. // Debug and error messages
  106.  
  107. //! Display a warning message
  108. void mxflib::warning(const char *Fmt, ...)
  109. {
  110.         char msg[MAX_MESSAGE_LEN];
  111.         va_list args;
  112.  
  113.         va_start(args, Fmt);
  114.         _vsnprintf(msg, MAX_MESSAGE_LEN, Fmt, args);
  115.         va_end(args);
  116.  
  117.         int message_len = strlen(msg) - 1;
  118.         if (msg[message_len] != '\n')
  119.                 message_len = MAX_MESSAGE_LEN;
  120. #ifndef __WXGTK__
  121.                 wxMutexGuiEnter();
  122. #endif /* __WXGTK__ */
  123.         wxLogMessage(wxT("[WARNING_MXF] %.*s"), message_len, msg);
  124. #ifndef __WXGTK__
  125.     wxMutexGuiLeave();
  126. #endif /* __WXGTK__ */
  127. }
  128.  
  129. //! Display an error message
  130. void mxflib::error(const char *Fmt, ...)
  131. {
  132.         char msg[MAX_MESSAGE_LEN];
  133.         va_list args;
  134.  
  135.         va_start(args, Fmt);
  136.         _vsnprintf(msg, MAX_MESSAGE_LEN, Fmt, args);
  137.         va_end(args);
  138.  
  139.         int message_len = strlen(msg) - 1;
  140.         if (msg[message_len] != '\n')
  141.                 message_len = MAX_MESSAGE_LEN;
  142. #ifndef __WXGTK__
  143.                 wxMutexGuiEnter();
  144. #endif /* __WXGTK__ */
  145.         wxLogMessage(wxT("[ERROR_MXF] %.*s"), message_len, msg);
  146. #ifndef __WXGTK__
  147.     wxMutexGuiLeave();
  148. #endif /* __WXGTK__ */
  149. }
  150.  
  151. //! Display an error message
  152. void mxflib::debug(const char *Fmt, ...)
  153. {
  154.         char msg[MAX_MESSAGE_LEN];
  155.         va_list args;
  156.  
  157.         va_start(args, Fmt);
  158.         _vsnprintf(msg, MAX_MESSAGE_LEN, Fmt, args);
  159.         va_end(args);
  160.  
  161.         int message_len = strlen(msg) - 1;
  162.         if (msg[message_len] != '\n')
  163.                 message_len = MAX_MESSAGE_LEN;
  164. #ifndef __WXGTK__
  165.                 wxMutexGuiEnter();
  166. #endif /* __WXGTK__ */
  167.         wxLogMessage(wxT("[DEBUG_MXF] %.*s"), message_len, msg);
  168. #ifndef __WXGTK__
  169.     wxMutexGuiLeave();
  170. #endif /* __WXGTK__ */
  171. }
  172.  
  173.  
  174.  
  175. //------------- JPEG 2000 Data Source Manager
  176.  
  177. #define J2K_CFMT 0
  178. #define JP2_CFMT 1
  179. #define JPT_CFMT 2
  180. #define MJ2_CFMT 3
  181. #define PXM_DFMT 0
  182. #define PGX_DFMT 1
  183. #define BMP_DFMT 2
  184. #define YUV_DFMT 3
  185.  
  186. /* sample error callback expecting a FILE* client object */
  187. void mxf_error_callback(const char *msg, void *client_data) {
  188.         int message_len = strlen(msg) - 1;
  189.         if (msg[message_len] != '\n')
  190.                 message_len = MAX_MESSAGE_LEN;
  191. #ifndef __WXGTK__
  192.                 wxMutexGuiEnter();
  193. #endif /* __WXGTK__ */
  194.         wxLogMessage(wxT("[ERROR] %.*s"), message_len, msg);
  195. #ifndef __WXGTK__
  196.     wxMutexGuiLeave();
  197. #endif /* __WXGTK__ */
  198. }
  199.  
  200. /* sample warning callback expecting a FILE* client object */
  201. void mxf_warning_callback(const char *msg, void *client_data) {
  202.         int message_len = strlen(msg) - 1;
  203.         if (msg[message_len] != '\n')
  204.                 message_len = MAX_MESSAGE_LEN;
  205. #ifndef __WXGTK__
  206.                 wxMutexGuiEnter();
  207. #endif /* __WXGTK__ */
  208.         wxLogMessage(wxT("[WARNING] %.*s"), message_len, msg);
  209. #ifndef __WXGTK__
  210.     wxMutexGuiLeave();
  211. #endif /* __WXGTK__ */
  212. }
  213.  
  214. /* sample debug callback expecting no client object */
  215. void mxf_info_callback(const char *msg, void *client_data) {
  216.         int message_len = strlen(msg) - 1;
  217.         if (msg[message_len] != '\n')
  218.                 message_len = MAX_MESSAGE_LEN;
  219. #ifndef __WXGTK__
  220.                 wxMutexGuiEnter();
  221. #endif /* __WXGTK__ */
  222.         wxLogMessage(wxT("[INFO] %.*s"), message_len, msg);
  223. #ifndef __WXGTK__
  224.     wxMutexGuiLeave();
  225. #endif /* __WXGTK__ */
  226. }
  227.  
  228.  
  229. /////////////////////////////////////////////////
  230. /////////////////////////////////////////////////
  231.  
  232. // load the mxf file format
  233. bool wxMXFHandler::LoadFile(wxImage *image, wxInputStream& stream, bool verbose, int index)
  234. {
  235.         opj_dparameters_t parameters;   /* decompression parameters */
  236.         opj_event_mgr_t event_mgr;              /* event manager */
  237.         opj_image_t *opjimage = NULL;
  238.         unsigned char *src = NULL;
  239.     unsigned char *ptr;
  240.         int file_length, j2k_point, j2k_len;
  241.         opj_codestream_info_t cstr_info;  /* Codestream information structure */
  242.        
  243.         // simply display the version of the library
  244.         wxLogMessage(wxT("Version of MXF: %s   "), wxString::FromAscii(LibraryVersion().c_str()));
  245.         //wxLogMessage(wxT("MXF file name: %s"), m_filename.GetFullPath());
  246.  
  247.         // open MXF file
  248.         MXFFilePtr TestFile = new MXFFile;
  249.         if (! TestFile->Open(m_filename.GetFullPath().c_str(), true))
  250.         {
  251.                 wxLogError(wxT("Could not find %s"), m_filename.GetFullPath().c_str());
  252.                 return false;
  253.         } else
  254.                 wxLogMessage(wxT("Found %s"), m_filename.GetFullPath().c_str());
  255.  
  256.         // Get the size
  257.         TestFile->SeekEnd();
  258.         wxLogMessage(wxT("Size is %d bytes"), TestFile->Tell());
  259.         TestFile->Seek(0);
  260.  
  261.         // essence information
  262.         //BuildEssenceInfo(TestFile, EssenceLookup);
  263.  
  264.         // close MXF file
  265.         TestFile->Close();
  266.  
  267.         return false;
  268.        
  269.         // destroy the image
  270.     image->Destroy();
  271.  
  272.         /* handle to a decompressor */
  273.         opj_dinfo_t* dinfo = NULL;     
  274.         opj_cio_t *cio = NULL;
  275.  
  276.         /* configure the event callbacks (not required) */
  277.         memset(&event_mgr, 0, sizeof(opj_event_mgr_t));
  278.         event_mgr.error_handler = mxf_error_callback;
  279.         event_mgr.warning_handler = mxf_warning_callback;
  280.         event_mgr.info_handler = mxf_info_callback;
  281.  
  282.         /* set decoding parameters to default values */
  283.         opj_set_default_decoder_parameters(&parameters);
  284.  
  285.         /* prepare parameters */
  286.         strncpy(parameters.infile, "", sizeof(parameters.infile)-1);
  287.         strncpy(parameters.outfile, "", sizeof(parameters.outfile)-1);
  288.         parameters.decod_format = J2K_CFMT;
  289.         parameters.cod_format = BMP_DFMT;
  290.         if (m_reducefactor)
  291.                 parameters.cp_reduce = m_reducefactor;
  292.         if (m_qualitylayers)
  293.                 parameters.cp_layer = m_qualitylayers;
  294.         /*if (n_components)
  295.                 parameters. = n_components;*/
  296.  
  297.         /* JPWL only */
  298. #ifdef USE_JPWL
  299.         parameters.jpwl_exp_comps = m_expcomps;
  300.         parameters.jpwl_max_tiles = m_maxtiles;
  301.         parameters.jpwl_correct = m_enablejpwl;
  302. #endif /* USE_JPWL */
  303.  
  304.         /* get a decoder handle */
  305.         dinfo = opj_create_decompress(CODEC_J2K);
  306.  
  307.         /* find length of the stream */
  308.         stream.SeekI(0, wxFromEnd);
  309.         file_length = (int) stream.TellI();
  310.  
  311.         /* search for the m_framenum codestream position and length  */
  312.         //jp2c_point = searchjp2c(stream, file_length, m_framenum);
  313.         //jp2c_len = searchjp2c(stream, file_length, m_framenum);
  314.         j2k_point = 0;
  315.         j2k_len = 10;
  316.  
  317.         // malloc memory source
  318.     src = (unsigned char *) malloc(j2k_len);
  319.  
  320.         // copy the jp2c
  321.         stream.SeekI(j2k_point, wxFromStart);
  322.         stream.Read(src, j2k_len);
  323.  
  324.         /* catch events using our callbacks and give a local context */
  325.         opj_set_event_mgr((opj_common_ptr)dinfo, &event_mgr, stderr);
  326.  
  327.         /* setup the decoder decoding parameters using user parameters */
  328.         opj_setup_decoder(dinfo, &parameters);
  329.  
  330.         /* open a byte stream */
  331.         cio = opj_cio_open((opj_common_ptr)dinfo, src, j2k_len);
  332.  
  333.         /* decode the stream and fill the image structure */
  334.         opjimage = opj_decode_with_info(dinfo, cio, &cstr_info);
  335.         if (!opjimage) {
  336.                 wxMutexGuiEnter();
  337.                 wxLogError(wxT("MXF: failed to decode image!"));
  338.                 wxMutexGuiLeave();
  339.                 opj_destroy_decompress(dinfo);
  340.                 opj_cio_close(cio);
  341.                 free(src);
  342.                 return false;
  343.         }
  344.  
  345.         /* close the byte stream */
  346.         opj_cio_close(cio);
  347.  
  348.         /* common rendering method */
  349. #include "imagjpeg2000.cpp"
  350.  
  351.     wxMutexGuiEnter();
  352.     wxLogMessage(wxT("MXF: image loaded."));
  353.     wxMutexGuiLeave();
  354.  
  355.         /* close openjpeg structs */
  356.         opj_destroy_decompress(dinfo);
  357.         opj_image_destroy(opjimage);
  358.         free(src);
  359.  
  360.         if (!image->Ok())
  361.                 return false;
  362.         else
  363.                 return true;
  364.  
  365. }
  366.  
  367. // save the mxf file format
  368. bool wxMXFHandler::SaveFile( wxImage *image, wxOutputStream& stream, bool verbose )
  369. {
  370.     wxLogError(wxT("MXF: Couldn't save movie -> not implemented."));
  371.     return false;
  372. }
  373.  
  374. #ifdef __VISUALC__
  375.     #pragma warning(default:4611)
  376. #endif /* VC++ */
  377.  
  378. // recognize the MXF JPEG 2000 starting box
  379. bool wxMXFHandler::DoCanRead( wxInputStream& stream )
  380. {
  381.     unsigned char hdr[4];
  382.  
  383.     if ( !stream.Read(hdr, WXSIZEOF(hdr)) )
  384.         return false;
  385.  
  386.     return (hdr[0] == 0x06 &&
  387.                         hdr[1] == 0x0E &&
  388.                         hdr[2] == 0x2B &&
  389.                         hdr[3] == 0x34);
  390. }
  391.  
  392. //! Build an EssenceInfoMap for the essence in a given file
  393. /*! \return True if al OK, else false
  394.  */
  395. bool BuildEssenceInfo(MXFFilePtr &File, EssenceInfoMap &EssenceLookup)
  396. {
  397.         // Empty any old data
  398.         EssenceLookup.clear();
  399.  
  400.         // Get the master metadata set (or the header if we must)
  401.         PartitionPtr MasterPartition = File->ReadMasterPartition();
  402.         if(!MasterPartition)
  403.         {
  404.                 File->Seek(0);
  405.                 MasterPartition = File->ReadPartition();
  406.                 warning("File %s does not contain a cloased copy of header metadata - using the open copy in the file header\n", File->Name.c_str());
  407.         }
  408.  
  409.         if(!MasterPartition)
  410.         {
  411.                 error("Could not read header metadata from file %s\n", File->Name.c_str());
  412.                 return false;
  413.         }
  414.  
  415.         // Read and parse the metadata
  416.         MasterPartition->ReadMetadata();
  417.         MetadataPtr HMeta = MasterPartition->ParseMetadata();
  418.        
  419.         if(!HMeta)
  420.         {
  421.                 error("Could not read header metadata from file %s\n", File->Name.c_str());
  422.                 return false;
  423.         }
  424.  
  425.         /* Scan the Essence container data sets to get PackageID to BodySID mapping */
  426.         MDObjectPtr ECDSet = HMeta[ContentStorage_UL];
  427.         if(ECDSet) ECDSet = ECDSet->GetLink();
  428.         if(ECDSet) ECDSet = ECDSet[EssenceContainerDataBatch_UL];
  429.         if(!ECDSet)
  430.         {
  431.                 error("Header metadata in file %s does not contain an EssenceContainerData set\n", File->Name.c_str());
  432.                 return false;
  433.         }
  434.  
  435.         MDObject::iterator it = ECDSet->begin();
  436.         while(it != ECDSet->end())
  437.         {
  438.                 MDObjectPtr ThisECDSet = (*it).second->GetLink();
  439.                 MDObjectPtr PackageID;
  440.                 if(ThisECDSet) PackageID = ThisECDSet->Child(LinkedPackageUID_UL);
  441.                 if(PackageID)
  442.                 {
  443.                         EssenceInfo NewEI;
  444.                         NewEI.PackageID = new UMID(PackageID->PutData()->Data);
  445.  
  446.                         // Inset the basic essence info - but not if this is external essence (BodySID == 0)
  447.                         UInt32 BodySID = ThisECDSet->GetUInt(BodySID_UL);
  448.                         if(BodySID) EssenceLookup[BodySID] = NewEI;
  449.                 }
  450.                 it++;
  451.         }
  452.  
  453.         /* Now find the other items for the essence lookup map */
  454.         if(EssenceLookup.size())
  455.         {
  456.                 PackageList::iterator it = HMeta->Packages.begin();
  457.                 while(it != HMeta->Packages.end())
  458.                 {
  459.                         // Only Source Packages are of interest
  460.                         if((*it)->IsA(SourcePackage_UL))
  461.                         {
  462.                                 MDObjectPtr Descriptor = (*it)->Child(Descriptor_UL);
  463.                                 if(Descriptor) Descriptor = Descriptor->GetLink();
  464.  
  465.                                 if(Descriptor)
  466.                                 {
  467.                                         MDObjectPtr PackageID = (*it)->Child(PackageUID_UL);
  468.                                         if(PackageID)
  469.                                         {
  470.                                                 UMIDPtr TheID = new UMID(PackageID->PutData()->Data);
  471.                                                
  472.                                                 /* Now do a lookup in the essence lookup map (it will need to be done the long way here */
  473.                                                 EssenceInfoMap::iterator EL_it = EssenceLookup.begin();
  474.                                                 while(EL_it != EssenceLookup.end())
  475.                                                 {
  476.                                                         if((*((*EL_it).second.PackageID)) == (*TheID))
  477.                                                         {
  478.                                                                 // If found, set the missing items and stop searching
  479.                                                                 (*EL_it).second.Package = (*it);
  480.                                                                 (*EL_it).second.Descriptor = Descriptor;
  481.                                                                 break;
  482.                                                         }
  483.                                                         EL_it++;
  484.                                                 }
  485.                                         }
  486.                                 }
  487.                         }
  488.  
  489.                         it++;
  490.                 }
  491.         }
  492.  
  493.         return true;
  494. }
  495.  
  496.  
  497. #endif   // wxUSE_STREAMS
  498.  
  499. #endif   // wxUSE_LIBOPENJPEG
  500.  
  501. #endif // USE_MXF
  502.  
  503.