LCOV - code coverage report
Current view: top level - filters - encrypt_cenc_isma.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 744 935 79.6 %
Date: 2021-04-29 23:48:07 Functions: 16 16 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2018-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / CENC and ISMA encrypt module
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/filters.h>
      27             : #include <gpac/constants.h>
      28             : #include <gpac/crypt_tools.h>
      29             : #include <gpac/crypt.h>
      30             : #include <gpac/base_coding.h>
      31             : #include <gpac/download.h>
      32             : #include <gpac/xml.h>
      33             : #include <gpac/internal/isomedia_dev.h>
      34             : 
      35             : #include <gpac/internal/media_dev.h>
      36             : 
      37             : #ifndef GPAC_DISABLE_CRYPTO
      38             : 
      39             : 
      40             : enum
      41             : {
      42             :         ISMAEA_STATE_ERROR,
      43             :         ISMAEA_STATE_SETUP,
      44             :         ISMAEA_STATE_PLAY,
      45             : };
      46             : 
      47             : 
      48             : typedef enum {
      49             :         CENC_FULL_SAMPLE,
      50             : 
      51             :         /*below types may have several ranges (clear/encrypted) per sample*/
      52             :         CENC_AVC, /*AVC, nalu-based*/
      53             :         CENC_HEVC, /*HEVC, nalu-based*/
      54             :         CENC_AV1,  /*AV1, OBU-based*/
      55             :         CENC_VPX,  /*VPX, custom, see https://www.webmproject.org/vp9/mp4/ */
      56             : } CENCCodecMode;
      57             : 
      58             : typedef struct
      59             : {
      60             :         GF_Crypt *crypt;
      61             :         char IV[16];
      62             :         bin128 key;
      63             :         u32 IV_size;
      64             : } CENC_MKey;
      65             : 
      66             : typedef struct
      67             : {
      68             :         Bool passthrough;
      69             : 
      70             :         GF_CryptInfo *cinfo;
      71             : 
      72             :         GF_FilterPid *ipid;
      73             :         GF_FilterPid *opid;
      74             :         GF_TrackCryptInfo *tci;
      75             : 
      76             :         //active keys (for multikey support)
      77             :         u32 nb_keys;
      78             :         CENC_MKey *keys;
      79             :         Bool multi_key;
      80             :         u32 codec_id;
      81             : 
      82             :         u32 nb_pck;
      83             : 
      84             :         //ISMA/OMA var
      85             :         u32 nalu_size_length;
      86             :         u32 dsi_crc;
      87             :         Bool isma_oma;
      88             :         u64 BSO;
      89             :         u64 range_end;
      90             :         Bool prev_pck_encryped;
      91             :         u32 KI_length;
      92             :         u32 isma_IV_size;
      93             :         Bool has_crypted_pck;
      94             : 
      95             :         Bool is_adobe;
      96             : 
      97             :         CENCCodecMode cenc_codec;
      98             : 
      99             :         u32 bytes_in_nal_hdr;
     100             :         Bool use_subsamples;
     101             :         Bool cenc_init;
     102             :         u32 nb_pck_encrypted, kidx;
     103             : 
     104             :         //true if using AES-CTR mode, false if using AES-CBC mode
     105             :         Bool ctr_mode;
     106             : 
     107             :         Bool rap_roll;
     108             : 
     109             : #ifndef GPAC_DISABLE_AV_PARSERS
     110             :         AVCState avc;
     111             : #ifndef GPAC_DISABLE_HEVC
     112             :         HEVCState hevc;
     113             : #endif
     114             :         AV1State av1;
     115             : #endif
     116             :         Bool slice_header_clear;
     117             : 
     118             :         GF_PropUIntList mkey_indices;
     119             : } GF_CENCStream;
     120             : 
     121             : typedef struct
     122             : {
     123             :         //options
     124             :         const char *cfile;
     125             :         Bool allc;
     126             :         
     127             :         //internal
     128             :         GF_CryptInfo *cinfo;
     129             : 
     130             :         GF_List *streams;
     131             :         GF_BitStream *bs_w, *bs_r;
     132             : } GF_CENCEncCtx;
     133             : 
     134             : 
     135           6 : static GF_Err isma_enc_configure(GF_CENCEncCtx *ctx, GF_CENCStream *cstr, Bool is_isma, const char *scheme_uri, const char *kms_uri)
     136             : {
     137             :         GF_Err e;
     138             :         bin128 IV;
     139             :         const GF_PropertyValue *p;
     140           6 :         p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_DECODER_CONFIG);
     141           6 :         if (!p) p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_DECODER_CONFIG_ENHANCEMENT);
     142             : 
     143           6 :         switch (cstr->codec_id) {
     144           1 :         case GF_CODECID_AVC:
     145             :         case GF_CODECID_SVC:
     146             :         case GF_CODECID_MVC:
     147           1 :                 if (p) {
     148           1 :                         GF_AVCConfig *avcc = gf_odf_avc_cfg_read(p->value.data.ptr, p->value.data.size);
     149           1 :                         cstr->nalu_size_length = avcc ? avcc->nal_unit_size : 0;
     150           1 :                         if (avcc) gf_odf_avc_cfg_del(avcc);
     151             :                 }
     152           1 :                 if (!cstr->nalu_size_length) {
     153           0 :                         cstr->nalu_size_length = 4;
     154           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[ISMACrypt] Missing NALU length size, assuming 4\n") );
     155             :                 }
     156             :                 break;
     157           1 :         case GF_CODECID_HEVC:
     158             :         case GF_CODECID_LHVC:
     159           1 :                 if (p) {
     160           1 :                         GF_HEVCConfig *hvcc = gf_odf_hevc_cfg_read(p->value.data.ptr, p->value.data.size, (cstr->codec_id==GF_CODECID_LHVC) ? GF_TRUE : GF_FALSE);
     161           1 :                         cstr->nalu_size_length = hvcc ? hvcc->nal_unit_size : 0;
     162           1 :                         if (hvcc) gf_odf_hevc_cfg_del(hvcc);
     163             :                 }
     164           1 :                 if (!cstr->nalu_size_length) {
     165           0 :                         cstr->nalu_size_length = 4;
     166           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[ISMACrypt] Missing NALU length size, assuming 4\n") );
     167             :                 }
     168             :                 break;
     169             :         }
     170             : 
     171           6 :         if (!scheme_uri || !strlen(scheme_uri)) scheme_uri = "urn:gpac:isma:encryption_scheme";
     172             : 
     173           6 :         if (cstr->tci && ((cstr->tci->sel_enc_type==GF_CRYPT_SELENC_RAND) || (cstr->tci->sel_enc_type==GF_CRYPT_SELENC_RAND_RANGE)) ) {
     174           0 :                 gf_rand_init(GF_TRUE);
     175             :         }
     176             : 
     177           6 :         cstr->isma_IV_size = 0;
     178           6 :         if (!is_isma) {
     179             :                 /*128 bit IV in OMA*/
     180           0 :                 cstr->isma_IV_size = 16;
     181             :         } else {
     182           6 :                 p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_ISMA_IV_LENGTH);
     183           6 :                 if (p) {
     184           0 :                         cstr->isma_IV_size = p->value.uint;
     185             :                 } else {
     186           6 :                         p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_MEDIA_DATA_SIZE);
     187           6 :                         if (p) {
     188           6 :                                 u64 BSO = p->value.longuint;
     189             : 
     190           6 :                                 if (BSO<0xFFFF) cstr->isma_IV_size = 2;
     191           2 :                                 else if (BSO<0xFFFFFFFF) cstr->isma_IV_size = 4;
     192           0 :                                 else cstr->isma_IV_size = 8;
     193             :                         }
     194             :                 }
     195           6 :                 if (!cstr->isma_IV_size || (cstr->isma_IV_size > 8)) cstr->isma_IV_size = 8;
     196             :         }
     197             : 
     198           6 :         if (!cstr->tci || !cstr->tci->nb_keys) {
     199           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[ISMACrypt] No keys specified for ISMA\n"));
     200             :                 return GF_BAD_PARAM;
     201             :         }
     202             : 
     203             :         /*init crypto*/
     204             :         memset(IV, 0, sizeof(char)*16);
     205           6 :         memcpy(IV, cstr->tci->keys[0].IV, sizeof(char)*8);
     206           6 :         if (cstr->keys[0].crypt) gf_crypt_close(cstr->keys[0].crypt);
     207           6 :         cstr->keys[0].crypt = gf_crypt_open(GF_AES_128, GF_CTR);
     208           6 :         if (!cstr->keys[0].crypt) {
     209           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[ISMACrypt] Cannot open AES-128 CTR\n"));
     210             :                 return GF_IO_ERR;
     211             :         }
     212             : 
     213           6 :         e = gf_crypt_init(cstr->keys[0].crypt, cstr->tci->keys[0].key, IV);
     214           6 :         if (e) {
     215           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[ISMACrypt] Cannot initialize AES-128 CTR (%s)\n", gf_error_to_string(e)) );
     216             :                 return GF_IO_ERR;
     217             :         }
     218             : 
     219           6 :         GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("[ISMACrypt] Encrypting stream %s - KMS: %s%s\n", gf_filter_pid_get_name(cstr->ipid), cstr->tci->KMS_URI, cstr->tci->sel_enc_type ? " - Selective Encryption" : ""));
     220             : 
     221           6 :         if (!stricmp(kms_uri, "self")) {
     222             :                 char Data[100], d64[100];
     223             :                 u32 size_b64;
     224           6 :                 memcpy(Data, cstr->tci->keys[0].key, sizeof(char)*16);
     225             :                 memcpy(Data+16, cstr->tci->keys[0].IV, sizeof(char)*8);
     226           6 :                 size_b64 = gf_base64_encode(Data, 24, d64, 100);
     227           6 :                 d64[size_b64] = 0;
     228           6 :                 cstr->tci->KMS_URI = gf_realloc(cstr->tci->KMS_URI, size_b64+6);
     229           6 :                 strcpy(cstr->tci->KMS_URI, "(key)");
     230           6 :                 strcat(cstr->tci->KMS_URI, d64);
     231           6 :                 kms_uri = cstr->tci->KMS_URI;
     232             :         }
     233             : 
     234             :         /*create ISMA protection*/
     235           6 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_PROTECTION_SCHEME_VERSION, &PROP_UINT(1) );
     236           6 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_PROTECTION_KMS_URI, kms_uri ? &PROP_STRING(kms_uri) : NULL);
     237           6 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_ISMA_SELECTIVE_ENC, &PROP_BOOL( (cstr->tci->sel_enc_type!=0) ? GF_TRUE : GF_FALSE) );
     238           6 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_ISMA_IV_LENGTH, &PROP_UINT(cstr->isma_IV_size) );
     239             : 
     240           6 :         if (is_isma) {
     241           6 :                 gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_PROTECTION_SCHEME_URI, scheme_uri ? &PROP_STRING(scheme_uri) : NULL );
     242             :         } else {
     243           0 :                 if ((cstr->tci->sel_enc_type==GF_CRYPT_SELENC_PREVIEW) && cstr->tci->sel_enc_range) {
     244             :                         char szSTR[100];
     245             :                         u32 len;
     246             :                         char *szPreview;
     247             : 
     248             :                         sprintf(szSTR, "PreviewRange:%d", cstr->tci->sel_enc_range);
     249           0 :                         len = (u32) strlen(szSTR) + ( cstr->tci->TextualHeaders ? (u32) strlen(cstr->tci->TextualHeaders) : 0 ) + 1;
     250           0 :                         szPreview = gf_malloc(sizeof(char) * len);
     251           0 :                         strcpy(szPreview, cstr->tci->TextualHeaders ? cstr->tci->TextualHeaders : "");
     252             :                         strcat(szPreview, szSTR);
     253             : 
     254           0 :                         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_OMA_TXT_HDR, &PROP_STRING_NO_COPY(szPreview));
     255             :                 } else {
     256           0 :                         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_OMA_TXT_HDR, cstr->tci->TextualHeaders ? &PROP_STRING(cstr->tci->TextualHeaders) : NULL);
     257             :                 }
     258             : 
     259           0 :                 gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_OMA_CID, scheme_uri ? &PROP_STRING(scheme_uri) : NULL );
     260             : 
     261           0 :                 gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_OMA_CRYPT_TYPE, &PROP_UINT(cstr->tci->encryption));
     262           0 :                 gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_OMA_CLEAR_LEN, &PROP_LONGUINT(cstr->tci->sel_enc_range) );
     263           0 :                 gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_ISMA_KI_LENGTH, &PROP_UINT(0) );
     264             :         }
     265             : 
     266           6 :         cstr->range_end = 0;
     267           6 :         if (cstr->tci->sel_enc_type==GF_CRYPT_SELENC_PREVIEW) {
     268           0 :                 p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_TIMESCALE);
     269           0 :                 if (p)
     270           0 :                         cstr->range_end = p->value.uint *cstr->tci->sel_enc_range;
     271             :         }
     272             : 
     273           6 :         cstr->isma_oma = GF_TRUE;
     274           6 :         cstr->prev_pck_encryped = GF_TRUE;
     275           6 :         cstr->has_crypted_pck = GF_FALSE;
     276             : 
     277             :         //we drop IPMPX support for now
     278             : #if GPAC_DEPRECTAED
     279             :         /*format as IPMP(X) - note that the ISMACryp spec is broken since it always uses IPMPPointers to a
     280             :         single desc which would assume the same protection (eg key & salt) for all streams using it...*/
     281             :         if (!tci->ipmp_type) return GF_OK;
     282             : 
     283             :         ipmpdp = (GF_IPMPPtr*)gf_odf_desc_new(GF_ODF_IPMP_PTR_TAG);
     284             :         if (!tci->ipmp_desc_id) tci->ipmp_desc_id = track;
     285             :         if (tci->ipmp_type==2) {
     286             :                 ipmpdp->IPMP_DescriptorID = 0xFF;
     287             :                 ipmpdp->IPMP_DescriptorIDEx = tci->ipmp_desc_id;
     288             :         } else {
     289             :                 ipmpdp->IPMP_DescriptorID = tci->ipmp_desc_id;
     290             :         }
     291             :         gf_isom_add_desc_to_description(mp4, track, 1, (GF_Descriptor *)ipmpdp);
     292             :         gf_odf_desc_del((GF_Descriptor*)ipmpdp);
     293             : 
     294             :         ipmpdU = (GF_IPMPUpdate*)gf_odf_com_new(GF_ODF_IPMP_UPDATE_TAG);
     295             :         /*format IPMPD*/
     296             :         ipmpd = (GF_IPMP_Descriptor*)gf_odf_desc_new(GF_ODF_IPMP_TAG);
     297             :         if (tci->ipmp_type==2) {
     298             : #ifndef GPAC_MINIMAL_ODF
     299             :                 ipmpd->IPMP_DescriptorID = 0xFF;
     300             :                 ipmpd->IPMP_DescriptorIDEx = tci->ipmp_desc_id;
     301             :                 ipmpd->IPMPS_Type = 0xFFFF;
     302             :                 ipmpd->IPMP_ToolID[14] = 0x49;
     303             :                 ipmpd->IPMP_ToolID[15] = 0x53;
     304             :                 ipmpd->control_point = 1;
     305             :                 ipmpd->cp_sequence_code = 0x80;
     306             :                 /*format IPMPXData*/
     307             :                 ismac = (GF_IPMPX_ISMACryp *) gf_ipmpx_data_new(GF_IPMPX_ISMACRYP_TAG);
     308             :                 ismac->cryptoSuite = 1;      /*default ISMA AESCTR128*/
     309             :                 ismac->IV_length = IV_size;
     310             :                 ismac->key_indicator_length = 0;
     311             :                 ismac->use_selective_encryption = (tci->sel_enc_type!=0)? 1 : 0;
     312             :                 gf_list_add(ipmpd->ipmpx_data, ismac);
     313             : #endif
     314             :         } else {
     315             :                 ipmpd->IPMP_DescriptorID = tci->ipmp_desc_id;
     316             :         }
     317             :         gf_list_add(ipmpdU->IPMPDescList, ipmpd);
     318             : 
     319             :         for (i=0; i<gf_isom_get_track_count(mp4); i++) {
     320             :                 GF_ODCodec *cod;
     321             :                 if (gf_isom_get_media_type(mp4, i+1) != GF_ISOM_MEDIA_OD) continue;
     322             : 
     323             :                 /*add com*/
     324             :                 samp = gf_isom_get_sample(mp4, i+1, 1, &di);
     325             :                 cod = gf_odf_codec_new();
     326             :                 gf_odf_codec_set_au(cod, samp->data, samp->dataLength);
     327             :                 gf_odf_codec_decode(cod);
     328             :                 gf_odf_codec_add_com(cod, (GF_ODCom *) ipmpdU);
     329             :                 gf_free(samp->data);
     330             :                 samp->data = NULL;
     331             :                 samp->dataLength = 0;
     332             :                 gf_odf_codec_encode(cod, 1);
     333             :                 gf_odf_codec_get_au(cod, &samp->data, &samp->dataLength);
     334             :                 ipmpdU = NULL;
     335             :                 gf_odf_codec_del(cod);
     336             :                 gf_isom_update_sample(mp4, i+1, 1, samp, 1);
     337             :                 gf_isom_sample_del(&samp);
     338             : 
     339             :                 if (tci->ipmp_type==2) {
     340             :                         GF_IPMP_ToolList*ipmptl = (GF_IPMP_ToolList*)gf_odf_desc_new(GF_ODF_IPMP_TL_TAG);
     341             :                         GF_IPMP_Tool *ipmpt = (GF_IPMP_Tool*)gf_odf_desc_new(GF_ODF_IPMP_TOOL_TAG);
     342             :                         gf_list_add(ipmptl->ipmp_tools, ipmpt);
     343             :                         ipmpt->IPMP_ToolID[14] = 0x49;
     344             :                         ipmpt->IPMP_ToolID[15] = 0x53;
     345             :                         gf_isom_add_desc_to_root_od(mp4, (GF_Descriptor *)ipmptl);
     346             :                         gf_odf_desc_del((GF_Descriptor *)ipmptl);
     347             :                 }
     348             :                 break;
     349             :         }
     350             : #endif
     351             :         return GF_OK;
     352             : }
     353             : 
     354           5 : static GF_Err adobe_enc_configure(GF_CENCEncCtx *ctx, GF_CENCStream *cstr)
     355             : {
     356           5 :         if (cstr->keys[0].crypt) gf_crypt_close(cstr->keys[0].crypt);
     357           5 :         cstr->keys[0].crypt = gf_crypt_open(GF_AES_128, GF_CBC);
     358           5 :         if (!cstr->keys[0].crypt) {
     359           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[Adobe] Cannot open AES-128 CBC \n"));
     360             :                 return GF_IO_ERR;
     361             :         }
     362             : 
     363             :         /*Adobe's protection scheme does not support selective key*/
     364           5 :         memcpy(cstr->keys[0].key, cstr->tci->keys[0].key, 16);
     365             : 
     366           5 :         if (cstr->tci->metadata)
     367           5 :                 gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_ADOBE_CRYPT_META, &PROP_DATA(cstr->tci->metadata, (u32) strlen(cstr->tci->metadata) ) );
     368             : 
     369           5 :         cstr->is_adobe = GF_TRUE;
     370             : 
     371             :         return GF_OK;
     372             : }
     373             : 
     374         155 : static GF_Err cenc_parse_pssh(GF_CENCEncCtx *ctx, GF_CENCStream *cstr, const char *cfile_name)
     375             : {
     376             :         GF_DOMParser *parser;
     377             :         GF_XMLNode *root, *node;
     378             :         u32 i;
     379             :         GF_Err e;
     380             :         u32 nb_pssh=0;
     381             :         GF_BitStream *pssh_bs=NULL;
     382             : 
     383         155 :         parser = gf_xml_dom_new();
     384         155 :         e = gf_xml_dom_parse(parser, cfile_name, NULL, NULL);
     385         155 :         if (e) {
     386           0 :                 gf_xml_dom_del(parser);
     387             :                 return e;
     388             :         }
     389         155 :         root = gf_xml_dom_get_root(parser);
     390         155 :         if (!root) {
     391           0 :                 gf_xml_dom_del(parser);
     392           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC/ISMA] Cannot open or validate xml file %s\n", ctx->cfile));
     393             :                 return GF_NOT_SUPPORTED;
     394             :         }
     395         155 :         pssh_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     396         155 :         gf_bs_write_u32(pssh_bs, 0);
     397             : 
     398         155 :         i=0;
     399        1223 :         while ((node = (GF_XMLNode *) gf_list_enum(root->content, &i))) {
     400             :                 Bool is_pssh;
     401             :                 u32 version, cypherMode, specInfoSize, len, KID_count, j;
     402             :                 bin128 cypherKey, cypherIV, systemID;
     403             :                 GF_XMLAttribute *att;
     404             :                 u8 *data, *specInfo;
     405             :                 GF_BitStream *bs;
     406             :                 bin128 *KIDs;
     407             :                 s32 cypherOffset = -1;
     408             :                 Bool has_key = GF_FALSE, has_IV = GF_FALSE;
     409             : 
     410        1935 :                 if (strcmp(node->name, "DRMInfo")) continue;
     411             : 
     412         201 :                 j = 0;
     413             :                 is_pssh = GF_FALSE;
     414             :                 version = cypherMode = 0;
     415         201 :                 data = specInfo = NULL;
     416             :                 bs = NULL;
     417             : 
     418        1068 :                 while ( (att = (GF_XMLAttribute *)gf_list_enum(node->attributes, &j))) {
     419         867 :                         if (!strcmp(att->name, "type")) {
     420         201 :                                 if (!strcmp(att->value, "pssh"))
     421             :                                         is_pssh = GF_TRUE;
     422         666 :                         } else if (!strcmp(att->name, "version")) {
     423         402 :                                 version = atoi(att->value);
     424         465 :                         } else if (!strcmp(att->name, "cypherMode")) {
     425             :                                 /*cypher-mode: 0: ctr (default mode) -  1: cbc - 2: clear*/
     426           0 :                                 if (!strcmp(att->value, "yes"))
     427             :                                         cypherMode = 0;
     428           0 :                                 else if (!strcmp(att->value, "no"))
     429             :                                         cypherMode = 1;
     430         465 :                         } else if (!strcmp(att->name, "cypherKey")) {
     431         155 :                                 e = gf_bin128_parse(att->value, cypherKey);
     432         155 :                 if (e != GF_OK) {
     433           0 :                     GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannnot parse cypherKey\n"));
     434           0 :                     return e;
     435             :                 }
     436             :                                 has_key = GF_TRUE;
     437         310 :                         } else if (!strcmp(att->name, "cypherIV")) {
     438         155 :                                 e = gf_bin128_parse(att->value, cypherIV);
     439         155 :                 if (e != GF_OK) {
     440           0 :                     GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannnot parse cypherIV\n"));
     441             :                     return e;
     442             :                 }
     443             :                                 has_IV = GF_TRUE;
     444         155 :                         } else if (!strcmp(att->name, "cypherOffset")) {
     445         155 :                                 cypherOffset = atoi(att->value);
     446             :                         }
     447             :                 }
     448             : 
     449         201 :                 if (!is_pssh) {
     450           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC/ISMA] Not a Protection System Specific Header Box - skipping\n"));
     451           0 :                         continue;
     452             :                 }
     453             : 
     454         201 :                 e = gf_xml_parse_bit_sequence(node, cfile_name, &specInfo, &specInfoSize);
     455         201 :                 if (e) {
     456           0 :                         if (specInfo) gf_free(specInfo);
     457           0 :                         gf_xml_dom_del(parser);
     458             :                         return e;
     459             :                 }
     460             : 
     461         201 :                 bs = gf_bs_new(specInfo, specInfoSize, GF_BITSTREAM_READ);
     462         201 :                 gf_bs_read_data(bs, (char *)systemID, 16);
     463         201 :                 if (version) {
     464         155 :                         KID_count = gf_bs_read_u32(bs);
     465         155 :                         KIDs = (bin128 *)gf_malloc(KID_count*sizeof(bin128));
     466         342 :                         for (j = 0; j < KID_count; j++) {
     467         187 :                                 gf_bs_read_data(bs, (char *)KIDs[j], 16);
     468             :                         }
     469             :                 }
     470             :                 else {
     471             :                         KID_count = 0;
     472             :                         KIDs = NULL;
     473             :                 }
     474         201 :                 if (specInfoSize < 16 + (version ? 4 + 16*KID_count : 0)) {
     475           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC/ISMA] Invalid PSSH blob in version %d: size %d key count %d - ignoring PSSH\n", version, specInfoSize, KID_count));
     476           0 :                         continue;
     477             :                 }
     478         201 :                 len = specInfoSize - 16 - (version ? 4 + 16*KID_count : 0);
     479         201 :                 data = (char *)gf_malloc(len*sizeof(char));
     480         201 :                 gf_bs_read_data(bs, data, len);
     481             : 
     482         201 :                 if (has_key && has_IV && (cypherOffset >= 0) && (cypherMode != 1)) {
     483         155 :                         GF_Crypt *gc = gf_crypt_open(GF_AES_128, GF_CTR);
     484         155 :                         if (!gc) {
     485           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC/ISMA] Cannot open AES-128 CTR\n"));
     486             :                                 return GF_IO_ERR;
     487             :                         }
     488         155 :                         e = gf_crypt_init(gc, cypherKey, cypherIV);
     489         155 :                         gf_crypt_encrypt(gc, data+cypherOffset, len-cypherOffset);
     490         155 :                         gf_crypt_close(gc);
     491             :                 }
     492         201 :                 if (!e) {
     493         201 :                         nb_pssh++;
     494         201 :                         gf_bs_write_data(pssh_bs, systemID, 16);
     495         201 :                         gf_bs_write_u32(pssh_bs, version);
     496         201 :                         gf_bs_write_u32(pssh_bs, KID_count);
     497         388 :                         for (j=0; j<KID_count; j++) {
     498         187 :                                 gf_bs_write_data(pssh_bs, KIDs[j], 16);
     499             :                         }
     500         201 :                         gf_bs_write_u32(pssh_bs, len);
     501         201 :                         gf_bs_write_data(pssh_bs, data, len);
     502             :                 }
     503             : 
     504         201 :                 if (specInfo) gf_free(specInfo);
     505         201 :                 if (data) gf_free(data);
     506         201 :                 if (KIDs) gf_free(KIDs);
     507         201 :                 if (bs) gf_bs_del(bs);
     508         201 :                 if (e) break;
     509             :         }
     510             : 
     511         155 :         gf_xml_dom_del(parser);
     512             : 
     513         155 :         if (nb_pssh) {
     514         155 :                 u8 *pssh=NULL;
     515         155 :                 u32 pssh_size=0;
     516         155 :                 u32 pos = (u32) gf_bs_get_position(pssh_bs);
     517         155 :                 gf_bs_seek(pssh_bs, 0);
     518         155 :                 gf_bs_write_u32(pssh_bs, nb_pssh);
     519         155 :                 gf_bs_seek(pssh_bs, pos);
     520         155 :                 gf_bs_get_content(pssh_bs, &pssh, &pssh_size);
     521         155 :                 gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_PSSH, &PROP_DATA_NO_COPY(pssh, pssh_size));
     522             :         }
     523         155 :         gf_bs_del(pssh_bs);
     524             : 
     525             :         return e;
     526             : }
     527             : 
     528             : 
     529         155 : static GF_Err cenc_enc_configure(GF_CENCEncCtx *ctx, GF_CENCStream *cstr, const char *cfile_name)
     530             : {
     531             : #if !defined(GPAC_DISABLE_AV_PARSERS)
     532             :         u32 i;
     533             : #endif
     534             :         u32 dsi_crc=0;
     535             :         Bool is_reinit=GF_FALSE;
     536             :         GF_AVCConfig *avccfg;
     537             :         GF_HEVCConfig *hevccfg;
     538             :         const GF_PropertyValue *p;
     539             : 
     540         155 :         p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_DECODER_CONFIG);
     541         155 :         if (!p) p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_DECODER_CONFIG_ENHANCEMENT);
     542             : 
     543         155 :         if (p) {
     544         155 :                 dsi_crc = gf_crc_32(p->value.data.ptr, p->value.data.size);
     545             :         }
     546         155 :         if (dsi_crc != cstr->dsi_crc)
     547             :                 is_reinit = GF_TRUE;
     548          18 :         else if (!dsi_crc && !cstr->keys[0].crypt)
     549             :                 is_reinit = GF_TRUE;
     550             : 
     551         137 :         cstr->dsi_crc = dsi_crc;
     552             : 
     553             :         if (is_reinit) {
     554             :                 const GF_PropertyValue *p2;
     555         137 :                 cstr->nalu_size_length = 0;
     556         137 :                 cstr->cenc_codec = CENC_FULL_SAMPLE;
     557         137 :                 switch (cstr->codec_id) {
     558          64 :                 case GF_CODECID_AVC:
     559             :                 case GF_CODECID_SVC:
     560             :                 case GF_CODECID_MVC:
     561          64 :                         if (!p)
     562             :                                 return GF_OK;
     563             : 
     564          64 :                         avccfg = gf_odf_avc_cfg_read(p->value.data.ptr, p->value.data.size);
     565          64 :                         if (avccfg) cstr->nalu_size_length = avccfg->nal_unit_size;
     566             : 
     567          64 :                         cstr->cenc_codec = CENC_AVC;
     568             : 
     569          64 :                         p2 = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_ISOM_SUBTYPE);
     570          64 :                         if (p2 && (p2->value.uint==GF_ISOM_BOX_TYPE_AVC1)) {
     571          52 :                                 if (!cstr->tci->allow_encrypted_slice_header) {
     572          49 :                                         cstr->slice_header_clear = GF_TRUE;
     573           3 :                                 } else if (cstr->tci->scheme_type==GF_CRYPT_TYPE_CBCS) {
     574           0 :                                         cstr->slice_header_clear = GF_TRUE;
     575             :                                 }
     576             :                         } else {
     577          12 :                                 cstr->slice_header_clear = GF_TRUE;
     578             :                         }
     579             : #ifndef GPAC_DISABLE_AV_PARSERS
     580          64 :                         if (avccfg) {
     581          64 :                                 for (i=0; i<gf_list_count(avccfg->sequenceParameterSets); i++) {
     582          64 :                                         GF_NALUFFParam *slc = gf_list_get(avccfg->sequenceParameterSets, i);
     583          64 :                                         gf_avc_read_sps(slc->data, slc->size, &cstr->avc, 0, NULL);
     584             :                                 }
     585          64 :                                 for (i=0; i<gf_list_count(avccfg->pictureParameterSets); i++) {
     586          64 :                                         GF_NALUFFParam *slc = gf_list_get(avccfg->pictureParameterSets, i);
     587          64 :                                         gf_avc_read_pps(slc->data, slc->size, &cstr->avc);
     588             :                                 }
     589             : 
     590          64 :                                 gf_odf_avc_cfg_del(avccfg);
     591             :                         }
     592             : #else
     593             :                         if (avccfg) gf_odf_avc_cfg_del(avccfg);
     594             : #endif
     595          64 :                         cstr->bytes_in_nal_hdr = 1;
     596             : 
     597          64 :                         if (!cstr->slice_header_clear && cstr->tci->clear_bytes)
     598           1 :                                 cstr->bytes_in_nal_hdr = cstr->tci->clear_bytes;
     599             : 
     600          64 :                         if (!cstr->nalu_size_length) {
     601           0 :                                 cstr->nalu_size_length = 4;
     602           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[CENCCrypt] Missing NALU length size, assuming 4\n") );
     603             :                         }
     604             :                         break;
     605          17 :                 case GF_CODECID_HEVC:
     606             :                 case GF_CODECID_LHVC:
     607          17 :                         if (!p)
     608             :                                 return GF_OK;
     609             : 
     610          17 :                         hevccfg = gf_odf_hevc_cfg_read(p->value.data.ptr, p->value.data.size, (cstr->codec_id==GF_CODECID_LHVC) ? GF_TRUE : GF_FALSE);
     611          17 :                         if (hevccfg) cstr->nalu_size_length = hevccfg->nal_unit_size;
     612             : 
     613             : #if !defined(GPAC_DISABLE_AV_PARSERS) && !defined(GPAC_DISABLE_HEVC)
     614          17 :                         gf_hevc_parse_ps(hevccfg, &cstr->hevc, GF_HEVC_NALU_VID_PARAM);
     615          17 :                         gf_hevc_parse_ps(hevccfg, &cstr->hevc, GF_HEVC_NALU_SEQ_PARAM);
     616          17 :                         gf_hevc_parse_ps(hevccfg, &cstr->hevc, GF_HEVC_NALU_PIC_PARAM);
     617             : #endif
     618             : 
     619             :                         //mandatory for HEVC
     620          17 :                         cstr->slice_header_clear = GF_TRUE;
     621             : 
     622          17 :                         cstr->cenc_codec = CENC_HEVC;
     623             : 
     624          17 :                         if (hevccfg) gf_odf_hevc_cfg_del(hevccfg);
     625          17 :                         cstr->bytes_in_nal_hdr = 2;
     626             : 
     627          17 :                         if (!cstr->nalu_size_length) {
     628           0 :                                 cstr->nalu_size_length = 4;
     629           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[CENCCrypt] Missing NALU length size, assuming 4\n") );
     630             :                         }
     631             :                         break;
     632          26 :                 case GF_CODECID_AV1:
     633          26 :                         if (!p)
     634             :                                 return GF_OK;
     635             : 
     636             : #if !defined(GPAC_DISABLE_AV_PARSERS) && !defined(GPAC_DISABLE_AV1)
     637          26 :                         cstr->av1.config = gf_odf_av1_cfg_read(p->value.data.ptr, p->value.data.size);
     638          26 :                         cstr->cenc_codec = CENC_AV1;
     639          26 :                         cstr->bytes_in_nal_hdr = 2;
     640             : #endif
     641             :                         //mandatory for AV1
     642          26 :                         cstr->slice_header_clear = GF_TRUE;
     643          26 :                         break;
     644           8 :                 case GF_CODECID_VP8:
     645             :                 case GF_CODECID_VP9:
     646           8 :                         if (p) {
     647           8 :                                 cstr->cenc_codec = CENC_VPX;
     648           8 :                                 cstr->bytes_in_nal_hdr = 2;
     649             :                         }
     650             :                         break;
     651             :                 }
     652             :         }
     653             : 
     654         155 :         if (((cstr->tci->scheme_type == GF_CRYPT_TYPE_CENS) || (cstr->tci->scheme_type == GF_CRYPT_TYPE_CBCS) ) && (cstr->cenc_codec>CENC_FULL_SAMPLE) && (cstr->cenc_codec<=CENC_AV1)
     655             :         )  {
     656          28 :                 if (!cstr->tci->crypt_byte_block || !cstr->tci->skip_byte_block) {
     657          16 :                         if (cstr->tci->crypt_byte_block || cstr->tci->skip_byte_block) {
     658           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] Using pattern mode, crypt_byte_block and skip_byte_block shall be 0 only for track other than video, using 1 crypt + 9 skip\n"));
     659             :                         }
     660          16 :                         cstr->tci->crypt_byte_block = 1;
     661          16 :                         cstr->tci->skip_byte_block = 9;
     662             :                 }
     663             :         }
     664             : 
     665         155 :         if ( (cstr->cenc_codec==CENC_VPX) && (cstr->tci->scheme_type != GF_CRYPT_TYPE_CENC) ) {
     666           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Encryption mode %s is not supported with VP8/VP9, only cenc is\n", gf_4cc_to_str(cstr->tci->scheme_type) ));
     667             :                 return GF_NOT_SUPPORTED;
     668             :         }
     669             : 
     670             : 
     671         155 :         cstr->use_subsamples = GF_FALSE;
     672         155 :         if (cstr->cenc_codec != CENC_FULL_SAMPLE) cstr->use_subsamples = GF_TRUE;
     673             :         //CBCS mode with skip byte block may be used for any track, in which case we need subsamples
     674          22 :         else if (cstr->tci->scheme_type == GF_CRYPT_TYPE_CBCS) {
     675           2 :                 if (cstr->tci->skip_byte_block) {
     676           0 :                         cstr->use_subsamples = GF_TRUE;
     677           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("\n[CENC] Using cbcs pattern mode on non NAL video track, this may not be supported by most devices; consider setting skip_byte_block to 0\n\n"));
     678             :                         //cbcs allows bytes of clear data
     679           0 :                         cstr->bytes_in_nal_hdr = cstr->tci->clear_bytes;
     680             :                 }
     681             :                 //This is not clear in the spec, setting skip and crypt to 0 means no pattern, in which case tenc version shall be 0
     682             :                 //but cbcs asks for 1 - needs further clarification
     683             : #if 0
     684             :                 //setup defaults
     685             :                 else if (!cstr->crypt_byte_block) {
     686             :                         cstr->tci->crypt_byte_block = 1;
     687             :                 }
     688             : #else
     689             :                 else {
     690           2 :                         cstr->tci->crypt_byte_block = 0;
     691             :                 }
     692             : #endif
     693             :         }
     694          20 :         else if (cstr->tci->scheme_type == GF_CRYPT_TYPE_CENS) {
     695           2 :                 if (cstr->tci->skip_byte_block) {
     696           2 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] Using cens pattern mode on non NAL video track not allowed, forcing skip_byte_block to 0\n"));
     697           2 :                         cstr->tci->skip_byte_block = 0;
     698           2 :                         if (!cstr->tci->crypt_byte_block) {
     699           0 :                                 cstr->tci->crypt_byte_block = 1;
     700             :                         }
     701             :                 }
     702             :         }
     703             : 
     704             :         //setup crypto context, disabling multikey if the stream doesn't use subsample
     705         155 :         if (!cstr->keys) {
     706           3 :                 if (!cstr->use_subsamples)
     707           0 :                         cstr->multi_key = GF_FALSE;
     708             : 
     709           3 :                 if (cstr->multi_key) {
     710           3 :                         cstr->nb_keys = cstr->tci->nb_keys;
     711             :                 } else {
     712           0 :                         cstr->nb_keys = 1;
     713             :                 }
     714           3 :                 cstr->keys = gf_malloc(sizeof(CENC_MKey) * cstr->nb_keys);
     715           3 :                 if (!cstr->keys) return GF_OUT_OF_MEM;
     716           3 :                 memset(cstr->keys, 0, sizeof(CENC_MKey) * cstr->nb_keys);
     717             :         }
     718             :         //init rand
     719         310 :         if ((cstr->tci->sel_enc_type==GF_CRYPT_SELENC_RAND)
     720         155 :                 || (cstr->tci->sel_enc_type==GF_CRYPT_SELENC_RAND_RANGE)
     721         155 :                 || cstr->tci->subs_rand
     722             :         ) {
     723           0 :                 gf_rand_init(GF_TRUE);
     724             :         }
     725             : 
     726             :         //configure roll rap
     727         155 :         if (cstr->tci->roll_rap) {
     728           0 :                 cstr->rap_roll = GF_TRUE;
     729             :                 //if no subsample, only use key roll "rap" if codec has sync point
     730           0 :                 if (!cstr->use_subsamples) {
     731           0 :                         p = gf_filter_pid_get_property(cstr->ipid, GF_PROP_PID_HAS_SYNC);
     732           0 :                         if (p && p->value.uint) {
     733           0 :                                 cstr->rap_roll = GF_TRUE;
     734             :                         } else {
     735           0 :                                 switch (cstr->codec_id) {
     736           0 :                                 case GF_CODECID_USAC:
     737           0 :                                         cstr->rap_roll = GF_TRUE;
     738           0 :                                         break;
     739             :                                 }
     740             :                         }
     741             :                 } else {
     742             :                         cstr->rap_roll = GF_TRUE;
     743             :                 }
     744             :         }
     745         155 :         if (cstr->multi_key && !cstr->mkey_indices.nb_items && cstr->tci->mkey_subs) {
     746           1 :                 GF_PropertyValue pval = gf_props_parse_value(GF_PROP_UINT_LIST, "subs", cstr->tci->mkey_subs, NULL, ',');
     747           1 :                 cstr->mkey_indices = pval.value.uint_list;
     748             :         }
     749             : 
     750         155 :         if (is_reinit) {
     751             :                 u32 nb_keys;
     752             : 
     753             :                 /*select key*/
     754         137 :                 if (!cstr->tci->keys) {
     755           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] No key specified\n"));
     756             :                         return GF_BAD_PARAM;
     757             :                 }
     758             : 
     759         137 :                 nb_keys = cstr->multi_key ? cstr->tci->nb_keys : 1;
     760         277 :                 for (i=0; i<nb_keys; i++) {
     761             : 
     762         140 :                         if (cstr->keys[i].crypt) gf_crypt_close(cstr->keys[i].crypt);
     763         140 :                         if (cstr->ctr_mode) {
     764         114 :                                 cstr->keys[i].crypt = gf_crypt_open(GF_AES_128, GF_CTR);
     765             :                         }
     766             :                         else {
     767          26 :                                 cstr->keys[i].crypt = gf_crypt_open(GF_AES_128, GF_CBC);
     768             :                         }
     769         140 :                         if (!cstr->keys[i].crypt) {
     770           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot open AES-128 %s\n", cstr->ctr_mode ? "CTR" : "CBC"));
     771             :                                 return GF_IO_ERR;
     772             :                         }
     773             : 
     774         140 :                         if (nb_keys>1) {
     775           6 :                                 memcpy(cstr->keys[i].key, cstr->tci->keys[i].key, 16);
     776           6 :                                 cstr->kidx = 0;
     777             :                         } else {
     778         134 :                                 if (cstr->tci->defaultKeyIdx && (cstr->tci->defaultKeyIdx < cstr->tci->nb_keys)) {
     779           0 :                                         cstr->kidx = cstr->tci->defaultKeyIdx;
     780             :                                 } else {
     781         134 :                                         cstr->kidx = 0;
     782             :                                 }
     783         134 :                                 memcpy(cstr->keys[0].key, cstr->tci->keys[cstr->kidx].key, 16);
     784             :                         }
     785             :                 }
     786             : 
     787         137 :                 cstr->prev_pck_encryped = cstr->tci->IsEncrypted;
     788             :         }
     789             : 
     790             :         /*set CENC protection properties*/
     791             : 
     792         155 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_PROTECTION_SCHEME_VERSION, &PROP_UINT(0x00010000) );
     793         155 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_ENCRYPTED, &PROP_BOOL(cstr->tci->IsEncrypted ? GF_TRUE : GF_FALSE) );
     794             : 
     795             :         u8 *data;
     796             :         u32 size;
     797         155 :         GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     798         155 :         if (cstr->multi_key) {
     799           3 :                 gf_bs_write_u8(bs, 1);
     800           3 :                 gf_bs_write_u16(bs, cstr->tci->nb_keys);
     801             : 
     802           9 :                 for (i=0; i<cstr->tci->nb_keys; i++) {
     803           6 :                         GF_CryptKeyInfo *ki = &cstr->tci->keys[i];
     804           6 :                         gf_bs_write_u8(bs, ki->constant_IV_size ? 0 : ki->IV_size);
     805           6 :                         gf_bs_write_data(bs, ki->KID, 16);
     806           6 :                         if (ki->constant_IV_size) {
     807           0 :                                 gf_bs_write_u8(bs, ki->constant_IV_size);
     808           0 :                                 gf_bs_write_data(bs, ki->IV, ki->constant_IV_size);
     809             :                         }
     810             :                 }
     811             :         } else {
     812         152 :                 GF_CryptKeyInfo *ki = &cstr->tci->keys[cstr->kidx];
     813         152 :                 gf_bs_write_u8(bs, 0);
     814         152 :                 gf_bs_write_u16(bs, 0);
     815         152 :                 gf_bs_write_u8(bs, ki->constant_IV_size ? 0 : ki->IV_size);
     816         152 :                 gf_bs_write_data(bs, ki->KID, 16);
     817         152 :                 if (ki->constant_IV_size) {
     818           9 :                         gf_bs_write_u8(bs, ki->constant_IV_size);
     819           9 :                         gf_bs_write_data(bs, ki->IV, ki->constant_IV_size);
     820             :                 }
     821             :         }
     822         155 :         gf_bs_get_content(bs, &data, &size);
     823         155 :         gf_bs_del(bs);
     824         155 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_KEY_INFO, &PROP_DATA_NO_COPY(data, size) );
     825             : 
     826         155 :         if (!cstr->multi_key) {
     827         152 :                 char *hls_info = cstr->tci->keys[0].hls_info;
     828         152 :                 gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_HLS_KMS, hls_info ? &PROP_STRING(hls_info) : NULL);
     829             :         }
     830             : 
     831         155 :         if (cstr->tci->skip_byte_block || cstr->tci->crypt_byte_block) {
     832          30 :                 gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_PATTERN, &PROP_FRAC_INT(cstr->tci->skip_byte_block, cstr->tci->crypt_byte_block ) );
     833             :         } else {
     834         125 :                 gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_PATTERN, NULL);
     835             :         }
     836             : 
     837             :         //if constantIV and not using CENC subsample, no CENC auxiliary info
     838         155 :         if (!cstr->tci->keys[0].constant_IV_size || cstr->use_subsamples) {
     839         154 :                 gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_STORE, &PROP_4CC(cstr->tci->sai_saved_box_type) );
     840             :         }
     841             : 
     842             :         //parse pssh even if reinit since we need to reassign pssh property
     843         155 :         return cenc_parse_pssh(ctx, cstr, cfile_name);
     844             : }
     845             : 
     846         149 : static void cenc_free_pid_context(GF_CENCStream *cstr)
     847             : {
     848             :         u32 i;
     849         300 :         for (i=0; i<cstr->nb_keys; i++) {
     850         151 :                 if (cstr->keys[i].crypt) gf_crypt_close(cstr->keys[i].crypt);
     851             :         }
     852         149 :         gf_free(cstr->keys);
     853         149 :         if (cstr->cinfo) gf_crypt_info_del(cstr->cinfo);
     854             : #ifndef GPAC_DISABLE_AV_PARSERS
     855         149 :         if (cstr->av1.config) gf_odf_av1_cfg_del(cstr->av1.config);
     856             : #endif
     857             : 
     858         149 :         if (cstr->mkey_indices.vals) gf_free(cstr->mkey_indices.vals);
     859         149 :         gf_free(cstr);
     860         149 : }
     861             : 
     862         167 : static GF_Err cenc_enc_configure_pid(GF_Filter *filter, GF_FilterPid *pid, Bool is_remove)
     863             : {
     864             :         const GF_PropertyValue *prop;
     865         167 :         GF_Err e = GF_OK;
     866             :         u32 scheme_type = 0;
     867             :         GF_TrackCryptInfo *tci = NULL;
     868             :         const char *scheme_uri = NULL;
     869             :         const char *kms_uri = NULL;
     870             :         GF_CryptInfo *cinfo = NULL;
     871             :         GF_CENCStream *cstr;
     872         167 :         GF_CENCEncCtx *ctx = (GF_CENCEncCtx *)gf_filter_get_udta(filter);
     873         167 :         const char *cfile_name = ctx->cfile;
     874             :         GF_TrackCryptInfo *tci_any = NULL;
     875             :         u32 i, count;
     876             : 
     877             : 
     878         167 :         if (is_remove) {
     879           0 :                 cstr = gf_filter_pid_get_udta(pid);
     880           0 :                 if (cstr) {
     881           0 :                         gf_list_del_item(ctx->streams, cstr);
     882           0 :                         if (cstr->opid)
     883           0 :                                 gf_filter_pid_remove(cstr->opid);
     884             : 
     885           0 :                         cenc_free_pid_context(cstr);
     886             :                 }
     887             :                 return GF_OK;
     888             :         }
     889             : 
     890         167 :         if (! gf_filter_pid_check_caps(pid))
     891             :                 return GF_NOT_SUPPORTED;
     892             : 
     893         167 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CRYPT_INFO);
     894         167 :         if (prop) {
     895           0 :                 cinfo = gf_crypt_info_load(prop->value.string, &e);
     896           0 :                 if (!cinfo) {
     897           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[CENCrypt] failed to load crypt info file %s for pid %s\n", prop->value.string, gf_filter_pid_get_name(pid) ) );
     898           0 :                         return e;
     899             :                 }
     900           0 :                 cfile_name = prop->value.string;
     901             :         }
     902         167 :         if (!cinfo) cinfo = ctx->cinfo;
     903             : 
     904             : 
     905         167 :         if (cinfo) {
     906         167 :                 prop = gf_filter_pid_get_property(pid, GF_PROP_PID_ID);
     907         167 :                 count = gf_list_count(cinfo->tcis);
     908         168 :                 for (i=0; i<count; i++) {
     909         167 :                         tci = gf_list_get(cinfo->tcis, i);
     910         167 :                         if (prop && tci->trackID && (tci->trackID==prop->value.uint)) break;
     911           1 :                         if (!tci_any && !tci->trackID) tci_any = tci;
     912           1 :                         if ((cinfo != ctx->cinfo) && !tci_any) tci_any = tci;
     913             :                         tci = NULL;
     914             :                 }
     915         167 :                 if (!tci) tci = tci_any;
     916           0 :         } else if (ctx->allc) {
     917           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[CENCrypt] Missing DRM config file\n") );
     918             :                 return GF_NOT_SUPPORTED;
     919             :         }
     920             : 
     921         167 :         if (!tci) {
     922           1 :                 if (cinfo) {
     923           1 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_MEDIA, ("[CENCrypt] Missing track crypt info in DRM config file, PID will not be crypted\n") );
     924             :                 }
     925             :         } else {
     926         166 :                 scheme_type = tci->scheme_type;
     927             : 
     928         166 :                 switch (scheme_type) {
     929             :                 case GF_CRYPT_TYPE_ISMA:
     930             :                 case GF_CRYPT_TYPE_OMA:
     931             :                 case GF_CRYPT_TYPE_ADOBE:
     932             :                 case GF_CRYPT_TYPE_CENC:
     933             :                 case GF_CRYPT_TYPE_CBC1:
     934             :                 case GF_CRYPT_TYPE_CENS:
     935             :                 case GF_CRYPT_TYPE_CBCS:
     936             :                 case GF_CRYPT_TYPE_PIFF:
     937             :                         break;
     938           0 :                 default:
     939           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_MEDIA, ("[CENCrypt] Unsupported scheme type %s\n", gf_4cc_to_str(scheme_type) ));
     940           0 :                         if (cinfo != ctx->cinfo) gf_crypt_info_del(cinfo);
     941             :                         return GF_NOT_SUPPORTED;
     942             :                 }
     943             :         }
     944             : 
     945         167 :         cstr = gf_filter_pid_get_udta(pid);
     946         167 :         if (!cstr) {
     947         149 :                 GF_SAFEALLOC(cstr, GF_CENCStream);
     948         149 :                 if (!cstr) return GF_OUT_OF_MEM;
     949         149 :                 cstr->ipid = pid;
     950         149 :                 cstr->opid = gf_filter_pid_new(filter);
     951         149 :                 cstr->tci = tci;
     952         149 :                 gf_list_add(ctx->streams, cstr);
     953         149 :                 gf_filter_pid_set_udta(pid, cstr);
     954             :                 //we need full sample
     955         149 :                 gf_filter_pid_set_framing_mode(pid, GF_TRUE);
     956             :         }
     957         167 :         if (cstr->cinfo) gf_crypt_info_del(cstr->cinfo);
     958         167 :         cstr->cinfo = (cinfo != ctx->cinfo) ? cinfo : NULL;
     959         167 :         cstr->tci = tci;
     960         167 :         cstr->passthrough = tci ? GF_FALSE : GF_TRUE;
     961             : 
     962             :         //copy properties at init or reconfig
     963         167 :         gf_filter_pid_copy_properties(cstr->opid, pid);
     964             : 
     965         167 :         prop = gf_filter_pid_get_property(pid, GF_PROP_PID_CODECID);
     966         167 :         if (prop) cstr->codec_id = prop->value.uint;
     967             : 
     968         167 :         if (cstr->tci) {
     969         166 :                 gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_PROTECTION_SCHEME_TYPE, &PROP_4CC(scheme_type) );
     970             : 
     971             : 
     972         166 :                 prop = gf_filter_pid_get_property(pid, GF_PROP_PID_STREAM_TYPE);
     973         166 :                 if (prop) {
     974         166 :                         switch (prop->value.uint) {
     975         166 :                         case GF_STREAM_VISUAL:
     976             :                         case GF_STREAM_AUDIO:
     977             :                         case GF_STREAM_SCENE:
     978             :                         case GF_STREAM_FONT:
     979             :                         case GF_STREAM_TEXT:
     980         166 :                                 gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_ORIG_STREAM_TYPE, & PROP_UINT(prop->value.uint) );
     981         166 :                                 break;
     982           0 :                         default:
     983           0 :                                 GF_LOG(GF_LOG_INFO, GF_LOG_AUTHOR, ("[CENCrypt] Stream type %s cannot be encrypted, using passthrough\n", gf_stream_type_name(prop->value.uint) ));
     984           0 :                                 cstr->passthrough = GF_TRUE;
     985           0 :                                 break;
     986             :                         }
     987           0 :                 }
     988         166 :                 gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_STSD_MODE, &PROP_UINT(tci->force_clear_stsd_idx) );
     989             :         }
     990             :         
     991         167 :         if (cstr->passthrough) return GF_OK;
     992             : 
     993         166 :         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_ENCRYPTED) );
     994             : 
     995         166 :         scheme_uri = cstr->tci->Scheme_URI;
     996         166 :         kms_uri = cstr->tci->KMS_URI;
     997             : 
     998             :         /*default to FILE uri*/
     999         166 :         if (!kms_uri || !strlen(kms_uri) ) {
    1000             :                 kms_uri = cfile_name;
    1001             :         }
    1002             : 
    1003         166 :         if (!cstr->keys) {
    1004         148 :                 cstr->multi_key = cstr->tci->multi_key;
    1005         148 :                 if (cstr->multi_key) {
    1006           3 :                         switch (scheme_type) {
    1007             :                         case GF_CRYPT_TYPE_CENC:
    1008             :                         case GF_CRYPT_TYPE_CENS:
    1009             :                         case GF_CRYPT_TYPE_PIFF:
    1010             :                         case GF_CRYPT_TYPE_CBC1:
    1011             :                         case GF_CRYPT_TYPE_CBCS:
    1012             :                                 break;
    1013           0 :                         default:
    1014           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[ISMACrypt] Multi-key not possible with scheme %s, ignoring\n", gf_4cc_to_str(scheme_type) ));
    1015           0 :                                 cstr->multi_key = 0;
    1016           0 :                                 break;
    1017             :                         }
    1018         145 :                 }
    1019         148 :                 if (!cstr->multi_key) {
    1020         145 :                         cstr->nb_keys = 1;
    1021         145 :                         cstr->keys = gf_malloc(sizeof(CENC_MKey) * cstr->nb_keys);
    1022         145 :                         if (!cstr->keys) return GF_OUT_OF_MEM;
    1023         145 :                         memset(cstr->keys, 0, sizeof(CENC_MKey) * cstr->nb_keys);
    1024             :                 }
    1025             :         }
    1026             : 
    1027         166 :         cstr->ctr_mode = GF_FALSE;
    1028             : 
    1029         166 :         switch (scheme_type) {
    1030           6 :         case GF_CRYPT_TYPE_ISMA:
    1031           6 :                 cstr->ctr_mode = GF_TRUE;
    1032           6 :                 return isma_enc_configure(ctx, cstr, GF_TRUE, scheme_uri, kms_uri);
    1033           0 :         case GF_CRYPT_TYPE_OMA:
    1034           0 :                 return isma_enc_configure(ctx, cstr, GF_FALSE, scheme_uri, kms_uri);
    1035           5 :         case GF_CRYPT_TYPE_ADOBE:
    1036           5 :                 return adobe_enc_configure(ctx, cstr);
    1037         129 :         case GF_CRYPT_TYPE_CENC:
    1038             :         case GF_CRYPT_TYPE_CENS:
    1039             :         case GF_CRYPT_TYPE_PIFF:
    1040         129 :                 cstr->ctr_mode = GF_TRUE;
    1041         155 :         case GF_CRYPT_TYPE_CBC1:
    1042             :         case GF_CRYPT_TYPE_CBCS:
    1043         155 :                 return cenc_enc_configure(ctx, cstr, cfile_name);
    1044             :         default:
    1045             :                 return GF_NOT_SUPPORTED;
    1046             :         }
    1047             : 
    1048             :         return e;
    1049             : }
    1050             : 
    1051             : 
    1052         979 : static GF_Err isma_process(GF_CENCEncCtx *ctx, GF_CENCStream *cstr, GF_FilterPacket *pck)
    1053             : {
    1054             :         u32 isma_hdr_size=0;
    1055             :         GF_FilterPacket *dst_pck;
    1056             :         const u8 *data;
    1057             :         u8 *output;
    1058             :         u32 size, rand, flags;
    1059         979 :         u64 cts = gf_filter_pck_get_cts(pck);
    1060         979 :         u8 sap = gf_filter_pck_get_sap(pck);
    1061             : 
    1062             : 
    1063             :         flags = 0;
    1064             : 
    1065         979 :         switch (cstr->tci->sel_enc_type) {
    1066           0 :         case GF_CRYPT_SELENC_RAP:
    1067           0 :                 if (sap) flags |= GF_ISOM_ISMA_IS_ENCRYPTED;
    1068             :                 break;
    1069           0 :         case GF_CRYPT_SELENC_NON_RAP:
    1070           0 :                 if (!sap) flags |= GF_ISOM_ISMA_IS_ENCRYPTED;
    1071             :                 break;
    1072             :         /*random*/
    1073           0 :         case GF_CRYPT_SELENC_RAND:
    1074           0 :                 rand = gf_rand();
    1075           0 :                 if (rand%2) flags |= GF_ISOM_ISMA_IS_ENCRYPTED;
    1076             :                 break;
    1077             :         /*random every sel_freq samples*/
    1078           0 :         case GF_CRYPT_SELENC_RAND_RANGE:
    1079           0 :                 if (! (cstr->nb_pck % cstr->tci->sel_enc_range) ) cstr->has_crypted_pck = 0;
    1080           0 :                 if (! cstr->has_crypted_pck) {
    1081           0 :                         rand = gf_rand();
    1082           0 :                         if (!(rand % cstr->tci->sel_enc_range)) flags |= GF_ISOM_ISMA_IS_ENCRYPTED;
    1083             : 
    1084           0 :                         if (!(flags & GF_ISOM_ISMA_IS_ENCRYPTED) && !( (1+cstr->nb_pck) % cstr->tci->sel_enc_range)) {
    1085             :                                 flags |= GF_ISOM_ISMA_IS_ENCRYPTED;
    1086             :                         }
    1087           0 :                         cstr->has_crypted_pck = (flags & GF_ISOM_ISMA_IS_ENCRYPTED);
    1088             :                 }
    1089             :                 break;
    1090             :         /*every sel_freq samples*/
    1091           0 :         case GF_CRYPT_SELENC_RANGE:
    1092           0 :                 if (!(cstr->nb_pck % cstr->tci->sel_enc_type)) flags |= GF_ISOM_ISMA_IS_ENCRYPTED;
    1093             :                 break;
    1094           0 :         case GF_CRYPT_SELENC_PREVIEW:
    1095           0 :                 if (cts >= cstr->range_end)
    1096             :                         flags |= GF_ISOM_ISMA_IS_ENCRYPTED;
    1097             :                 break;
    1098         979 :         case 0:
    1099             :                 flags |= GF_ISOM_ISMA_IS_ENCRYPTED;
    1100             :                 break;
    1101             :         default:
    1102             :                 break;
    1103             :         }
    1104             : 
    1105         979 :         if (cstr->tci->sel_enc_type) flags |= GF_ISOM_ISMA_USE_SEL_ENC;
    1106             : 
    1107         979 :         if (flags & GF_ISOM_ISMA_USE_SEL_ENC) isma_hdr_size = 1;
    1108         979 :         if (flags & GF_ISOM_ISMA_IS_ENCRYPTED) isma_hdr_size += cstr->isma_IV_size + cstr->KI_length;
    1109             : 
    1110         979 :         data = gf_filter_pck_get_data(pck, &size);
    1111         979 :         if (!data) {
    1112           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[ISMACrypt] No data associated with packet\n" ));
    1113             :                 return GF_OK;
    1114             :         }
    1115         979 :         dst_pck = gf_filter_pck_new_alloc(cstr->opid, size+isma_hdr_size, &output);
    1116         979 :         if (!dst_pck) return GF_OUT_OF_MEM;
    1117             : 
    1118         979 :         memcpy(output+isma_hdr_size, data, sizeof(char)*size);
    1119         979 :         gf_filter_pck_merge_properties(pck, dst_pck);
    1120             : 
    1121             :         
    1122             :         /*isma e&a stores AVC1 in AVC/H264 annex B bitstream fashion, with 0x00000001 start codes*/
    1123         979 :         if (cstr->nalu_size_length) {
    1124             :                 u32 done = 0;
    1125         425 :                 u8 *d = (u8*) output+isma_hdr_size;
    1126        3111 :                 while (done < size) {
    1127        2686 :                         u32 nal_size = GF_4CC(d[0], d[1], d[2], d[3]);
    1128        2686 :                         d[0] = d[1] = d[2] = 0;
    1129        2686 :                         d[3] = 1;
    1130        2686 :                         d += 4 + nal_size;
    1131        2686 :                         done += 4 + nal_size;
    1132             :                 }
    1133             :         }
    1134             : 
    1135             :         //encrypt
    1136         979 :         if (flags & GF_ISOM_ISMA_IS_ENCRYPTED) {
    1137             :                 /*resync IV*/
    1138         979 :                 if (!cstr->prev_pck_encryped) {
    1139             :                         char IV[17];
    1140             :                         u64 count;
    1141             :                         u32 remain;
    1142             :                         GF_BitStream *bs;
    1143           0 :                         count = cstr->BSO / 16;
    1144           0 :                         remain = (u32) (cstr->BSO % 16);
    1145             : 
    1146             :                         /*format IV to begin of counter*/
    1147           0 :                         bs = gf_bs_new(IV, 17, GF_BITSTREAM_WRITE);
    1148           0 :                         gf_bs_write_u8(bs, 0);  /*begin of counter*/
    1149           0 :                         gf_bs_write_data(bs, cstr->tci->keys[0].IV, 8);
    1150           0 :                         gf_bs_write_u64(bs, (s64) count);
    1151           0 :                         gf_bs_del(bs);
    1152           0 :                         gf_crypt_set_IV(cstr->keys[0].crypt, IV, GF_AES_128_KEYSIZE+1);
    1153             : 
    1154             :                         /*decrypt remain bytes*/
    1155           0 :                         if (remain) {
    1156             :                                 char dummy[20];
    1157           0 :                                 gf_crypt_decrypt(cstr->keys[0].crypt, dummy, remain);
    1158             :                         }
    1159             :                 }
    1160         979 :                 gf_crypt_encrypt(cstr->keys[0].crypt, output+isma_hdr_size, size);
    1161         979 :                 cstr->prev_pck_encryped = GF_TRUE;
    1162             :         } else {
    1163           0 :                 cstr->prev_pck_encryped = GF_FALSE;
    1164             :         }
    1165             : 
    1166             :         //rewrite ISMA header
    1167         979 :         if (!ctx->bs_w) ctx->bs_w = gf_bs_new(output, isma_hdr_size, GF_BITSTREAM_WRITE);
    1168         973 :         else gf_bs_reassign_buffer(ctx->bs_w, output, isma_hdr_size);
    1169             : 
    1170         979 :         if (flags & GF_ISOM_ISMA_USE_SEL_ENC) {
    1171           0 :                 gf_bs_write_int(ctx->bs_w, (flags & GF_ISOM_ISMA_IS_ENCRYPTED) ? 1 : 0, 1);
    1172           0 :                 gf_bs_write_int(ctx->bs_w, 0, 7);
    1173             :         }
    1174         979 :         if (flags & GF_ISOM_ISMA_IS_ENCRYPTED) {
    1175         979 :                 if (cstr->isma_IV_size) gf_bs_write_long_int(ctx->bs_w, (s64) cstr->BSO, 8*cstr->isma_IV_size);
    1176             :                 //not yet implemented
    1177             : //              if (cstr->KI_length) gf_bs_write_data(ctx->bs_w, (char*) key_indicator, cstr->KI_length);
    1178             :         }
    1179             : 
    1180         979 :         cstr->BSO += size;
    1181             : 
    1182         979 :         gf_filter_pck_send(dst_pck);
    1183             :         return GF_OK;
    1184             : }
    1185             : 
    1186         932 : static GF_Err adobe_process(GF_CENCEncCtx *ctx, GF_CENCStream *cstr, GF_FilterPacket *pck)
    1187             : {
    1188             :         Bool is_encrypted = GF_TRUE;
    1189             :         GF_FilterPacket *dst_pck;
    1190             :         const u8 *data;
    1191             :         u8 *output;
    1192             :         GF_Err e;
    1193             :         bin128 IV;
    1194             :         u32 size, adobe_hdr_size;
    1195             :         u32 len, padding_bytes;
    1196         932 :         u8 sap = gf_filter_pck_get_sap(pck);
    1197             : 
    1198         932 :         switch (cstr->tci->sel_enc_type) {
    1199         932 :         case GF_CRYPT_SELENC_RAP:
    1200         932 :                 if (!sap) is_encrypted = GF_FALSE;
    1201             :                 break;
    1202           0 :         case GF_CRYPT_SELENC_NON_RAP:
    1203           0 :                 if (sap) is_encrypted = GF_FALSE;
    1204             :                 break;
    1205             :         default:
    1206             :                 break;
    1207             :         }
    1208             : 
    1209             :         adobe_hdr_size = 1;
    1210             :         if (is_encrypted) adobe_hdr_size += 16;
    1211             : 
    1212         932 :         data = gf_filter_pck_get_data(pck, &size);
    1213         932 :         if (!data) {
    1214           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[ISMACrypt] No data associated with packet\n" ));
    1215             :                 return GF_OK;
    1216             :         }
    1217             :         padding_bytes = 0;
    1218         932 :         len = size;
    1219         932 :         if (is_encrypted) {
    1220         346 :                 padding_bytes = 16 - len % 16;
    1221         346 :                 len += padding_bytes;
    1222             :         }
    1223         932 :         dst_pck = gf_filter_pck_new_alloc(cstr->opid, len + adobe_hdr_size, &output);
    1224         932 :         if (!dst_pck) return GF_OUT_OF_MEM;
    1225         932 :         memcpy(output+adobe_hdr_size, data, sizeof(char)*size);
    1226         932 :         gf_filter_pck_merge_properties(pck, dst_pck);
    1227             : 
    1228             : 
    1229         932 :         if (is_encrypted) {
    1230         346 :                 if (!cstr->prev_pck_encryped) {
    1231           5 :                         memcpy(IV, cstr->tci->keys[0].IV, sizeof(char)*16);
    1232           5 :                         e = gf_crypt_init(cstr->keys[0].crypt, cstr->keys[0].key, IV);
    1233           5 :                         cstr->prev_pck_encryped = GF_TRUE;
    1234             :                 } else {
    1235         341 :                         cstr->isma_IV_size = 16;
    1236         341 :                         e = gf_crypt_get_IV(cstr->keys[0].crypt, IV, &cstr->isma_IV_size);
    1237             :                 }
    1238             : 
    1239         346 :                 if (e) {
    1240           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[ADOBE] Cannot initialize AES-128 CBC (%s)\n",  gf_error_to_string(e)) );
    1241           0 :                         gf_filter_pck_discard(dst_pck);
    1242             :                         return GF_IO_ERR;
    1243             :                 }
    1244             : 
    1245         346 :                 memset(output+adobe_hdr_size+size, padding_bytes, sizeof(char)*padding_bytes);
    1246             : 
    1247         346 :                 gf_crypt_encrypt(cstr->keys[0].crypt, output+adobe_hdr_size, len);
    1248             : 
    1249             :                 /*write encrypted AU header*/
    1250         346 :                 output[0] = 0x10;
    1251         346 :                 memcpy(output+1, (char *) IV, sizeof(char) * 16);
    1252             :         } else {
    1253             :                 /*write encrypted AU header*/
    1254         586 :                 output[0] = 0x0;
    1255             :         }
    1256             : 
    1257         932 :         gf_filter_pck_send(dst_pck);
    1258             :         return GF_OK;
    1259             : }
    1260             : 
    1261             : 
    1262             : /*Common Encryption*/
    1263             : static void increase_counter(char *x, int x_size) {
    1264             :         register int i;
    1265             : 
    1266       12827 :         for (i=x_size-1; i>=0; i--) {
    1267             :                 register int y=0;
    1268        7732 :                 if ((u8) x[i] == 0xFF) {
    1269          32 :                         x[i] = 0;
    1270             :                         y = 1;
    1271        7700 :                 } else x[i]++;
    1272             : 
    1273             :                 if (y==0) break;
    1274             :         }
    1275             : 
    1276             :         return;
    1277             : }
    1278             : 
    1279       21117 : static void cenc_resync_IV(GF_Crypt *mc, char IV[16], u8 IV_size)
    1280             : {
    1281             :         char next_IV[17];
    1282       21117 :         u32 size = 17;
    1283             : 
    1284       21117 :         gf_crypt_get_IV(mc, (u8 *) next_IV, &size);
    1285             :         /*
    1286             :                 NOTE 1: the next_IV returned by get_state has 17 bytes, the first byte being the current counter position in the following 16 bytes.
    1287             :                 If this index is 0, this means that we are at the beginning of a new block and we can use it as IV for next sample,
    1288             :                 otherwise we must discard unused bytes in the counter (next sample shall begin with counter at 0)
    1289             :                 if less than 16 blocks were cyphered, we must force increasing the next IV for next sample, not doing so would produce the same IV for the next bytes cyphered,
    1290             :                 which is forbidden by CENC (unique IV per sample). In GPAC, we ALWAYS force counter increase
    1291             : 
    1292             :                 NOTE 2: in case where IV_size is 8, because the cypher block is treated as 16 bytes while processing,
    1293             :                 we need to increment manually the 8-bytes IV (bytes 0 to 7) for the next sample, otherwise we would likely use the same IV (eg unless we had cyphered 16 * 2^64 - 1
    1294             :                 bytes in the last sample , quite unlikely !)
    1295             : 
    1296             :                 NOTE 3: Bytes 8 to 15 are set to 0 when forcing a new IV for 8-bytes IVs.
    1297             : 
    1298             :                 NOTE 4: Since CENC forces declaration of a unique, potentially random, IV per sample, we could increase the IV counter at each sample start
    1299             :                 but this is currently not done
    1300             :         */
    1301       21117 :         if (IV_size == 8) {
    1302             :                 /*cf note 2*/
    1303             :                 increase_counter(&next_IV[1], IV_size);
    1304        2637 :                 next_IV[0] = 0;
    1305             :                 /*cf note 3*/
    1306             :                 memset(&next_IV[9], 0, 8*sizeof(char));
    1307       18480 :         } else if (next_IV[0]) {
    1308             :                 /*cf note 1*/
    1309        5063 :                 increase_counter(&next_IV[1], IV_size);
    1310        5063 :                 next_IV[0] = 0;
    1311             :         }
    1312             : 
    1313       21117 :         gf_crypt_set_IV(mc, next_IV, size);
    1314             : 
    1315             :         memset(IV, 0, 16*sizeof(char));
    1316             :         memcpy(IV, next_IV+1, 16*sizeof(char));
    1317       21117 : }
    1318             : 
    1319             : #ifndef GPAC_DISABLE_AV_PARSERS
    1320             : //parses slice header and returns its size
    1321       65729 : static u32 cenc_get_clear_bytes(GF_CENCStream *cstr, GF_BitStream *plaintext_bs, char *samp_data, u32 nal_size, u32 bytes_in_nalhr)
    1322             : {
    1323             :         u32 clear_bytes = 0;
    1324       65729 :         if (cstr->slice_header_clear) {
    1325       65207 :                 u32 nal_start = (u32) gf_bs_get_position(plaintext_bs);
    1326       65207 :                 if (cstr->cenc_codec==CENC_AVC) {
    1327             :                         u32 ntype;
    1328        7349 :                         gf_avc_parse_nalu(plaintext_bs, &cstr->avc);
    1329        7349 :                         ntype = cstr->avc.last_nal_type_parsed;
    1330             :                         switch (ntype) {
    1331        7280 :                         case GF_AVC_NALU_NON_IDR_SLICE:
    1332             :                         case GF_AVC_NALU_DP_A_SLICE:
    1333             :                         case GF_AVC_NALU_DP_B_SLICE:
    1334             :                         case GF_AVC_NALU_DP_C_SLICE:
    1335             :                         case GF_AVC_NALU_IDR_SLICE:
    1336             :                         case GF_AVC_NALU_SLICE_AUX:
    1337             :                         case GF_AVC_NALU_SVC_SLICE:
    1338        7280 :                                 gf_bs_align(plaintext_bs);
    1339        7280 :                                 clear_bytes = (u32) gf_bs_get_position(plaintext_bs) - nal_start;
    1340        7280 :                                 break;
    1341             :                         default:
    1342             :                                 clear_bytes = nal_size;
    1343             :                                 break;
    1344             :                         }
    1345             :                 } else {
    1346             : #if !defined(GPAC_DISABLE_HEVC)
    1347             :                         u8 ntype, ntid, nlid;
    1348       57858 :                         cstr->hevc.full_slice_header_parse = GF_TRUE;
    1349       57858 :                         gf_hevc_parse_nalu (samp_data + nal_start, nal_size, &cstr->hevc, &ntype, &ntid, &nlid);
    1350       57858 :                         if (ntype<=GF_HEVC_NALU_SLICE_CRA) {
    1351       52058 :                                 clear_bytes = cstr->hevc.s_info.payload_start_offset;
    1352             :                         } else {
    1353             :                                 clear_bytes = nal_size;
    1354             :                         }
    1355             : #endif
    1356             :                 }
    1357       65207 :                 gf_bs_seek(plaintext_bs, nal_start);
    1358             :         } else {
    1359             :                 clear_bytes = bytes_in_nalhr;
    1360             :         }
    1361       65729 :         gf_bs_enable_emulation_byte_removal(plaintext_bs, GF_FALSE);
    1362       65729 :         return clear_bytes;
    1363             : }
    1364             : #endif
    1365             : 
    1366       23159 : static GF_Err cenc_encrypt_packet(GF_CENCEncCtx *ctx, GF_CENCStream *cstr, GF_FilterPacket *pck)
    1367             : {
    1368             :         GF_BitStream *sai_bs;
    1369             :         u32 prev_entry_bytes_clear=0;
    1370             :         u32 prev_entry_bytes_crypt=0;
    1371             :         u32 prev_entry_mkey_idx=0;
    1372             :         u32 pck_size;
    1373             :         GF_FilterPacket *dst_pck;
    1374             :         const u8 *data;
    1375             :         u8 *output;
    1376             :         u32 sai_size;
    1377             :         u32 i, nb_iv_init=0, nb_keys, nb_subsamples_bits, sai_size_sub, nb_subsamples=0;
    1378             :         u32 key_idx = 0;
    1379             :         u32 subsample_idx = 0;
    1380             :         u32 nb_subs_crypted = 0;
    1381             :         u32 nb_sub_offset;
    1382             :         Bool multi_key;
    1383             : 
    1384       23159 :         if (cstr->multi_key) {
    1385        2250 :                 nb_keys = cstr->tci->nb_keys;
    1386             :                 multi_key = GF_TRUE;
    1387             :                 nb_subsamples_bits = 32;
    1388             :                 sai_size_sub = 8;
    1389             :         } else {
    1390             :                 nb_keys = 1;
    1391             :                 multi_key = GF_FALSE;
    1392             :                 nb_subsamples_bits = 16;
    1393             :                 sai_size_sub = 6;
    1394             :         }
    1395       25409 :         for (i=0; i<nb_keys; i++) {
    1396       25409 :                 if (cstr->tci->keys[i].IV_size) {
    1397             :                         //in cbcs scheme, if Per_Sample_IV_size is not 0 (no constant IV), fetch current IV
    1398       23376 :                         if (!cstr->ctr_mode) {
    1399        2259 :                                 u32 IV_size = 16;
    1400        2259 :                                 gf_crypt_get_IV(cstr->keys[i].crypt, cstr->keys[i].IV, &IV_size);
    1401             :                         }
    1402       23376 :                         nb_iv_init++;
    1403             :                 }
    1404             :         }
    1405             : 
    1406       23159 :         data = gf_filter_pck_get_data(pck, &pck_size);
    1407             : 
    1408             :         //CENC can use inplace processing for decryption
    1409       23159 :         dst_pck = gf_filter_pck_new_clone(cstr->opid, pck, &output);
    1410       23159 :         if (!dst_pck) return GF_OUT_OF_MEM;
    1411             : 
    1412       23159 :         gf_filter_pck_merge_properties(pck, dst_pck);
    1413       23159 :         gf_filter_pck_set_crypt_flags(dst_pck, GF_FILTER_PCK_CRYPT);
    1414             : 
    1415       23159 :         if (!ctx->bs_r) ctx->bs_r = gf_bs_new(data, pck_size, GF_BITSTREAM_READ);
    1416       23042 :         else gf_bs_reassign_buffer(ctx->bs_r, data, pck_size);
    1417             : 
    1418       23159 :         sai_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
    1419             : 
    1420       23159 :         if (multi_key) {
    1421        2250 :                 gf_bs_write_u16(sai_bs, nb_iv_init);
    1422        4500 :                 for (i=0; i<nb_keys; i++) {
    1423             :                         //for now we use all our keys in one sample
    1424        4500 :                         if (cstr->tci->keys[i].IV_size) {
    1425        4500 :                                 gf_bs_write_u16(sai_bs, i+1);
    1426        4500 :                                 gf_bs_write_data(sai_bs, cstr->keys[i].IV, cstr->tci->keys[i].IV_size);
    1427             :                         }
    1428             :                 }
    1429             :                 nb_subsamples_bits = 32;
    1430             :         } else {
    1431       20909 :                 gf_bs_write_data(sai_bs, cstr->keys[0].IV, cstr->tci->keys[0].IV_size);
    1432             :         }
    1433       23159 :         sai_size = nb_sub_offset = (u32) gf_bs_get_position(sai_bs);
    1434             : 
    1435       98927 :         while (gf_bs_available(ctx->bs_r)) {
    1436             :                 GF_Err e=GF_OK;
    1437             : 
    1438       75768 :                 if (cstr->use_subsamples) {
    1439             : #ifndef GPAC_DISABLE_AV_PARSERS
    1440             :                         ObuType obut;
    1441       69930 :                         u32 num_frames_in_superframe = 0, superframe_index_size = 0;
    1442             :                         u32 frame_sizes[VP9_MAX_FRAMES_IN_SUPERFRAME];
    1443             :                         struct {
    1444             :                                 int clear, encrypted;
    1445             :                         } ranges[AV1_MAX_TILE_ROWS * AV1_MAX_TILE_COLS];
    1446             :                         u64 obu_size;
    1447             :                         u32 hdr_size;
    1448             : #else
    1449             :                         struct {
    1450             :                                 int clear, encrypted;
    1451             :                         } ranges[1];
    1452             : #endif
    1453             :                         u64 pos;
    1454             :                         u32 clear_bytes_at_end = 0;
    1455             :                         u32 clear_bytes = 0;
    1456             :                         u32 nb_ranges = 1;
    1457             :                         u32 range_idx = 0;
    1458             :                         u32 nalu_size = 0;
    1459             : 
    1460             : #ifndef GPAC_DISABLE_AV_PARSERS
    1461       69930 :                         switch (cstr->cenc_codec) {
    1462       65729 :                         case CENC_AVC:
    1463             :                         case CENC_HEVC:
    1464       65729 :                                 nalu_size = gf_bs_read_int(ctx->bs_r, 8*cstr->nalu_size_length);
    1465       65729 :                                 if (nalu_size == 0) {
    1466           0 :                                         continue;
    1467             :                                 }
    1468       65729 :                                 clear_bytes = cenc_get_clear_bytes(cstr, ctx->bs_r, (char *) data, nalu_size, cstr->bytes_in_nal_hdr);
    1469             :                                 break;
    1470             : 
    1471        2426 :                         case CENC_AV1:
    1472        2426 :                                 pos = gf_bs_get_position(ctx->bs_r);
    1473        2426 :                                 e = gf_av1_parse_obu(ctx->bs_r, &obut, &obu_size, &hdr_size, &cstr->av1);
    1474        2426 :                                 if (e) {
    1475           0 :                                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Failed to parse OBU\n" ));
    1476           0 :                                         return e;
    1477             :                                 }
    1478        2426 :                                 gf_bs_seek(ctx->bs_r, pos);
    1479             : 
    1480        2426 :                                 nalu_size = (u32)obu_size;
    1481        2426 :                                 switch (obut) {
    1482             :                                 //we only encrypt frame and tile group
    1483        2328 :                                 case OBU_FRAME:
    1484             :                                 case OBU_TILE_GROUP:
    1485        2328 :                                         if (!cstr->av1.frame_state.nb_tiles_in_obu) {
    1486             :                                                 clear_bytes = (u32) obu_size;
    1487             :                                         } else {
    1488             :                                                 nb_ranges = cstr->av1.frame_state.nb_tiles_in_obu;
    1489             : 
    1490        2328 :                                                 ranges[0].clear = cstr->av1.frame_state.tiles[0].obu_start_offset;
    1491        2328 :                                                 ranges[0].encrypted = cstr->av1.frame_state.tiles[0].size;
    1492           0 :                                                 for (i = 1; i < nb_ranges; ++i) {
    1493           0 :                                                         ranges[i].clear = cstr->av1.frame_state.tiles[i].obu_start_offset - (cstr->av1.frame_state.tiles[i - 1].obu_start_offset + cstr->av1.frame_state.tiles[i - 1].size);
    1494           0 :                                                         ranges[i].encrypted = cstr->av1.frame_state.tiles[i].size;
    1495             :                                                 }
    1496        2328 :                                                 clear_bytes = ranges[0].clear;
    1497        2328 :                                                 nalu_size = clear_bytes + ranges[0].encrypted;
    1498             : 
    1499             :                                                 /* A subsample SHALL be created for each tile even if less than 16 bytes
    1500             :                                                         see https://github.com/AOMediaCodec/av1-isobmff/pull/116#discussion_r340176740
    1501             : 
    1502             :                                                 If previous range had encrypted bytes, create a new one, otherwise merge in prev
    1503             :                                                 */
    1504        2328 :                                                 if (prev_entry_bytes_crypt) {
    1505         346 :                                                         if (!nb_subsamples) gf_bs_write_int(sai_bs, 0, nb_subsamples_bits);
    1506         346 :                                                         nb_subsamples++;
    1507         346 :                                                         if (multi_key)
    1508           0 :                                                                 gf_bs_write_u16(sai_bs, prev_entry_bytes_crypt ? (prev_entry_mkey_idx+1) : 0);
    1509         346 :                                                         gf_bs_write_u16(sai_bs, prev_entry_bytes_clear);
    1510         346 :                                                         gf_bs_write_u32(sai_bs, prev_entry_bytes_crypt);
    1511         346 :                                                         sai_size += sai_size_sub;
    1512             : 
    1513             :                                                         prev_entry_bytes_crypt = 0;
    1514             :                                                         prev_entry_bytes_clear = 0;
    1515             :                                                         prev_entry_mkey_idx = 0;
    1516             :                                                 }
    1517             :                                         }
    1518             :                                         break;
    1519             :                                 default:
    1520             :                                         clear_bytes = (u32) obu_size;
    1521             :                                         break;
    1522             :                                 }
    1523             :                                 break;
    1524        1775 :                         case CENC_VPX:
    1525        1775 :                                 if (cstr->tci->block_align != 2) {
    1526           7 :                                         GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[CENC] VP9 mandates that blockAlign=\"always\". Forcing value.\n"));
    1527           7 :                                         cstr->tci->block_align = 2;
    1528             :                                 }
    1529             : 
    1530        1775 :                                 pos = gf_bs_get_position(ctx->bs_r);
    1531        1775 :                                 e = gf_media_vp9_parse_superframe(ctx->bs_r, pck_size, &num_frames_in_superframe, frame_sizes, &superframe_index_size);
    1532        1775 :                                 if (e || !num_frames_in_superframe) return e;
    1533        1775 :                                 gf_bs_seek(ctx->bs_r, pos);
    1534             : 
    1535        1775 :                                 nb_ranges = num_frames_in_superframe;
    1536             : 
    1537        1775 :                                 for (i = 0; i < num_frames_in_superframe; ++i) {
    1538             :                                         Bool key_frame;
    1539        1775 :                                         u32 width = 0, height = 0, renderWidth = 0, renderHeight = 0;
    1540        1775 :                                         GF_VPConfig *vp9_cfg = gf_odf_vp_cfg_new();
    1541        1775 :                                         u64 pos2 = gf_bs_get_position(ctx->bs_r);
    1542        1775 :                                         e = gf_media_vp9_parse_sample(ctx->bs_r, vp9_cfg, &key_frame, &width, &height, &renderWidth, &renderHeight);
    1543        1775 :                                         gf_odf_vp_cfg_del(vp9_cfg);
    1544        1775 :                                         if (e) {
    1545           0 :                                                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[CENC] Error parsing VP9 frame at DTS "LLU"\n", gf_filter_pck_get_dts(pck) ));
    1546           0 :                                                 return e;
    1547             :                                         }
    1548             : 
    1549        1775 :                                         ranges[i].clear = (int)(gf_bs_get_position(ctx->bs_r) - pos2);
    1550        1775 :                                         ranges[i].encrypted = frame_sizes[i] - ranges[i].clear;
    1551             : 
    1552        1775 :                                         gf_bs_seek(ctx->bs_r, pos2 + frame_sizes[i]);
    1553             :                                 }
    1554        1775 :                                 if (gf_bs_get_position(ctx->bs_r) + superframe_index_size != pos + pck_size) {
    1555           0 :                                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[CENC] Inconsistent VP9 size %u (parsed "LLU") at DTS "LLU". Re-import raw VP9/IVF for more details.\n",
    1556             :                                                 pck_size, gf_bs_get_position(ctx->bs_r) + superframe_index_size - pos, gf_filter_pck_get_dts(pck)));
    1557             :                                 }
    1558        1775 :                                 gf_bs_seek(ctx->bs_r, pos);
    1559             : 
    1560        1775 :                                 clear_bytes = ranges[0].clear;
    1561             :                                 assert(frame_sizes[0] == ranges[0].clear + ranges[0].encrypted);
    1562        1775 :                                 nalu_size = frame_sizes[0];
    1563             : 
    1564             :                                 //final superframe index must be in clear
    1565        1775 :                                 if (superframe_index_size > 0) {
    1566           0 :                                         ranges[nb_ranges].clear = superframe_index_size;
    1567           0 :                                         ranges[nb_ranges].encrypted = 0;
    1568           0 :                                         nb_ranges++;
    1569             :                                 }
    1570             : 
    1571             :                                 //not clearly defined in the spec (so we do the same as in AV1 which is more clearly defined):
    1572        1775 :                                 if (frame_sizes[0] - clear_bytes >= 16) {
    1573             :                                         //A subsample SHALL be created for each tile >= 16 bytes. If previous range had encrypted bytes, create a new one, otherwise merge in prev
    1574        1775 :                                         if (prev_entry_bytes_crypt) {
    1575           0 :                                                 if (!nb_subsamples) gf_bs_write_int(sai_bs, 0, nb_subsamples_bits);
    1576           0 :                                                 nb_subsamples++;
    1577           0 :                                                 if (multi_key)
    1578           0 :                                                         gf_bs_write_u16(sai_bs, prev_entry_bytes_crypt ? (prev_entry_mkey_idx+1) : 0);
    1579           0 :                                                 gf_bs_write_u16(sai_bs, prev_entry_bytes_clear);
    1580           0 :                                                 gf_bs_write_u32(sai_bs, prev_entry_bytes_crypt);
    1581           0 :                                                 sai_size += sai_size_sub;
    1582             : 
    1583             :                                                 prev_entry_bytes_crypt = 0;
    1584             :                                                 prev_entry_bytes_clear = 0;
    1585             :                                                 prev_entry_mkey_idx = 0;
    1586             :                                         }
    1587             :                                 } else {
    1588             :                                         clear_bytes = nalu_size;
    1589             :                                 }
    1590             :                                 break;
    1591       69930 :                         default:
    1592             :                                 assert(0);
    1593             :                         }
    1594             : #else
    1595             :                         clear_bytes = nalu_size;
    1596             : #endif
    1597             : 
    1598             :                         //VCL subsample, check out settings to decide if we leave it in the clear
    1599      133893 :                         if ((nalu_size > clear_bytes) &&
    1600      121176 :                                 (cstr->tci->subs_crypt || cstr->tci->subs_rand || cstr->multi_key)
    1601             :                         ) {
    1602             :                                 Bool do_crypt = GF_TRUE;
    1603             : 
    1604       27000 :                                 if (cstr->mkey_indices.nb_items) {
    1605        6750 :                                         if (subsample_idx>=cstr->mkey_indices.nb_items)
    1606             :                                                 do_crypt = GF_FALSE;
    1607             :                                         else {
    1608        6750 :                                                 key_idx = cstr->mkey_indices.vals[subsample_idx];
    1609        6750 :                                                 if (!key_idx || (key_idx>cstr->nb_keys))
    1610             :                                                         do_crypt = GF_FALSE;
    1611             :                                                 else
    1612        4500 :                                                         key_idx-=1;
    1613             :                                         }
    1614             :                                 }
    1615       27000 :                                 subsample_idx++;
    1616       27000 :                                 if (do_crypt && cstr->tci->subs_crypt) {
    1617             :                                         char szSub[20], *sep;
    1618             :                                         sprintf(szSub, "%d", subsample_idx);
    1619        6750 :                                         sep = strstr(cstr->tci->subs_crypt, szSub);
    1620        6750 :                                         if (sep) {
    1621        2250 :                                                 u32 len = (u32) strlen(szSub);
    1622        2250 :                                                 if ((sep[len]!=',') && sep[len])
    1623             :                                                         do_crypt = GF_FALSE;
    1624             :                                         } else {
    1625             :                                                 do_crypt = GF_FALSE;
    1626             :                                         }
    1627             :                                 }
    1628       22500 :                                 if (do_crypt && cstr->tci->subs_rand) {
    1629           0 :                                         u32 rndm = gf_rand() % cstr->tci->subs_rand;
    1630           0 :                                         if (rndm)
    1631             :                                                 do_crypt = GF_FALSE;
    1632             :                                 }
    1633             : 
    1634       27000 :                                 if (!do_crypt) {
    1635             :                                         clear_bytes = nalu_size;
    1636             :                                 } else {
    1637       20250 :                                         nb_subs_crypted++;
    1638             :                                 }
    1639             :                         }
    1640             :                         
    1641       69930 :                         while (nb_ranges) {
    1642       69930 :                                 if (cstr->ctr_mode) {
    1643             : 
    1644             :                                         // adjust so that encrypted bytes are a multiple of 16 bytes: cenc SHOULD, cens SHALL, we always do it
    1645       61880 :                                         if (nalu_size > clear_bytes) {
    1646       49735 :                                                 u32 ret = (nalu_size - clear_bytes) % 16;
    1647             :                                                 //in AV1 always enforced
    1648       49735 :                                                 if (cstr->cenc_codec==CENC_AV1) {
    1649        1899 :                                                         clear_bytes += ret;
    1650             :                                                 }
    1651             :                                                 //for CENC (should),
    1652       47836 :                                                 else if ((cstr->tci->scheme_type == GF_CRYPT_TYPE_CENC) || (cstr->tci->scheme_type == GF_CRYPT_TYPE_PIFF))  {
    1653             :                                                         //do it if not disabled by user
    1654       42622 :                                                         if (cstr->tci->block_align != 1) {
    1655             :                                                                 //always align even if sample is not encrypted in the end
    1656       39841 :                                                                 if (cstr->tci->block_align==2) {
    1657        4382 :                                                                         clear_bytes += ret;
    1658             :                                                                 }
    1659             :                                                                 //or if we don't end up with sample in the clear
    1660       35459 :                                                                 else if (nalu_size > clear_bytes + ret) {
    1661             :                                                                         clear_bytes += ret;
    1662             :                                                                 }
    1663             :                                                         }
    1664             :                                                 } else {
    1665        5214 :                                                         clear_bytes += ret;
    1666             :                                                 }
    1667             :                                         }
    1668             :                                 } else {
    1669             :                                         //in cbcs, we don't adjust bytes_encrypted_data to be a multiple of 16 bytes and leave the last block unencrypted
    1670             :                                         //except in VPX, where BytesOfProtectedData SHALL end on the last byte of the decode_tile structure
    1671        8050 :                                         if ((cstr->cenc_codec != CENC_VPX) && (cstr->tci->scheme_type == GF_CRYPT_TYPE_CBCS)) {
    1672        7887 :                                                 u32 ret = (nalu_size - clear_bytes) % 16;
    1673             :                                                 clear_bytes_at_end = ret;
    1674             :                                         }
    1675             :                                         //in cbc1 or cbcs+VPX, we adjust bytes_encrypted_data to be a multiple of 16 bytes
    1676             :                                         else {
    1677         163 :                                                 u32 ret = (nalu_size - clear_bytes) % 16;
    1678         163 :                                                 clear_bytes += ret;
    1679             :                                                 clear_bytes_at_end = 0;
    1680             :                                         }
    1681             : 
    1682             :                                 }
    1683             : 
    1684             :                                 /*skip bytes of clear data*/
    1685       69930 :                                 gf_bs_skip_bytes(ctx->bs_r, clear_bytes);
    1686             : 
    1687             :                                 //read data to encrypt
    1688       69930 :                                 if (nalu_size > clear_bytes) {
    1689             :                                         /*get encrypted data start*/
    1690       56023 :                                         u32 cur_pos = (u32) gf_bs_get_position(ctx->bs_r);
    1691             : 
    1692             :                                         /*skip bytes of encrypted data*/
    1693       56023 :                                         gf_bs_skip_bytes(ctx->bs_r, nalu_size - clear_bytes);
    1694             : 
    1695             :                                         //cbcs scheme with constant IV, reinit at each sub sample,
    1696       56023 :                                         if (!cstr->ctr_mode && !cstr->tci->keys[key_idx].IV_size)
    1697        3744 :                                                 gf_crypt_set_IV(cstr->keys[key_idx].crypt, cstr->keys[key_idx].IV, 16);
    1698             : 
    1699             :                                         //pattern encryption
    1700       56023 :                                         if (cstr->tci->crypt_byte_block && cstr->tci->skip_byte_block) {
    1701       12545 :                                                 u32 res = nalu_size - clear_bytes - clear_bytes_at_end;
    1702             :                                                 pos = cur_pos;
    1703             :                                                 assert((res % 16) == 0);
    1704             : 
    1705       47725 :                                                 while (res) {
    1706       35180 :                                                         e = gf_crypt_encrypt(cstr->keys[key_idx].crypt, output+pos, res >= (u32) (16*cstr->tci->crypt_byte_block) ? 16*cstr->tci->crypt_byte_block : res);
    1707       35180 :                                                         if (res >= (u32) (16 * (cstr->tci->crypt_byte_block + cstr->tci->skip_byte_block))) {
    1708       23866 :                                                                 pos += 16 * (cstr->tci->crypt_byte_block + cstr->tci->skip_byte_block);
    1709       23866 :                                                                 res -= 16 * (cstr->tci->crypt_byte_block + cstr->tci->skip_byte_block);
    1710             :                                                         } else {
    1711             :                                                                 res = 0;
    1712             :                                                         }
    1713             :                                                 }
    1714             :                                         }
    1715             :                                         //full subsample encryption
    1716             :                                         else {
    1717       43478 :                                                 e = gf_crypt_encrypt(cstr->keys[key_idx].crypt, output+cur_pos, nalu_size - clear_bytes);
    1718             :                                         }
    1719             :                                 }
    1720             : 
    1721             : 
    1722             :                                 //prev entry is not a VCL, append this NAL
    1723       69930 :                                 if (!prev_entry_bytes_crypt) {
    1724       24619 :                                         prev_entry_bytes_clear += cstr->nalu_size_length + clear_bytes;
    1725       24619 :                                         prev_entry_bytes_crypt += nalu_size - clear_bytes;
    1726       24619 :                                         if (prev_entry_bytes_crypt)
    1727             :                                                 prev_entry_mkey_idx = key_idx;
    1728             :                                 } else {
    1729             :                                         //store current
    1730       45311 :                                         if (!nb_subsamples) gf_bs_write_int(sai_bs, 0, nb_subsamples_bits);
    1731       45311 :                                         nb_subsamples++;
    1732       45311 :                                         if (multi_key)
    1733       18000 :                                                 gf_bs_write_u16(sai_bs, prev_entry_bytes_crypt ? (prev_entry_mkey_idx+1) : 0);
    1734       45311 :                                         gf_bs_write_u16(sai_bs, prev_entry_bytes_clear);
    1735       45311 :                                         gf_bs_write_u32(sai_bs, prev_entry_bytes_crypt);
    1736       45311 :                                         sai_size += sai_size_sub;
    1737             : 
    1738       45311 :                                         prev_entry_bytes_clear = cstr->nalu_size_length + clear_bytes;
    1739       45311 :                                         prev_entry_bytes_crypt = nalu_size - clear_bytes;
    1740             :                                         prev_entry_mkey_idx = key_idx;
    1741             :                                 }
    1742             : 
    1743             :                                 //subsample was a possible encryption target, apply key roll
    1744       69930 :                                 if (multi_key && prev_entry_bytes_crypt && !cstr->mkey_indices.nb_items) {
    1745             :                                         Bool change_key = GF_FALSE;
    1746       13500 :                                         if (!cstr->tci->mkey_roll_plus_one) {
    1747             :                                                 change_key = GF_TRUE;
    1748        6750 :                                         } else if (cstr->tci->mkey_roll_plus_one>1) {
    1749        6750 :                                                 if (nb_subs_crypted + 1 == cstr->tci->mkey_roll_plus_one) {
    1750             :                                                         change_key = GF_TRUE;
    1751             :                                                         nb_subs_crypted = 0;
    1752             :                                                 }
    1753             :                                         }
    1754             :                                         if (change_key) {
    1755        9750 :                                                 key_idx++;
    1756        9750 :                                                 if (key_idx==cstr->nb_keys)
    1757             :                                                         key_idx = 0;
    1758             :                                         }
    1759             :                                 }
    1760             : 
    1761             :                                 //check bytes of clear is not larger than 16bits
    1762       69930 :                                 while (prev_entry_bytes_clear > 0xFFFF) {
    1763             :                                         //store current
    1764           0 :                                         if (!nb_subsamples) gf_bs_write_int(sai_bs, 0, nb_subsamples_bits);
    1765           0 :                                         nb_subsamples++;
    1766           0 :                                         if (multi_key)
    1767           0 :                                                 gf_bs_write_u16(sai_bs, 0);
    1768           0 :                                         gf_bs_write_u16(sai_bs, 0xFFFF);
    1769           0 :                                         gf_bs_write_u32(sai_bs, 0);
    1770           0 :                                         sai_size += sai_size_sub;
    1771             : 
    1772           0 :                                         prev_entry_bytes_clear -= 0xFFFF;
    1773             :                                 }
    1774             : 
    1775             : 
    1776       69930 :                                 nb_ranges--;
    1777       69930 :                                 if (!nb_ranges) break;
    1778             : 
    1779           0 :                                 range_idx++;
    1780           0 :                                 if (range_idx >= AV1_MAX_TILE_ROWS * AV1_MAX_TILE_COLS) {
    1781           0 :                                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] More ranges than tiles allowed spec, bitstream error ?\n"));
    1782             :                                         return GF_BAD_PARAM;
    1783             :                                 }
    1784           0 :                                 switch (cstr->cenc_codec) {
    1785           0 :                                 case CENC_AV1:
    1786           0 :                                         clear_bytes = ranges[range_idx].clear;
    1787           0 :                                         nalu_size = clear_bytes + ranges[range_idx].encrypted;
    1788             :                                         break;
    1789           0 :                                 case CENC_VPX:
    1790           0 :                                         if (nb_ranges > 1) {
    1791           0 :                                                 clear_bytes = ranges[range_idx].clear;
    1792           0 :                                                 nalu_size = clear_bytes + ranges[range_idx].encrypted;
    1793             :                                         } else { /*last*/
    1794           0 :                                                 nalu_size = clear_bytes = ranges[range_idx].clear;
    1795             :                                                 assert(ranges[range_idx].encrypted == 0);
    1796             :                                         }
    1797             :                                         break;
    1798           0 :                                 default:
    1799           0 :                                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Unexpected subrange for sample format, only allowed for VPX and AV1\n"));
    1800             :                                         return GF_BAD_PARAM;
    1801             :                                 }
    1802             :                         }
    1803             :                 }
    1804             :                 //the other cases are NOT multi-key
    1805             :                 //CTR full sample
    1806        5838 :                 else if (cstr->ctr_mode) {
    1807        4848 :                         gf_bs_skip_bytes(ctx->bs_r, pck_size);
    1808        4848 :                         e = gf_crypt_encrypt(cstr->keys[0].crypt, output, pck_size);
    1809             :                 }
    1810             :                 //CBC full sample with padding
    1811             :                 else {
    1812             :                         u32 clear_trailing;
    1813             : 
    1814         990 :                         clear_trailing = pck_size % 16;
    1815             : 
    1816             :                         //cbcs scheme with constant IV, reinit at each sample,
    1817         990 :                         if (!cstr->tci->keys[0].IV_size)
    1818         330 :                                 gf_crypt_set_IV(cstr->keys[0].crypt, cstr->keys[0].IV, 16);
    1819             : 
    1820         990 :                         if (pck_size >= 16) {
    1821         990 :                                 gf_crypt_encrypt(cstr->keys[0].crypt, output, pck_size - clear_trailing);
    1822             :                         }
    1823         990 :                         gf_bs_skip_bytes(ctx->bs_r, pck_size);
    1824             :                 }
    1825             : 
    1826       75768 :                 if (e) {
    1827           0 :                         gf_filter_pck_discard(dst_pck);
    1828             :                         return e;
    1829             :                 }
    1830             :         }
    1831             :         
    1832       23159 :         if (prev_entry_bytes_clear || prev_entry_bytes_crypt) {
    1833       17321 :                 if (!nb_subsamples) gf_bs_write_int(sai_bs, 0, nb_subsamples_bits);
    1834       17321 :                 nb_subsamples++;
    1835       17321 :                 if (multi_key)
    1836        2250 :                         gf_bs_write_u16(sai_bs, prev_entry_bytes_crypt ? (prev_entry_mkey_idx+1) : 0);
    1837       17321 :                 gf_bs_write_u16(sai_bs, prev_entry_bytes_clear);
    1838       17321 :                 gf_bs_write_u32(sai_bs, prev_entry_bytes_crypt);
    1839       17321 :                 sai_size += sai_size_sub;
    1840             :         }
    1841       23159 :         if (cstr->ctr_mode) {
    1842       21117 :                 for (i=0; i<nb_keys; i++) {
    1843       21117 :                         cenc_resync_IV(cstr->keys[i].crypt, cstr->keys[i].IV, cstr->tci->keys[i].IV_size);
    1844             :                 }
    1845             :         }
    1846             : 
    1847       23159 :         if (sai_size) {
    1848       22829 :                 u8 *sai=NULL;
    1849       22829 :                 if (cstr->use_subsamples) {
    1850       17321 :                         sai_size = (u32) gf_bs_get_position(sai_bs);
    1851       17321 :                         gf_bs_seek(sai_bs, nb_sub_offset);
    1852       17321 :                         gf_bs_write_int(sai_bs, nb_subsamples, nb_subsamples_bits);
    1853       17321 :                         gf_bs_seek(sai_bs, sai_size);
    1854             :                 }
    1855       22829 :                 sai_size = 0;
    1856       22829 :                 gf_bs_get_content(sai_bs, &sai, &sai_size);
    1857             : 
    1858       22829 :                 gf_filter_pck_set_property(dst_pck, GF_PROP_PCK_CENC_SAI, &PROP_DATA_NO_COPY(sai, sai_size) );
    1859             :         }
    1860       23159 :         gf_bs_del(sai_bs);
    1861             : 
    1862       23159 :         gf_filter_pck_send(dst_pck);
    1863             :         return GF_OK;
    1864             : }
    1865             : 
    1866       25786 : static GF_Err cenc_process(GF_CENCEncCtx *ctx, GF_CENCStream *cstr, GF_FilterPacket *pck)
    1867             : {
    1868             :         Bool is_encrypted = GF_TRUE;
    1869             :         const u8 *data;
    1870             :         GF_Err e;
    1871             :         Bool all_rap=GF_FALSE;
    1872             :         u32 pck_size;
    1873             :         Bool force_clear = GF_FALSE;
    1874       25786 :         u8 sap = gf_filter_pck_get_sap(pck);
    1875             : 
    1876       25786 :         data = gf_filter_pck_get_data(pck, &pck_size);
    1877       25786 :         if (!data) {
    1878           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_AUTHOR, ("[ISMACrypt] No data associated with packet\n" ));
    1879             :                 return GF_OK;
    1880             :         }
    1881             : 
    1882       25786 :         if (!ctx->bs_w) ctx->bs_w = gf_bs_new((char *) &sap, 1, GF_BITSTREAM_WRITE);
    1883             : 
    1884       25786 :         switch (cstr->tci->sel_enc_type) {
    1885        3040 :         case GF_CRYPT_SELENC_RAP:
    1886        3040 :                 if (!sap && !all_rap) {
    1887             :                         is_encrypted = GF_FALSE;
    1888             :                 }
    1889             :                 break;
    1890           0 :         case GF_CRYPT_SELENC_NON_RAP:
    1891           0 :                 if (sap || all_rap) {
    1892             :                         is_encrypted = GF_FALSE;
    1893             :                 }
    1894             :                 break;
    1895             :         case GF_CRYPT_SELENC_CLEAR:
    1896             :                 is_encrypted = GF_FALSE;
    1897             :                 break;
    1898         323 :         case GF_CRYPT_SELENC_CLEAR_FORCED:
    1899             :                 is_encrypted = GF_FALSE;
    1900         323 :                 if (!cstr->multi_key) {
    1901             :                         force_clear = GF_TRUE;
    1902         323 :                         if (cstr->tci->sel_enc_range && (cstr->nb_pck+1 >= cstr->tci->sel_enc_range)) {
    1903           3 :                                 cstr->tci->sel_enc_type = GF_CRYPT_SELENC_NONE;
    1904             :                         }
    1905             :                 }
    1906             :                 break;
    1907             :         default:
    1908             :                 break;
    1909             :         }
    1910             : 
    1911             :         if (!is_encrypted) {
    1912        2627 :                 u8 *sai=NULL;
    1913        2627 :                 u32 i, sai_size = 0;
    1914             :                 Bool signal_sai = GF_FALSE;
    1915             :                 GF_FilterPacket *dst_pck;
    1916        2627 :                 dst_pck = gf_filter_pck_new_ref(cstr->opid, 0, 0, pck);
    1917        2627 :                 if (!dst_pck) return GF_OUT_OF_MEM;
    1918             :                 
    1919        2627 :                 gf_filter_pck_merge_properties(pck, dst_pck);
    1920             : 
    1921        2627 :                 if (force_clear && !cstr->tci->force_clear_stsd_idx)
    1922             :                         signal_sai = GF_TRUE;
    1923             :                 //format NULL bitstream only for forced clear mode
    1924        2627 :                 if (cstr->use_subsamples && signal_sai) {
    1925             :                         GF_BitStream *bs;
    1926             :                         u32 subsample_count = 1;
    1927          50 :                         u32 olen = pck_size;
    1928         100 :                         while (olen>0xFFFF) {
    1929           0 :                                 olen -= 0xFFFF;
    1930           0 :                                 subsample_count ++;
    1931             :                         }
    1932          50 :                         bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
    1933          50 :                         if (force_clear) {
    1934             :                                 bin128 NULL_IV;
    1935             :                                 memset(NULL_IV, 0, 16);
    1936             :                                 memcpy(NULL_IV, (char *) &cstr->nb_pck, 4);
    1937          50 :                                 gf_bs_write_data(bs, NULL_IV, cstr->tci->keys[0].IV_size);
    1938             :                         }
    1939          50 :                         gf_bs_write_u16(bs, subsample_count);
    1940          50 :                         olen = pck_size;
    1941         100 :                         for (i = 0; i < subsample_count; i++) {
    1942          50 :                                 if (olen<0xFFFF) {
    1943          50 :                                         gf_bs_write_u16(bs, olen);
    1944             :                                 } else {
    1945           0 :                                         gf_bs_write_u16(bs, 0xFFFF);
    1946           0 :                                         olen -= 0xFFFF;
    1947             :                                 }
    1948          50 :                                 gf_bs_write_u32(bs, 0);
    1949             :                         }
    1950          50 :                         gf_bs_get_content(bs, &sai, &sai_size);
    1951          50 :                         gf_bs_del(bs);
    1952             :                 }
    1953        2627 :                 if (sai)
    1954          50 :                         gf_filter_pck_set_property(dst_pck, GF_PROP_PCK_CENC_SAI, &PROP_DATA_NO_COPY(sai, sai_size) );
    1955             : 
    1956        2627 :                 gf_filter_pck_set_crypt_flags(dst_pck, signal_sai ? GF_FILTER_PCK_CRYPT : 0);
    1957        2627 :                 gf_filter_pck_send(dst_pck);
    1958        2627 :                 return GF_OK;
    1959             :         }
    1960             : 
    1961             :         /*load initialization vector for the first sample in track ... */
    1962       23159 :         if (!cstr->cenc_init) {
    1963         135 :                 u32 i, nb_keys = cstr->multi_key ? cstr->tci->nb_keys : 1;
    1964             : 
    1965         273 :                 for (i=0; i<nb_keys; i++) {
    1966             :                         //memset IV to 0, and copy from start (0-padding at the end)
    1967         138 :                         memset(cstr->keys[i].IV, 0, sizeof(char)*16);
    1968             :                         //IV
    1969         138 :                         if ((cstr->tci->keys[i].IV_size == 8) || (cstr->tci->keys[i].IV_size == 16)) {
    1970         129 :                                 memcpy(cstr->keys[i].IV, cstr->tci->keys[i].IV, sizeof(char) * cstr->tci->keys[i].IV_size);
    1971             :                         }
    1972             :                         //const IV
    1973           9 :                         else if (!cstr->tci->keys[i].IV_size) {
    1974           9 :                                 if ((cstr->tci->keys[i].constant_IV_size == 8) || (cstr->tci->keys[i].constant_IV_size == 16)) {
    1975           9 :                                         memcpy(cstr->keys[i].IV, cstr->tci->keys[i].IV, sizeof(char) * cstr->tci->keys[i].constant_IV_size);
    1976             :                                 } else {
    1977             :                                         return GF_NOT_SUPPORTED;
    1978             :                                 }
    1979             :                         } else {
    1980             :                                 return GF_NOT_SUPPORTED;
    1981             :                         }
    1982             : 
    1983         138 :                         e = gf_crypt_init(cstr->keys[i].crypt, cstr->keys[i].key, cstr->keys[i].IV);
    1984         138 :                         if (e) {
    1985           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot initialize AES-128 %s (%s)\n", cstr->ctr_mode ? "CTR" : "CBC", gf_error_to_string(e)) );
    1986             :                                 return GF_IO_ERR;
    1987             :                         }
    1988             :                 }
    1989         135 :                 cstr->cenc_init = GF_TRUE;
    1990       23024 :         } else if (!cstr->multi_key) {
    1991       20777 :                 u32 new_idx = cstr->kidx;
    1992             :                 Bool key_changed = GF_FALSE;
    1993             : 
    1994       20777 :                 if (cstr->tci->keyRoll) {
    1995        1354 :                         new_idx = (cstr->nb_pck_encrypted / cstr->tci->keyRoll) % cstr->tci->nb_keys;
    1996       19423 :                 } else if (cstr->rap_roll) {
    1997           0 :                         if ((sap==GF_FILTER_SAP_1) || (sap==GF_FILTER_SAP_2)) {
    1998           0 :                                 new_idx = (new_idx + 1) % cstr->tci->nb_keys;
    1999             :                         }
    2000             :                 }
    2001       20777 :                 if (cstr->kidx != new_idx) {
    2002         172 :                         cstr->kidx = new_idx;
    2003         172 :                         memcpy(cstr->keys[0].key, cstr->tci->keys[cstr->kidx].key, 16);
    2004             :                         key_changed = GF_TRUE;
    2005         172 :                         e = gf_crypt_set_key(cstr->keys[0].crypt, cstr->keys[0].key);
    2006         172 :                         if (e) {
    2007           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Cannot set key AES-128 %s (%s)\n", cstr->ctr_mode ? "CTR" : "CBC", gf_error_to_string(e)) );
    2008             :                                 return e;
    2009             :                         }
    2010             :                 }
    2011             : 
    2012             :                 if (key_changed) {
    2013             :                         char *hls_info;
    2014         172 :                         GF_CryptKeyInfo *ki = &cstr->tci->keys[cstr->kidx];
    2015             :                         u8 key_info[40];
    2016             :                         u32 key_info_size = 20;
    2017         172 :                         key_info[0] = 0;
    2018         172 :                         key_info[1] = 0;
    2019         172 :                         key_info[2] = 0;
    2020         172 :                         key_info[3] = ki->IV_size;
    2021             :                         memcpy(key_info+4, ki->KID, 16);
    2022         172 :                         if (!ki->IV_size) {
    2023           7 :                                 key_info[20] = ki->constant_IV_size;
    2024           7 :                                 memcpy(key_info+21, ki->IV, ki->constant_IV_size);
    2025           7 :                                 key_info_size += ki->constant_IV_size + 1;
    2026             :                         }
    2027             : 
    2028         172 :                         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_CENC_KEY_INFO, &PROP_DATA( key_info, key_info_size ) );
    2029             : 
    2030         172 :                         hls_info = cstr->tci->keys[cstr->kidx].hls_info;
    2031         172 :                         gf_filter_pid_set_property(cstr->opid, GF_PROP_PID_HLS_KMS, hls_info ? &PROP_STRING(hls_info) : NULL);
    2032             :                 }
    2033             :         }
    2034             : 
    2035       23159 :         e = cenc_encrypt_packet(ctx, cstr, pck);
    2036       23159 :         if (e) {
    2037           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENC] Error encrypting packet %d in PID %s: %s\n", cstr->nb_pck, gf_filter_pid_get_name(cstr->ipid), gf_error_to_string(e)) );
    2038             :                 return e;
    2039             :         }
    2040             : 
    2041       23159 :         cstr->nb_pck_encrypted++;
    2042       23159 :         return GF_OK;
    2043             : }
    2044             : 
    2045       29680 : static GF_Err cenc_enc_process(GF_Filter *filter)
    2046             : {
    2047       29680 :         GF_CENCEncCtx *ctx = (GF_CENCEncCtx *)gf_filter_get_udta(filter);
    2048       29680 :         u32 i, nb_eos, count = gf_list_count(ctx->streams);
    2049             : 
    2050             :         nb_eos = 0;
    2051       63821 :         for (i=0; i<count; i++) {
    2052             :                 GF_Err e = GF_OK;;
    2053       34141 :                 GF_CENCStream *cstr = gf_list_get(ctx->streams, i);
    2054       34141 :                 GF_FilterPacket *pck = gf_filter_pid_get_packet(cstr->ipid);
    2055       34141 :                 if (!pck) {
    2056        5152 :                         if (gf_filter_pid_is_eos(cstr->ipid)) {
    2057        1990 :                                 gf_filter_pid_set_eos(cstr->opid);
    2058        1990 :                                 nb_eos++;
    2059             :                         }
    2060        5152 :                         continue;
    2061             :                 }
    2062             : 
    2063       28989 :                 if (cstr->passthrough) {
    2064        1292 :                         gf_filter_pck_forward(pck, cstr->opid);
    2065             :                 }
    2066       27697 :                 else if (cstr->isma_oma) {
    2067         979 :                         e = isma_process(ctx, cstr, pck);
    2068       26718 :                 } else if (cstr->is_adobe) {
    2069         932 :                         e = adobe_process(ctx, cstr, pck);
    2070             :                 } else {
    2071       25786 :                         e = cenc_process(ctx, cstr, pck);
    2072             :                 }
    2073       28989 :                 gf_filter_pid_drop_packet(cstr->ipid);
    2074       28989 :                 cstr->nb_pck++;
    2075             : 
    2076       28989 :                 if (e) return e;
    2077             :         }
    2078       29680 :         if (nb_eos==count) return GF_EOS;
    2079             : 
    2080       29547 :         return GF_OK;
    2081             : }
    2082             : 
    2083         130 : static GF_Err cenc_enc_initialize(GF_Filter *filter)
    2084             : {
    2085         130 :         GF_CENCEncCtx *ctx = (GF_CENCEncCtx *)gf_filter_get_udta(filter);
    2086             : 
    2087         130 :         if (ctx->cfile) {
    2088             :                 GF_Err e;
    2089         130 :                 ctx->cinfo = gf_crypt_info_load(ctx->cfile, &e);
    2090         130 :                 if (!ctx->cinfo) {
    2091           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_AUTHOR, ("[CENCCrypt] Cannot load config file %s\n", ctx->cfile ));
    2092           0 :                         return GF_BAD_PARAM;
    2093             :                 }
    2094             :         }
    2095             : 
    2096         130 :         ctx->streams = gf_list_new();
    2097         130 :         return GF_OK;
    2098             : }
    2099             : 
    2100         130 : static void cenc_enc_finalize(GF_Filter *filter)
    2101             : {
    2102         130 :         GF_CENCEncCtx *ctx = (GF_CENCEncCtx *)gf_filter_get_udta(filter);
    2103         130 :         if (ctx->cinfo) gf_crypt_info_del(ctx->cinfo);
    2104         279 :         while (gf_list_count(ctx->streams)) {
    2105         149 :                 GF_CENCStream *s = gf_list_pop_back(ctx->streams);
    2106         149 :                 cenc_free_pid_context(s);
    2107             :         }
    2108         130 :         gf_list_del(ctx->streams);
    2109         130 :         if (ctx->bs_w) gf_bs_del(ctx->bs_w);
    2110         130 :         if (ctx->bs_r) gf_bs_del(ctx->bs_r);
    2111         130 : }
    2112             : 
    2113             : 
    2114             : static const GF_FilterCapability CENCEncCaps[] =
    2115             : {
    2116             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_STREAM_TYPE, GF_STREAM_ENCRYPTED),
    2117             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_STREAM_TYPE, GF_STREAM_FILE),
    2118             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_RAW),
    2119             :         CAP_UINT(GF_CAPS_INPUT_EXCLUDED, GF_PROP_PID_UNFRAMED, GF_TRUE),
    2120             : 
    2121             :         CAP_UINT(GF_CAPS_OUTPUT, GF_PROP_PID_STREAM_TYPE, GF_STREAM_ENCRYPTED),
    2122             :         CAP_UINT(GF_CAPS_OUTPUT_EXCLUDED, GF_PROP_PID_CODECID, GF_CODECID_RAW),
    2123             : //      CAP_UINT(GF_CAPS_OUTPUT_STATIC_EXCLUDED,  GF_PROP_PID_UNFRAMED, GF_TRUE),
    2124             : };
    2125             : 
    2126             : #define OFFS(_n)        #_n, offsetof(GF_CENCEncCtx, _n)
    2127             : static const GF_FilterArgs GF_CENCEncArgs[] =
    2128             : {
    2129             :         { OFFS(cfile), "crypt file location - see filter help", GF_PROP_STRING, NULL, NULL, 0},
    2130             :         { OFFS(allc), "throw error if no DRM config file is found for a PID - see filter help", GF_PROP_STRING, NULL, NULL, 0},
    2131             :         {0}
    2132             : };
    2133             : 
    2134             : GF_FilterRegister CENCEncRegister = {
    2135             :         .name = "cecrypt",
    2136             :         GF_FS_SET_DESCRIPTION("CENC  encryptor")
    2137             :         GF_FS_SET_HELP("The CENC encryptor supports CENC, ISMA and Adobe encryption. It uses a DRM config file for declaring keys.\n"
    2138             :         "The syntax is available at https://wiki.gpac.io/Common-Encryption\n"
    2139             :         "The DRM config file can be set per PID using the property `CryptInfo`, or set at the filter level using [-cfile]().\n"
    2140             :         "When the DRM config file is set per PID, the first `CrypTrack` in the DRM config file with the same ID is used, otherwise the first `CrypTrack` is used.\n"
    2141             :         "If no DRM config file is defined for a given PID, this PID will not be encrypted, or an error will be thrown if [-allc]() is specified.\n"
    2142             :         )
    2143             :         .private_size = sizeof(GF_CENCEncCtx),
    2144             :         .max_extra_pids=-1,
    2145             :         //encryptor shall be explicitly loaded
    2146             :         .flags = GF_FS_REG_EXPLICIT_ONLY,
    2147             :         .args = GF_CENCEncArgs,
    2148             :         SETCAPS(CENCEncCaps),
    2149             :         .configure_pid = cenc_enc_configure_pid,
    2150             :         .initialize = cenc_enc_initialize,
    2151             :         .finalize = cenc_enc_finalize,
    2152             :         .process = cenc_enc_process
    2153             : 
    2154             : };
    2155             : 
    2156             : #endif /*GPAC_DISABLE_CRYPTO*/
    2157             : 
    2158        2877 : const GF_FilterRegister *cenc_encrypt_register(GF_FilterSession *session)
    2159             : {
    2160             : #ifndef GPAC_DISABLE_CRYPTO
    2161        2877 :         return &CENCEncRegister;
    2162             : #else
    2163             :         return NULL;
    2164             : #endif
    2165             : }

Generated by: LCOV version 1.13