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

多媒体编程

开发平台:

Visual C++

  1. /*****************************************************************
  2. |
  3. |    AP4 - Sample Description Objects
  4. |
  5. |    Copyright 2002 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 "Ap4IsmaCryp.h"
  32. #include "Ap4SchmAtom.h"
  33. #include "Ap4StsdAtom.h"
  34. #include "Ap4Sample.h"
  35. #include "Ap4StreamCipher.h"
  36. #include "Ap4IsfmAtom.h"
  37. #include "Ap4FrmaAtom.h"
  38. #include "Ap4IkmsAtom.h"
  39. #include "Ap4IsfmAtom.h"
  40. #include "Ap4Utils.h"
  41. #include "Ap4TrakAtom.h"
  42. /*----------------------------------------------------------------------
  43. |       AP4_EncaSampleEntry::AP4_EncaSampleEntry
  44. +---------------------------------------------------------------------*/
  45. AP4_EncaSampleEntry::AP4_EncaSampleEntry(AP4_UI32          sample_rate, 
  46.                                          AP4_UI16          sample_size,
  47.                                          AP4_UI16          channel_count,
  48.                                          AP4_EsDescriptor* descriptor) :
  49. AP4_AudioSampleEntry(AP4_ATOM_TYPE_ENCA, 
  50.                      descriptor,
  51.                      sample_rate, 
  52.                      sample_size, 
  53.                      channel_count)
  54. {
  55. }
  56. /*----------------------------------------------------------------------
  57. |       AP4_EncaSampleEntry::AP4_EncaSampleEntry
  58. +---------------------------------------------------------------------*/
  59. AP4_EncaSampleEntry::AP4_EncaSampleEntry(AP4_Size         size,
  60.                                          AP4_ByteStream&  stream,
  61.                                          AP4_AtomFactory& atom_factory) :
  62. AP4_AudioSampleEntry(AP4_ATOM_TYPE_ENCA, size, stream, atom_factory)
  63. {
  64. }
  65. /*----------------------------------------------------------------------
  66. |       AP4_EncaSampleEntry::ToSampleDescription
  67. +---------------------------------------------------------------------*/
  68. AP4_SampleDescription*
  69. AP4_EncaSampleEntry::ToSampleDescription()
  70. {
  71.     // get the original sample format
  72.     AP4_FrmaAtom* frma = (AP4_FrmaAtom*)FindChild("sinf/frma");
  73.     // get the scheme info
  74.     AP4_SchmAtom* schm = (AP4_SchmAtom*)FindChild("sinf/schm");
  75.     if (schm == NULL) return NULL;
  76.     // get the sample description for the original sample entry
  77.     AP4_MpegAudioSampleDescription* original_sample_description = 
  78.         (AP4_MpegAudioSampleDescription*)
  79.         AP4_AudioSampleEntry::ToSampleDescription();
  80.     // get the schi atom
  81.     AP4_ContainerAtom* schi;
  82.     schi = static_cast<AP4_ContainerAtom*>(FindChild("sinf/schi"));
  83.     // create the sample description
  84.     return new AP4_IsmaCrypSampleDescription(
  85.         original_sample_description,
  86.         frma?frma->GetOriginalFormat():AP4_ATOM_TYPE_MP4A,
  87.         schm->GetSchemeType(),
  88.         schm->GetSchemeVersion(),
  89.         schm->GetSchemeUri().c_str(),
  90.         schi);
  91. }
  92. /*----------------------------------------------------------------------
  93. |       AP4_EncvSampleEntry::AP4_EncaSampleEntry
  94. +---------------------------------------------------------------------*/
  95. AP4_EncvSampleEntry::AP4_EncvSampleEntry(AP4_UI16          width,
  96.                                          AP4_UI16          height,
  97.                                          AP4_UI16          depth,
  98.                                          const char*       compressor_name,
  99.                                          AP4_EsDescriptor* descriptor) :
  100.     AP4_VisualSampleEntry(AP4_ATOM_TYPE_ENCV,
  101.                           descriptor,
  102.                           width,
  103.                           height, 
  104.                           depth,
  105.                           compressor_name)
  106. {
  107. }
  108. /*----------------------------------------------------------------------
  109. |       AP4_EncvSampleEntry::AP4_EncvSampleEntry
  110. +---------------------------------------------------------------------*/
  111. AP4_EncvSampleEntry::AP4_EncvSampleEntry(AP4_Size         size,
  112.                                          AP4_ByteStream&  stream,
  113.                                          AP4_AtomFactory& atom_factory) :
  114.     AP4_VisualSampleEntry(AP4_ATOM_TYPE_ENCV, size, stream, atom_factory)
  115. {
  116. }
  117. /*----------------------------------------------------------------------
  118. |       AP4_EncvSampleEntry::ToSampleDescription
  119. +---------------------------------------------------------------------*/
  120. AP4_SampleDescription*
  121. AP4_EncvSampleEntry::ToSampleDescription()
  122. {
  123.     // get the original sample format
  124.     AP4_FrmaAtom* frma = (AP4_FrmaAtom*)FindChild("sinf/frma");
  125.     // get the scheme info
  126.     AP4_SchmAtom* schm = (AP4_SchmAtom*)FindChild("sinf/schm");
  127.     if (schm == NULL) return NULL;
  128.     // get the sample description for the original sample entry
  129.     AP4_MpegVideoSampleDescription* original_sample_description = 
  130.         (AP4_MpegVideoSampleDescription*)
  131.         AP4_VisualSampleEntry::ToSampleDescription();
  132.     // get the schi atom
  133.     AP4_ContainerAtom* schi;
  134.     schi = static_cast<AP4_ContainerAtom*>(FindChild("sinf/schi"));
  135.     // create the sample description
  136.     return new AP4_IsmaCrypSampleDescription(
  137.         original_sample_description,
  138.         frma?frma->GetOriginalFormat():AP4_ATOM_TYPE_MP4V,
  139.         schm->GetSchemeType(),
  140.         schm->GetSchemeVersion(),
  141.         schm->GetSchemeUri().c_str(),
  142.         schi);
  143. }
  144. /*----------------------------------------------------------------------
  145. |       AP4_IsmaCrypSampleDescription::AP4_IsmaCrypSampleDescription
  146. +---------------------------------------------------------------------*/
  147. AP4_IsmaCrypSampleDescription::AP4_IsmaCrypSampleDescription(
  148.     AP4_MpegSampleDescription* original_sample_description,
  149.     AP4_UI32                   original_format,
  150.     AP4_UI32                   scheme_type,
  151.     AP4_UI32                   scheme_version,
  152.     const char*                scheme_uri,
  153.     AP4_ContainerAtom*         schi) :
  154.     AP4_SampleDescription(TYPE_ISMACRYP),
  155.     m_OriginalSampleDescription(original_sample_description),
  156.     m_OriginalFormat(original_format),
  157.     m_SchemeType(scheme_type),
  158.     m_SchemeVersion(scheme_version),
  159.     m_SchemeUri(scheme_uri)
  160. {
  161.     m_SchemeInfo = new AP4_IsmaCrypSchemeInfo(schi);
  162. }
  163. /*----------------------------------------------------------------------
  164. |       AP4_IsmaCrypSampleDescription::~AP4_IsmaCrypSampleDescription
  165. +---------------------------------------------------------------------*/
  166. AP4_IsmaCrypSampleDescription::~AP4_IsmaCrypSampleDescription()
  167. {
  168.     delete m_SchemeInfo;
  169.     delete m_OriginalSampleDescription;
  170. }
  171. /*----------------------------------------------------------------------
  172. |       AP4_IsmaCrypSampleDescription::ToAtom
  173. +---------------------------------------------------------------------*/
  174. AP4_Atom*
  175. AP4_IsmaCrypSampleDescription::ToAtom() const
  176. {
  177.     // TODO: not implemented yet
  178.     return NULL;
  179. }
  180. /*----------------------------------------------------------------------
  181. |       AP4_IsmaCrypSchemeInfo::AP4_IsmaCrypSchemeInfo
  182. +---------------------------------------------------------------------*/
  183. AP4_IsmaCrypSchemeInfo::AP4_IsmaCrypSchemeInfo(AP4_ContainerAtom* schi) :
  184.     m_SchiAtom(AP4_ATOM_TYPE_SCHI)
  185. {
  186.     if (schi) {
  187.         AP4_List<AP4_Atom>& children = schi->GetChildren();
  188.         AP4_List<AP4_Atom>::Item* child_item = children.FirstItem();
  189.         while (child_item) {
  190.             AP4_Atom* child_atom = child_item->GetData();
  191.             AP4_Atom* clone = child_atom->Clone();
  192.             if (clone) m_SchiAtom.AddChild(clone);
  193.             child_item = child_item->GetNext();
  194.         }
  195.     }
  196. }
  197. /*----------------------------------------------------------------------
  198. |       AP4_IsmaCrypCipher::AP4_IsmaCipher
  199. +---------------------------------------------------------------------*/
  200. AP4_IsmaCipher::AP4_IsmaCipher(const AP4_UI08* key, 
  201.                                const AP4_UI08* salt, 
  202.                                AP4_Size        iv_length, 
  203.                                AP4_Size        key_indicator_length, 
  204.                                bool            selective_encryption) :
  205.     m_IvLength(iv_length),
  206.     m_KeyIndicatorLength(key_indicator_length),
  207.     m_SelectiveEncryption(selective_encryption)
  208. {
  209.     // NOTE: we do not handle key indicators yey, so there is only one key.
  210.     // left-align the salt
  211.     unsigned char salt_128[AP4_ISMACRYP_IAEC_KEY_LENGTH];
  212.     for (unsigned int i=0; i<8; i++) {
  213.         salt_128[i] = salt[i];
  214.     }
  215.     for (unsigned int i=0; i<8; i++) {
  216.         salt_128[8+i] = 0;
  217.     }
  218.     
  219.     // create a cipher
  220.     m_Cipher = new AP4_StreamCipher(key, salt_128);
  221. }
  222. /*----------------------------------------------------------------------
  223. |       AP4_IsmaCipher::~AP4_IsmaCipher
  224. +---------------------------------------------------------------------*/
  225. AP4_IsmaCipher::~AP4_IsmaCipher()
  226. {
  227.     delete m_Cipher;
  228. }
  229. /*----------------------------------------------------------------------
  230. |       AP4_IsmaCipher::DecryptSample
  231. +---------------------------------------------------------------------*/
  232. AP4_Result 
  233. AP4_IsmaCipher::DecryptSample(AP4_DataBuffer& data_in,
  234.                               AP4_DataBuffer& data_out)
  235. {
  236.     bool                 is_encrypted = true;
  237.     const unsigned char* in = data_in.GetData();
  238.     if (m_SelectiveEncryption) {
  239.         is_encrypted = ((in[0]&1)==1);
  240.         in++;
  241.     }
  242.     // get the IV (this implementation only supports un to 32 bits of IV)
  243.     // so we skip anything beyond the last 4 bytes
  244.     unsigned int to_read = m_IvLength;
  245.     if (to_read > 16 || to_read == 0) return AP4_ERROR_INVALID_FORMAT;
  246.     while (to_read > 4) {
  247.         to_read--;
  248.         in++;
  249.     }
  250.     AP4_UI32 iv = 0;
  251.     while (to_read--) {
  252.         iv = (iv<<8) | *in++; 
  253.     }
  254.     // get the key indicator (we only support up to 32 bits as well)
  255.     to_read = m_KeyIndicatorLength;
  256.     if (to_read > 4 ) return AP4_ERROR_INVALID_FORMAT;
  257.     while (to_read > 4) {
  258.         to_read--;
  259.         in++;
  260.     }
  261.     AP4_UI32 key_indicator = 0;
  262.     while (to_read--) {
  263.         key_indicator = (key_indicator<<8) | *in++; 
  264.     }
  265.     // we only support key indicator = 0 for now... (TODO)
  266.     if (key_indicator != 0) {
  267.         return AP4_FAILURE;
  268.     }
  269.     // process the sample data
  270.     unsigned int header_size = in-data_in.GetData();
  271.     unsigned int payload_size = data_in.GetDataSize()-header_size;
  272.     data_out.SetDataSize(payload_size);
  273.     unsigned char* out = data_out.UseData();
  274.     if (is_encrypted) {
  275.         m_Cipher->SetStreamOffset(iv);
  276.         m_Cipher->ProcessBuffer(in, out, payload_size);
  277.     } else {
  278.         memcpy(out, in, payload_size);
  279.     }
  280.     return AP4_SUCCESS;
  281. }
  282. /*----------------------------------------------------------------------
  283. |       AP4_IsmaCipher::EncryptSample
  284. +---------------------------------------------------------------------*/
  285. AP4_Result 
  286. AP4_IsmaCipher::EncryptSample(AP4_DataBuffer& data_in,
  287.                               AP4_DataBuffer& data_out,
  288.                               AP4_Offset      iv,
  289.                               bool            skip_encryption)
  290. {
  291.     // setup the buffers
  292.     const unsigned char* in = data_in.GetData();
  293.     data_out.SetDataSize(data_in.GetDataSize()+4);
  294.     unsigned char* out = data_out.UseData();
  295.     // IV on 4 bytes
  296.     AP4_BytesFromUInt32BE(out, iv);
  297.     out += 4;
  298.     // encrypt the payload
  299.     m_Cipher->SetStreamOffset(iv);
  300.     m_Cipher->ProcessBuffer(in, out, data_in.GetDataSize());
  301.     return AP4_FAILURE;
  302. }
  303. /*----------------------------------------------------------------------
  304. |       AP4_IsmaTrackDecrypter
  305. +---------------------------------------------------------------------*/
  306. class AP4_IsmaTrackDecrypter : public AP4_Processor::TrackHandler {
  307. public:
  308.     // constructor
  309.     AP4_IsmaTrackDecrypter(const AP4_UI08*                key,
  310.                            const AP4_UI08*                salt,
  311.                            AP4_IsmaCrypSampleDescription* sample_description,
  312.                            AP4_SampleEntry*               sample_entry);
  313.     virtual ~AP4_IsmaTrackDecrypter();
  314.     // methods
  315.     virtual AP4_Size   GetProcessedSampleSize(AP4_Sample& sample);
  316.     virtual AP4_Result ProcessTrack();
  317.     virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
  318.         AP4_DataBuffer& data_out);
  319. private:
  320.     // members
  321.     AP4_IsfmAtom*    m_CipherParams;
  322.     AP4_IsmaCipher*  m_Cipher;
  323.     AP4_SampleEntry* m_SampleEntry;
  324.     AP4_UI32         m_OriginalFormat;
  325. };
  326. /*----------------------------------------------------------------------
  327. |       AP4_IsmaTrackDecrypter::AP4_IsmaTrackDecrypter
  328. +---------------------------------------------------------------------*/
  329. AP4_IsmaTrackDecrypter::AP4_IsmaTrackDecrypter(
  330.     const AP4_UI08*                key,
  331.     const AP4_UI08*                salt,
  332.     AP4_IsmaCrypSampleDescription* sample_description,
  333.     AP4_SampleEntry*               sample_entry) :
  334.     m_SampleEntry(sample_entry)
  335. {
  336.     // get the cipher params
  337.     m_CipherParams = (AP4_IsfmAtom*)sample_description->GetSchemeInfo()->GetSchiAtom().FindChild("iSFM");
  338.     
  339.     // instantiate the cipher
  340.     m_Cipher = new AP4_IsmaCipher(key, salt, 
  341.                                   m_CipherParams->GetIvLength(),
  342.                                   m_CipherParams->GetKeyIndicatorLength(),
  343.                                   m_CipherParams->GetSelectiveEncryption());
  344.     // get the sample entry details
  345.     m_OriginalFormat = sample_description->GetOriginalFormat();
  346. }
  347. /*----------------------------------------------------------------------
  348. |       AP4_IsmaTrackDecrypter::~AP4_IsmaTrackDecrypter
  349. +---------------------------------------------------------------------*/
  350. AP4_IsmaTrackDecrypter::~AP4_IsmaTrackDecrypter()
  351. {
  352.     delete m_Cipher;
  353. }
  354. /*----------------------------------------------------------------------
  355. |       AP4_IsmaTrackDecrypter::GetProcessedSampleSize
  356. +---------------------------------------------------------------------*/
  357. AP4_Size   
  358. AP4_IsmaTrackDecrypter::GetProcessedSampleSize(AP4_Sample& sample)
  359. {
  360.     AP4_Size isma_header_size = 
  361.         m_CipherParams->GetKeyIndicatorLength() +
  362.         m_CipherParams->GetIvLength();
  363.     if (m_CipherParams->GetSelectiveEncryption()) {
  364.         isma_header_size++;
  365.     }
  366.     return sample.GetSize()-isma_header_size;
  367. }
  368. /*----------------------------------------------------------------------
  369. |       AP4_IsmaTrackDecrypter::ProcessTrack
  370. +---------------------------------------------------------------------*/
  371. AP4_Result   
  372. AP4_IsmaTrackDecrypter::ProcessTrack()
  373. {
  374.     m_SampleEntry->SetType(m_OriginalFormat);
  375.     m_SampleEntry->DeleteChild(AP4_ATOM_TYPE_SINF);
  376.     return AP4_SUCCESS;
  377. }
  378. /*----------------------------------------------------------------------
  379. |       AP4_IsmaDecrypter::ProcessSample
  380. +---------------------------------------------------------------------*/
  381. AP4_Result 
  382. AP4_IsmaTrackDecrypter::ProcessSample(AP4_DataBuffer& data_in,
  383.                                       AP4_DataBuffer& data_out)
  384. {
  385.     return m_Cipher->DecryptSample(data_in, data_out);
  386. }
  387. /*----------------------------------------------------------------------
  388. |       AP4_IsmaDecryptingProcessor:CreateTrackHandler
  389. +---------------------------------------------------------------------*/
  390. AP4_Processor::TrackHandler* 
  391. AP4_IsmaDecryptingProcessor::CreateTrackHandler(AP4_TrakAtom* trak)
  392. {
  393.     // find the stsd atom
  394.     AP4_StsdAtom* stsd = dynamic_cast<AP4_StsdAtom*>(
  395.         trak->FindChild("mdia/minf/stbl/stsd"));
  396.     // avoid tracks with no stsd atom (should not happen)
  397.     if (stsd == NULL) return NULL;
  398.     // we only look at the first sample description
  399.     AP4_SampleDescription* desc = stsd->GetSampleDescription(0);
  400.     AP4_SampleEntry* entry = stsd->GetSampleEntry(0);
  401.     if (desc == NULL || entry == NULL) return NULL;
  402.     if (desc->GetType() == AP4_SampleDescription::TYPE_ISMACRYP) {
  403.         // create a handler for this track
  404.         AP4_IsmaCrypSampleDescription* ismacryp_desc = 
  405.             static_cast<AP4_IsmaCrypSampleDescription*>(desc);
  406.         if (ismacryp_desc->GetSchemeType() == AP4_ISMACRYP_SCHEME_TYPE_IAEC) {
  407.             const AP4_UI08* key;
  408.             const AP4_UI08* salt;
  409.             if (AP4_SUCCEEDED(m_KeyMap.GetKey(trak->GetId(), key, salt))) {
  410.                 return new AP4_IsmaTrackDecrypter(key, salt, ismacryp_desc, entry);
  411.             }
  412.         }
  413.     }
  414.     return NULL;
  415. }
  416. /*----------------------------------------------------------------------
  417. |       AP4_IsmaTrackEncrypter
  418. +---------------------------------------------------------------------*/
  419. class AP4_IsmaTrackEncrypter : public AP4_Processor::TrackHandler {
  420. public:
  421.     // constructor
  422.     AP4_IsmaTrackEncrypter(const char*      kms_uri,
  423.                            const AP4_UI08*  key,
  424.                            const AP4_UI08*  salt,
  425.                            AP4_SampleEntry* sample_entry,
  426.                            AP4_UI32         format);
  427.     virtual ~AP4_IsmaTrackEncrypter();
  428.     // methods
  429.     virtual AP4_Size   GetProcessedSampleSize(AP4_Sample& sample);
  430.     virtual AP4_Result ProcessTrack();
  431.     virtual AP4_Result ProcessSample(AP4_DataBuffer& data_in,
  432.                                      AP4_DataBuffer& data_out);
  433. private:
  434.     // members
  435.     AP4_String       m_KmsUri;
  436.     AP4_IsmaCipher*  m_Cipher;
  437.     AP4_SampleEntry* m_SampleEntry;
  438.     AP4_UI32         m_Format;
  439.     AP4_Offset       m_ByteOffset;
  440. };
  441. /*----------------------------------------------------------------------
  442. |       AP4_IsmaTrackEncrypter::AP4_IsmaTrackEncrypter
  443. +---------------------------------------------------------------------*/
  444. AP4_IsmaTrackEncrypter::AP4_IsmaTrackEncrypter(
  445.     const char*      kms_uri,
  446.     const AP4_UI08*  key,
  447.     const AP4_UI08*  salt,
  448.     AP4_SampleEntry* sample_entry,
  449.     AP4_UI32         format) :
  450.     m_KmsUri(kms_uri),
  451.     m_SampleEntry(sample_entry),
  452.     m_Format(format),
  453.     m_ByteOffset(0)
  454. {
  455.     // instantiate the cipher (fixed params for now)
  456.     m_Cipher = new AP4_IsmaCipher(key, salt, 4, 0, false);
  457. }
  458. /*----------------------------------------------------------------------
  459. |       AP4_IsmaTrackEncrypter::~AP4_IsmaTrackEncrypter
  460. +---------------------------------------------------------------------*/
  461. AP4_IsmaTrackEncrypter::~AP4_IsmaTrackEncrypter()
  462. {
  463.     delete m_Cipher;
  464. }
  465. /*----------------------------------------------------------------------
  466. |       AP4_IsmaTrackEncrypter::GetProcessedSampleSize
  467. +---------------------------------------------------------------------*/
  468. AP4_Size   
  469. AP4_IsmaTrackEncrypter::GetProcessedSampleSize(AP4_Sample& sample)
  470. {
  471.     return sample.GetSize()+4; //fixed header size for now
  472. }
  473. /*----------------------------------------------------------------------
  474. |       AP4_IsmaTrackEncrypter::ProcessTrack
  475. +---------------------------------------------------------------------*/
  476. AP4_Result   
  477. AP4_IsmaTrackEncrypter::ProcessTrack()
  478. {
  479.     // sinf container
  480.     AP4_ContainerAtom* sinf = new AP4_ContainerAtom(AP4_ATOM_TYPE_SINF);
  481.     // original format
  482.     AP4_FrmaAtom* frma = new AP4_FrmaAtom(m_SampleEntry->GetType());
  483.     
  484.     // scheme
  485.     AP4_SchmAtom* schm = new AP4_SchmAtom(AP4_ISMACRYP_SCHEME_TYPE_IAEC, 1);
  486.     
  487.     // scheme info
  488.     AP4_ContainerAtom* schi = new AP4_ContainerAtom(AP4_ATOM_TYPE_SCHI);
  489.     AP4_IkmsAtom* ikms      = new AP4_IkmsAtom(m_KmsUri.c_str());
  490.     AP4_IsfmAtom* isfm      = new AP4_IsfmAtom(false, 0, 4);
  491.     // populate the schi container
  492.     schi->AddChild(ikms);
  493.     schi->AddChild(isfm);
  494.     // populate the sinf container
  495.     sinf->AddChild(frma);
  496.     sinf->AddChild(schm);
  497.     sinf->AddChild(schi);
  498.     // add the sinf atom to the sample description
  499.     m_SampleEntry->AddChild(sinf);
  500.     // change the atom type of the sample description
  501.     m_SampleEntry->SetType(m_Format);
  502.     
  503.     return AP4_SUCCESS;
  504. }
  505. /*----------------------------------------------------------------------
  506. |       AP4_IsmaTrackEncrypter::ProcessSample
  507. +---------------------------------------------------------------------*/
  508. AP4_Result 
  509. AP4_IsmaTrackEncrypter::ProcessSample(AP4_DataBuffer& data_in,
  510.                                       AP4_DataBuffer& data_out)
  511. {
  512.     AP4_Result result = m_Cipher->EncryptSample(data_in, data_out, m_ByteOffset, false);
  513.     if (AP4_FAILED(result)) return result;
  514.     m_ByteOffset += data_in.GetDataSize();
  515.     return AP4_SUCCESS;
  516. }
  517. /*----------------------------------------------------------------------
  518. |       AP4_IsmaEncryptingProcessor::AP4_IsmaEncryptingProcessor
  519. +---------------------------------------------------------------------*/
  520. AP4_IsmaEncryptingProcessor::AP4_IsmaEncryptingProcessor(const char* kms_uri) :
  521.     m_KmsUri(kms_uri)
  522. {
  523. }
  524. /*----------------------------------------------------------------------
  525. |       AP4_IsmaEncryptingProcessor:CreateTrackHandler
  526. +---------------------------------------------------------------------*/
  527. AP4_Processor::TrackHandler* 
  528. AP4_IsmaEncryptingProcessor::CreateTrackHandler(AP4_TrakAtom* trak)
  529. {
  530.     // find the stsd atom
  531.     AP4_StsdAtom* stsd = dynamic_cast<AP4_StsdAtom*>(
  532.         trak->FindChild("mdia/minf/stbl/stsd"));
  533.     // avoid tracks with no stsd atom (should not happen)
  534.     if (stsd == NULL) return NULL;
  535.     // only look at the first sample description
  536.     AP4_SampleEntry* entry = stsd->GetSampleEntry(0);
  537.     if (entry == NULL) return NULL;
  538.         
  539.     // create a handler for this track if we have a key for it and we know
  540.     // how to map the type
  541.     const AP4_UI08* key;
  542.     const AP4_UI08* salt;
  543.     AP4_UI32        format = 0;
  544.     if (AP4_SUCCEEDED(m_KeyMap.GetKey(trak->GetId(), key, salt))) {
  545.         switch (entry->GetType()) {
  546.             case AP4_ATOM_TYPE_MP4A:
  547.                 format = AP4_ATOM_TYPE_ENCA;
  548.                 break;
  549.             case AP4_ATOM_TYPE_MP4V:
  550.             case AP4_ATOM_TYPE_AVC1:
  551.                 format = AP4_ATOM_TYPE_ENCV;
  552.                 break;
  553.         }
  554.         if (format) {
  555.             return new AP4_IsmaTrackEncrypter(m_KmsUri.c_str(), 
  556.                                               key, 
  557.                                               salt, 
  558.                                               entry,
  559.                                               format);
  560.         }
  561.     }
  562.     return NULL;
  563. }
  564. /*----------------------------------------------------------------------
  565. |       AP4_IsmaKeyMap::AP4_IsmaKeyMap
  566. +---------------------------------------------------------------------*/
  567. AP4_IsmaKeyMap::AP4_IsmaKeyMap()
  568. {
  569. }
  570. /*----------------------------------------------------------------------
  571. |       AP4_IsmaKeyMap::~AP4_IsmaKeyMap
  572. +---------------------------------------------------------------------*/
  573. AP4_IsmaKeyMap::~AP4_IsmaKeyMap()
  574. {
  575.     m_KeyEntries.DeleteReferences();
  576. }
  577. /*----------------------------------------------------------------------
  578. |       AP4_IsmaKeyMap::SetKey
  579. +---------------------------------------------------------------------*/
  580. AP4_Result 
  581. AP4_IsmaKeyMap::SetKey(AP4_UI32 track_id, const AP4_UI08* key, const AP4_UI08* salt)
  582. {
  583.     KeyEntry* entry = GetEntry(track_id);
  584.     if (entry == NULL) {
  585.         m_KeyEntries.Add(new KeyEntry(track_id, key, salt));
  586.     } else {
  587.         entry->SetKey(key, salt);
  588.     }
  589.     return AP4_SUCCESS;
  590. }
  591. /*----------------------------------------------------------------------
  592. |       AP4_IsmaKeyMap::GetKey
  593. +---------------------------------------------------------------------*/
  594. AP4_Result 
  595. AP4_IsmaKeyMap::GetKey(AP4_UI32 track_id, const AP4_UI08*& key, const AP4_UI08*& salt)
  596. {
  597.     KeyEntry* entry = GetEntry(track_id);
  598.     if (entry) {
  599.         key = entry->m_Key;
  600.         salt = entry->m_Salt;
  601.         return AP4_SUCCESS;
  602.     } else {
  603.         return AP4_ERROR_NO_SUCH_ITEM;
  604.     }
  605. }
  606. /*----------------------------------------------------------------------
  607. |       AP4_IsmaKeyMap::GetEntry
  608. +---------------------------------------------------------------------*/
  609. AP4_IsmaKeyMap::KeyEntry*
  610. AP4_IsmaKeyMap::GetEntry(AP4_UI32 track_id)
  611. {
  612.     AP4_List<KeyEntry>::Item* item = m_KeyEntries.FirstItem();
  613.     while (item) {
  614.         KeyEntry* entry = (KeyEntry*)item->GetData();
  615.         if (entry->m_TrackId == track_id) return entry;
  616.         item = item->GetNext();
  617.     }
  618.     return NULL;
  619. }
  620. /*----------------------------------------------------------------------
  621. |       AP4_IsmaKeyMap::KeyEntry::KeyEntry
  622. +---------------------------------------------------------------------*/
  623. AP4_IsmaKeyMap::KeyEntry::KeyEntry(AP4_UI32        track_id, 
  624.                                    const AP4_UI08* key, 
  625.                                    const AP4_UI08* salt /* = NULL */) :
  626.     m_TrackId(track_id)
  627. {
  628.     SetKey(key, salt);
  629. }
  630. /*----------------------------------------------------------------------
  631. |       AP4_IsmaKeyMap::KeyEntry::SetKey
  632. +---------------------------------------------------------------------*/
  633. void
  634. AP4_IsmaKeyMap::KeyEntry::SetKey(const AP4_UI08* key, const AP4_UI08* salt)
  635. {
  636.     memcpy(m_Key, key, sizeof(m_Key));
  637.     if (salt) {
  638.         memcpy(m_Salt, salt, sizeof(m_Salt));
  639.     } else {
  640.         memset(m_Salt, 0, sizeof(m_Salt));
  641.     }
  642. }