LCOV - code coverage report
Current view: top level - isomedia - meta.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 690 927 74.4 %
Date: 2021-04-29 23:48:07 Functions: 29 30 96.7 %

          Line data    Source code
       1             : /*
       2             :  *                                      GPAC Multimedia Framework
       3             :  *
       4             :  *                      Authors: Cyril Concolato - Jean le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2005-2020
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / ISO Media File Format sub-project
       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             : 
      27             : #include <gpac/internal/isomedia_dev.h>
      28             : 
      29             : #ifndef GPAC_DISABLE_ISOM
      30             : 
      31        5352 : GF_MetaBox *gf_isom_get_meta(GF_ISOFile *file, Bool root_meta, u32 track_num)
      32             : {
      33             :         GF_TrackBox *tk;
      34        5352 :         if (!file) return NULL;
      35        5352 :         if (root_meta) return file->meta;
      36        1619 :         if (!track_num) return file->moov ? file->moov->meta : NULL;
      37             : 
      38         879 :         tk = (GF_TrackBox*)gf_list_get(file->moov->trackList, track_num-1);
      39         879 :         return tk ? tk->meta : NULL;
      40             : }
      41             : 
      42             : GF_EXPORT
      43         755 : u32 gf_isom_get_meta_type(GF_ISOFile *file, Bool root_meta, u32 track_num)
      44             : {
      45         755 :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
      46         755 :         if (!meta) return 0;
      47          86 :         if (!meta->handler) return 0;
      48          86 :         return meta->handler->handlerType;
      49             : }
      50             : 
      51             : GF_EXPORT
      52         651 : u32 gf_isom_has_meta_xml(GF_ISOFile *file, Bool root_meta, u32 track_num)
      53             : {
      54             :         u32 i, count;
      55         651 :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
      56         651 :         if (!meta) return 0;
      57             : 
      58          69 :         count = gf_list_count(meta->child_boxes);
      59         375 :         for (i=0; i<count; i++) {
      60         307 :                 GF_Box *a = (GF_Box *)gf_list_get(meta->child_boxes, i);
      61         307 :                 if (a->type == GF_ISOM_BOX_TYPE_XML) return 1;
      62         306 :                 if (a->type == GF_ISOM_BOX_TYPE_BXML) return 2;
      63             :         }
      64             :         return 0;
      65             : }
      66             : 
      67             : GF_EXPORT
      68           1 : GF_Err gf_isom_extract_meta_xml(GF_ISOFile *file, Bool root_meta, u32 track_num, char *outName, Bool *is_binary)
      69             : {
      70             :         u32 i, count;
      71             :         FILE *didfile;
      72             :         GF_XMLBox *xml = NULL;
      73           1 :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
      74           1 :         if (!meta) return GF_BAD_PARAM;
      75             : 
      76             :         /*Find XMLBox*/
      77           1 :         count = gf_list_count(meta->child_boxes);
      78           5 :         for (i = 0; i <count; i++) {
      79           5 :                 GF_Box *a = (GF_Box *)gf_list_get(meta->child_boxes, i);
      80           5 :                 if ((a->type == GF_ISOM_BOX_TYPE_XML) || (a->type == GF_ISOM_BOX_TYPE_BXML) ) {
      81             :                         xml = (GF_XMLBox *)a;
      82             :                         break;
      83             :                 }
      84             :         }
      85           1 :         if (!xml || !xml->xml) return GF_BAD_PARAM;
      86             : 
      87           1 :         didfile = gf_fopen(outName, "wb");
      88           1 :         if (!didfile) return GF_IO_ERR;
      89           1 :         gf_fwrite(xml->xml, strlen(xml->xml), didfile);
      90           1 :         gf_fclose(didfile);
      91             : 
      92           1 :         if (is_binary) *is_binary = (xml->type==GF_ISOM_BOX_TYPE_BXML) ? 1 : 0;
      93             :         return GF_OK;
      94             : }
      95             : 
      96             : #if 0 //unused
      97             : GF_XMLBox *gf_isom_get_meta_xml(GF_ISOFile *file, Bool root_meta, u32 track_num, Bool *is_binary)
      98             : {
      99             :         u32 i, count;
     100             :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
     101             :         if (!meta) return NULL;
     102             : 
     103             :         /*Find XMLBox*/
     104             :         count = gf_list_count(meta->child_boxes);
     105             :         for (i = 0; i <count; i++) {
     106             :                 GF_Box *a = (GF_Box *)gf_list_get(meta->child_boxes, i);
     107             :                 if (a->type == GF_ISOM_BOX_TYPE_XML) {
     108             :                         *is_binary = 0;
     109             :                         return (GF_XMLBox *)a;
     110             :                 } else if (a->type == GF_ISOM_BOX_TYPE_BXML) {
     111             :                         *is_binary = 1;
     112             :                         return (GF_XMLBox *)a;
     113             :                 }
     114             :         }
     115             :         return NULL;
     116             : }
     117             : #endif
     118             : 
     119             : 
     120             : GF_EXPORT
     121        1664 : u32 gf_isom_get_meta_item_count(GF_ISOFile *file, Bool root_meta, u32 track_num)
     122             : {
     123        1664 :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
     124        1664 :         if (!meta || !meta->item_infos || !meta->item_locations) return 0;
     125         163 :         return gf_list_count(meta->item_infos->item_infos);
     126             : }
     127             : 
     128             : GF_EXPORT
     129         233 : GF_Err gf_isom_get_meta_item_info(GF_ISOFile *file, Bool root_meta, u32 track_num, u32 item_num,
     130             :                                   u32 *itemID, u32 *type, u32 *protection_scheme, u32 *protection_scheme_version, Bool *is_self_reference,
     131             :                                   const char **item_name, const char **item_mime_type, const char **item_encoding,
     132             :                                   const char **item_url, const char **item_urn)
     133             : {
     134             :         GF_ItemInfoEntryBox *iinf;
     135             :         u32 i, count;
     136         233 :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
     137         233 :         if (!meta || !meta->item_infos || !meta->item_locations) return GF_BAD_PARAM;
     138             : 
     139         233 :         iinf = (GF_ItemInfoEntryBox *)gf_list_get(meta->item_infos->item_infos, item_num-1);
     140         233 :         if (!iinf) return GF_BAD_PARAM;
     141             : 
     142         233 :         if (itemID) (*itemID) = iinf->item_ID;
     143         233 :         if (item_name) (*item_name) = iinf->item_name;
     144         233 :         if (item_mime_type) (*item_mime_type) = iinf->content_type;
     145         233 :         if (item_encoding) (*item_encoding) = iinf->content_encoding;
     146         233 :         if (is_self_reference) *is_self_reference = 0;
     147         233 :         if (type) *type = iinf->item_type;
     148             : 
     149         233 :         if (item_url) (*item_url) = NULL;
     150         233 :         if (item_urn) (*item_urn) = NULL;
     151             : 
     152             : 
     153         233 :         if (iinf->item_protection_index) {
     154             :                 GF_ProtectionSchemeInfoBox *sinf;
     155          36 :                 if (!meta->protections) return GF_ISOM_INVALID_FILE;
     156          36 :                 sinf = gf_list_get(meta->protections->protection_information, iinf->item_protection_index-1);
     157          36 :                 if (!sinf) return GF_ISOM_INVALID_FILE;
     158             : 
     159          36 :                 if (sinf->scheme_type) {
     160          36 :                         if (protection_scheme) *protection_scheme = sinf->scheme_type->scheme_type;
     161          36 :                         if (protection_scheme_version) *protection_scheme_version = sinf->scheme_type->scheme_version;
     162             :                 } else {
     163           0 :                         if (protection_scheme) *protection_scheme = GF_4CC('u','k','n','w');
     164           0 :                         if (protection_scheme_version) *protection_scheme_version = 0;
     165             : 
     166             :                 }
     167             :         } else {
     168         197 :                 if (protection_scheme) *protection_scheme = 0;
     169         197 :                 if (protection_scheme_version) *protection_scheme_version = 0;
     170             :         }
     171             : 
     172         233 :         count = gf_list_count(meta->item_locations->location_entries);
     173        1778 :         for (i=0; i<count; i++) {
     174        1545 :                 GF_ItemLocationEntry *iloc = (GF_ItemLocationEntry *)gf_list_get(meta->item_locations->location_entries, i);
     175        1545 :                 if (iloc->item_ID==iinf->item_ID) {
     176         233 :                         if (iloc->data_reference_index) {
     177           0 :                                 GF_Box *a = (GF_Box *)gf_list_get(meta->file_locations->dref->child_boxes, iloc->data_reference_index-1);
     178           0 :                                 if (!a) return GF_ISOM_INVALID_FILE;
     179           0 :                                 if (a->type==GF_ISOM_BOX_TYPE_URL) {
     180           0 :                                         if (item_url) (*item_url) = ((GF_DataEntryURLBox*)a)->location;
     181           0 :                                 } else if (a->type==GF_ISOM_BOX_TYPE_URN) {
     182           0 :                                         if (item_url) (*item_url) = ((GF_DataEntryURNBox*)a)->location;
     183           0 :                                         if (item_urn) (*item_urn) = ((GF_DataEntryURNBox*)a)->nameURN;
     184             :                                 }
     185             :                                 break;
     186         233 :                         } else if (is_self_reference && !iloc->base_offset) {
     187           0 :                                 GF_ItemExtentEntry *entry = (GF_ItemExtentEntry *)gf_list_get(iloc->extent_entries, 0);
     188           0 :                                 if (!entry) return GF_ISOM_INVALID_FILE;
     189             : 
     190           0 :                                 if (!entry->extent_length
     191             : #ifndef GPAC_DISABLE_ISOM_WRITE
     192           0 :                                         && !entry->original_extent_offset
     193             : #endif
     194             :                                    )
     195           0 :                                         *is_self_reference = 1;
     196             :                         }
     197             :                 }
     198             :         }
     199             :         return GF_OK;
     200             : }
     201             : 
     202             : GF_EXPORT
     203         156 : GF_Err gf_isom_get_meta_item_flags(GF_ISOFile *file, Bool root_meta, u32 track_num, u32 item_num)
     204             : {
     205             :         GF_ItemInfoEntryBox *iinf;
     206         156 :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
     207         156 :         if (!meta || !meta->item_infos || !meta->item_locations) return 0;
     208             : 
     209         156 :         iinf = (GF_ItemInfoEntryBox *)gf_list_get(meta->item_infos->item_infos, item_num-1);
     210         156 :         if (!iinf) return 0;
     211         156 :         return iinf->flags;
     212             : }
     213             : 
     214             : GF_EXPORT
     215         322 : u32 gf_isom_get_meta_item_by_id(GF_ISOFile *file, Bool root_meta, u32 track_num, u32 item_ID)
     216             : {
     217             :         u32 i, count;
     218         322 :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
     219         322 :         if (!meta || !meta->item_infos || !meta->item_locations) return 0;
     220         322 :         count = gf_list_count(meta->item_infos->item_infos);
     221        1127 :         for (i=0; i<count; i++) {
     222        1127 :                 GF_ItemInfoEntryBox *iinf = (GF_ItemInfoEntryBox *)gf_list_get(meta->item_infos->item_infos, i);
     223        1127 :                 if (iinf->item_ID==item_ID) return i+1;
     224             :         }
     225             :         return 0;
     226             : }
     227             : 
     228          90 : static GF_Err gf_isom_extract_meta_item_intern(GF_ISOFile *file, Bool root_meta, u32 track_num, u32 item_id, const char *dump_file_name, u8 **out_data, u32 *out_size, u32 *out_alloc_size, const char **out_mime, Bool use_annex_b)
     229             : {
     230             :         GF_BitStream *item_bs;
     231             :         char szPath[1024];
     232             :         FILE *resource = NULL;
     233             :         u32 i, count;
     234             :         GF_Err e;
     235             :         GF_ItemLocationEntry *location_entry;
     236             :         u32 item_num;
     237             :         u32 item_type = 0;
     238             :         u32 nalu_size_length = 0;
     239             :         u64 idat_offset = 0;
     240             :         char *item_name = NULL;
     241             : 
     242          90 :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
     243          90 :         if (!meta || !meta->item_infos || !meta->item_locations) return GF_BAD_PARAM;
     244             : 
     245          90 :         if (out_mime) *out_mime = NULL;
     246             : 
     247          90 :         item_num = gf_isom_get_meta_item_by_id(file, root_meta, track_num, item_id);
     248          90 :         if (item_num) {
     249          90 :                 GF_ItemInfoEntryBox *item_entry = (GF_ItemInfoEntryBox *)gf_list_get(meta->item_infos->item_infos, item_num-1);
     250          90 :                 item_name = item_entry->item_name;
     251          90 :                 if (out_mime) *out_mime = item_entry->content_type;
     252             : 
     253          90 :                 item_type = item_entry->item_type;
     254             :         }
     255             : 
     256             :         location_entry = NULL;
     257          90 :         count = gf_list_count(meta->item_locations->location_entries);
     258         298 :         for (i=0; i<count; i++) {
     259         298 :                 location_entry = (GF_ItemLocationEntry *)gf_list_get(meta->item_locations->location_entries, i);
     260         298 :                 if (location_entry->item_ID == item_id) break;
     261             :                 location_entry = NULL;
     262             :         }
     263             : 
     264          90 :         if (!location_entry) return GF_BAD_PARAM;
     265             : 
     266             :         /* offsets are expressed from the start of the idat box instead of the start of the file */
     267          90 :         if (location_entry->construction_method == 1) {
     268             :                 Bool found = GF_FALSE;
     269             : 
     270           0 :                 count = gf_list_count(meta->child_boxes);
     271           0 :                 for (i = 0; i <count; i++) {
     272           0 :                         GF_Box *a = (GF_Box *)gf_list_get(meta->child_boxes, i);
     273             : 
     274           0 :                         if (a->type == GF_ISOM_BOX_TYPE_IDAT) {
     275             :                                 GF_MediaDataBox *p = (GF_MediaDataBox *)a;
     276           0 :                                 idat_offset = p->bsOffset;
     277             :                                 found = GF_TRUE;
     278             :                                 break;
     279             :                         }
     280             :                 }
     281             :                 if (!found) {
     282           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[IsoMedia] Item %d references an inexistant idat box\n", item_num));
     283             :                         return GF_BAD_PARAM;
     284             :                 }
     285             :         }
     286             :         /* when construction_method==1, data_reference_index is ignored */
     287             :         /*FIXME*/
     288          90 :         else if (location_entry->data_reference_index) {
     289             :                 char *item_url = NULL, *item_urn = NULL;
     290           0 :                 GF_Box *a = (GF_Box *)gf_list_get(meta->file_locations->dref->child_boxes, location_entry->data_reference_index-1);
     291           0 :                 if (!a) return GF_ISOM_INVALID_FILE;
     292           0 :                 if (a->type==GF_ISOM_BOX_TYPE_URL) {
     293           0 :                         item_url = ((GF_DataEntryURLBox*)a)->location;
     294           0 :                 } else if (a->type==GF_ISOM_BOX_TYPE_URN) {
     295           0 :                         item_url = ((GF_DataEntryURNBox*)a)->location;
     296           0 :                         item_urn = ((GF_DataEntryURNBox*)a)->nameURN;
     297             :                 }
     298           0 :                 GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[IsoMedia] Item already outside the ISO file at URL: %s, URN: %s\n", (item_url?item_url:"N/A"), (item_urn?item_urn:"N/A") ));
     299             :                 return GF_OK;
     300             :         }
     301             : 
     302             :         /*don't extract self-reference item*/
     303          90 :         count = gf_list_count(location_entry->extent_entries);
     304          90 :         if (!location_entry->base_offset && (count==1)) {
     305           0 :                 GF_ItemExtentEntry *extent_entry = (GF_ItemExtentEntry *)gf_list_get(location_entry->extent_entries, 0);
     306           0 :                 if (!extent_entry->extent_length
     307             : #ifndef GPAC_DISABLE_ISOM_WRITE
     308           0 :                         && !extent_entry->original_extent_offset
     309             : #endif
     310             :                    ) return GF_BAD_PARAM;
     311             :         }
     312             : 
     313             :         item_bs = NULL;
     314             : 
     315             : 
     316          90 :         if (out_data) {
     317          85 :                 item_bs = gf_bs_new(*out_data, *out_size, GF_BITSTREAM_WRITE_DYN);
     318           5 :         } else if (dump_file_name) {
     319             :                 strcpy(szPath, dump_file_name);
     320           5 :                 resource = gf_fopen(szPath, "wb");
     321           5 :                 item_bs = gf_bs_from_file(resource, GF_BITSTREAM_WRITE);
     322             :         } else {
     323           0 :                 if (item_name && strlen(item_name) > 0) strcpy(szPath, item_name);
     324             :                 else sprintf(szPath, "item_id%02d", item_id);
     325           0 :                 resource = gf_fopen(szPath, "wb");
     326           0 :                 item_bs = gf_bs_from_file(resource, GF_BITSTREAM_WRITE);
     327             :         }
     328             : 
     329          90 :         if ((item_type == GF_ISOM_SUBTYPE_HVC1) || (item_type == GF_ISOM_SUBTYPE_AVC_H264) ) {
     330             :                 u32 j, nb_assoc;
     331             :                 GF_HEVCConfigurationBox *hvcc = NULL;
     332             :                 GF_AVCConfigurationBox *avcc = NULL;
     333          73 :                 if (! meta->item_props) return GF_NON_COMPLIANT_BITSTREAM;
     334          73 :                 if (! meta->item_props->property_container) {
     335           0 :                         if (item_bs) gf_bs_del(item_bs);
     336             :                         return GF_NON_COMPLIANT_BITSTREAM;
     337             :                 }
     338          73 :                 if (! meta->item_props->property_association) {
     339           0 :                         if (item_bs) gf_bs_del(item_bs);
     340             :                         return GF_NON_COMPLIANT_BITSTREAM;
     341             :                 }
     342          73 :                 nb_assoc = gf_list_count(meta->item_props->property_association->entries);
     343         262 :                 for (i=0; i<nb_assoc; i++) {
     344         262 :                         GF_ItemPropertyAssociationEntry *e = gf_list_get(meta->item_props->property_association->entries, i);
     345         262 :                         if (e->item_id!=item_id) continue;
     346         146 :                         for (j=0; j<e->nb_associations; j++) {
     347         219 :                                 u32 idx = e->associations[j].index;
     348         219 :                                 if (! idx) continue;
     349         219 :                                 hvcc = gf_list_get(meta->item_props->property_container->child_boxes, idx - 1);
     350         219 :                                 if (!hvcc) {
     351           0 :                                         if (item_bs) gf_bs_del(item_bs);
     352             :                                         return GF_NON_COMPLIANT_BITSTREAM;
     353             :                                 }
     354         219 :                                 if (hvcc->type == GF_ISOM_BOX_TYPE_HVCC) break;
     355         166 :                                 if (hvcc->type == GF_ISOM_BOX_TYPE_AVCC) {
     356             :                                         avcc = (GF_AVCConfigurationBox *) hvcc;
     357             :                                         hvcc = NULL;
     358             :                                         break;
     359             :                                 }
     360             :                         }
     361          73 :                         if (avcc || hvcc) break;
     362             :                 }
     363          73 :                 if (hvcc) {
     364          53 :                         if (! hvcc->config) {
     365           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Missing HEVC config in hvcC\n"));
     366             :                         } else {
     367          53 :                                 if (use_annex_b) {
     368           1 :                                         hvcc->config->write_annex_b = GF_TRUE;
     369           1 :                                         gf_odf_hevc_cfg_write_bs(hvcc->config, item_bs);
     370           1 :                                         hvcc->config->write_annex_b = GF_FALSE;
     371             :                                 }
     372          53 :                                 nalu_size_length = hvcc->config->nal_unit_size;
     373             :                         }
     374          20 :                 } else if (avcc) {
     375          20 :                         if (! avcc->config) {
     376           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Missing AVC config in avcC\n"));
     377             :                         } else {
     378          20 :                                 if (use_annex_b) {
     379           0 :                                         avcc->config->write_annex_b = GF_TRUE;
     380           0 :                                         gf_odf_avc_cfg_write_bs(avcc->config, item_bs);
     381           0 :                                         avcc->config->write_annex_b = GF_FALSE;
     382             :                                 }
     383          20 :                                 nalu_size_length = avcc->config->nal_unit_size;
     384             :                         }
     385             :                 }
     386             :         }
     387             : 
     388             :         e = GF_OK;
     389         180 :         for (i=0; i<count; i++) {
     390             :                 char buf_cache[4096];
     391             :                 u64 remain;
     392          90 :                 GF_ItemExtentEntry *extent_entry = (GF_ItemExtentEntry *)gf_list_get(location_entry->extent_entries, i);
     393          90 :                 gf_bs_seek(file->movieFileMap->bs, idat_offset + location_entry->base_offset + extent_entry->extent_offset);
     394             : 
     395          90 :                 remain = extent_entry->extent_length;
     396         758 :                 while (remain) {
     397         578 :                         if (nalu_size_length) {
     398         558 :                                 if (remain < nalu_size_length) {
     399             :                                         e = GF_ISOM_INVALID_FILE;
     400             :                                         break;
     401             :                                 }
     402             : 
     403         558 :                                 u32 nal_size = gf_bs_read_int(file->movieFileMap->bs, 8*nalu_size_length);
     404         558 :                                 if (remain - nalu_size_length < nal_size) {
     405             :                                         e = GF_ISOM_INVALID_FILE;
     406             :                                         break;
     407             :                                 }
     408             : 
     409         558 :                                 if (use_annex_b)
     410          11 :                                         gf_bs_write_u32(item_bs, 1);
     411             :                                 else
     412         547 :                                         gf_bs_write_int(item_bs, nal_size, 8*nalu_size_length);
     413             : 
     414         558 :                                 remain -= nalu_size_length + nal_size;
     415        1752 :                                 while (nal_size) {
     416         636 :                                         u32 cache_size = (nal_size>4096) ? 4096 : (u32) nal_size;
     417             : 
     418         636 :                                         gf_bs_read_data(file->movieFileMap->bs, buf_cache, cache_size);
     419         636 :                                         gf_bs_write_data(item_bs, buf_cache, cache_size);
     420         636 :                                         nal_size -= cache_size;
     421             :                                 }
     422             :                         } else {
     423          20 :                                 u32 cache_size = (remain>4096) ? 4096 : (u32) remain;
     424          20 :                                 gf_bs_read_data(file->movieFileMap->bs, buf_cache, cache_size);
     425          20 :                                 gf_bs_write_data(item_bs, buf_cache, cache_size);
     426          20 :                                 remain -= cache_size;
     427             :                         }
     428             :                 }
     429             :         }
     430          90 :         if (out_data) {
     431          85 :                 gf_bs_get_content_no_truncate(item_bs, out_data, out_size, out_alloc_size);
     432             :         }
     433          90 :         gf_bs_del(item_bs);
     434          90 :         if (resource) {
     435           5 :                 gf_fclose(resource);
     436             :         }
     437             :         return e;
     438             : }
     439             : 
     440             : GF_EXPORT
     441           5 : GF_Err gf_isom_extract_meta_item(GF_ISOFile *file, Bool root_meta, u32 track_num, u32 item_id, const char *dump_file_name)
     442             : {
     443           5 :         return gf_isom_extract_meta_item_intern(file, root_meta, track_num, item_id, dump_file_name, NULL, NULL, NULL, NULL, GF_TRUE);
     444             : }
     445             : 
     446             : GF_EXPORT
     447          85 : GF_Err gf_isom_extract_meta_item_mem(GF_ISOFile *file, Bool root_meta, u32 track_num, u32 item_id, u8 **out_data, u32 *out_size, u32 *out_alloc_size, const char **out_mime, Bool use_annex_b)
     448             : {
     449          85 :         return gf_isom_extract_meta_item_intern(file, root_meta, track_num, item_id, NULL, out_data, out_size, out_alloc_size, out_mime, use_annex_b);
     450             : }
     451             : 
     452             : GF_EXPORT
     453          13 : GF_Err gf_isom_extract_meta_item_get_cenc_info(GF_ISOFile *file, Bool root_meta, u32 track_num, u32 item_id, Bool *is_protected,
     454             :         u8 *skip_byte_block, u8 *crypt_byte_block, const u8 **key_info, u32 *key_info_size, u32 *aux_info_type_param,
     455             :         u8 **cenc_sai_data, u32 *cenc_sai_data_size, u32 *cenc_sai_alloc_size)
     456             : {
     457             :         u32 count, i;
     458             :         u32 j, sai_item_id;
     459             :         Bool found = GF_FALSE;
     460             :         GF_ItemPropertyAssociationBox *ipma = NULL;
     461             :         GF_ItemPropertyContainerBox *ipco = NULL;
     462          13 :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
     463          13 :         if (!meta) return GF_BAD_PARAM;
     464             : 
     465          13 :         ipma = meta->item_props->property_association;
     466          13 :         ipco = meta->item_props->property_container;
     467             : 
     468          13 :         count = gf_list_count(ipma->entries);
     469          13 :         for (i = 0; i < count; i++) {
     470          13 :                 GF_ItemPropertyAssociationEntry *entry = (GF_ItemPropertyAssociationEntry *)gf_list_get(ipma->entries, i);
     471          13 :                 if (entry->item_id != item_id) continue;
     472          52 :                 for (j = 0; j < entry->nb_associations; j++) {
     473             :                         GF_ItemEncryptionPropertyBox *ienc;
     474          65 :                         u32 index = entry->associations[j].index;
     475          65 :                         ienc = index ? (GF_ItemEncryptionPropertyBox *)gf_list_get(ipco->child_boxes, index - 1) : NULL;
     476          65 :                         if (!ienc) continue;
     477             : 
     478          65 :                         if (ienc->type!=GF_ISOM_BOX_TYPE_IENC) continue;
     479          13 :                         if (ienc->key_info_size<19) return GF_ISOM_INVALID_FILE;
     480             :                         
     481          13 :                         *skip_byte_block = ienc->skip_byte_block;
     482          13 :                         *crypt_byte_block = ienc->crypt_byte_block;
     483          13 :                         *key_info = ienc->key_info;
     484          13 :                         *key_info_size = ienc->key_info_size;
     485             :                         found = GF_TRUE;
     486             :                         break;
     487             :                 }
     488             :                 if (found) break;
     489             :         }
     490          13 :         if (!found) {
     491           0 :                 *is_protected = GF_FALSE;
     492           0 :                 return GF_OK;
     493             :         }
     494          13 :         *is_protected = GF_TRUE;
     495             :         sai_item_id = 0;
     496             : 
     497             :         //look for item reference
     498          13 :         if (!meta->item_refs)
     499             :                 return GF_ISOM_INVALID_FILE;
     500          13 :         count = gf_list_count(meta->item_refs->references);
     501          13 :         for (i=0; i<count; i++) {
     502          13 :                 GF_ItemReferenceTypeBox *iref = gf_list_get(meta->item_refs->references, i);
     503          13 :                 if (iref->reference_type!=GF_ISOM_REF_AUXR) continue;
     504          13 :                 sai_item_id = iref->to_item_IDs[0];
     505          13 :                 break;
     506             :         }
     507          13 :         if (!sai_item_id) return GF_ISOM_INVALID_FILE;
     508             : 
     509          13 :         if (aux_info_type_param) {
     510          13 :                 count = gf_list_count(ipma->entries);
     511             :                 found = GF_FALSE;
     512          26 :                 for (i = 0; i < count; i++) {
     513          16 :                         GF_ItemPropertyAssociationEntry *entry = (GF_ItemPropertyAssociationEntry *)gf_list_get(ipma->entries, i);
     514          16 :                         if (entry->item_id != sai_item_id) continue;
     515           0 :                         for (j = 0; j < entry->nb_associations; j++) {
     516             :                                 GF_AuxiliaryInfoPropertyBox *iaux;
     517           3 :                                 u32 index = entry->associations[j].index;
     518           3 :                                 iaux = index ? (GF_AuxiliaryInfoPropertyBox *)gf_list_get(ipco->child_boxes, index - 1) : NULL;
     519           3 :                                 if (!iaux) continue;
     520             : 
     521           3 :                                 if (iaux->type!=GF_ISOM_BOX_TYPE_IAUX) continue;
     522           3 :                                 switch (iaux->aux_info_type) {
     523             :                                 case GF_ISOM_CENC_SCHEME:
     524             :                                 case GF_ISOM_CENS_SCHEME:
     525             :                                 case GF_ISOM_CBC_SCHEME:
     526             :                                 case GF_ISOM_CBCS_SCHEME:
     527             :                                 case 0:
     528             :                                         break;
     529           0 :                                 default:
     530           0 :                                         continue;
     531             :                                 }
     532           3 :                                 *aux_info_type_param = iaux->aux_info_parameter;
     533             :                                 found = GF_TRUE;
     534             :                                 break;
     535             :                         }
     536             :                         if (found) break;
     537             :                 }
     538             :         }
     539          13 :         if (!cenc_sai_data)
     540             :                 return GF_OK;
     541             : 
     542          13 :         return gf_isom_extract_meta_item_mem(file, root_meta, track_num, sai_item_id, cenc_sai_data, cenc_sai_data_size, cenc_sai_alloc_size, NULL, GF_FALSE);
     543             : }
     544             : 
     545             : 
     546             : GF_EXPORT
     547         716 : u32 gf_isom_get_meta_primary_item_id(GF_ISOFile *file, Bool root_meta, u32 track_num)
     548             : {
     549         716 :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
     550         716 :         if (!meta || !meta->primary_resource) return 0;
     551          45 :         return meta->primary_resource->item_ID;
     552             : }
     553             : 
     554             : 
     555             : #ifndef GPAC_DISABLE_ISOM_WRITE
     556             : 
     557             : 
     558             : GF_EXPORT
     559          94 : GF_Err gf_isom_set_meta_type(GF_ISOFile *file, Bool root_meta, u32 track_num, u32 metaType)
     560             : {
     561             :         char szName[40];
     562             :         GF_MetaBox *meta;
     563             : 
     564          94 :         GF_Err e = CanAccessMovie(file, GF_ISOM_OPEN_WRITE);
     565          94 :         if (e) return e;
     566             : 
     567          94 :         meta = gf_isom_get_meta(file, root_meta, track_num);
     568          94 :         if (!meta) {
     569          90 :                 if (!metaType) return GF_OK;
     570          90 :                 meta = (GF_MetaBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_META);
     571          90 :                 if (!meta) return GF_OUT_OF_MEM;
     572          90 :                 if (root_meta) {
     573          89 :                         file->meta = meta;
     574          89 :                         gf_list_add(file->TopBoxes, meta);
     575             :                 } else {
     576           1 :                         e = gf_isom_insert_moov(file);
     577           1 :                         if (e) return e;
     578           1 :                         if (!track_num) {
     579           0 :                                 file->moov->meta = meta;
     580           0 :                                 if (!file->moov->child_boxes) file->moov->child_boxes = gf_list_new();
     581           0 :                                 gf_list_add(file->moov->child_boxes, meta);
     582             :                         } else {
     583           1 :                                 GF_TrackBox *tk = (GF_TrackBox *)gf_list_get(file->moov->trackList, track_num-1);
     584           1 :                                 if (!tk) {
     585           0 :                                         gf_isom_box_del((GF_Box *)meta);
     586           0 :                                         return GF_BAD_PARAM;
     587             :                                 }
     588           1 :                                 if (!tk->child_boxes) tk->child_boxes = gf_list_new();
     589           1 :                                 gf_list_add(tk->child_boxes, meta);
     590           1 :                                 tk->meta = meta;
     591             :                         }
     592             :                 }
     593           4 :         } else if (!metaType) {
     594           0 :                 if (root_meta) {
     595           0 :                         gf_list_del_item(file->TopBoxes, meta);
     596           0 :                         gf_isom_box_del((GF_Box *)file->meta);
     597           0 :                         file->meta = NULL;
     598           0 :                 } else if (file->moov) {
     599           0 :                         if (!track_num) {
     600           0 :                                 gf_isom_box_del_parent(&file->moov->child_boxes, (GF_Box *)file->moov->meta);
     601           0 :                                 file->moov->meta = NULL;
     602             :                         } else {
     603           0 :                                 GF_TrackBox *tk = (GF_TrackBox *)gf_list_get(file->moov->trackList, track_num-1);
     604           0 :                                 if (!tk) return GF_BAD_PARAM;
     605           0 :                                 gf_isom_box_del_parent(&tk->child_boxes, (GF_Box *)tk->meta);
     606           0 :                                 tk->meta = NULL;
     607             :                         }
     608             :                 }
     609             :                 return GF_OK;
     610             :         }
     611             : 
     612          94 :         if (!meta->handler) {
     613          90 :                 meta->handler = (GF_HandlerBox *)gf_isom_box_new_parent(&meta->child_boxes, GF_ISOM_BOX_TYPE_HDLR);
     614          90 :                 if (!meta->handler) return GF_OUT_OF_MEM;
     615             :         }
     616          94 :         if (meta->handler->nameUTF8) gf_free(meta->handler->nameUTF8);
     617          94 :         meta->handler->handlerType = metaType;
     618          94 :         sprintf(szName, "GPAC %s Handler", gf_4cc_to_str(metaType));
     619          94 :         meta->handler->nameUTF8 = gf_strdup(szName);
     620          94 :         if (!meta->handler->nameUTF8) return GF_OUT_OF_MEM;
     621          94 :         return GF_OK;
     622             : }
     623             : 
     624             : GF_EXPORT
     625           3 : GF_Err gf_isom_remove_meta_xml(GF_ISOFile *file, Bool root_meta, u32 track_num)
     626             : {
     627             :         u32 i;
     628             :         GF_Box *a;
     629           3 :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
     630           3 :         if (!meta) return GF_BAD_PARAM;
     631           3 :         i=0;
     632          12 :         while ((a = (GF_Box*)gf_list_enum(meta->child_boxes, &i))) {
     633           6 :                 switch (a->type) {
     634           0 :                 case GF_ISOM_BOX_TYPE_XML:
     635             :                 case GF_ISOM_BOX_TYPE_BXML:
     636           0 :                         gf_isom_box_del_parent(&meta->child_boxes, a);
     637             :                         i--;
     638           0 :                         return GF_OK;
     639             :                 }
     640             :         }
     641             :         return GF_OK;
     642             : }
     643             : 
     644             : GF_EXPORT
     645           3 : GF_Err gf_isom_set_meta_xml(GF_ISOFile *file, Bool root_meta, u32 track_num, char *XMLFileName, unsigned char *data, u32 data_size, Bool IsBinaryXML)
     646             : {
     647             :         GF_Err e;
     648             :         GF_XMLBox *xml;
     649             :         GF_MetaBox *meta;
     650             :         u32 length;
     651           3 :         if (!XMLFileName && !data)
     652             :                 return GF_BAD_PARAM;
     653             : 
     654           3 :         e = CanAccessMovie(file, GF_ISOM_OPEN_WRITE);
     655           3 :         if (e) return e;
     656             : 
     657           3 :         meta = gf_isom_get_meta(file, root_meta, track_num);
     658           3 :         if (!meta) return GF_BAD_PARAM;
     659             : 
     660           3 :         e = gf_isom_remove_meta_xml(file, root_meta, track_num);
     661           3 :         if (e) return e;
     662             : 
     663           3 :         xml = (GF_XMLBox *)gf_isom_box_new_parent(&meta->child_boxes, GF_ISOM_BOX_TYPE_XML);
     664           3 :         if (!xml) return GF_OUT_OF_MEM;
     665           3 :         if (IsBinaryXML) xml->type = GF_ISOM_BOX_TYPE_BXML;
     666             : 
     667           3 :         if (XMLFileName) {
     668             :                 /*assume 32bit max size = 4Go should be sufficient for a DID!!*/
     669           3 :                 return gf_file_load_data(XMLFileName, (u8 **) &xml->xml, &length);
     670             :         }
     671             : 
     672             :         /*assume 32bit max size = 4Go should be sufficient for a DID!!*/
     673           0 :         xml->xml = (char*)gf_malloc(sizeof(unsigned char)*data_size);
     674           0 :         if (!xml->xml) return GF_OUT_OF_MEM;
     675             :         memcpy(xml->xml, data, sizeof(unsigned char)*data_size);
     676           0 :         return GF_OK;
     677             : }
     678             : 
     679             : 
     680             : GF_EXPORT
     681         156 : GF_Err gf_isom_get_meta_image_props(GF_ISOFile *file, Bool root_meta, u32 track_num, u32 item_id, GF_ImageItemProperties *prop) {
     682             :         u32 count, i, inum;
     683             :         u32 j;
     684             :         GF_ItemPropertyAssociationBox *ipma = NULL;
     685             :         GF_ItemPropertyContainerBox *ipco = NULL;
     686         156 :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
     687         156 :         if (!meta) return GF_BAD_PARAM;
     688             : 
     689             :         memset(prop, 0, sizeof(GF_ImageItemProperties));
     690         156 :         if (!meta->item_props) return GF_OK;
     691             : 
     692         156 :         ipma = meta->item_props->property_association;
     693         156 :         ipco = meta->item_props->property_container;
     694             : 
     695         156 :         inum = gf_isom_get_meta_item_by_id(file, root_meta, track_num, item_id);
     696         156 :         i = gf_isom_get_meta_item_flags(file, root_meta, track_num, inum);
     697         156 :         if (i & 0x1)
     698           0 :                 prop->hidden = GF_TRUE;
     699             : 
     700         156 :         count = gf_list_count(ipma->entries);
     701        1134 :         for (i = 0; i < count; i++) {
     702         978 :                 GF_ItemPropertyAssociationEntry *entry = (GF_ItemPropertyAssociationEntry *)gf_list_get(ipma->entries, i);
     703         978 :                 if (entry->item_id != item_id) continue;
     704         650 :                 for (j = 0; j < entry->nb_associations; j++) {
     705             :                         GF_Box *b;
     706         650 :                         u32 index = entry->associations[j].index;
     707         650 :                         b = index ? (GF_Box *)gf_list_get(ipco->child_boxes, index - 1) : NULL;
     708         650 :                         if (!b) continue;
     709             : 
     710         650 :                         switch (b->type) {
     711         156 :                         case GF_ISOM_BOX_TYPE_ISPE:
     712             :                         {
     713             :                                 GF_ImageSpatialExtentsPropertyBox *ispe = (GF_ImageSpatialExtentsPropertyBox *)b;
     714         156 :                                 prop->width = ispe->image_width;
     715         156 :                                 prop->height = ispe->image_height;
     716             :                         }
     717         156 :                         break;
     718           0 :                         case GF_ISOM_BOX_TYPE_RLOC:
     719             :                         {
     720             :                                 GF_RelativeLocationPropertyBox *rloc = (GF_RelativeLocationPropertyBox *)b;
     721           0 :                                 prop->hOffset = rloc->horizontal_offset;
     722           0 :                                 prop->vOffset = rloc->vertical_offset;
     723             :                         }
     724           0 :                         break;
     725         156 :                         case GF_ISOM_BOX_TYPE_PASP:
     726             :                         {
     727             :                                 GF_PixelAspectRatioBox *pasp = (GF_PixelAspectRatioBox *)b;
     728         156 :                                 prop->hSpacing = pasp->hSpacing;
     729         156 :                                 prop->vSpacing = pasp->vSpacing;
     730             :                         }
     731         156 :                         break;
     732         156 :                         case GF_ISOM_BOX_TYPE_PIXI:
     733             :                         {
     734             :                                 GF_PixelInformationPropertyBox *pixi = (GF_PixelInformationPropertyBox *)b;
     735         156 :                                 if (pixi->num_channels > 3) {
     736             :                                         return GF_BAD_PARAM;
     737             :                                 }
     738         156 :                                 prop->num_channels = pixi->num_channels;
     739         156 :                                 memset(prop->bits_per_channel, 0, 3);
     740         156 :                                 memcpy(prop->bits_per_channel, pixi->bits_per_channel, pixi->num_channels);
     741             :                         }
     742             :                         break;
     743           0 :                         case GF_ISOM_BOX_TYPE_IROT:
     744             :                         {
     745             :                                 GF_ImageRotationBox *irot = (GF_ImageRotationBox *)b;
     746           0 :                                 prop->angle = irot->angle * 90;
     747             :                         }
     748           0 :                         break;
     749           0 :                         case GF_ISOM_BOX_TYPE_IMIR:
     750             :                         {
     751             :                                 GF_ImageMirrorBox *imir = (GF_ImageMirrorBox *)b;
     752           0 :                                 prop->mirror = imir->axis+1;
     753             :                         }
     754           0 :                         break;
     755           0 :                         case GF_ISOM_BOX_TYPE_CLAP:
     756             :                         {
     757             :                                 GF_CleanApertureBox *clap = (GF_CleanApertureBox *)b;
     758           0 :                                 prop->clap_hden = clap->cleanApertureHeightD;
     759           0 :                                 prop->clap_hnum = clap->cleanApertureHeightN;
     760           0 :                                 prop->clap_wden = clap->cleanApertureWidthD;
     761           0 :                                 prop->clap_wnum = clap->cleanApertureWidthN;
     762           0 :                                 prop->clap_hoden = clap->horizOffD;
     763           0 :                                 prop->clap_honum = clap->horizOffN;
     764           0 :                                 prop->clap_voden = clap->vertOffD;
     765           0 :                                 prop->clap_vonum = clap->vertOffN;
     766             :                         }
     767           0 :                         break;
     768         156 :                         case GF_ISOM_BOX_TYPE_HVCC:
     769             :                         case GF_ISOM_BOX_TYPE_AVCC:
     770             :                         case GF_ISOM_BOX_TYPE_AV1C:
     771         156 :                                 prop->config = b;
     772         156 :                                 break;
     773             :                         }
     774             :                 }
     775             :         }
     776             :         return GF_OK;
     777             : }
     778             : 
     779         882 : static s32 meta_find_prop(GF_ItemPropertyContainerBox *boxes, GF_ImageItemProperties *prop) {
     780             :         u32 i;
     781             :         u32 count;
     782         882 :         count = gf_list_count(boxes->child_boxes);
     783        1771 :         for (i = 0; i < count; i++) {
     784        2243 :                 GF_Box *b = (GF_Box *)gf_list_get(boxes->child_boxes, i);
     785        2243 :                 switch(b->type) {
     786         944 :                 case GF_ISOM_BOX_TYPE_ISPE:
     787             :                 {
     788             :                         GF_ImageSpatialExtentsPropertyBox *ispe = (GF_ImageSpatialExtentsPropertyBox *)b;
     789         944 :                         if ((prop->width || prop->height) && ispe->image_width == prop->width && ispe->image_height == prop->height) {
     790         115 :                                 return i;
     791             :                         }
     792             :                 }
     793             :                 break;
     794           0 :                 case GF_ISOM_BOX_TYPE_RLOC:
     795             :                 {
     796             :                         GF_RelativeLocationPropertyBox *rloc = (GF_RelativeLocationPropertyBox *)b;
     797           0 :                         if ((prop->hOffset || prop->vOffset) && rloc->horizontal_offset == prop->hOffset && rloc->vertical_offset == prop->vOffset) {
     798           0 :                                 return i;
     799             :                         }
     800             :                 }
     801             :                 break;
     802         584 :                 case GF_ISOM_BOX_TYPE_PASP:
     803             :                 {
     804             :                         GF_PixelAspectRatioBox *pasp = (GF_PixelAspectRatioBox *)b;
     805         584 :                         if ((prop->hSpacing || prop->vSpacing) && pasp->hSpacing == prop->hSpacing && pasp->vSpacing == prop->vSpacing) {
     806         119 :                                 return i;
     807             :                         }
     808             :                 }
     809             :                 break;
     810          76 :                 case GF_ISOM_BOX_TYPE_IROT:
     811             :                 {
     812             :                         GF_ImageRotationBox *irot = (GF_ImageRotationBox *)b;
     813          76 :                         if (prop->angle && irot->angle*90 == prop->angle) {
     814           0 :                                 return i;
     815             :                         }
     816             :                 }
     817             :                 break;
     818          66 :                 case GF_ISOM_BOX_TYPE_IMIR:
     819             :                 {
     820             :                         GF_ImageMirrorBox *imir = (GF_ImageMirrorBox *)b;
     821          66 :                         if (prop->mirror && imir->axis == prop->mirror-1) {
     822           0 :                                 return i;
     823             :                         }
     824             :                 }
     825             :                 break;
     826          64 :                 case GF_ISOM_BOX_TYPE_CLAP:
     827             :                 {
     828             :                         GF_CleanApertureBox *clap = (GF_CleanApertureBox *)b;
     829          64 :                         if (prop->clap_hden == clap->cleanApertureHeightD &&
     830           0 :                                 prop->clap_hnum == clap->cleanApertureHeightN &&
     831           0 :                                 prop->clap_wden == clap->cleanApertureWidthD &&
     832           0 :                                 prop->clap_wnum == clap->cleanApertureWidthN &&
     833           0 :                                 prop->clap_hoden == clap->horizOffD &&
     834           0 :                                 prop->clap_honum == clap->horizOffN &&
     835           0 :                                 prop->clap_voden == clap->vertOffD &&
     836           0 :                                 prop->clap_vonum == clap->vertOffN) {
     837           0 :                                 return i;
     838             :                         }
     839             :                 }
     840             :                 break;
     841         152 :                 case GF_ISOM_BOX_TYPE_PIXI:
     842             :                 {
     843             :                         GF_PixelInformationPropertyBox *pixi = (GF_PixelInformationPropertyBox *)b;
     844         152 :                         if (prop->num_channels && pixi->num_channels == prop->num_channels) {
     845             :                                 int j;
     846             :                                 for (j = 0; j < pixi->num_channels; j++) {
     847             :                                         if (pixi->bits_per_channel[j] != prop->bits_per_channel[j]) {
     848             :                                                 break;
     849             :                                         }
     850             :                                 }
     851         119 :                                 return i;
     852             :                         }
     853             :                 }
     854             :                 break;
     855           0 :                 case GF_ISOM_BOX_TYPE_IENC:
     856             :                 {
     857             :                         GF_ItemEncryptionPropertyBox *ienc = (GF_ItemEncryptionPropertyBox *)b;
     858           0 :                         if (prop->cenc_info
     859           0 :                                 && (prop->cenc_info->skip_byte_block == ienc->skip_byte_block)
     860           0 :                                 && (prop->cenc_info->crypt_byte_block == ienc->crypt_byte_block)
     861           0 :                                 && (prop->cenc_info->key_info_size == ienc->key_info_size)
     862           0 :                                 && prop->cenc_info->key_info && ienc->key_info
     863           0 :                                 && !memcmp(prop->cenc_info->key_info, ienc->key_info, ienc->key_info_size)
     864             :                         ) {
     865           0 :                                 return i;
     866             :                         }
     867             :                 }
     868             :                 break;
     869             :                 
     870         357 :                 default:
     871         357 :                         if (gf_isom_box_equal(prop->config, b)) {
     872         119 :                                 return i;
     873             :                         }
     874             :                 }
     875             :         }
     876             :         return -1;
     877             : }
     878             : 
     879         885 : static GF_Err meta_add_item_property_association(GF_ItemPropertyAssociationBox *ipma, u32 item_ID, u32 prop_index, Bool essential) {
     880             :         u32 i, count;
     881             :         GF_ItemPropertyAssociationEntry *found_entry = NULL;
     882             : 
     883         885 :         count = gf_list_count(ipma->entries);
     884        3183 :         for (i = 0; i < count; i++) {
     885        3850 :                 found_entry = (GF_ItemPropertyAssociationEntry *)gf_list_get(ipma->entries, i);
     886        3850 :                 if (found_entry->item_id == item_ID) break;
     887             :                 found_entry = NULL;
     888             :         }
     889         885 :         if (!found_entry) {
     890         218 :                 GF_SAFEALLOC(found_entry, GF_ItemPropertyAssociationEntry);
     891         218 :                 if (!found_entry) return GF_OUT_OF_MEM;
     892         218 :                 gf_list_add(ipma->entries, found_entry);
     893         218 :                 found_entry->item_id = item_ID;
     894             :         }
     895         885 :         found_entry->associations = gf_realloc(found_entry->associations, sizeof(GF_ItemPropertyAssociationSlot) * (found_entry->nb_associations+1));
     896         885 :         if (!found_entry->associations) return GF_OUT_OF_MEM;
     897             : 
     898         885 :         found_entry->associations[found_entry->nb_associations].essential = essential;
     899         885 :         found_entry->associations[found_entry->nb_associations].index = prop_index;
     900         885 :         found_entry->nb_associations++;
     901             :         return GF_OK;
     902             : }
     903             : 
     904         215 : static GF_Err meta_process_image_properties(GF_MetaBox *meta, u32 item_ID, GF_ImageItemProperties *image_props)
     905             : {
     906             :         GF_ImageItemProperties searchprop;
     907             :         GF_ItemPropertyAssociationBox *ipma;
     908             :         GF_ItemPropertyContainerBox *ipco;
     909             :         s32 prop_index;
     910             :         GF_Err e;
     911             :         memset(&searchprop, 0, sizeof(GF_ImageItemProperties));
     912             : 
     913         215 :         if (!meta->item_props) {
     914          87 :                 meta->item_props = (GF_ItemPropertiesBox *)gf_isom_box_new_parent(&meta->child_boxes, GF_ISOM_BOX_TYPE_IPRP);
     915          87 :                 if (!meta->item_props) return GF_OUT_OF_MEM;
     916          87 :                 meta->item_props->property_container = (GF_ItemPropertyContainerBox *)gf_isom_box_new_parent(&meta->item_props->child_boxes, GF_ISOM_BOX_TYPE_IPCO);
     917          87 :                 if (!meta->item_props->property_container) return GF_OUT_OF_MEM;
     918             :                 ipco = meta->item_props->property_container;
     919          87 :                 ipma = (GF_ItemPropertyAssociationBox *)gf_isom_box_new_parent(&meta->item_props->child_boxes, GF_ISOM_BOX_TYPE_IPMA);
     920          87 :                 if (!ipma) return GF_OUT_OF_MEM;
     921          87 :                 meta->item_props->property_association = ipma;
     922             :         } else {
     923         128 :                 ipco = meta->item_props->property_container;
     924         128 :                 ipma = meta->item_props->property_association;
     925             :         }
     926         215 :         if (!ipco->child_boxes)
     927          87 :                 ipco->child_boxes = gf_list_new();
     928             : 
     929         215 :         if (strlen(image_props->iccPath) > 0) {
     930             :                 u32 size;
     931             :                 u8 *data;
     932           0 :                 e = gf_file_load_data(image_props->iccPath, &data, &size);
     933           0 :                 if (e) {
     934           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Error opening ICC colour profile file at %s\n", &image_props->iccPath));
     935             : 
     936             :                 } else {
     937             : 
     938           0 :                         GF_ColourInformationBox *colr = (GF_ColourInformationBox *)gf_isom_box_new_parent(&ipco->child_boxes, GF_ISOM_BOX_TYPE_COLR);
     939           0 :                         if (!colr) return GF_OUT_OF_MEM;
     940           0 :                         GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[iso file] reading ICC colour profile from file %s\n", &image_props->iccPath));
     941           0 :                         colr->colour_type = GF_ISOM_SUBTYPE_PROF;
     942           0 :                         colr->opaque_size = size;
     943           0 :                         colr->opaque = data;
     944             : 
     945           0 :                         prop_index = gf_list_count(ipco->child_boxes) - 1;
     946           0 :                         meta_add_item_property_association(ipma, item_ID, prop_index + 1, GF_FALSE);
     947             :                 }
     948             :         }
     949             : 
     950         215 :         if (image_props->width || image_props->height) {
     951         215 :                 searchprop.width = image_props->width;
     952         215 :                 searchprop.height = image_props->height;
     953         215 :                 prop_index = meta_find_prop(ipco, &searchprop);
     954         215 :                 if (prop_index < 0) {
     955         100 :                         GF_ImageSpatialExtentsPropertyBox *ispe = (GF_ImageSpatialExtentsPropertyBox *)gf_isom_box_new_parent(&ipco->child_boxes, GF_ISOM_BOX_TYPE_ISPE);
     956         100 :                         if (!ispe) return GF_OUT_OF_MEM;
     957         100 :                         ispe->image_width = image_props->width;
     958         100 :                         ispe->image_height = image_props->height;
     959         100 :                         prop_index = gf_list_count(ipco->child_boxes) - 1;
     960             :                 }
     961         215 :                 e = meta_add_item_property_association(ipma, item_ID, prop_index + 1, GF_FALSE);
     962         215 :                 if (e) return e;
     963         215 :                 searchprop.width = 0;
     964         215 :                 searchprop.height = 0;
     965             :         }
     966         215 :         if (image_props->hOffset || image_props->vOffset) {
     967           0 :                 searchprop.hOffset = image_props->hOffset;
     968           0 :                 searchprop.vOffset = image_props->vOffset;
     969           0 :                 prop_index = meta_find_prop(ipco, &searchprop);
     970           0 :                 if (prop_index < 0) {
     971           0 :                         GF_RelativeLocationPropertyBox *rloc = (GF_RelativeLocationPropertyBox *)gf_isom_box_new_parent(&ipco->child_boxes, GF_ISOM_BOX_TYPE_RLOC);
     972           0 :                         if (!rloc) return GF_OUT_OF_MEM;
     973           0 :                         rloc->horizontal_offset = image_props->hOffset;
     974           0 :                         rloc->vertical_offset = image_props->vOffset;
     975           0 :                         prop_index = gf_list_count(ipco->child_boxes) - 1;
     976             :                 }
     977           0 :                 e = meta_add_item_property_association(ipma, item_ID, prop_index + 1, GF_TRUE);
     978           0 :                 if (e) return e;
     979           0 :                 searchprop.hOffset = 0;
     980           0 :                 searchprop.vOffset = 0;
     981             :         }
     982         215 :         if (image_props->hSpacing || image_props->vSpacing) {
     983         206 :                 searchprop.hSpacing = image_props->hSpacing;
     984         206 :                 searchprop.vSpacing = image_props->vSpacing;
     985         206 :                 prop_index = meta_find_prop(ipco, &searchprop);
     986         206 :                 if (prop_index < 0) {
     987          87 :                         GF_PixelAspectRatioBox *pasp = (GF_PixelAspectRatioBox *)gf_isom_box_new_parent(&ipco->child_boxes, GF_ISOM_BOX_TYPE_PASP);
     988          87 :                         if (!pasp) return GF_OUT_OF_MEM;
     989          87 :                         pasp->hSpacing = image_props->hSpacing;
     990          87 :                         pasp->vSpacing = image_props->vSpacing;
     991          87 :                         prop_index = gf_list_count(ipco->child_boxes) - 1;
     992             :                 }
     993         206 :                 e = meta_add_item_property_association(ipma, item_ID, prop_index + 1, GF_FALSE);
     994         206 :                 if (e) return e;
     995         206 :                 searchprop.hSpacing = 0;
     996         206 :                 searchprop.vSpacing = 0;
     997             :         }
     998         215 :         if (image_props->angle) {
     999          12 :                 searchprop.angle = image_props->angle;
    1000          12 :                 prop_index = meta_find_prop(ipco, &searchprop);
    1001          12 :                 if (prop_index < 0) {
    1002          12 :                         GF_ImageRotationBox *irot = (GF_ImageRotationBox *)gf_isom_box_new_parent(&ipco->child_boxes, GF_ISOM_BOX_TYPE_IROT);
    1003          12 :                         if (!irot) return GF_OUT_OF_MEM;
    1004          12 :                         irot->angle = image_props->angle/90;
    1005          12 :                         prop_index = gf_list_count(ipco->child_boxes) - 1;
    1006             :                 }
    1007          12 :                 e = meta_add_item_property_association(ipma, item_ID, prop_index + 1, GF_TRUE);
    1008          12 :                 if (e) return e;
    1009          12 :                 searchprop.angle = 0;
    1010             :         }
    1011         215 :         if (image_props->mirror) {
    1012           9 :                 searchprop.mirror = image_props->mirror;
    1013           9 :                 prop_index = meta_find_prop(ipco, &searchprop);
    1014           9 :                 if (prop_index < 0) {
    1015           9 :                         GF_ImageMirrorBox *imir = (GF_ImageMirrorBox *)gf_isom_box_new_parent(&ipco->child_boxes, GF_ISOM_BOX_TYPE_IMIR);
    1016           9 :                         if (!imir) return GF_OUT_OF_MEM;
    1017           9 :                         imir->axis = image_props->mirror-1;
    1018           9 :                         prop_index = gf_list_count(ipco->child_boxes) - 1;
    1019             :                 }
    1020           9 :                 e = meta_add_item_property_association(ipma, item_ID, prop_index + 1, GF_TRUE);
    1021           9 :                 if (e) return e;
    1022           9 :                 searchprop.mirror = 0;
    1023             :         }
    1024         215 :         if (image_props->clap_wnum || image_props->clap_wden || image_props->clap_hnum || image_props->clap_hden || image_props->clap_honum || image_props->clap_hoden || image_props->clap_vonum || image_props->clap_voden) {
    1025          10 :                 searchprop.clap_wnum = image_props->clap_wnum;
    1026          10 :                 searchprop.clap_wden = image_props->clap_wden;
    1027          10 :                 searchprop.clap_hnum = image_props->clap_hnum;
    1028          10 :                 searchprop.clap_hden = image_props->clap_hden;
    1029          10 :                 searchprop.clap_honum = image_props->clap_honum;
    1030          10 :                 searchprop.clap_hoden = image_props->clap_hoden;
    1031          10 :                 searchprop.clap_vonum = image_props->clap_vonum;
    1032          10 :                 searchprop.clap_voden = image_props->clap_voden;
    1033          10 :                 prop_index = meta_find_prop(ipco, &searchprop);
    1034          10 :                 if (prop_index < 0) {
    1035          10 :                         GF_CleanApertureBox *clap = (GF_CleanApertureBox *)gf_isom_box_new_parent(&ipco->child_boxes, GF_ISOM_BOX_TYPE_CLAP);
    1036          10 :                         if (!clap) return GF_OUT_OF_MEM;
    1037          10 :                         clap->cleanApertureHeightD = image_props->clap_hden;
    1038          10 :                         clap->cleanApertureHeightN = image_props->clap_hnum;
    1039          10 :                         clap->cleanApertureWidthD = image_props->clap_wden;
    1040          10 :                         clap->cleanApertureWidthN = image_props->clap_wnum;
    1041          10 :                         clap->horizOffD = image_props->clap_hoden;
    1042          10 :                         clap->horizOffN = image_props->clap_honum;
    1043          10 :                         clap->vertOffD = image_props->clap_voden;
    1044          10 :                         clap->vertOffN = image_props->clap_vonum;
    1045          10 :                         prop_index = gf_list_count(ipco->child_boxes) - 1;
    1046             :                 }
    1047          10 :                 e = meta_add_item_property_association(ipma, item_ID, prop_index + 1, GF_TRUE);
    1048          10 :                 if (e) return e;
    1049          10 :                 searchprop.clap_wnum = searchprop.clap_wden = searchprop.clap_hnum = searchprop.clap_hden = searchprop.clap_honum = searchprop.clap_hoden = searchprop.clap_vonum = searchprop.clap_voden = 0;
    1050             :         }
    1051         215 :         if (image_props->config) {
    1052         203 :                 searchprop.config = image_props->config;
    1053         203 :                 prop_index = meta_find_prop(ipco, &searchprop);
    1054         203 :                 if (prop_index < 0) {
    1055          84 :                         gf_list_add(ipco->child_boxes, gf_isom_clone_config_box(image_props->config));
    1056          84 :                         prop_index = gf_list_count(ipco->child_boxes) - 1;
    1057             :                 }
    1058         203 :                 e = meta_add_item_property_association(ipma, item_ID, prop_index + 1, GF_TRUE);
    1059         203 :                 if (e) return e;
    1060         203 :                 searchprop.config = NULL;
    1061             :         }
    1062         215 :         if (image_props->alpha) {
    1063           1 :                 searchprop.alpha = image_props->alpha;
    1064           1 :                 prop_index = meta_find_prop(ipco, &searchprop);
    1065           1 :                 if (prop_index < 0) {
    1066           1 :                         GF_AuxiliaryTypePropertyBox *auxC = (GF_AuxiliaryTypePropertyBox *)gf_isom_box_new_parent(&ipco->child_boxes, GF_ISOM_BOX_TYPE_AUXC);
    1067           1 :                         if (!auxC) return GF_OUT_OF_MEM;
    1068           1 :                         auxC->aux_urn = gf_strdup("urn:mpeg:mpegB:cicp:systems:auxiliary:alpha");
    1069           1 :                         prop_index = gf_list_count(ipco->child_boxes) - 1;
    1070             :                 }
    1071           1 :                 e = meta_add_item_property_association(ipma, item_ID, prop_index + 1, GF_TRUE);
    1072           1 :                 if (e) return e;
    1073           1 :                 searchprop.alpha = GF_FALSE;
    1074             :         }
    1075         215 :         if (image_props->num_channels) {
    1076         203 :                 searchprop.num_channels = image_props->num_channels;
    1077             :                 memcpy(searchprop.bits_per_channel, image_props->bits_per_channel, 3);
    1078         203 :                 prop_index = meta_find_prop(ipco, &searchprop);
    1079         203 :                 if (prop_index < 0) {
    1080          84 :                         GF_PixelInformationPropertyBox *pixi = (GF_PixelInformationPropertyBox *)gf_isom_box_new_parent(&ipco->child_boxes, GF_ISOM_BOX_TYPE_PIXI);
    1081          84 :                         if (!pixi) return GF_OUT_OF_MEM;
    1082          84 :                         pixi->num_channels = image_props->num_channels;
    1083          84 :                         pixi->bits_per_channel = gf_malloc(pixi->num_channels);
    1084          84 :                         if (!pixi->bits_per_channel) return GF_OUT_OF_MEM;
    1085          84 :                         memcpy(pixi->bits_per_channel, image_props->bits_per_channel, image_props->num_channels);
    1086          84 :                         prop_index = gf_list_count(ipco->child_boxes) - 1;
    1087             :                 }
    1088         203 :                 e = meta_add_item_property_association(ipma, item_ID, prop_index + 1, GF_TRUE);
    1089         203 :                 if (e) return e;
    1090         203 :                 searchprop.num_channels = 0;
    1091             :         }
    1092             : 
    1093         215 :         if (image_props->cenc_info) {
    1094             :                 GF_ItemEncryptionPropertyBox *ienc = NULL;
    1095             : 
    1096          23 :                 if (!gf_cenc_validate_key_info(image_props->cenc_info->key_info, image_props->cenc_info->key_info_size))
    1097             :                         return GF_BAD_PARAM;
    1098             : 
    1099          23 :                 searchprop.cenc_info = image_props->cenc_info;
    1100             : 
    1101          23 :                 prop_index = meta_find_prop(ipco, &searchprop);
    1102          23 :                 if (prop_index < 0) {
    1103          23 :                         ienc = (GF_ItemEncryptionPropertyBox *)gf_isom_box_new_parent(&ipco->child_boxes, GF_ISOM_BOX_TYPE_IENC);
    1104          23 :                         if (!ienc) return GF_OUT_OF_MEM;
    1105          23 :                         ienc->skip_byte_block = image_props->cenc_info->skip_byte_block;
    1106          23 :                         ienc->crypt_byte_block = image_props->cenc_info->crypt_byte_block;
    1107          23 :                         ienc->key_info_size = image_props->cenc_info->key_info_size;
    1108          23 :                         ienc->key_info = gf_malloc(sizeof(u8) * image_props->cenc_info->key_info_size);
    1109          23 :                         if (!ienc->key_info) {
    1110           0 :                                 gf_free(ienc);
    1111           0 :                                 return GF_OUT_OF_MEM;
    1112             :                         }
    1113          23 :                         memcpy(ienc->key_info, image_props->cenc_info->key_info, image_props->cenc_info->key_info_size);
    1114          23 :                         prop_index = gf_list_count(ipco->child_boxes) - 1;
    1115             :                 }
    1116             : 
    1117             :                 //add property
    1118          23 :                 e = meta_add_item_property_association(ipma, item_ID, prop_index + 1, GF_TRUE);
    1119          23 :                 if (e) return e;
    1120             :                 searchprop.cenc_info = NULL;
    1121             :         }
    1122             : 
    1123             :         return GF_OK;
    1124             : }
    1125             : 
    1126             : GF_EXPORT
    1127          95 : GF_Err gf_isom_meta_get_next_item_id(GF_ISOFile *file, Bool root_meta, u32 track_num, u32 *item_id)
    1128             : {
    1129             :         GF_MetaBox *meta;
    1130             :         u32 lastItemID = 0;
    1131             : 
    1132          95 :         if (!file || !item_id) return GF_BAD_PARAM;
    1133          95 :         meta = gf_isom_get_meta(file, root_meta, track_num);
    1134          95 :         if (!meta) {
    1135           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Missing meta box"));
    1136             :                 return GF_BAD_PARAM;
    1137             :         }
    1138             : 
    1139          95 :         if (meta->item_infos) {
    1140             :                 u32 i;
    1141          47 :                 u32 item_count = gf_list_count(meta->item_infos->item_infos);
    1142         240 :                 for (i = 0; i < item_count; i++) {
    1143         193 :                         GF_ItemInfoEntryBox *e = (GF_ItemInfoEntryBox *)gf_list_get(meta->item_infos->item_infos, i);
    1144         193 :                         if (e->item_ID > lastItemID) lastItemID = e->item_ID;
    1145             :                 }
    1146          47 :                 *item_id = lastItemID+1;
    1147             :         }
    1148             :         else {
    1149          48 :                 *item_id = lastItemID + 1;
    1150             :         }
    1151          95 :         if (meta->groups_list) {
    1152             :                 u32 i;
    1153           0 :                 u32 groups_count = gf_list_count(meta->groups_list->child_boxes);
    1154           0 :                 for (i = 0; i < groups_count; i++) {
    1155           0 :                         GF_EntityToGroupTypeBox *g = (GF_EntityToGroupTypeBox *)gf_list_get(meta->groups_list->child_boxes, i);
    1156           0 :                         if (g->group_id > lastItemID) lastItemID = g->group_id;
    1157             :                 }
    1158           0 :                 *item_id = lastItemID+1;
    1159             :         }
    1160             :         return GF_OK;
    1161             : }
    1162             : 
    1163         244 : GF_Err gf_isom_add_meta_item_extended(GF_ISOFile *file, Bool root_meta, u32 track_num, Bool self_reference, char *resource_path,
    1164             :                                       const char *item_name, u32 *io_item_id, u32 item_type, const char *mime_type, const char *content_encoding,
    1165             :                                       GF_ImageItemProperties *image_props,
    1166             :                                       const char *URL, const char *URN,
    1167             :                                       char *data, u32 data_len, GF_List *item_extent_refs, u32 tk_id, u32 sample_num)
    1168             : {
    1169             :         u32 i;
    1170             :         GF_Err e;
    1171             :         GF_ItemLocationEntry *location_entry;
    1172             :         GF_ItemInfoEntryBox *infe;
    1173             :         GF_MetaBox *meta;
    1174             :         u32 lastItemID = 0;
    1175         244 :         u32 item_id = io_item_id ? *io_item_id : 0;
    1176             : 
    1177         244 :         if (!self_reference && !resource_path && !data && !tk_id && !item_extent_refs) return GF_BAD_PARAM;
    1178         244 :         e = CanAccessMovie(file, GF_ISOM_OPEN_WRITE);
    1179         244 :         if (e) return e;
    1180         244 :         meta = gf_isom_get_meta(file, root_meta, track_num);
    1181         244 :         if (!meta) {
    1182           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Trying to add item, but missing meta box"));
    1183             :                 return GF_BAD_PARAM;
    1184             :         }
    1185             : 
    1186         244 :         e = FlushCaptureMode(file);
    1187         244 :         if (e) return e;
    1188             : 
    1189             :         /*check file exists */
    1190         244 :         if (resource_path) {
    1191           5 :                 FILE *src = gf_fopen(resource_path, "rb");
    1192           5 :                 if (!src) return GF_URL_ERROR;
    1193           5 :                 gf_fclose(src);
    1194             :         }
    1195             : 
    1196         244 :         if (meta->item_infos) {
    1197         155 :                 u32 item_count = gf_list_count(meta->item_infos->item_infos);
    1198         988 :                 for (i = 0; i < item_count; i++) {
    1199         833 :                         GF_ItemInfoEntryBox *iinf_e= (GF_ItemInfoEntryBox *)gf_list_get(meta->item_infos->item_infos, i);
    1200         833 :                         if (iinf_e->item_ID > lastItemID) lastItemID = iinf_e->item_ID;
    1201         833 :                         if (item_id == iinf_e->item_ID) {
    1202          29 :                                 GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("[IsoMedia] Item with id %d already exists, ignoring id\n", item_id));
    1203             :                                 item_id = 0;
    1204             :                         }
    1205             :                 }
    1206             :         } else {
    1207          89 :                 meta->item_infos = (GF_ItemInfoBox *)gf_isom_box_new_parent(&meta->child_boxes, GF_ISOM_BOX_TYPE_IINF);
    1208             :         }
    1209             : 
    1210             :         /*Creation an ItemLocation Box if it does not exist*/
    1211         244 :         if (!meta->item_locations)
    1212          89 :                 meta->item_locations = (GF_ItemLocationBox *)gf_isom_box_new_parent(&meta->child_boxes, GF_ISOM_BOX_TYPE_ILOC);
    1213             : 
    1214         244 :         infe = (GF_ItemInfoEntryBox *)gf_isom_box_new_parent(&meta->item_infos->child_boxes, GF_ISOM_BOX_TYPE_INFE);
    1215         244 :         if (!infe) return GF_OUT_OF_MEM;
    1216             : 
    1217         244 :         if (item_id) {
    1218         213 :                 infe->item_ID = item_id;
    1219             :         } else {
    1220          31 :                 infe->item_ID = ++lastItemID;
    1221             :         }
    1222         244 :         if (io_item_id) *io_item_id = infe->item_ID;
    1223             :         
    1224         244 :         if (tk_id && sample_num) {
    1225           1 :                 data_len = gf_isom_get_sample_size(file, tk_id, sample_num);
    1226             :         }
    1227             :         /*get relative name*/
    1228         243 :         else if (item_name) {
    1229         207 :                 infe->item_name = gf_strdup(item_name);
    1230         207 :                 file->no_inplace_rewrite = GF_TRUE;
    1231          36 :         } else if (resource_path) {
    1232           4 :                 infe->item_name = gf_strdup(gf_file_basename( resource_path ));
    1233           4 :                 file->no_inplace_rewrite = GF_TRUE;
    1234             :         }
    1235             : 
    1236         244 :         infe->item_type = item_type;
    1237             : 
    1238         244 :         if (mime_type) {
    1239           6 :                 infe->content_type = gf_strdup(mime_type);
    1240             :         } else {
    1241         238 :                 infe->content_type = gf_strdup("application/octet-stream");
    1242             :         }
    1243         244 :         if (content_encoding) infe->content_encoding = gf_strdup(content_encoding);
    1244             : 
    1245             :         /*Creation of the ItemLocation */
    1246         244 :         location_entry = (GF_ItemLocationEntry*)gf_malloc(sizeof(GF_ItemLocationEntry));
    1247         244 :         if (!location_entry) {
    1248           0 :                 gf_isom_box_del_parent(&meta->item_infos->child_boxes, (GF_Box *)infe);
    1249           0 :                 return GF_OUT_OF_MEM;
    1250             :         }
    1251             :         memset(location_entry, 0, sizeof(GF_ItemLocationEntry));
    1252         244 :         location_entry->extent_entries = gf_list_new();
    1253             : 
    1254             :         /*Creates an mdat if it does not exist*/
    1255         244 :         if (!file->mdat) {
    1256           0 :                 file->mdat = (GF_MediaDataBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_MDAT);
    1257           0 :                 if (!file->mdat) return GF_OUT_OF_MEM;
    1258           0 :                 gf_list_add(file->TopBoxes, file->mdat);
    1259             :         }
    1260             : 
    1261         244 :         gf_list_add(meta->item_locations->location_entries, location_entry);
    1262         244 :         location_entry->item_ID = infe->item_ID;
    1263             : 
    1264         244 :         e = gf_list_add(meta->item_infos->item_infos, infe);
    1265         244 :         if (e) return e;
    1266             : 
    1267         244 :         if (image_props) {
    1268         215 :                 if (image_props->hidden) {
    1269           2 :                         infe->flags = 0x1;
    1270             :                 }
    1271         215 :                 e = meta_process_image_properties(meta, infe->item_ID, image_props);
    1272         215 :                 if (e) return e;
    1273             : 
    1274         215 :                 if (image_props->cenc_info) {
    1275             :                         GF_ProtectionSchemeInfoBox *sinf;
    1276          23 :                         u32 cenc_item_id = infe->item_ID + 1;
    1277             : 
    1278             :                         //create a new auxi item
    1279          23 :                         e = gf_isom_add_meta_item_memory(file, root_meta, track_num, NULL, &cenc_item_id, GF_ISOM_ITEM_TYPE_AUXI, NULL, NULL, NULL, (u8 *) image_props->cenc_info->sai_data, image_props->cenc_info->sai_data_size, NULL);
    1280          23 :                         if (e) return e;
    1281             :                         //add item reference
    1282          23 :                         e = gf_isom_meta_add_item_ref(file, root_meta, track_num, infe->item_ID, cenc_item_id, GF_ISOM_REF_AUXR, NULL);
    1283          23 :                         if (e) return e;
    1284             : 
    1285             :                         //multikey, we MUST have a 'iaux' prop with aux_info_type_param=1 associated
    1286          23 :                         if (image_props->cenc_info->key_info[0]) {
    1287           3 :                                 GF_ItemPropertyContainerBox *ipco = meta->item_props->property_container;
    1288           3 :                                 GF_ItemPropertyAssociationBox *ipma = meta->item_props->property_association;
    1289           3 :                                 u32 k, pcount = gf_list_count(ipco->child_boxes);
    1290             :                                 s32 prop_index = -1;
    1291          18 :                                 for (k=0; k<pcount; k++) {
    1292          15 :                                         GF_AuxiliaryInfoPropertyBox *b = (GF_AuxiliaryInfoPropertyBox*)gf_list_get(ipco->child_boxes, k);
    1293          15 :                                         if (b->type != GF_ISOM_BOX_TYPE_IAUX) continue;
    1294           0 :                                         switch (b->aux_info_type) {
    1295             :                                         case GF_ISOM_CENC_SCHEME:
    1296             :                                         case GF_ISOM_CENS_SCHEME:
    1297             :                                         case GF_ISOM_CBC_SCHEME:
    1298             :                                         case GF_ISOM_CBCS_SCHEME:
    1299             :                                         case 0:
    1300             :                                                 break;
    1301           0 :                                         default:
    1302           0 :                                                 continue;
    1303             :                                         }
    1304           0 :                                         if (b->aux_info_parameter!=1) continue;
    1305           0 :                                         prop_index = k;
    1306           0 :                                         break;
    1307             :                                 }
    1308             : 
    1309           3 :                                 if (prop_index < 0) {
    1310           3 :                                         GF_AuxiliaryInfoPropertyBox *iaux = (GF_AuxiliaryInfoPropertyBox *)gf_isom_box_new_parent(&ipco->child_boxes, GF_ISOM_BOX_TYPE_IAUX);
    1311           3 :                                         if (!iaux) return GF_OUT_OF_MEM;
    1312           3 :                                         iaux->aux_info_parameter = 1;
    1313           3 :                                         prop_index = gf_list_count(ipco->child_boxes) - 1;
    1314             :                                 }
    1315             : 
    1316             :                                 //add property
    1317           3 :                                 e = meta_add_item_property_association(ipma, cenc_item_id, prop_index + 1, GF_TRUE);
    1318           3 :                                 if (e) return e;
    1319             :                         }
    1320             : 
    1321             :                         //look for scheme in ipro
    1322          23 :                         if (!meta->protections) {
    1323          23 :                                 meta->protections = (GF_ItemProtectionBox *) gf_isom_box_new_parent(&meta->child_boxes, GF_ISOM_BOX_TYPE_IPRO);
    1324          23 :                                 if (!meta->protections) return GF_OUT_OF_MEM;
    1325             :                         }
    1326             :                         sinf = NULL;
    1327           0 :                         for (i=0; i<gf_list_count(meta->protections->protection_information); i++) {
    1328           0 :                                 sinf = gf_list_get(meta->protections->protection_information, i);
    1329           0 :                                 if (sinf->scheme_type && (sinf->scheme_type->scheme_type==image_props->cenc_info->scheme_type)
    1330           0 :                                         && (sinf->scheme_type->scheme_version==image_props->cenc_info->scheme_version))
    1331             :                                         break;
    1332             :                                 sinf = NULL;
    1333             :                         }
    1334          23 :                         if (!sinf) {
    1335          23 :                                 sinf = (GF_ProtectionSchemeInfoBox *)gf_isom_box_new_parent(&meta->protections->child_boxes, GF_ISOM_BOX_TYPE_SINF);
    1336          23 :                                 if (!sinf) return GF_OUT_OF_MEM;
    1337          23 :                                 gf_list_add(meta->protections->protection_information, sinf);
    1338          23 :                                 sinf->scheme_type = (GF_SchemeTypeBox *)gf_isom_box_new_parent(&sinf->child_boxes, GF_ISOM_BOX_TYPE_SCHM);
    1339          23 :                                 if (!sinf->scheme_type) return GF_OUT_OF_MEM;
    1340          23 :                                 sinf->scheme_type->scheme_type = image_props->cenc_info->scheme_type;
    1341          23 :                                 sinf->scheme_type->scheme_version = image_props->cenc_info->scheme_version;
    1342             :                         }
    1343          23 :                         infe->item_protection_index = 1 + gf_list_find(meta->protections->protection_information, sinf);
    1344             :                 }
    1345             :         }
    1346             : 
    1347             :         /*0: the current file*/
    1348         244 :         location_entry->data_reference_index = 0;
    1349         244 :         if (self_reference) {
    1350             :                 GF_ItemExtentEntry *entry;
    1351           0 :                 GF_SAFEALLOC(entry, GF_ItemExtentEntry);
    1352           0 :                 if (!entry) return GF_OUT_OF_MEM;
    1353           0 :                 gf_list_add(location_entry->extent_entries, entry);
    1354           0 :                 if (!infe->item_name) infe->item_name = gf_strdup("");
    1355             :                 return GF_OK;
    1356             :         }
    1357             : 
    1358             :         /*file not copied, just referenced*/
    1359         244 :         if (URL || URN) {
    1360             :                 u32 dataRefIndex;
    1361           0 :                 if (!meta->file_locations) {
    1362           0 :                         meta->file_locations = (GF_DataInformationBox *) gf_isom_box_new_parent(&meta->child_boxes, GF_ISOM_BOX_TYPE_DINF);
    1363           0 :                         if (!meta->file_locations) return GF_OUT_OF_MEM;
    1364             :                 }
    1365           0 :                 if (!meta->file_locations->dref) {
    1366           0 :                         meta->file_locations->dref = (GF_DataReferenceBox *) gf_isom_box_new_parent(&meta->file_locations->child_boxes, GF_ISOM_BOX_TYPE_DREF);
    1367           0 :                         if (!meta->file_locations->dref) return GF_OUT_OF_MEM;
    1368             :                 }
    1369             : 
    1370           0 :                 e = Media_FindDataRef(meta->file_locations->dref, (char *) URL, (char *) URN, &dataRefIndex);
    1371           0 :                 if (e) return e;
    1372           0 :                 if (!dataRefIndex) {
    1373           0 :                         e = Media_CreateDataRef(file, meta->file_locations->dref, (char *) URL, (char *) URN, &dataRefIndex);
    1374           0 :                         if (e) return e;
    1375             :                 }
    1376           0 :                 location_entry->data_reference_index = dataRefIndex;
    1377             :         }
    1378             : 
    1379         244 :         if (item_extent_refs && gf_list_count(item_extent_refs)) {
    1380             :                 u32 refs_count;
    1381           1 :                 location_entry->construction_method = 2;
    1382           1 :                 meta->item_locations->index_size = 4;
    1383           1 :                 refs_count = gf_list_count(item_extent_refs);
    1384          10 :                 for (i = 0; i < refs_count; i++) {
    1385             :                         u32 *item_index;
    1386             :                         GF_ItemExtentEntry *entry;
    1387           9 :                         GF_SAFEALLOC(entry, GF_ItemExtentEntry);
    1388           9 :                         if (!entry) return GF_OUT_OF_MEM;
    1389           9 :                         gf_list_add(location_entry->extent_entries, entry);
    1390           9 :                         item_index = (u32 *)gf_list_get(item_extent_refs, i);
    1391           9 :                         gf_isom_meta_add_item_ref(file, root_meta, track_num, infe->item_ID, *item_index, GF_ISOM_REF_ILOC, &(entry->extent_index));
    1392             :                 }
    1393             :         }
    1394         243 :         else if (tk_id && sample_num) {
    1395           1 :                 if ((file->openMode == GF_ISOM_OPEN_WRITE) || (file->openMode == GF_ISOM_OPEN_EDIT)) {
    1396             :                         GF_ItemExtentEntry *entry;
    1397           1 :                         GF_SAFEALLOC(entry, GF_ItemExtentEntry);
    1398           1 :                         if (!entry) return GF_OUT_OF_MEM;
    1399             : 
    1400           1 :                         entry->extent_length = data_len;
    1401           1 :                         location_entry->base_offset = 0;
    1402           1 :                         GF_ISOSample *samp = gf_isom_get_sample_info(file, tk_id, sample_num, NULL, &entry->extent_offset);
    1403           1 :                         if (samp) gf_isom_sample_del(&samp);
    1404           1 :                         gf_list_add(location_entry->extent_entries, entry);
    1405             : 
    1406             :                         if (data_len>0xFFFFFFFF) meta->item_locations->length_size = 8;
    1407           1 :                         else if (! meta->item_locations->base_offset_size) meta->item_locations->length_size = 4;
    1408             : 
    1409             :                         //for in-place rewrite + add-image
    1410           1 :                         if (file->openMode == GF_ISOM_OPEN_EDIT) {
    1411           1 :                                 location_entry->base_offset = 0;
    1412           1 :                                 infe->tk_id = tk_id;
    1413           1 :                                 infe->sample_num = sample_num;
    1414           1 :                                 infe->data_len = data_len;
    1415             :                         }
    1416             :                 } else {
    1417           0 :                         infe->tk_id = tk_id;
    1418           0 :                         infe->sample_num = sample_num;
    1419           0 :                         infe->data_len = data_len;
    1420           0 :                         file->no_inplace_rewrite = GF_TRUE;
    1421             :                 }
    1422           1 :                 meta->use_item_sample_sharing = GF_TRUE;
    1423             :         }
    1424             :         else {
    1425             :                 /*capture mode, write to disk*/
    1426         242 :                 if ((file->openMode == GF_ISOM_OPEN_WRITE) && !location_entry->data_reference_index) {
    1427             :                         FILE *src;
    1428             :                         GF_ItemExtentEntry *entry;
    1429           0 :                         GF_SAFEALLOC(entry, GF_ItemExtentEntry);
    1430           0 :                         if (!entry) return GF_OUT_OF_MEM;
    1431             : 
    1432           0 :                         location_entry->base_offset = gf_bs_get_position(file->editFileMap->bs);
    1433             : 
    1434             :                         /*update base offset size*/
    1435           0 :                         if (location_entry->base_offset > 0xFFFFFFFF) meta->item_locations->base_offset_size = 8;
    1436           0 :                         else if (location_entry->base_offset && !meta->item_locations->base_offset_size) meta->item_locations->base_offset_size = 4;
    1437             : 
    1438           0 :                         entry->extent_length = 0;
    1439           0 :                         entry->extent_offset = 0;
    1440           0 :                         gf_list_add(location_entry->extent_entries, entry);
    1441             : 
    1442           0 :                         if (data) {
    1443           0 :                                 gf_bs_write_data(file->editFileMap->bs, data, data_len);
    1444             :                                 /*update length size*/
    1445           0 :                                 if (entry->extent_length > 0xFFFFFFFF) meta->item_locations->length_size = 8;
    1446           0 :                                 else if (entry->extent_length && !meta->item_locations->length_size) meta->item_locations->length_size = 4;
    1447             :                         }
    1448           0 :                         else if (resource_path) {
    1449           0 :                                 src = gf_fopen(resource_path, "rb");
    1450           0 :                                 if (src) {
    1451             :                                         char cache_data[4096];
    1452             :                                         u64 remain;
    1453           0 :                                         entry->extent_length = gf_fsize(src);
    1454             : 
    1455             :                                         remain = entry->extent_length;
    1456           0 :                                         while (remain) {
    1457           0 :                                                 u32 size_cache = (remain > 4096) ? 4096 : (u32)remain;
    1458           0 :                                                 size_t read = gf_fread(cache_data, size_cache, src);
    1459           0 :                                                 if (read == (size_t)-1) break;
    1460           0 :                                                 gf_bs_write_data(file->editFileMap->bs, cache_data, (u32)read);
    1461           0 :                                                 remain -= (u32)read;
    1462             :                                         }
    1463           0 :                                         gf_fclose(src);
    1464             : 
    1465             :                                         /*update length size*/
    1466           0 :                                         if (entry->extent_length > 0xFFFFFFFF) meta->item_locations->length_size = 8;
    1467           0 :                                         else if (entry->extent_length && !meta->item_locations->length_size) meta->item_locations->length_size = 4;
    1468             :                                 }
    1469             :                         }
    1470             :                 }
    1471             :                 /*store full path for info*/
    1472         242 :                 else if (!location_entry->data_reference_index) {
    1473         242 :                         if (data) {
    1474         237 :                                 infe->full_path = (char *)gf_malloc(sizeof(char) * data_len);
    1475         237 :                                 if (!infe->full_path) return GF_OUT_OF_MEM;
    1476             :                                 
    1477             :                                 memcpy(infe->full_path, data, sizeof(char) * data_len);
    1478         237 :                                 infe->data_len = data_len;
    1479             :                         }
    1480             :                         else {
    1481           5 :                                 infe->full_path = gf_strdup(resource_path);
    1482           5 :                                 infe->data_len = 0;
    1483             :                         }
    1484             :                 }
    1485             :         }
    1486             :         return GF_OK;
    1487             : }
    1488             : 
    1489             : GF_EXPORT
    1490           5 : GF_Err gf_isom_add_meta_item(GF_ISOFile *file, Bool root_meta, u32 track_num, Bool self_reference, char *resource_path, const char *item_name, u32 item_id, u32 item_type,
    1491             :                              const char *mime_type, const char *content_encoding, const char *URL, const char *URN,
    1492             :                              GF_ImageItemProperties *image_props)
    1493             : {
    1494           5 :         return gf_isom_add_meta_item_extended(file, root_meta, track_num, self_reference, resource_path, item_name, &item_id, item_type, mime_type, content_encoding, image_props, URL, URN, NULL, 0, NULL, 0, 0);
    1495             : }
    1496             : 
    1497             : GF_EXPORT
    1498         238 : GF_Err gf_isom_add_meta_item_memory(GF_ISOFile *file, Bool root_meta, u32 track_num, const char *item_name, u32 *item_id, u32 item_type, const char *mime_type, const char *content_encoding, GF_ImageItemProperties *image_props, char *data, u32 data_len, GF_List *item_extent_refs)
    1499             : {
    1500         238 :         return gf_isom_add_meta_item_extended(file, root_meta, track_num, GF_FALSE, NULL, item_name, item_id, item_type, mime_type, content_encoding, image_props, NULL, NULL, data, data_len, item_extent_refs, 0, 0);
    1501             : }
    1502             : 
    1503             : GF_EXPORT
    1504           1 : GF_Err gf_isom_add_meta_item_sample_ref(GF_ISOFile *file, Bool root_meta, u32 track_num, const char *item_name, u32 *item_id, u32 item_type, const char *mime_type, const char *content_encoding, GF_ImageItemProperties *image_props, u32 tk_id, u32 sample_len)
    1505             : {
    1506           1 :         return gf_isom_add_meta_item_extended(file, root_meta, track_num, GF_FALSE, NULL, item_name, item_id, item_type, mime_type, content_encoding, image_props, NULL, NULL, NULL, 0, NULL, tk_id, sample_len);
    1507             : }
    1508             : 
    1509             : GF_EXPORT
    1510           4 : GF_Err gf_isom_remove_meta_item(GF_ISOFile *file, Bool root_meta, u32 track_num, u32 item_id)
    1511             : {
    1512             :         GF_ItemInfoEntryBox *iinf;
    1513             :         u32 i, count;
    1514           4 :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
    1515             :         u32 item_num;
    1516           4 :         if (!meta || !meta->item_infos || !meta->item_locations) return GF_BAD_PARAM;
    1517             : 
    1518           4 :         item_num = gf_isom_get_meta_item_by_id(file, root_meta, track_num, item_id);
    1519           4 :         if (!item_num) return GF_BAD_PARAM;
    1520           4 :         iinf = (GF_ItemInfoEntryBox *)gf_list_get(meta->item_infos->item_infos, item_num-1);
    1521           4 :         gf_list_rem(meta->item_infos->item_infos, item_num-1);
    1522             : 
    1523           4 :         count = gf_list_count(meta->item_locations->location_entries);
    1524           4 :         for (i=0; i<count; i++) {
    1525           4 :                 GF_ItemLocationEntry *iloc = (GF_ItemLocationEntry *)gf_list_get(meta->item_locations->location_entries, i);
    1526           4 :                 if (iloc->item_ID==iinf->item_ID) {
    1527             :                         /*FIXME: remove data ref...*/
    1528             :                         if (iloc->data_reference_index) { }
    1529             : 
    1530           4 :                         gf_list_rem(meta->item_locations->location_entries, i);
    1531           4 :                         iloc_entry_del(iloc);
    1532           4 :                         break;
    1533             :                 }
    1534             :         }
    1535           4 :         gf_isom_box_del_parent(&meta->item_infos->child_boxes, (GF_Box *)iinf);
    1536           4 :         return GF_OK;
    1537             : }
    1538             : 
    1539             : GF_EXPORT
    1540          60 : GF_Err gf_isom_set_meta_primary_item(GF_ISOFile *file, Bool root_meta, u32 track_num, u32 item_id)
    1541             : {
    1542          60 :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
    1543          60 :         if (!meta || !meta->item_infos || !meta->item_locations) return GF_BAD_PARAM;
    1544             :         /*either one or the other*/
    1545          60 :         if (gf_isom_has_meta_xml(file, root_meta, track_num)) return GF_BAD_PARAM;
    1546             : 
    1547          60 :         if (meta->primary_resource) gf_isom_box_del_parent(&meta->child_boxes, (GF_Box*)meta->primary_resource);
    1548          60 :         meta->primary_resource = (GF_PrimaryItemBox*) gf_isom_box_new_parent(&meta->child_boxes, GF_ISOM_BOX_TYPE_PITM);
    1549          60 :         if (!meta->primary_resource) return GF_OUT_OF_MEM;
    1550          60 :         meta->primary_resource->item_ID = item_id;
    1551          60 :         return GF_OK;
    1552             : }
    1553             : 
    1554             : 
    1555             : #endif  /*GPAC_DISABLE_ISOM_WRITE*/
    1556             : 
    1557             : GF_EXPORT
    1558          90 : GF_Err gf_isom_meta_add_item_ref(GF_ISOFile *file, Bool root_meta, u32 track_num, u32 from_id, u32 to_id, u32 type, u64 *ref_index)
    1559             : {
    1560             :         u32 i, count;
    1561             :         s32 index = -1;
    1562             :         GF_ItemReferenceTypeBox *ref;
    1563          90 :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
    1564          90 :         if (!meta) return GF_BAD_PARAM;
    1565          90 :         if (!meta->item_refs) {
    1566          34 :                 meta->item_refs = (GF_ItemReferenceBox *)gf_isom_box_new_parent(&meta->child_boxes, GF_ISOM_BOX_TYPE_IREF);
    1567          34 :                 if (!meta->item_refs) return GF_OUT_OF_MEM;
    1568             :         }
    1569          90 :         count = gf_list_count(meta->item_refs->references);
    1570         207 :         for (i = 0; i < count; i++) {
    1571         164 :                 ref = (GF_ItemReferenceTypeBox *)gf_list_get(meta->item_refs->references, i);
    1572         164 :                 if (ref->from_item_id == from_id && ref->reference_type == type) {
    1573          47 :                         index = i;
    1574          47 :                         break;
    1575             :                 }
    1576             :         }
    1577          90 :         if (index < 0) {
    1578          43 :                 ref = (GF_ItemReferenceTypeBox *)gf_isom_box_new_parent(&meta->item_refs->child_boxes, GF_ISOM_BOX_TYPE_REFI);
    1579          43 :                 if (!ref) return GF_OUT_OF_MEM;
    1580          43 :                 gf_list_add(meta->item_refs->references, ref);
    1581          43 :                 ref->reference_type = type;
    1582          43 :                 ref->from_item_id = from_id;
    1583             :         }
    1584             :         else {
    1585         148 :                 for (i = 0; i < ref->reference_count; i++) {
    1586         148 :                         if (ref->to_item_IDs[i] == to_id) {
    1587             :                                 return GF_OK;
    1588             :                         }
    1589             :                 }
    1590             :         }
    1591             : 
    1592          90 :         ref->to_item_IDs = (u32 *)gf_realloc(ref->to_item_IDs, (ref->reference_count + 1) * sizeof(u32));
    1593          90 :         if (!ref->to_item_IDs) return GF_OUT_OF_MEM;
    1594          90 :         ref->to_item_IDs[ref->reference_count] = to_id;
    1595          90 :         ref->reference_count++;
    1596          90 :         if (ref_index) {
    1597           9 :                 *ref_index = ref->reference_count;
    1598             :         }
    1599             :         return GF_OK;
    1600             : 
    1601             : }
    1602             : 
    1603          17 : void gf_isom_meta_restore_items_ref(GF_ISOFile *movie, GF_MetaBox *meta)
    1604             : {
    1605             :         u32 i, nb_items, nb_tracks;
    1606          17 :         if (!meta->item_locations || !meta->item_infos) return;
    1607          15 :         nb_tracks = gf_list_count(movie->moov->trackList);
    1608          15 :         nb_items = gf_list_count(meta->item_locations->location_entries);
    1609          46 :         for (i=0; i<nb_items; i++) {
    1610             :                 u32 j;
    1611             :                 u64 item_offset;
    1612             :                 GF_ItemExtentEntry *entry;
    1613          31 :                 GF_ItemLocationEntry *iloc = (GF_ItemLocationEntry *)gf_list_get(meta->item_locations->location_entries, i);
    1614             :                 /*get item info*/
    1615             :                 GF_ItemInfoEntryBox *iinf = NULL;
    1616          31 :                 j=0;
    1617         102 :                 while ((iinf = (GF_ItemInfoEntryBox *)gf_list_enum(meta->item_infos->item_infos, &j))) {
    1618          71 :                         if (iinf->item_ID==iloc->item_ID) break;
    1619             :                         iinf = NULL;
    1620             :                 }
    1621          31 :                 if (!iinf) continue;
    1622          31 :                 if (gf_list_count(iloc->extent_entries) != 1) continue;
    1623          31 :                 entry = (GF_ItemExtentEntry *)gf_list_get(iloc->extent_entries, 0);
    1624          31 :                 if (!entry) continue;
    1625          31 :                 item_offset = iloc->base_offset + entry->extent_offset;
    1626             : 
    1627          61 :                 for (j=0;j<nb_tracks; j++) {
    1628             :                         GF_TrackBox *trak;
    1629             :                         GF_SampleSizeBox *stsz;
    1630             :                         u32 k;
    1631          31 :                         trak = gf_list_get(movie->moov->trackList, j);
    1632          31 :                         if (! gf_isom_is_video_handler_type(trak->Media->handler->handlerType))
    1633           0 :                                 continue;
    1634             : 
    1635          31 :                         stsz = trak->Media->information->sampleTable->SampleSize;
    1636          31 :                         if (stsz->sampleSize) continue;
    1637          31 :                         if (!stsz->sampleCount) continue;
    1638        7722 :                         for (k=0; k<stsz->sampleCount; k++) {
    1639             :                                 GF_Err e;
    1640             :                                 u32 chunk, di;
    1641             :                                 u64 samp_offset;
    1642        7723 :                                 if (stsz->sizes[k] != entry->extent_length)
    1643       15444 :                                         continue;
    1644             : 
    1645           1 :                                 e = stbl_GetSampleInfos(trak->Media->information->sampleTable, k+1, &samp_offset, &chunk, &di, NULL);
    1646           1 :                                 if (e) continue;
    1647           1 :                                 if (samp_offset == item_offset) {
    1648           1 :                                         iinf->tk_id = trak->Header->trackID;
    1649           1 :                                         iinf->sample_num = k+1;
    1650           1 :                                         iinf->data_len = (u32) entry->extent_length;
    1651           1 :                                         meta->use_item_sample_sharing = GF_TRUE;
    1652           1 :                                         break;
    1653             :                                 }
    1654             :                         }
    1655          31 :                         if (iinf->tk_id) break;
    1656             :                 }
    1657             :         }
    1658             : 
    1659             : }
    1660             : 
    1661             : GF_EXPORT
    1662           0 : GF_Err gf_isom_meta_add_item_group(GF_ISOFile *file, Bool root_meta, u32 track_num, u32 item_id, u32 group_id, u32 group_type)
    1663             : {
    1664             :         u32 i, count;
    1665             :         GF_EntityToGroupTypeBox *group;
    1666             :         s32 index = -1;
    1667           0 :         GF_MetaBox *meta = gf_isom_get_meta(file, root_meta, track_num);
    1668           0 :         if (!meta) return GF_BAD_PARAM;
    1669           0 :         if (!group_type) return GF_BAD_PARAM;
    1670           0 :         if (!group_id) {
    1671           0 :                 GF_Err e = gf_isom_meta_get_next_item_id(file, root_meta, track_num, &group_id);
    1672           0 :                 if (e != GF_OK) return e;
    1673             :         }
    1674           0 :         if (!meta->groups_list) {
    1675           0 :                 meta->groups_list = (GF_GroupListBox *)gf_isom_box_new_parent(&meta->child_boxes, GF_ISOM_BOX_TYPE_GRPL);
    1676           0 :                 if (!meta->groups_list) return GF_OUT_OF_MEM;
    1677           0 :                 meta->groups_list->child_boxes = gf_list_new();
    1678           0 :                 if (!meta->groups_list->child_boxes) return GF_OUT_OF_MEM;
    1679             :         }
    1680           0 :         count = gf_list_count(meta->groups_list->child_boxes);
    1681           0 :         for (i = 0; i < count; i++) {
    1682           0 :                 group = (GF_EntityToGroupTypeBox *)gf_list_get(meta->groups_list->child_boxes, i);
    1683           0 :                 if (group->grouping_type == group_type && group->group_id == group_id) {
    1684           0 :                         index = i;
    1685           0 :                         break;
    1686             :                 }
    1687             :         }
    1688           0 :         if (index < 0) {
    1689           0 :                 group = (GF_EntityToGroupTypeBox *)gf_isom_box_new_parent(&meta->groups_list->child_boxes, GF_ISOM_BOX_TYPE_GRPT);
    1690           0 :                 if (!group) return GF_OUT_OF_MEM;
    1691           0 :                 group->grouping_type = group_type;
    1692           0 :                 group->group_id = group_id;
    1693           0 :                 group->entity_ids = NULL;
    1694           0 :                 group->entity_id_count = 0;
    1695             :         } else {
    1696           0 :                 group = (GF_EntityToGroupTypeBox *)gf_list_get(meta->groups_list->child_boxes, index);
    1697             :         }
    1698             : 
    1699           0 :         group->entity_ids = (u32 *)gf_realloc(group->entity_ids, (group->entity_id_count + 1) * sizeof(u32));
    1700           0 :         if (!group->entity_ids) return GF_OUT_OF_MEM;
    1701           0 :         group->entity_ids[group->entity_id_count] = item_id;
    1702           0 :         group->entity_id_count++;
    1703             : 
    1704           0 :         return GF_OK;
    1705             : }
    1706             : 
    1707             : #endif /*GPAC_DISABLE_ISOM*/

Generated by: LCOV version 1.13