LCOV - code coverage report
Current view: top level - isomedia - iff.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 740 823 89.9 %
Date: 2021-04-29 23:48:07 Functions: 100 101 99.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Cyril Concolato
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2021
       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             : #include <gpac/internal/isomedia_dev.h>
      27             : #include <gpac/constants.h>
      28             : #include <gpac/media_tools.h>
      29             : 
      30             : #ifndef GPAC_DISABLE_ISOM
      31             : 
      32         160 : GF_Box *ispe_box_new()
      33             : {
      34         320 :         ISOM_DECL_BOX_ALLOC(GF_ImageSpatialExtentsPropertyBox, GF_ISOM_BOX_TYPE_ISPE);
      35         160 :         return (GF_Box *)tmp;
      36             : }
      37             : 
      38         160 : void ispe_box_del(GF_Box *a)
      39             : {
      40             :         GF_ImageSpatialExtentsPropertyBox *p = (GF_ImageSpatialExtentsPropertyBox *)a;
      41         160 :         gf_free(p);
      42         160 : }
      43             : 
      44          58 : GF_Err ispe_box_read(GF_Box *s, GF_BitStream *bs)
      45             : {
      46             :         GF_ImageSpatialExtentsPropertyBox *p = (GF_ImageSpatialExtentsPropertyBox *)s;
      47             : 
      48          58 :         if (p->version == 0 && p->flags == 0) {
      49          58 :                 p->image_width = gf_bs_read_u32(bs);
      50          58 :                 p->image_height = gf_bs_read_u32(bs);
      51          58 :                 return GF_OK;
      52             :         } else {
      53           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("version and flags for ispe box not supported" ));
      54           0 :                 gf_bs_skip_bytes(bs, p->size);
      55           0 :                 return GF_NOT_SUPPORTED;
      56             :         }
      57             : }
      58             : 
      59             : #ifndef GPAC_DISABLE_ISOM_WRITE
      60         102 : GF_Err ispe_box_write(GF_Box *s, GF_BitStream *bs)
      61             : {
      62             :         GF_Err e;
      63             :         GF_ImageSpatialExtentsPropertyBox *p = (GF_ImageSpatialExtentsPropertyBox*)s;
      64             : 
      65         102 :         p->version = 0;
      66         102 :         p->flags = 0;
      67         102 :         e = gf_isom_full_box_write(s, bs);
      68         102 :         if (e) return e;
      69         102 :         gf_bs_write_u32(bs, p->image_width);
      70         102 :         gf_bs_write_u32(bs, p->image_height);
      71         102 :         return GF_OK;
      72             : }
      73             : 
      74         308 : GF_Err ispe_box_size(GF_Box *s)
      75             : {
      76             :         GF_ImageSpatialExtentsPropertyBox *p = (GF_ImageSpatialExtentsPropertyBox*)s;
      77         308 :         if (p->version == 0 && p->flags == 0) {
      78         308 :                 p->size += 8;
      79         308 :                 return GF_OK;
      80             :         } else {
      81           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("version and flags for ispe box not supported" ));
      82             :                 return GF_NOT_SUPPORTED;
      83             :         }
      84             : }
      85             : 
      86             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
      87             : 
      88         454 : GF_Box *colr_box_new()
      89             : {
      90         908 :         ISOM_DECL_BOX_ALLOC(GF_ColourInformationBox, GF_ISOM_BOX_TYPE_COLR);
      91         454 :         return (GF_Box *)tmp;
      92             : }
      93             : 
      94         454 : void colr_box_del(GF_Box *a)
      95             : {
      96             :         GF_ColourInformationBox *p = (GF_ColourInformationBox *)a;
      97         454 :         if (p->opaque) gf_free(p->opaque);
      98         454 :         gf_free(p);
      99         454 : }
     100             : 
     101         377 : GF_Err colr_box_read(GF_Box *s, GF_BitStream *bs)
     102             : {
     103             :         GF_ColourInformationBox *p = (GF_ColourInformationBox *)s;
     104             : 
     105         377 :         if (p->is_jp2) {
     106          27 :                 ISOM_DECREASE_SIZE(p, 3);
     107          27 :                 p->method = gf_bs_read_u8(bs);
     108          27 :                 p->precedence = gf_bs_read_u8(bs);
     109          27 :                 p->approx = gf_bs_read_u8(bs);
     110          27 :                 if (p->size) {
     111          27 :                         p->opaque = gf_malloc(sizeof(u8)*(size_t)p->size);
     112          27 :                         p->opaque_size = (u32) p->size;
     113          27 :                         gf_bs_read_data(bs, (char *) p->opaque, p->opaque_size);
     114             :                 }
     115             :         } else {
     116         350 :                 ISOM_DECREASE_SIZE(p, 4);
     117         350 :                 p->colour_type = gf_bs_read_u32(bs);
     118         350 :                 switch (p->colour_type) {
     119         335 :                 case GF_ISOM_SUBTYPE_NCLX:
     120         335 :                         ISOM_DECREASE_SIZE(p, 7);
     121         335 :                         p->colour_primaries = gf_bs_read_u16(bs);
     122         335 :                         p->transfer_characteristics = gf_bs_read_u16(bs);
     123         335 :                         p->matrix_coefficients = gf_bs_read_u16(bs);
     124         335 :                         p->full_range_flag = (gf_bs_read_u8(bs) & 0x80) ? GF_TRUE : GF_FALSE;
     125         335 :                         break;
     126          13 :                 case GF_ISOM_SUBTYPE_NCLC:
     127          13 :                         ISOM_DECREASE_SIZE(p, 6);
     128          13 :                         p->colour_primaries = gf_bs_read_u16(bs);
     129          13 :                         p->transfer_characteristics = gf_bs_read_u16(bs);
     130          13 :                         p->matrix_coefficients = gf_bs_read_u16(bs);
     131          13 :                         break;
     132           2 :                 default:
     133           2 :                         p->opaque = gf_malloc(sizeof(u8)*(size_t)p->size);
     134           2 :                         p->opaque_size = (u32) p->size;
     135           2 :                         gf_bs_read_data(bs, (char *) p->opaque, p->opaque_size);
     136           2 :                         break;
     137             :                 }
     138             :         }
     139             :         return GF_OK;
     140             : }
     141             : 
     142             : #ifndef GPAC_DISABLE_ISOM_WRITE
     143         252 : GF_Err colr_box_write(GF_Box *s, GF_BitStream *bs)
     144             : {
     145             :         GF_Err e;
     146             :         GF_ColourInformationBox *p = (GF_ColourInformationBox*)s;
     147         252 :         e = gf_isom_box_write_header(s, bs);
     148         252 :         if (e) return e;
     149             : 
     150         252 :         if (p->is_jp2) {
     151          23 :                 gf_bs_write_u8(bs, p->method);
     152          23 :                 gf_bs_write_u8(bs, p->precedence);
     153          23 :                 gf_bs_write_u8(bs, p->approx);
     154          23 :                 if (p->opaque_size)
     155          23 :                         gf_bs_write_data(bs, (char *)p->opaque, p->opaque_size);
     156             :         } else {
     157         229 :                 switch (p->colour_type) {
     158         216 :                 case GF_ISOM_SUBTYPE_NCLX:
     159         216 :                         gf_bs_write_u32(bs, p->colour_type);
     160         216 :                         gf_bs_write_u16(bs, p->colour_primaries);
     161         216 :                         gf_bs_write_u16(bs, p->transfer_characteristics);
     162         216 :                         gf_bs_write_u16(bs, p->matrix_coefficients);
     163         216 :                         gf_bs_write_u8(bs, (p->full_range_flag == GF_TRUE ? 0x80 : 0));
     164         216 :                         break;
     165          11 :                 case GF_ISOM_SUBTYPE_NCLC:
     166          11 :                         gf_bs_write_u32(bs, p->colour_type);
     167          11 :                         gf_bs_write_u16(bs, p->colour_primaries);
     168          11 :                         gf_bs_write_u16(bs, p->transfer_characteristics);
     169          11 :                         gf_bs_write_u16(bs, p->matrix_coefficients);
     170          11 :                         break;
     171           2 :                 default:
     172           2 :                         gf_bs_write_u32(bs, p->colour_type);
     173           2 :                         gf_bs_write_data(bs, (char *)p->opaque, p->opaque_size);
     174           2 :                         break;
     175             :                 }
     176             :         }
     177             :         return GF_OK;
     178             : }
     179             : 
     180         433 : GF_Err colr_box_size(GF_Box *s)
     181             : {
     182             :         GF_ColourInformationBox *p = (GF_ColourInformationBox*)s;
     183             : 
     184         433 :         if (p->is_jp2) {
     185          30 :                 p->size += 3 + p->opaque_size;
     186             :         } else {
     187         403 :                 switch (p->colour_type) {
     188         380 :                 case GF_ISOM_SUBTYPE_NCLX:
     189         380 :                         p->size += 11;
     190         380 :                         break;
     191          21 :                 case GF_ISOM_SUBTYPE_NCLC:
     192          21 :                         p->size += 10;
     193          21 :                         break;
     194           2 :                 default:
     195           2 :                         p->size += 4 + p->opaque_size;
     196           2 :                         break;
     197             :                 }
     198             :         }
     199         433 :         return GF_OK;
     200             : }
     201             : 
     202             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     203             : 
     204         140 : GF_Box *pixi_box_new()
     205             : {
     206         280 :         ISOM_DECL_BOX_ALLOC(GF_PixelInformationPropertyBox, GF_ISOM_BOX_TYPE_PIXI);
     207         140 :         return (GF_Box *)tmp;
     208             : }
     209             : 
     210         140 : void pixi_box_del(GF_Box *a)
     211             : {
     212             :         GF_PixelInformationPropertyBox *p = (GF_PixelInformationPropertyBox *)a;
     213         140 :         if (p->bits_per_channel) gf_free(p->bits_per_channel);
     214         140 :         gf_free(p);
     215         140 : }
     216             : 
     217          54 : GF_Err pixi_box_read(GF_Box *s, GF_BitStream *bs)
     218             : {
     219             :         u32 i;
     220             :         GF_PixelInformationPropertyBox *p = (GF_PixelInformationPropertyBox *)s;
     221             : 
     222          54 :         if (p->version == 0 && p->flags == 0) {
     223          54 :                 p->num_channels = gf_bs_read_u8(bs);
     224          54 :                 p->bits_per_channel = (u8 *)gf_malloc(p->num_channels);
     225         213 :                 for (i = 0; i < p->num_channels; i++) {
     226         159 :                         ISOM_DECREASE_SIZE(p, 1)
     227         159 :                         p->bits_per_channel[i] = gf_bs_read_u8(bs);
     228             :                 }
     229             :                 return GF_OK;
     230             :         } else {
     231           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("version and flags for pixi box not supported" ));
     232           0 :                 gf_bs_skip_bytes(bs, p->size);
     233           0 :                 return GF_NOT_SUPPORTED;
     234             :         }
     235             : }
     236             : 
     237             : #ifndef GPAC_DISABLE_ISOM_WRITE
     238          86 : GF_Err pixi_box_write(GF_Box *s, GF_BitStream *bs)
     239             : {
     240             :         u32 i;
     241             :         GF_Err e;
     242             :         GF_PixelInformationPropertyBox *p = (GF_PixelInformationPropertyBox*)s;
     243             : 
     244          86 :         p->version = 0;
     245          86 :         p->flags = 0;
     246          86 :         e = gf_isom_full_box_write(s, bs);
     247          86 :         if (e) return e;
     248          86 :         gf_bs_write_u8(bs, p->num_channels);
     249         341 :         for (i = 0; i < p->num_channels; i++) {
     250         255 :                 gf_bs_write_u8(bs, p->bits_per_channel[i]);
     251             :         }
     252             :         return GF_OK;
     253             : }
     254             : 
     255         257 : GF_Err pixi_box_size(GF_Box *s)
     256             : {
     257             :         GF_PixelInformationPropertyBox *p = (GF_PixelInformationPropertyBox*)s;
     258         257 :         if (p->version == 0 && p->flags == 0) {
     259         257 :                 p->size += 1 + p->num_channels;
     260         257 :                 return GF_OK;
     261             :         } else {
     262           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("version and flags for pixi box not supported" ));
     263             :                 return GF_NOT_SUPPORTED;
     264             :         }
     265             : }
     266             : 
     267             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     268             : 
     269           3 : GF_Box *rloc_box_new()
     270             : {
     271           6 :         ISOM_DECL_BOX_ALLOC(GF_RelativeLocationPropertyBox, GF_ISOM_BOX_TYPE_RLOC);
     272           3 :         return (GF_Box *)tmp;
     273             : }
     274             : 
     275           3 : void rloc_box_del(GF_Box *a)
     276             : {
     277             :         GF_RelativeLocationPropertyBox *p = (GF_RelativeLocationPropertyBox *)a;
     278           3 :         gf_free(p);
     279           3 : }
     280             : 
     281           1 : GF_Err rloc_box_read(GF_Box *s, GF_BitStream *bs)
     282             : {
     283             :         GF_RelativeLocationPropertyBox *p = (GF_RelativeLocationPropertyBox *)s;
     284             : 
     285           1 :         if (p->version == 0 && p->flags == 0) {
     286           1 :                 p->horizontal_offset = gf_bs_read_u32(bs);
     287           1 :                 p->vertical_offset = gf_bs_read_u32(bs);
     288           1 :                 return GF_OK;
     289             :         } else {
     290           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("version and flags for rloc box not supported" ));
     291           0 :                 gf_bs_skip_bytes(bs, p->size);
     292           0 :                 return GF_NOT_SUPPORTED;
     293             :         }
     294             : }
     295             : 
     296             : #ifndef GPAC_DISABLE_ISOM_WRITE
     297           1 : GF_Err rloc_box_write(GF_Box *s, GF_BitStream *bs)
     298             : {
     299             :         GF_Err e;
     300             :         GF_RelativeLocationPropertyBox *p = (GF_RelativeLocationPropertyBox*)s;
     301             : 
     302           1 :         p->version = 0;
     303           1 :         p->flags = 0;
     304           1 :         e = gf_isom_full_box_write(s, bs);
     305           1 :         if (e) return e;
     306           1 :         gf_bs_write_u32(bs, p->horizontal_offset);
     307           1 :         gf_bs_write_u32(bs, p->vertical_offset);
     308           1 :         return GF_OK;
     309             : }
     310             : 
     311           1 : GF_Err rloc_box_size(GF_Box *s)
     312             : {
     313             :         GF_RelativeLocationPropertyBox *p = (GF_RelativeLocationPropertyBox*)s;
     314           1 :         if (p->version == 0 && p->flags == 0) {
     315           1 :                 p->size += 8;
     316           1 :                 return GF_OK;
     317             :         } else {
     318           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("version and flags for rloc box not supported" ));
     319             :                 return GF_NOT_SUPPORTED;
     320             :         }
     321             : }
     322             : 
     323             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     324             : 
     325          17 : GF_Box *irot_box_new()
     326             : {
     327          34 :         ISOM_DECL_BOX_ALLOC(GF_ImageRotationBox, GF_ISOM_BOX_TYPE_IROT);
     328          17 :         return (GF_Box *)tmp;
     329             : }
     330             : 
     331          17 : void irot_box_del(GF_Box *a)
     332             : {
     333             :         GF_ImageRotationBox *p = (GF_ImageRotationBox *)a;
     334          17 :         gf_free(p);
     335          17 : }
     336             : 
     337           3 : GF_Err irot_box_read(GF_Box *s, GF_BitStream *bs)
     338             : {
     339             :         GF_ImageRotationBox *p = (GF_ImageRotationBox *)s;
     340           3 :         p->angle = gf_bs_read_u8(bs) & 0x3;
     341           3 :         return GF_OK;
     342             : }
     343             : 
     344             : #ifndef GPAC_DISABLE_ISOM_WRITE
     345          13 : GF_Err irot_box_write(GF_Box *s, GF_BitStream *bs)
     346             : {
     347             :         GF_Err e;
     348             :         GF_ImageRotationBox *p = (GF_ImageRotationBox*)s;
     349          13 :         e = gf_isom_box_write_header(s, bs);
     350          13 :         if (e) return e;
     351          13 :         gf_bs_write_u8(bs, p->angle);
     352          13 :         return GF_OK;
     353             : }
     354             : 
     355          37 : GF_Err irot_box_size(GF_Box *s)
     356             : {
     357             :         GF_ImageRotationBox *p = (GF_ImageRotationBox*)s;
     358          37 :         p->size += 1;
     359          37 :         return GF_OK;
     360             : }
     361             : 
     362             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     363             : 
     364          12 : GF_Box *imir_box_new()
     365             : {
     366          24 :         ISOM_DECL_BOX_ALLOC(GF_ImageMirrorBox, GF_ISOM_BOX_TYPE_IMIR);
     367          12 :         return (GF_Box *)tmp;
     368             : }
     369             : 
     370          12 : void imir_box_del(GF_Box *a)
     371             : {
     372             :         GF_ImageMirrorBox *p = (GF_ImageMirrorBox *)a;
     373          12 :         gf_free(p);
     374          12 : }
     375             : 
     376           1 : GF_Err imir_box_read(GF_Box *s, GF_BitStream *bs)
     377             : {
     378             :         GF_ImageMirrorBox *p = (GF_ImageMirrorBox *)s;
     379           1 :         p->axis = gf_bs_read_u8(bs) & 0x1;
     380           1 :         return GF_OK;
     381             : }
     382             : 
     383             : #ifndef GPAC_DISABLE_ISOM_WRITE
     384          10 : GF_Err imir_box_write(GF_Box *s, GF_BitStream *bs)
     385             : {
     386             :         GF_Err e;
     387             :         GF_ImageMirrorBox *p = (GF_ImageMirrorBox*)s;
     388          10 :         e = gf_isom_box_write_header(s, bs);
     389          10 :         if (e) return e;
     390          10 :         gf_bs_write_u8(bs, p->axis);
     391          10 :         return GF_OK;
     392             : }
     393             : 
     394          28 : GF_Err imir_box_size(GF_Box *s)
     395             : {
     396             :         GF_ImageMirrorBox *p = (GF_ImageMirrorBox*)s;
     397          28 :         p->size += 1;
     398          28 :         return GF_OK;
     399             : }
     400             : 
     401             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     402             : 
     403         143 : GF_Box *ipco_box_new()
     404             : {
     405         286 :         ISOM_DECL_BOX_ALLOC(GF_ItemPropertyContainerBox, GF_ISOM_BOX_TYPE_IPCO);
     406         143 :         return (GF_Box *)tmp;
     407             : }
     408             : 
     409         143 : void ipco_box_del(GF_Box *s)
     410             : {
     411             :         GF_ItemPropertyContainerBox *p = (GF_ItemPropertyContainerBox *)s;
     412         143 :         gf_free(p);
     413         143 : }
     414             : 
     415          54 : GF_Err ipco_box_read(GF_Box *s, GF_BitStream *bs)
     416             : {
     417          54 :         return gf_isom_box_array_read(s, bs);
     418             : }
     419             : 
     420             : #ifndef GPAC_DISABLE_ISOM_WRITE
     421             : 
     422          89 : GF_Err ipco_box_write(GF_Box *s, GF_BitStream *bs)
     423             : {
     424          89 :         if (!s) return GF_BAD_PARAM;
     425          89 :         return gf_isom_box_write_header(s, bs);
     426             : }
     427             : 
     428         269 : GF_Err ipco_box_size(GF_Box *s)
     429             : {
     430         269 :         return GF_OK;
     431             : }
     432             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     433             : 
     434         143 : GF_Box *iprp_box_new()
     435             : {
     436         286 :         ISOM_DECL_BOX_ALLOC(GF_ItemPropertiesBox, GF_ISOM_BOX_TYPE_IPRP);
     437         143 :         return (GF_Box *)tmp;
     438             : }
     439             : 
     440         143 : void iprp_box_del(GF_Box *s)
     441             : {
     442         143 :         gf_free(s);
     443         143 : }
     444             : 
     445         106 : GF_Err iprp_on_child_box(GF_Box *s, GF_Box *a, Bool is_rem)
     446             : {
     447             :         GF_ItemPropertiesBox *ptr = (GF_ItemPropertiesBox *)s;
     448         106 :         switch (a->type) {
     449          53 :         case GF_ISOM_BOX_TYPE_IPCO:
     450          53 :                 BOX_FIELD_ASSIGN(property_container, GF_ItemPropertyContainerBox)
     451          53 :                 break;
     452          53 :         case GF_ISOM_BOX_TYPE_IPMA:
     453          53 :                 BOX_FIELD_ASSIGN(property_association, GF_ItemPropertyAssociationBox)
     454          53 :                 break;
     455             :         default:
     456             :                 return GF_OK;
     457             :         }
     458             :         return GF_OK;
     459             : }
     460             : 
     461          54 : GF_Err iprp_box_read(GF_Box *s, GF_BitStream *bs)
     462             : {
     463          54 :         return gf_isom_box_array_read(s, bs);
     464             : }
     465             : 
     466             : #ifndef GPAC_DISABLE_ISOM_WRITE
     467             : 
     468          89 : GF_Err iprp_box_write(GF_Box *s, GF_BitStream *bs)
     469             : {
     470          89 :         return gf_isom_box_write_header(s, bs);
     471             : }
     472             : 
     473         269 : GF_Err iprp_box_size(GF_Box *s)
     474             : {
     475         269 :         u32 pos=0;
     476             :         GF_ItemPropertiesBox *p = (GF_ItemPropertiesBox *)s;
     477         269 :         gf_isom_check_position(s, (GF_Box*)p->property_container, &pos);
     478         269 :         gf_isom_check_position(s, (GF_Box*)p->property_association, &pos);
     479         269 :         return GF_OK;
     480             : }
     481             : 
     482             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     483             : 
     484         144 : GF_Box *ipma_box_new()
     485             : {
     486         288 :         ISOM_DECL_BOX_ALLOC(GF_ItemPropertyAssociationBox, GF_ISOM_BOX_TYPE_IPMA);
     487         144 :         tmp->entries = gf_list_new();
     488         144 :         return (GF_Box *)tmp;
     489             : }
     490             : 
     491         144 : void ipma_box_del(GF_Box *a)
     492             : {
     493             :         GF_ItemPropertyAssociationBox *p = (GF_ItemPropertyAssociationBox *)a;
     494         144 :         if (p->entries) {
     495             :                 u32 i;
     496             :                 u32 count;
     497         144 :                 count = gf_list_count(p->entries);
     498             : 
     499         481 :                 for (i = 0; i < count; i++) {
     500         337 :                         GF_ItemPropertyAssociationEntry *entry = (GF_ItemPropertyAssociationEntry *)gf_list_get(p->entries, i);
     501         337 :                         if (entry) {
     502         337 :                                 gf_free(entry->associations);
     503         337 :                                 gf_free(entry);
     504             :                         }
     505             :                 }
     506         144 :                 gf_list_del(p->entries);
     507             :         }
     508         144 :         gf_free(p);
     509         144 : }
     510             : 
     511          54 : GF_Err ipma_box_read(GF_Box *s, GF_BitStream *bs)
     512             : {
     513             :         u32 i, j;
     514             :         GF_ItemPropertyAssociationBox *p = (GF_ItemPropertyAssociationBox *)s;
     515             :         u32 entry_count;
     516             : 
     517          54 :         ISOM_DECREASE_SIZE(p, 4)
     518          54 :         entry_count = gf_bs_read_u32(bs);
     519         173 :         for (i = 0; i < entry_count; i++) {
     520             :                 GF_ItemPropertyAssociationEntry *entry;
     521         119 :                 GF_SAFEALLOC(entry, GF_ItemPropertyAssociationEntry);
     522         119 :                 if (!entry) return GF_OUT_OF_MEM;
     523         119 :                 gf_list_add(p->entries, entry);
     524         119 :                 if (p->version == 0) {
     525         119 :                         ISOM_DECREASE_SIZE(p, 3)
     526         119 :                         entry->item_id = gf_bs_read_u16(bs);
     527             :                 } else {
     528           0 :                         ISOM_DECREASE_SIZE(p, 5)
     529           0 :                         entry->item_id = gf_bs_read_u32(bs);
     530             :                 }
     531         119 :                 entry->nb_associations = gf_bs_read_u8(bs);
     532         119 :                 entry->associations = gf_malloc(sizeof(GF_ItemPropertyAssociationSlot) * entry->nb_associations);
     533         119 :                 if (!entry->associations) return GF_OUT_OF_MEM;
     534         492 :                 for (j = 0; j < entry->nb_associations; j++) {
     535         492 :                         if (p->flags & 1) {
     536           0 :                                 u16 tmp = gf_bs_read_u16(bs);
     537           0 :                                 entry->associations[j].essential = (tmp >> 15) ? GF_TRUE : GF_FALSE;
     538           0 :                                 entry->associations[j].index = (tmp & 0x7FFF);
     539             :                         } else {
     540         492 :                                 u8 tmp = gf_bs_read_u8(bs);
     541         492 :                                 entry->associations[j].essential = (tmp >> 7) ? GF_TRUE : GF_FALSE;
     542         492 :                                 entry->associations[j].index = (tmp & 0x7F);
     543             :                         }
     544             :                 }
     545             :         }
     546             :         return GF_OK;
     547             : }
     548             : 
     549             : #ifndef GPAC_DISABLE_ISOM_WRITE
     550          89 : GF_Err ipma_box_write(GF_Box *s, GF_BitStream *bs)
     551             : {
     552             :         u32 i, j;
     553             :         GF_Err e;
     554             :         u32 entry_count;
     555             :         GF_ItemPropertyAssociationBox *p = (GF_ItemPropertyAssociationBox*)s;
     556             : 
     557          89 :         e = gf_isom_full_box_write(s, bs);
     558          89 :         if (e) return e;
     559          89 :         entry_count = gf_list_count(p->entries);
     560          89 :         gf_bs_write_u32(bs, entry_count);
     561         308 :         for (i = 0; i < entry_count; i++) {
     562         219 :                 GF_ItemPropertyAssociationEntry *entry = (GF_ItemPropertyAssociationEntry *)gf_list_get(p->entries, i);
     563         219 :                 if (p->version == 0) {
     564         219 :                         gf_bs_write_u16(bs, entry->item_id);
     565             :                 } else {
     566           0 :                         gf_bs_write_u32(bs, entry->item_id);
     567             :                 }
     568         219 :                 gf_bs_write_u8(bs, entry->nb_associations);
     569        1110 :                 for (j = 0; j < entry->nb_associations; j++) {
     570         891 :                         if (p->flags & 1) {
     571           0 :                                 gf_bs_write_u16(bs, (u16)( ( (entry->associations[j].essential ? 1 : 0) << 15) | (entry->associations[j].index & 0x7F) ) );
     572             :                         } else {
     573         891 :                                 gf_bs_write_u8(bs, (u32)(( (entry->associations[j].essential ? 1 : 0) << 7) | entry->associations[j].index));
     574             :                         }
     575             :                 }
     576             :         }
     577             :         return GF_OK;
     578             : }
     579             : 
     580         269 : GF_Err ipma_box_size(GF_Box *s)
     581             : {
     582             :         u32 i;
     583             :         u32 entry_count;
     584             :         GF_ItemPropertyAssociationBox *p = (GF_ItemPropertyAssociationBox*)s;
     585             : 
     586         269 :         entry_count = gf_list_count(p->entries);
     587         269 :         p->size += 4;
     588         269 :         if (p->version == 0) {
     589         269 :                 p->size += entry_count * 2;
     590             :         } else {
     591           0 :                 p->size += entry_count * 4;
     592             :         }
     593         269 :         p->size += entry_count;
     594         930 :         for (i = 0; i < entry_count; i++) {
     595         661 :                 GF_ItemPropertyAssociationEntry *entry = (GF_ItemPropertyAssociationEntry *)gf_list_get(p->entries, i);
     596         661 :                 if (p->flags & 1) {
     597           0 :                         p->size += entry->nb_associations * 2;
     598             :                 } else {
     599         661 :                         p->size += entry->nb_associations;
     600             :                 }
     601             :         }
     602         269 :         return GF_OK;
     603             : }
     604             : 
     605             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     606             : 
     607           3 : GF_Box *grpl_box_new()
     608             : {
     609           6 :         ISOM_DECL_BOX_ALLOC(GF_GroupListBox, GF_ISOM_BOX_TYPE_GRPL);
     610           3 :         return (GF_Box *)tmp;
     611             : }
     612             : 
     613           3 : void grpl_box_del(GF_Box *s)
     614             : {
     615             :         GF_GroupListBox *p = (GF_GroupListBox *)s;
     616           3 :         gf_free(p);
     617           3 : }
     618             : 
     619           1 : GF_Err grpl_box_read(GF_Box *s, GF_BitStream *bs)
     620             : {
     621           1 :         return gf_isom_box_array_read_ex(s, bs, s->type);
     622             : }
     623             : 
     624             : #ifndef GPAC_DISABLE_ISOM_WRITE
     625             : 
     626           1 : GF_Err grpl_box_write(GF_Box *s, GF_BitStream *bs)
     627             : {
     628           1 :         if (!s) return GF_BAD_PARAM;
     629           1 :         return gf_isom_box_write_header(s, bs);
     630             : }
     631             : 
     632           1 : GF_Err grpl_box_size(GF_Box *s)
     633             : {
     634           1 :         return GF_OK;
     635             : }
     636             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     637             : 
     638             : 
     639           2 : void grptype_box_del(GF_Box *s)
     640             : {
     641             :         GF_EntityToGroupTypeBox *ptr = (GF_EntityToGroupTypeBox *)s;
     642           2 :         if (!ptr) return;
     643           2 :         if (ptr->entity_ids) gf_free(ptr->entity_ids);
     644           2 :         gf_free(ptr);
     645             : }
     646             : 
     647             : 
     648           0 : GF_Err grptype_box_read(GF_Box *s, GF_BitStream *bs)
     649             : {
     650             :         u32 i;
     651             :         GF_EntityToGroupTypeBox *ptr = (GF_EntityToGroupTypeBox *)s;
     652             : 
     653           0 :         ISOM_DECREASE_SIZE(ptr, 8)
     654           0 :         ptr->group_id = gf_bs_read_u32(bs);
     655           0 :         ptr->entity_id_count = gf_bs_read_u32(bs);
     656             : 
     657           0 :         if (ptr->entity_id_count > ptr->size / 4) return GF_ISOM_INVALID_FILE;
     658             : 
     659           0 :         ptr->entity_ids = (u32 *) gf_malloc(ptr->entity_id_count * sizeof(u32));
     660           0 :         if (!ptr->entity_ids) return GF_OUT_OF_MEM;
     661             : 
     662           0 :         for (i = 0; i < ptr->entity_id_count; i++) {
     663           0 :                 ptr->entity_ids[i] = gf_bs_read_u32(bs);
     664             :         }
     665             :         return GF_OK;
     666             : }
     667             : 
     668           2 : GF_Box *grptype_box_new()
     669             : {
     670           4 :         ISOM_DECL_BOX_ALLOC(GF_EntityToGroupTypeBox, GF_ISOM_BOX_TYPE_GRPT);
     671             :         //the group type code is assign in gf_isom_box_parse_ex
     672           2 :         return (GF_Box *)tmp;
     673             : }
     674             : 
     675             : #ifndef GPAC_DISABLE_ISOM_WRITE
     676             : 
     677           1 : GF_Err grptype_box_write(GF_Box *s, GF_BitStream *bs)
     678             : {
     679             :         GF_Err e;
     680             :         u32 i;
     681             :         GF_EntityToGroupTypeBox *ptr = (GF_EntityToGroupTypeBox *)s;
     682           1 :         ptr->type = ptr->grouping_type;
     683           1 :         e = gf_isom_full_box_write(s, bs);
     684           1 :         if (e) return e;
     685           1 :         ptr->type = GF_ISOM_BOX_TYPE_GRPT;
     686             : 
     687           1 :         gf_bs_write_u32(bs, ptr->group_id);
     688           1 :         gf_bs_write_u32(bs, ptr->entity_id_count);
     689             : 
     690           1 :         for (i = 0; i < ptr->entity_id_count; i++) {
     691           0 :                 gf_bs_write_u32(bs, ptr->entity_ids[i]);
     692             :         }
     693             :         return GF_OK;
     694             : }
     695             : 
     696             : 
     697           1 : GF_Err grptype_box_size(GF_Box *s)
     698             : {
     699             :         GF_EntityToGroupTypeBox *ptr = (GF_EntityToGroupTypeBox *)s;
     700           1 :         ptr->size += 8 + 4*ptr->entity_id_count;
     701           1 :         return GF_OK;
     702             : }
     703             : 
     704             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     705             : 
     706             : 
     707           4 : GF_Box *auxc_box_new()
     708             : {
     709           8 :         ISOM_DECL_BOX_ALLOC(GF_AuxiliaryTypePropertyBox, GF_ISOM_BOX_TYPE_AUXC);
     710           4 :         return (GF_Box *)tmp;
     711             : }
     712             : 
     713           4 : void auxc_box_del(GF_Box *a)
     714             : {
     715             :         GF_AuxiliaryTypePropertyBox *p = (GF_AuxiliaryTypePropertyBox *)a;
     716           4 :         if (p->aux_urn) gf_free(p->aux_urn);
     717           4 :         if (p->data) gf_free(p->data);
     718           4 :         gf_free(p);
     719           4 : }
     720             : 
     721           1 : GF_Err auxc_box_read(GF_Box *s, GF_BitStream *bs)
     722             : {
     723             :         GF_AuxiliaryTypePropertyBox *p = (GF_AuxiliaryTypePropertyBox *)s;
     724             :         GF_Err e;
     725             : 
     726           1 :         e = gf_isom_read_null_terminated_string(s, bs, s->size, &p->aux_urn);
     727           1 :         if (e) return e;
     728           1 :         p->data_size = (u32) p->size;
     729           1 :         p->data = gf_malloc(sizeof(char) * p->data_size);
     730           1 :         gf_bs_read_data(bs, p->data, p->data_size);
     731           1 :         return GF_OK;
     732             : }
     733             : 
     734             : #ifndef GPAC_DISABLE_ISOM_WRITE
     735           2 : GF_Err auxc_box_write(GF_Box *s, GF_BitStream *bs)
     736             : {
     737             :         GF_Err e;
     738             :         GF_AuxiliaryTypePropertyBox *p = (GF_AuxiliaryTypePropertyBox*)s;
     739             : 
     740           2 :         e = gf_isom_full_box_write(s, bs);
     741           2 :         if (e) return e;
     742             :         //with terminating 0
     743           2 :     if (p->aux_urn)
     744           1 :         gf_bs_write_data(bs, p->aux_urn, (u32) strlen(p->aux_urn) );
     745           2 :     gf_bs_write_u8(bs, 0);
     746           2 :         gf_bs_write_data(bs, p->data, p->data_size);
     747             : 
     748           2 :         return GF_OK;
     749             : }
     750             : 
     751           4 : GF_Err auxc_box_size(GF_Box *s)
     752             : {
     753             :         GF_AuxiliaryTypePropertyBox *p = (GF_AuxiliaryTypePropertyBox*)s;
     754           4 :     p->size += (p->aux_urn ? strlen(p->aux_urn) : 0) + 1 + p->data_size;
     755           4 :         return GF_OK;
     756             : }
     757             : 
     758             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     759             : 
     760           4 : void auxi_box_del(GF_Box *s)
     761             : {
     762             :         GF_AuxiliaryTypeInfoBox *ptr = (GF_AuxiliaryTypeInfoBox *)s;
     763           4 :         if (ptr->aux_track_type) gf_free(ptr->aux_track_type);
     764           4 :         if (ptr) gf_free(ptr);
     765           4 :         return;
     766             : }
     767             : 
     768           1 : GF_Err auxi_box_read(GF_Box *s, GF_BitStream *bs)
     769             : {
     770             :         GF_AuxiliaryTypeInfoBox *ptr = (GF_AuxiliaryTypeInfoBox *)s;
     771           1 :         return gf_isom_read_null_terminated_string(s, bs, s->size, &ptr->aux_track_type);
     772             : }
     773             : 
     774           4 : GF_Box *auxi_box_new()
     775             : {
     776           8 :         ISOM_DECL_BOX_ALLOC(GF_AuxiliaryTypeInfoBox, GF_ISOM_BOX_TYPE_AUXI);
     777           4 :         return (GF_Box *) tmp;
     778             : }
     779             : 
     780             : #ifndef GPAC_DISABLE_ISOM_WRITE
     781             : 
     782           2 : GF_Err auxi_box_write(GF_Box *s, GF_BitStream *bs)
     783             : {
     784             :         GF_Err e;
     785             :         GF_AuxiliaryTypeInfoBox *ptr = (GF_AuxiliaryTypeInfoBox *)s;
     786             : 
     787           2 :         e = gf_isom_full_box_write(s, bs);
     788           2 :         if (e) return e;
     789             :         //with terminating 0
     790           2 :     if (ptr->aux_track_type)
     791           1 :         gf_bs_write_data(bs, ptr->aux_track_type, (u32) strlen(ptr->aux_track_type) );
     792           2 :     gf_bs_write_u8(bs, 0);
     793           2 :         return GF_OK;
     794             : }
     795             : 
     796           4 : GF_Err auxi_box_size(GF_Box *s)
     797             : {
     798             :         GF_AuxiliaryTypeInfoBox *ptr = (GF_AuxiliaryTypeInfoBox *)s;
     799           4 :     ptr->size += (ptr->aux_track_type ? strlen(ptr->aux_track_type) : 0 )+ 1;
     800           4 :         return GF_OK;
     801             : }
     802             : 
     803             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     804           3 : GF_Box *oinf_box_new()
     805             : {
     806           6 :         ISOM_DECL_BOX_ALLOC(GF_OINFPropertyBox, GF_ISOM_BOX_TYPE_OINF);
     807           3 :         tmp->oinf = gf_isom_oinf_new_entry();
     808           3 :         return (GF_Box *)tmp;
     809             : }
     810             : 
     811           3 : void oinf_box_del(GF_Box *a)
     812             : {
     813             :         GF_OINFPropertyBox *p = (GF_OINFPropertyBox *)a;
     814           3 :         if (p->oinf) gf_isom_oinf_del_entry(p->oinf);
     815           3 :         gf_free(p);
     816           3 : }
     817             : 
     818           1 : GF_Err oinf_box_read(GF_Box *s, GF_BitStream *bs)
     819             : {
     820             :         GF_OINFPropertyBox *p = (GF_OINFPropertyBox *)s;
     821           1 :         return gf_isom_oinf_read_entry(p->oinf, bs);
     822             : }
     823             : 
     824             : #ifndef GPAC_DISABLE_ISOM_WRITE
     825           1 : GF_Err oinf_box_write(GF_Box *s, GF_BitStream *bs)
     826             : {
     827             :         GF_Err e;
     828             :         GF_OINFPropertyBox *p = (GF_OINFPropertyBox*)s;
     829             : 
     830           1 :         e = gf_isom_full_box_write(s, bs);
     831           1 :         if (e) return e;
     832           1 :         return gf_isom_oinf_write_entry(p->oinf, bs);
     833             : }
     834             : 
     835           1 : GF_Err oinf_box_size(GF_Box *s)
     836             : {
     837             :         GF_OINFPropertyBox *p = (GF_OINFPropertyBox*)s;
     838           1 :         if (!p->oinf) return GF_BAD_PARAM;
     839           1 :         p->size += gf_isom_oinf_size_entry(p->oinf);
     840           1 :         return GF_OK;
     841             : }
     842             : 
     843             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     844             : 
     845           3 : GF_Box *tols_box_new()
     846             : {
     847           6 :         ISOM_DECL_BOX_ALLOC(GF_TargetOLSPropertyBox, GF_ISOM_BOX_TYPE_TOLS);
     848           3 :         return (GF_Box *)tmp;
     849             : }
     850             : 
     851           3 : void tols_box_del(GF_Box *a)
     852             : {
     853           3 :         gf_free(a);
     854           3 : }
     855             : 
     856           1 : GF_Err tols_box_read(GF_Box *s, GF_BitStream *bs)
     857             : {
     858             :         GF_TargetOLSPropertyBox *p = (GF_TargetOLSPropertyBox *)s;
     859             : 
     860           1 :         ISOM_DECREASE_SIZE(p, 2)
     861           1 :         p->target_ols_index = gf_bs_read_u16(bs);
     862           1 :         return GF_OK;
     863             : }
     864             : 
     865             : #ifndef GPAC_DISABLE_ISOM_WRITE
     866           1 : GF_Err tols_box_write(GF_Box *s, GF_BitStream *bs)
     867             : {
     868             :         GF_Err e;
     869             :         GF_TargetOLSPropertyBox *p = (GF_TargetOLSPropertyBox*)s;
     870             : 
     871           1 :         e = gf_isom_full_box_write(s, bs);
     872           1 :         if (e) return e;
     873           1 :         gf_bs_write_u16(bs, p->target_ols_index);
     874           1 :         return GF_OK;
     875             : }
     876             : 
     877           1 : GF_Err tols_box_size(GF_Box *s)
     878             : {
     879             :         GF_TargetOLSPropertyBox *p = (GF_TargetOLSPropertyBox*)s;
     880           1 :         p->size += 2;
     881           1 :         return GF_OK;
     882             : }
     883             : 
     884             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     885             : 
     886             : 
     887           4 : GF_Box *clli_box_new()
     888             : {
     889           8 :         ISOM_DECL_BOX_ALLOC(GF_ContentLightLevelBox, GF_ISOM_BOX_TYPE_CLLI);
     890           4 :         return (GF_Box *)tmp;
     891             : }
     892             : 
     893           4 : void clli_box_del(GF_Box *a)
     894             : {
     895             :         GF_ContentLightLevelBox *p = (GF_ContentLightLevelBox *)a;
     896           4 :         gf_free(p);
     897           4 : }
     898             : 
     899           1 : GF_Err clli_box_read(GF_Box *s, GF_BitStream *bs)
     900             : {
     901             :         GF_ContentLightLevelBox *p = (GF_ContentLightLevelBox *)s;
     902           1 :         ISOM_DECREASE_SIZE(p, 4)
     903           1 :         p->clli.max_content_light_level = gf_bs_read_u16(bs);
     904           1 :         p->clli.max_pic_average_light_level = gf_bs_read_u16(bs);
     905           1 :         return GF_OK;
     906             : }
     907             : 
     908             : #ifndef GPAC_DISABLE_ISOM_WRITE
     909             : 
     910           2 : GF_Err clli_box_write(GF_Box *s, GF_BitStream *bs)
     911             : {
     912             :         GF_Err e;
     913             :         GF_ContentLightLevelBox *p = (GF_ContentLightLevelBox*)s;
     914           2 :         e = gf_isom_box_write_header(s, bs);
     915           2 :         if (e) return e;
     916           2 :         gf_bs_write_u16(bs, p->clli.max_content_light_level);
     917           2 :         gf_bs_write_u16(bs, p->clli.max_pic_average_light_level);
     918           2 :         return GF_OK;
     919             : }
     920             : 
     921           4 : GF_Err clli_box_size(GF_Box *s)
     922             : {
     923             :         GF_ContentLightLevelBox *p = (GF_ContentLightLevelBox*)s;
     924           4 :         p->size += 4;
     925           4 :         return GF_OK;
     926             : }
     927             : 
     928             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     929             : 
     930             : 
     931           4 : GF_Box *mdcv_box_new()
     932             : {
     933           8 :         ISOM_DECL_BOX_ALLOC(GF_MasteringDisplayColourVolumeBox, GF_ISOM_BOX_TYPE_MDCV);
     934           4 :         return (GF_Box *)tmp;
     935             : }
     936             : 
     937           4 : void mdcv_box_del(GF_Box *a)
     938             : {
     939             :         GF_MasteringDisplayColourVolumeBox *p = (GF_MasteringDisplayColourVolumeBox *)a;
     940           4 :         gf_free(p);
     941           4 : }
     942             : 
     943           1 : GF_Err mdcv_box_read(GF_Box *s, GF_BitStream *bs)
     944             : {
     945             :         int c = 0;
     946             :         GF_MasteringDisplayColourVolumeBox *p = (GF_MasteringDisplayColourVolumeBox *)s;
     947           1 :         ISOM_DECREASE_SIZE(p, 24)
     948           4 :         for (c = 0; c<3; c++) {
     949           3 :                 p->mdcv.display_primaries[c].x = gf_bs_read_u16(bs);
     950           3 :                 p->mdcv.display_primaries[c].y = gf_bs_read_u16(bs);
     951             :         }
     952           1 :         p->mdcv.white_point_x = gf_bs_read_u16(bs);
     953           1 :         p->mdcv.white_point_y = gf_bs_read_u16(bs);
     954           1 :         p->mdcv.max_display_mastering_luminance = gf_bs_read_u32(bs);
     955           1 :         p->mdcv.min_display_mastering_luminance = gf_bs_read_u32(bs);
     956             : 
     957           1 :         return GF_OK;
     958             : }
     959             : 
     960             : #ifndef GPAC_DISABLE_ISOM_WRITE
     961             : 
     962           2 : GF_Err mdcv_box_write(GF_Box *s, GF_BitStream *bs)
     963             : {
     964             :         int c = 0;
     965             :         GF_Err e;
     966             :         GF_MasteringDisplayColourVolumeBox *p = (GF_MasteringDisplayColourVolumeBox*)s;
     967           2 :         e = gf_isom_box_write_header(s, bs);
     968           2 :         if (e) return e;
     969             : 
     970           6 :         for (c = 0; c<3; c++) {
     971           6 :                 gf_bs_write_u16(bs, p->mdcv.display_primaries[c].x);
     972           6 :                 gf_bs_write_u16(bs, p->mdcv.display_primaries[c].y);
     973             :         }
     974           2 :         gf_bs_write_u16(bs, p->mdcv.white_point_x);
     975           2 :         gf_bs_write_u16(bs, p->mdcv.white_point_y);
     976           2 :         gf_bs_write_u32(bs, p->mdcv.max_display_mastering_luminance);
     977           2 :         gf_bs_write_u32(bs, p->mdcv.min_display_mastering_luminance);
     978             :         
     979           2 :         return GF_OK;
     980             : }
     981             : 
     982           4 : GF_Err mdcv_box_size(GF_Box *s)
     983             : {
     984             :         GF_MasteringDisplayColourVolumeBox *p = (GF_MasteringDisplayColourVolumeBox*)s;
     985           4 :         p->size += 24;
     986           4 :         return GF_OK;
     987             : }
     988             : 
     989             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     990             : 
     991             : 
     992          48 : GF_Box *ienc_box_new()
     993             : {
     994          96 :         ISOM_DECL_BOX_ALLOC(GF_ItemEncryptionPropertyBox, GF_ISOM_BOX_TYPE_IENC);
     995          48 :         return (GF_Box *)tmp;
     996             : }
     997             : 
     998          48 : void ienc_box_del(GF_Box *a)
     999             : {
    1000             :         GF_ItemEncryptionPropertyBox *p = (GF_ItemEncryptionPropertyBox *)a;
    1001          48 :         if (p->key_info) gf_free(p->key_info);
    1002          48 :         gf_free(p);
    1003          48 : }
    1004             : 
    1005          23 : GF_Err ienc_box_read(GF_Box *s, GF_BitStream *bs)
    1006             : {
    1007             :         u32 nb_keys;
    1008             :         GF_ItemEncryptionPropertyBox *p = (GF_ItemEncryptionPropertyBox *)s;
    1009             : 
    1010          23 :         ISOM_DECREASE_SIZE(p, 3)
    1011          23 :         gf_bs_read_u8(bs);
    1012          23 :         if (p->version == 0) {
    1013          15 :                 gf_bs_read_u8(bs);
    1014             :         } else {
    1015           8 :                 p->skip_byte_block = gf_bs_read_int(bs, 4);
    1016           8 :                 p->crypt_byte_block = gf_bs_read_int(bs, 4);
    1017             :         }
    1018          23 :         nb_keys = gf_bs_read_u8(bs);
    1019          23 :         if (nb_keys * (sizeof(bin128)+1) > p->size)
    1020             :                 return GF_NON_COMPLIANT_BITSTREAM;
    1021          23 :         p->key_info_size = (u32) (3+p->size);
    1022          23 :         p->key_info = gf_malloc(sizeof(u8) * p->key_info_size);
    1023          23 :         if (!p->key_info) return GF_OUT_OF_MEM;
    1024          23 :         p->key_info[0] = 1;
    1025          23 :         p->key_info[1] = 0;
    1026          23 :         p->key_info[2] = nb_keys;
    1027          23 :         gf_bs_read_data(bs, p->key_info+3, (u32) p->size);
    1028          23 :         p->size = 0;
    1029          23 :         if (!gf_cenc_validate_key_info(p->key_info, p->key_info_size))
    1030             :                 return GF_ISOM_INVALID_FILE;
    1031          23 :         return GF_OK;
    1032             : }
    1033             : 
    1034             : #ifndef GPAC_DISABLE_ISOM_WRITE
    1035          23 : GF_Err ienc_box_write(GF_Box *s, GF_BitStream *bs)
    1036             : {
    1037             :         GF_Err e;
    1038             :         u32 nb_keys;
    1039             :         GF_ItemEncryptionPropertyBox *p = (GF_ItemEncryptionPropertyBox*)s;
    1040          23 :         if (p->skip_byte_block || p->crypt_byte_block)
    1041           8 :                 p->version = 1;
    1042          23 :         e = gf_isom_full_box_write(s, bs);
    1043          23 :         if (e) return e;
    1044          23 :         gf_bs_write_u8(bs, 0);
    1045          23 :         if (p->version) {
    1046           8 :                 gf_bs_write_int(bs, p->skip_byte_block, 4);
    1047           8 :                 gf_bs_write_int(bs, p->crypt_byte_block, 4);
    1048             :         } else {
    1049          15 :                 gf_bs_write_u8(bs, 0);
    1050             :         }
    1051          23 :         if (p->key_info[0]) {
    1052           3 :                 if (p->key_info[1]) {
    1053           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Too many keys for ienc box, max is 255)\n"))
    1054             :                         return GF_BAD_PARAM;
    1055             :                 }
    1056           3 :                 nb_keys = p->key_info[2];
    1057             :         } else {
    1058             :                 nb_keys = 1;
    1059             :         }
    1060          23 :         gf_bs_write_u8(bs, nb_keys);
    1061          23 :         gf_bs_write_data(bs, p->key_info+3, p->key_info_size-3);
    1062          23 :         return GF_OK;
    1063             : }
    1064             : 
    1065          70 : GF_Err ienc_box_size(GF_Box *s)
    1066             : {
    1067             :         GF_ItemEncryptionPropertyBox *p = (GF_ItemEncryptionPropertyBox*)s;
    1068          70 :         if (!p->key_info || (p->key_info_size<19))
    1069             :                 return GF_BAD_PARAM;
    1070          69 :         p->size += 3 + p->key_info_size-3;
    1071          69 :         return GF_OK;
    1072             : }
    1073             : 
    1074             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
    1075             : 
    1076             : 
    1077           9 : GF_Box *iaux_box_new()
    1078             : {
    1079          18 :         ISOM_DECL_BOX_ALLOC(GF_AuxiliaryInfoPropertyBox, GF_ISOM_BOX_TYPE_IAUX);
    1080           9 :         return (GF_Box *)tmp;
    1081             : }
    1082             : 
    1083           9 : void iaux_box_del(GF_Box *a)
    1084             : {
    1085           9 :         gf_free(a);
    1086           9 : }
    1087             : 
    1088           4 : GF_Err iaux_box_read(GF_Box *s, GF_BitStream *bs)
    1089             : {
    1090             :         GF_AuxiliaryInfoPropertyBox *p = (GF_AuxiliaryInfoPropertyBox *)s;
    1091             : 
    1092           4 :         ISOM_DECREASE_SIZE(p, 8)
    1093           4 :         p->aux_info_type = gf_bs_read_u32(bs);
    1094           4 :         p->aux_info_parameter = gf_bs_read_u32(bs);
    1095           4 :         return GF_OK;
    1096             : }
    1097             : 
    1098             : #ifndef GPAC_DISABLE_ISOM_WRITE
    1099           4 : GF_Err iaux_box_write(GF_Box *s, GF_BitStream *bs)
    1100             : {
    1101             :         GF_Err e;
    1102             :         GF_AuxiliaryInfoPropertyBox *p = (GF_AuxiliaryInfoPropertyBox*)s;
    1103             : 
    1104           4 :         e = gf_isom_full_box_write(s, bs);
    1105           4 :         if (e) return e;
    1106           4 :         gf_bs_write_u32(bs, p->aux_info_type);
    1107           4 :         gf_bs_write_u32(bs, p->aux_info_parameter);
    1108           4 :         return GF_OK;
    1109             : }
    1110             : 
    1111          10 : GF_Err iaux_box_size(GF_Box *s)
    1112             : {
    1113             :         GF_AuxiliaryInfoPropertyBox *p = (GF_AuxiliaryInfoPropertyBox*)s;
    1114          10 :         p->size += 8;
    1115          10 :         return GF_OK;
    1116             : }
    1117             : 
    1118             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
    1119             : 
    1120             : 
    1121             : 
    1122         102 : static GF_Err gf_isom_iff_create_image_item_from_track_internal(GF_ISOFile *movie, Bool root_meta, u32 meta_track_number, u32 imported_track, const char *item_name, u32 item_id, GF_ImageItemProperties *image_props, GF_List *item_extent_refs, u32 sample_number) {
    1123             : #ifndef GPAC_DISABLE_ISOM_WRITE
    1124             :         GF_Err e;
    1125             :         u32 w, h, hSpacing, vSpacing;
    1126             :         u8 num_channels;
    1127             :         u8 bits_per_channel[3];
    1128             :         u32 subtype;
    1129         102 :         GF_ISOSample *sample = NULL;
    1130             :         u32 timescale;
    1131             :         u32 item_type = 0;
    1132             :         GF_ImageItemProperties local_image_props;
    1133             :         GF_ImageItemProtection ipro, *orig_ipro = NULL;
    1134             :         Bool config_needed = 0;
    1135             :         GF_Box *config_box = NULL;
    1136             :         Bool is_cenc = GF_FALSE;
    1137             :         Bool is_first = GF_TRUE;
    1138         102 :         Bool neg_time = (image_props && image_props->time<0) ? GF_TRUE : GF_FALSE;
    1139         102 :         u8 *sai = NULL;
    1140         102 :         u32 sai_size = 0, sai_alloc_size = 0;
    1141         102 :         u32 sample_desc_index = 0;
    1142             :         GF_ISOFile *fsrc = movie;
    1143             : 
    1144         102 :         if (image_props && image_props->src_file)
    1145             :                 fsrc = image_props->src_file;
    1146             : 
    1147         102 :         if (image_props && image_props->tile_mode != TILE_ITEM_NONE) {
    1148             :                 /* Processing the input file in Tiled mode:
    1149             :                    The single track is split into multiple tracks
    1150             :                    and each track is processed to create an item */
    1151             :                 u32 i, count;
    1152             :                 u32 tile_track;
    1153             :                 GF_List *tile_item_ids;
    1154             :                 char sz_item_name[256];
    1155             :                 GF_TileItemMode orig_tile_mode;
    1156             : 
    1157             : #if !defined(GPAC_DISABLE_HEVC) && !defined(GPAC_DISABLE_AV_PARSERS)
    1158           1 :                 if (image_props->src_file)
    1159             :                         e = GF_SERVICE_ERROR;
    1160             :                 else
    1161           1 :                         e = gf_media_split_hevc_tiles(movie, 0);
    1162             : #else
    1163             :                 e = GF_NOT_SUPPORTED;
    1164             : #endif
    1165             : 
    1166           1 :                 if (e) return e;
    1167           1 :                 tile_item_ids = gf_list_new();
    1168           1 :                 orig_tile_mode = image_props->tile_mode;
    1169           1 :                 image_props->tile_mode = TILE_ITEM_NONE;
    1170           1 :                 count = gf_isom_get_reference_count(movie, imported_track, GF_ISOM_REF_SABT);
    1171          11 :                 for (i = 0; i < count; i++) {
    1172           9 :                         u32 *tile_item_id = gf_malloc(sizeof(u32));
    1173           9 :                         if (!tile_item_id) return GF_OUT_OF_MEM;
    1174             : 
    1175           9 :                         *tile_item_id = item_id + i+1;
    1176           9 :                         gf_list_add(tile_item_ids, tile_item_id);
    1177           9 :                         e = gf_isom_get_reference(movie, imported_track, GF_ISOM_REF_SABT, 1, &tile_track);
    1178           9 :                         if (e) return e;
    1179           9 :                         sprintf(sz_item_name, "%s-Tile%d", (item_name ? item_name : "Image"), i + 1);
    1180           9 :                         if (orig_tile_mode != TILE_ITEM_SINGLE || image_props->single_tile_number == i + 1) {
    1181           9 :                                 e = gf_isom_iff_create_image_item_from_track(movie, root_meta, meta_track_number, tile_track, sz_item_name, *tile_item_id, NULL, NULL);
    1182             :                         }
    1183           9 :                         if (e) return e;
    1184           9 :                         gf_isom_remove_track(movie, tile_track);
    1185           9 :                         if (orig_tile_mode == TILE_ITEM_ALL_BASE) {
    1186           9 :                                 e = gf_isom_meta_add_item_ref(movie, root_meta, meta_track_number, *tile_item_id, item_id, GF_ISOM_REF_TBAS, NULL);
    1187             :                         }
    1188           9 :                         if (e) return e;
    1189             :                 }
    1190           1 :                 sprintf(sz_item_name, "%s-TileBase", (item_name ? item_name : "Image"));
    1191           1 :                 if (orig_tile_mode == TILE_ITEM_ALL_BASE) {
    1192           1 :                         gf_isom_iff_create_image_item_from_track(movie, root_meta, meta_track_number, imported_track, sz_item_name, item_id, image_props, tile_item_ids);
    1193             :                 }
    1194             :                 else if (orig_tile_mode == TILE_ITEM_ALL_GRID) {
    1195             :                         // TODO
    1196             :                 }
    1197           9 :                 for (i = 0; i < count; i++) {
    1198           9 :                         u32 *tile_item_id = gf_list_get(tile_item_ids, i);
    1199           9 :                         gf_free(tile_item_id);
    1200             :                 }
    1201           1 :                 gf_list_del(tile_item_ids);
    1202           1 :                 return GF_OK;
    1203             :         }
    1204             : 
    1205         101 :         if (!image_props) {
    1206             :                 image_props = &local_image_props;
    1207             :                 memset(image_props, 0, sizeof(GF_ImageItemProperties));
    1208             :         } else {
    1209          51 :                 orig_ipro = image_props->cenc_info;
    1210          51 :                 image_props->cenc_info = NULL;
    1211             :         }
    1212             : 
    1213         101 : import_next_sample:
    1214             : 
    1215         385 :         timescale = gf_isom_get_media_timescale(fsrc, imported_track);
    1216         385 :         if (image_props->sample_num) {
    1217           5 :                 sample_number = image_props->sample_num;
    1218           5 :                 sample = gf_isom_get_sample(fsrc, imported_track, sample_number, &sample_desc_index);
    1219           5 :                 e = gf_isom_last_error(fsrc);
    1220         380 :         } else if (image_props->time<0) {
    1221         265 :                 sample = gf_isom_get_sample(fsrc, imported_track, sample_number, &sample_desc_index);
    1222         265 :                 e = gf_isom_last_error(fsrc);
    1223             :         } else {
    1224         115 :                 e = gf_isom_get_sample_for_media_time(fsrc, imported_track, (u64)(image_props->time*timescale), &sample_desc_index, GF_ISOM_SEARCH_SYNC_FORWARD, &sample, &sample_number, NULL);
    1225             :         }
    1226         385 :         if (e || !sample || !sample->IsRAP) {
    1227         243 :                 if (!sample) {
    1228           2 :                         if (is_first) {
    1229           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("No sample found%s\n", (image_props->time<0) ? "" : " for requested time"));
    1230             :                         } else {
    1231             :                                 e = GF_OK;
    1232             :                                 goto exit;
    1233             :                         }
    1234         241 :                 } else if ((image_props->time<0) || (image_props->step_time)) {
    1235         241 :                         if (image_props->sample_num) {
    1236           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Error: imported sample %d (DTS "LLU") is not a sync sample (RAP %d size %d)\n", sample_number, sample->DTS, sample->IsRAP, sample->dataLength));
    1237         241 :                         } else if (image_props->step_time) {
    1238           0 :                                 gf_isom_sample_del(&sample);
    1239             :                                 e = GF_OK;
    1240           0 :                                 goto exit;
    1241             :                         } else {
    1242         241 :                                 gf_isom_sample_del(&sample);
    1243         241 :                                 sample_number++;
    1244         241 :                                 if (sample_number == gf_isom_get_sample_count(fsrc, imported_track)) {
    1245             :                                         e = GF_OK;
    1246             :                                         goto exit;
    1247             :                                 }
    1248             :                                 goto import_next_sample;
    1249             :                         }
    1250             :                 } else {
    1251           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Error no sync sample found after time %g\n", image_props->time));
    1252             :                 }
    1253           0 :                 if (!e) e = GF_BAD_PARAM;
    1254             :                 goto exit;
    1255             :         }
    1256             : 
    1257             :         /* Check if the track type is supported as item type */
    1258             :         /* Get the config box if needed */
    1259         142 :         subtype = gf_isom_get_media_subtype(fsrc, imported_track, sample_desc_index);
    1260         142 :         if (gf_isom_is_media_encrypted(fsrc, imported_track, sample_desc_index)) {
    1261          13 :                 if (gf_isom_is_cenc_media(fsrc, imported_track, sample_desc_index)) {
    1262          13 :                         e = gf_isom_get_original_format_type(fsrc, imported_track, sample_desc_index, &subtype);
    1263          13 :                         if (e) goto exit;
    1264             :                         is_cenc = GF_TRUE;
    1265             :                 } else {
    1266           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Protected sample not using CENC, cannot add as item\n"));
    1267             :                         e = GF_BAD_PARAM;
    1268             :                         goto exit;
    1269             :                 }
    1270             :         }
    1271             : 
    1272             : 
    1273         142 :         switch (subtype) {
    1274          12 :         case GF_ISOM_SUBTYPE_AVC_H264:
    1275             :         case GF_ISOM_SUBTYPE_AVC2_H264:
    1276             :         case GF_ISOM_SUBTYPE_AVC3_H264:
    1277             :         case GF_ISOM_SUBTYPE_AVC4_H264:
    1278             :                 //FIXME: in avc1 with multiple descriptor, we should take the right description index
    1279          12 :                 config_box = gf_isom_box_new(GF_ISOM_BOX_TYPE_AVCC);
    1280          12 :                 if (!config_box) { e = GF_OUT_OF_MEM; goto exit; }
    1281          12 :                 ((GF_AVCConfigurationBox *)config_box)->config = gf_isom_avc_config_get(fsrc, imported_track, sample_desc_index);
    1282          12 :                 if (! ((GF_AVCConfigurationBox *)config_box)->config) { e = GF_OUT_OF_MEM; goto exit; }
    1283             :                 item_type = GF_ISOM_SUBTYPE_AVC_H264;
    1284             :                 config_needed = 1;
    1285             :                 num_channels = 3;
    1286          12 :                 bits_per_channel[0] = ((GF_AVCConfigurationBox *)config_box)->config->luma_bit_depth;
    1287          12 :                 bits_per_channel[1] = ((GF_AVCConfigurationBox *)config_box)->config->chroma_bit_depth;
    1288             :                 bits_per_channel[2] = ((GF_AVCConfigurationBox *)config_box)->config->chroma_bit_depth;
    1289          12 :                 break;
    1290           0 :         case GF_ISOM_SUBTYPE_SVC_H264:
    1291           0 :                 config_box = gf_isom_box_new(GF_ISOM_BOX_TYPE_SVCC);
    1292           0 :                 if (!config_box) { e = GF_OUT_OF_MEM; goto exit; }
    1293           0 :                 ((GF_AVCConfigurationBox *)config_box)->config = gf_isom_svc_config_get(fsrc, imported_track, sample_desc_index);
    1294           0 :                 if (! ((GF_AVCConfigurationBox *)config_box)->config) { e = GF_OUT_OF_MEM; goto exit; }
    1295             :                 item_type = GF_ISOM_SUBTYPE_SVC_H264;
    1296             :                 config_needed = 1;
    1297             :                 num_channels = 3;
    1298           0 :                 bits_per_channel[0] = ((GF_AVCConfigurationBox *)config_box)->config->luma_bit_depth;
    1299           0 :                 bits_per_channel[1] = ((GF_AVCConfigurationBox *)config_box)->config->chroma_bit_depth;
    1300             :                 bits_per_channel[2] = ((GF_AVCConfigurationBox *)config_box)->config->chroma_bit_depth;
    1301           0 :                 break;
    1302           0 :         case GF_ISOM_SUBTYPE_MVC_H264:
    1303           0 :                 config_box = gf_isom_box_new(GF_ISOM_BOX_TYPE_MVCC);
    1304           0 :                 if (!config_box) { e = GF_OUT_OF_MEM; goto exit; }
    1305           0 :                 ((GF_AVCConfigurationBox *)config_box)->config = gf_isom_mvc_config_get(fsrc, imported_track, sample_desc_index);
    1306           0 :                 if (! ((GF_AVCConfigurationBox *)config_box)->config) { e = GF_OUT_OF_MEM; goto exit; }
    1307             :                 item_type = GF_ISOM_SUBTYPE_MVC_H264;
    1308             :                 config_needed = 1;
    1309             :                 num_channels = 3;
    1310           0 :                 bits_per_channel[0] = ((GF_AVCConfigurationBox *)config_box)->config->luma_bit_depth;
    1311           0 :                 bits_per_channel[1] = ((GF_AVCConfigurationBox *)config_box)->config->chroma_bit_depth;
    1312             :                 bits_per_channel[2] = ((GF_AVCConfigurationBox *)config_box)->config->chroma_bit_depth;
    1313           0 :                 break;
    1314          78 :         case GF_ISOM_SUBTYPE_HVC1:
    1315             :         case GF_ISOM_SUBTYPE_HEV1:
    1316             :         case GF_ISOM_SUBTYPE_HVC2:
    1317             :         case GF_ISOM_SUBTYPE_HEV2:
    1318             :         case GF_ISOM_SUBTYPE_HVT1:
    1319             :         case GF_ISOM_SUBTYPE_LHV1:
    1320             :         case GF_ISOM_SUBTYPE_LHE1:
    1321          78 :                 config_box = gf_isom_box_new(GF_ISOM_BOX_TYPE_HVCC);
    1322          78 :                 if (!config_box) { e = GF_OUT_OF_MEM; goto exit; }
    1323          78 :                 ((GF_HEVCConfigurationBox *)config_box)->config = gf_isom_hevc_config_get(fsrc, imported_track, sample_desc_index);
    1324          78 :                 if (! ((GF_HEVCConfigurationBox *)config_box)->config) { e = GF_OUT_OF_MEM; goto exit; }
    1325          78 :                 if (subtype == GF_ISOM_SUBTYPE_HVT1) {
    1326             :                         item_type = GF_ISOM_SUBTYPE_HVT1;
    1327             :                 }
    1328             :                 else {
    1329             :                         item_type = GF_ISOM_SUBTYPE_HVC1;
    1330             :                 }
    1331             :                 config_needed = 1;
    1332             :                 if (!((GF_HEVCConfigurationBox *)config_box)->config) {
    1333             :                         ((GF_HEVCConfigurationBox *)config_box)->config = gf_isom_lhvc_config_get(fsrc, imported_track, sample_desc_index);
    1334             :                         if (! ((GF_HEVCConfigurationBox *)config_box)->config) { e = GF_OUT_OF_MEM; goto exit; }
    1335             :                         item_type = GF_ISOM_SUBTYPE_LHV1;
    1336             :                 }
    1337             :                 num_channels = 3;
    1338          78 :                 bits_per_channel[0] = ((GF_HEVCConfigurationBox *)config_box)->config->luma_bit_depth;
    1339          78 :                 bits_per_channel[1] = ((GF_HEVCConfigurationBox *)config_box)->config->chroma_bit_depth;
    1340             :                 bits_per_channel[2] = ((GF_HEVCConfigurationBox *)config_box)->config->chroma_bit_depth;
    1341             :                 //media_brand = GF_ISOM_BRAND_HEIC;
    1342          78 :                 break;
    1343          52 :         case GF_ISOM_SUBTYPE_AV01:
    1344             :                 {
    1345          52 :                         config_box = gf_isom_box_new(GF_ISOM_BOX_TYPE_AV1C);
    1346          52 :                         if (!config_box) { e = GF_OUT_OF_MEM; goto exit; }
    1347          52 :                         ((GF_AV1ConfigurationBox *)config_box)->config = gf_isom_av1_config_get(fsrc, imported_track, sample_desc_index);
    1348          52 :                         if (! ((GF_AV1ConfigurationBox *)config_box)->config) { e = GF_OUT_OF_MEM; goto exit; }
    1349             :                         item_type = GF_ISOM_SUBTYPE_AV01;
    1350             :                         config_needed = 1;
    1351          52 :                         u8 depth = ((GF_AV1ConfigurationBox *)config_box)->config->high_bitdepth ? (((GF_AV1ConfigurationBox *)config_box)->config->twelve_bit ? 12 : 10 ) : 8;
    1352          52 :                         if (((GF_AV1ConfigurationBox *)config_box)->config->monochrome) {
    1353             :                                 num_channels = 1;
    1354             :                                 bits_per_channel[0] = depth;
    1355             :                                 bits_per_channel[1] = 0;
    1356             :                                 bits_per_channel[2] = 0;
    1357             :                         } else {
    1358             :                                 num_channels = 3;
    1359             :                                 bits_per_channel[0] = depth;
    1360             :                                 bits_per_channel[1] = depth;
    1361             :                                 bits_per_channel[2] = depth;
    1362             :                         }
    1363             :                         //media_brand = GF_ISOM_BRAND_AVIF;
    1364             :                 }
    1365             :                 break;
    1366             : 
    1367           0 :         case GF_ISOM_SUBTYPE_VVC1:
    1368           0 :                 config_box = gf_isom_box_new(GF_ISOM_BOX_TYPE_VVCC);
    1369           0 :                 if (!config_box) { e = GF_OUT_OF_MEM; goto exit; }
    1370           0 :                 ((GF_VVCConfigurationBox *)config_box)->config = gf_isom_vvc_config_get(fsrc, imported_track, sample_desc_index);
    1371           0 :                 if (! ((GF_VVCConfigurationBox *)config_box)->config) { e = GF_OUT_OF_MEM; goto exit; }
    1372             :                 item_type = GF_ISOM_SUBTYPE_VVC1;
    1373             : 
    1374             :                 config_needed = 1;
    1375             :                 num_channels = 3;
    1376           0 :                 bits_per_channel[0] = ((GF_VVCConfigurationBox *)config_box)->config->bit_depth_plus_one - 1;
    1377             :                 bits_per_channel[1] = bits_per_channel[2] = bits_per_channel[0];
    1378             :                 //media_brand = GF_ISOM_BRAND_HEIC;
    1379           0 :                 break;
    1380           0 :         default:
    1381           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Error: Codec not supported to create HEIF image items\n"));
    1382             :                 e = GF_NOT_SUPPORTED;
    1383             :                 goto exit;
    1384             :         }
    1385         142 :         if (config_needed && !config_box && !((GF_AVCConfigurationBox *)config_box)->config) {
    1386           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Error: Image type %s requires a missing configuration box\n", gf_4cc_to_str(item_type)));
    1387             :                 e = GF_BAD_PARAM;
    1388             :                 goto exit;
    1389             :         }
    1390             :         /* Get some images properties from the track data */
    1391         142 :         e = gf_isom_get_visual_info(fsrc, imported_track, sample_desc_index, &w, &h);
    1392         142 :         if (e) {
    1393           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Error determining image size\n"));
    1394             :                 goto exit;
    1395             :         }
    1396         142 :         e = gf_isom_get_pixel_aspect_ratio(fsrc, imported_track, sample_desc_index, &hSpacing, &vSpacing);
    1397         142 :         if (e) {
    1398           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Error determining image aspect ratio\n"));
    1399             :                 goto exit;
    1400             :         }
    1401         142 :         if (!image_props->width && !image_props->height) {
    1402         101 :                 image_props->width = w;
    1403         101 :                 image_props->height = h;
    1404             :         }
    1405         142 :         if (!image_props->hSpacing && !image_props->vSpacing) {
    1406         101 :                 image_props->hSpacing = hSpacing;
    1407         101 :                 image_props->vSpacing = vSpacing;
    1408             :         }
    1409         142 :         image_props->config = config_box;
    1410         142 :         if (!image_props->num_channels) {
    1411         101 :                 image_props->num_channels = num_channels;
    1412         101 :                 image_props->bits_per_channel[0] = bits_per_channel[0];
    1413         101 :                 image_props->bits_per_channel[1] = bits_per_channel[1];
    1414         101 :                 image_props->bits_per_channel[2] = bits_per_channel[2];
    1415             :         }
    1416         142 :         if (is_cenc) {
    1417             :                 Bool Is_Encrypted;
    1418             : 
    1419             :                 memset(&ipro, 0, sizeof(GF_ImageItemProtection));
    1420          13 :                 gf_isom_get_cenc_info(fsrc, imported_track, sample_desc_index, NULL, &ipro.scheme_type, &ipro.scheme_version);
    1421          13 :                 e = gf_isom_get_sample_cenc_info(fsrc, imported_track, sample_desc_index, &Is_Encrypted, &ipro.crypt_byte_block, &ipro.skip_byte_block, &ipro.key_info, &ipro.key_info_size);
    1422          13 :                 if (e) goto exit;
    1423             : 
    1424          13 :                 if (Is_Encrypted) {
    1425          13 :                         sai_size = sai_alloc_size;
    1426          13 :                         e = gf_isom_cenc_get_sample_aux_info(fsrc, imported_track, sample_number, sample_desc_index, NULL, &sai, &sai_size);
    1427          13 :                         if (e) goto exit;
    1428             : 
    1429          13 :                         if (sai_size > sai_alloc_size)
    1430             :                                 sai_alloc_size = sai_size;
    1431             : 
    1432          13 :                         ipro.sai_data = sai;
    1433          13 :                         ipro.sai_data_size = sai_size;
    1434          13 :                         image_props->cenc_info = &ipro;
    1435             : 
    1436          13 :                         if (is_first) {
    1437          13 :                                 u32 i, nb_pssh = gf_isom_get_pssh_count(fsrc);
    1438          44 :                                 for (i=0; i<nb_pssh; i++) {
    1439             :                                         bin128 SystemID;
    1440             :                                         u32 version;
    1441             :                                         u32 KID_count;
    1442             :                                         const bin128 *KIDs;
    1443             :                                         const u8 *private_data;
    1444             :                                         u32 private_data_size;
    1445             : 
    1446          18 :                                         gf_isom_get_pssh_info(fsrc, i+1, SystemID, &version, &KID_count, &KIDs, &private_data, &private_data_size);
    1447             :                                         
    1448          18 :                                         gf_cenc_set_pssh(movie, SystemID, version, KID_count, (bin128 *) KIDs, (u8 *) private_data, private_data_size, 2);
    1449             :                                 }
    1450             :                         }
    1451             : 
    1452             :                 } else {
    1453           0 :                         image_props->cenc_info = NULL;
    1454             :                 }
    1455             :         }
    1456             : 
    1457         142 :         if (!item_id) {
    1458          41 :                 e = gf_isom_meta_get_next_item_id(movie, root_meta, meta_track_number, &item_id);
    1459          41 :                 if (e) goto exit;
    1460             :         }
    1461         142 :         if (image_props->use_reference) {
    1462           1 :                 if (image_props->sample_num) {
    1463           1 :                         GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("referring trackID %d sample %d as item %d\n", imported_track, sample_number, item_id));
    1464             :                 } else {
    1465           0 :                         GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("referring trackID %d sample at time %.3f as item %d\n", imported_track, (sample->DTS+sample->CTS_Offset)*1.0/timescale, item_id));
    1466             :                 }
    1467           1 :                 e = gf_isom_add_meta_item_sample_ref(movie, root_meta, meta_track_number, (!item_name || !strlen(item_name)) ? "Image" : item_name, &item_id, item_type, NULL, NULL, image_props, imported_track, sample_number);
    1468             :         } else {
    1469             : 
    1470         141 :                 if (image_props->sample_num) {
    1471           4 :                         GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("Adding sample %d as item %d\n", sample_number, item_id));
    1472             :                 } else {
    1473         137 :                         GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("Adding sample at time %.3f as item %d\n", (sample->DTS+sample->CTS_Offset)*1.0/timescale, item_id));
    1474             :                 }
    1475         141 :                 e = gf_isom_add_meta_item_memory(movie, root_meta, meta_track_number, (!item_name || !strlen(item_name) ? "Image" : item_name), &item_id, item_type, NULL, NULL, image_props, sample->data, sample->dataLength, item_extent_refs);
    1476             : 
    1477             :         }
    1478             : 
    1479         142 :         image_props->cenc_info = NULL;
    1480             : 
    1481         142 :         gf_isom_set_brand_info(movie, GF_ISOM_BRAND_MIF1, 0);
    1482         142 :         gf_isom_reset_alt_brands(movie);
    1483             :         // TODO Analyze configuration to determine the brand */
    1484             :         //if (media_brand) {
    1485             :         //      gf_isom_modify_alternate_brand(movie, media_brand, GF_TRUE);
    1486             :         //}
    1487             : 
    1488         142 :         if (neg_time)
    1489          25 :                 image_props->time = -1;
    1490             : 
    1491         421 :         if (!e && !image_props->sample_num && ((image_props->time<0) || image_props->end_time || image_props->step_time)) {
    1492          48 :                 if (image_props->end_time || image_props->step_time) {
    1493          26 :                         Double t = (Double) (sample->DTS + sample->CTS_Offset);
    1494          26 :                         t /= timescale;
    1495          26 :                         if (image_props->step_time) {
    1496           6 :                                 t += image_props->step_time;
    1497             :                         } else {
    1498             :                                 //step 1ms
    1499          20 :                                 t += 0.001;
    1500             :                         }
    1501             : 
    1502          26 :                         if ((image_props->end_time>0) && (t>image_props->end_time)) {
    1503             :                                 goto exit;
    1504             :                         }
    1505          22 :                         image_props->time = t;
    1506             :                 }
    1507             : 
    1508          44 :                 item_id=0;
    1509          44 :                 gf_isom_sample_del(&sample);
    1510          44 :                 if (config_box) {
    1511          44 :                         gf_isom_box_del(config_box);
    1512             :                         config_box = NULL;
    1513             :                 }
    1514             :                 is_first = GF_FALSE;
    1515          44 :                 if (sample_number >= gf_isom_get_sample_count(fsrc, imported_track)) return e;
    1516          43 :                 sample_number++;
    1517             :                 //avoid recursion this could get quite big
    1518          43 :                 goto import_next_sample;
    1519             :         }
    1520             : 
    1521         198 : exit:
    1522         100 :         if (sai) gf_free(sai);
    1523         100 :         gf_isom_sample_del(&sample);
    1524         100 :         if (config_box) gf_isom_box_del(config_box);
    1525         100 :         image_props->cenc_info = orig_ipro;
    1526         100 :         return e;
    1527             : 
    1528             : 
    1529             : #else
    1530             :         return GF_NOT_SUPPORTED;
    1531             : #endif
    1532             : 
    1533             : }
    1534             : 
    1535             : static
    1536           9 : GF_Err gf_isom_iff_create_image_grid_item_internal(GF_ISOFile *movie, Bool root_meta, u32 meta_track_number, const char *item_name, u32 *item_id, GF_ImageItemProperties *image_props) {
    1537             :         GF_Err e = GF_OK;
    1538             :         u32 grid4cc = GF_4CC('g', 'r', 'i', 'd');
    1539             :         GF_BitStream *grid_bs;
    1540           9 :         if (image_props->num_grid_rows < 1 || image_props->num_grid_columns < 1 || image_props->width == 0 || image_props->height == 0) {
    1541             :                 return GF_BAD_PARAM;
    1542             :         }
    1543           9 :         grid_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
    1544           9 :         if (!grid_bs) return GF_OUT_OF_MEM;
    1545           9 :         gf_bs_write_u8(grid_bs, 0);
    1546           9 :         gf_bs_write_u8(grid_bs, 0);
    1547           9 :         gf_bs_write_u8(grid_bs, image_props->num_grid_rows-1);
    1548           9 :         gf_bs_write_u8(grid_bs, image_props->num_grid_columns-1);
    1549           9 :         gf_bs_write_u16(grid_bs, image_props->width);
    1550           9 :         gf_bs_write_u16(grid_bs, image_props->height);
    1551             :         u8 *grid_data;
    1552             :         u32 grid_data_size;
    1553           9 :         gf_bs_get_content(grid_bs, &grid_data, &grid_data_size);
    1554           9 :         e = gf_isom_add_meta_item_memory(movie, root_meta, meta_track_number, item_name, item_id, grid4cc, NULL, NULL, image_props, grid_data, grid_data_size, NULL);
    1555           9 :         gf_free(grid_data);
    1556           9 :         gf_bs_del(grid_bs);
    1557           9 :         return e;
    1558             : }
    1559             : 
    1560             : GF_EXPORT
    1561           7 : GF_Err gf_isom_iff_create_image_grid_item(GF_ISOFile *movie, Bool root_meta, u32 meta_track_number, const char *item_name, u32 item_id, GF_ImageItemProperties *image_props)
    1562             : {
    1563           7 :         return gf_isom_iff_create_image_grid_item_internal(movie, root_meta, meta_track_number, item_name, &item_id, image_props);
    1564             : }
    1565             : 
    1566           2 : static GF_Err iff_create_auto_grid(GF_ISOFile *movie, Bool root_meta, u32 meta_track_number, const char *item_name, u32 item_id, GF_ImageItemProperties *image_props)
    1567             : {
    1568             :         GF_Err e;
    1569             :         GF_ImageItemProperties props;
    1570             :         u32 w=0, h=0;
    1571             :         u32 *imgs_ids=NULL;
    1572             :         u32 nb_imgs=0, nb_src_imgs;
    1573             :         u32 nb_cols, nb_rows;
    1574             :         u32 last_valid_nb_cols;
    1575             :         Bool first_pass = GF_TRUE;
    1576             :         Double ar;
    1577           2 :         u32 i, nb_items = gf_isom_get_meta_item_count(movie, root_meta, meta_track_number);
    1578          16 :         for (i=0; i<nb_items; i++) {
    1579             :                 u32 an_item_id, item_type;
    1580          12 :                 gf_isom_get_meta_item_info(movie, root_meta, meta_track_number, i+1, &an_item_id, &item_type, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
    1581             : 
    1582          12 :                 if (!item_id) continue;
    1583          12 :                 if (item_type==GF_ISOM_ITEM_TYPE_AUXI) continue;
    1584             : 
    1585             :                 memset(&props, 0, sizeof(props));
    1586          12 :                 gf_isom_get_meta_image_props(movie, root_meta, meta_track_number, an_item_id, &props);
    1587          12 :                 if (!props.width || !props.height) continue;
    1588             : 
    1589          12 :                 if (!w) w = props.width;
    1590          12 :                 if (!h) h = props.height;
    1591             : 
    1592          12 :                 if ((w != props.width) || (h != props.height)) {
    1593           0 :                         if (imgs_ids) gf_free(imgs_ids);
    1594           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Auto grid can only be generated for images of the same size - try using `-add-image-grid`\n"));
    1595           0 :                         return GF_NOT_SUPPORTED;
    1596             :                 }
    1597          12 :                 imgs_ids = gf_realloc(imgs_ids, sizeof(u32) * (nb_imgs+1));
    1598          12 :                 if (!imgs_ids) return GF_OUT_OF_MEM;
    1599          12 :                 imgs_ids[nb_imgs] = an_item_id;
    1600             :                 nb_imgs++;
    1601             :         }
    1602             : 
    1603           2 :         if (!nb_imgs || !w || !h) {
    1604           0 :                 if (imgs_ids) gf_free(imgs_ids);
    1605           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("No image items found\n"));
    1606             :                 return GF_BAD_PARAM;
    1607             :         }
    1608             : 
    1609             :         //try roughly the same aspect ratio
    1610           2 :         if (image_props->auto_grid_ratio) {
    1611             :                 ar = image_props->auto_grid_ratio;
    1612             :         } else {
    1613           1 :                 ar = w;
    1614           1 :                 ar /= h;
    1615             :         }
    1616             :         nb_src_imgs = nb_imgs;
    1617             : 
    1618           2 : recompute_grid:
    1619             :         nb_cols=1;
    1620             :         nb_rows=1;
    1621             :         last_valid_nb_cols = 0;
    1622             : 
    1623           2 :         if (nb_imgs>1) {
    1624           5 :                 while (nb_cols < nb_imgs) {
    1625           5 :                         Double target_ar = ((Double) nb_cols) * w;
    1626           5 :                         nb_rows = nb_imgs / nb_cols;
    1627           5 :                         if (nb_rows * nb_cols != nb_imgs) {
    1628           0 :                                 nb_cols++;
    1629           0 :                                 continue;
    1630             :                         }
    1631           5 :                         target_ar /= ((Double)nb_rows) * h;
    1632           5 :                         if (target_ar >= ar) break;
    1633             :                         last_valid_nb_cols = nb_cols;
    1634           3 :                         nb_cols++;
    1635             :                 }
    1636             :         }
    1637           2 :         if ((nb_cols==nb_imgs) && last_valid_nb_cols) {
    1638             :                 nb_cols = last_valid_nb_cols;
    1639           0 :                 nb_rows = nb_imgs / nb_cols;
    1640             :         }
    1641             : 
    1642           2 :         if (first_pass && (nb_imgs>1) && ((nb_cols==1) || (nb_rows==1) ) ) {
    1643           0 :                 if (nb_imgs % 2) {
    1644           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("Not an even number of images, removing last item from grid\n"));
    1645           0 :                         nb_imgs--;
    1646             :                         first_pass = GF_FALSE;
    1647           0 :                         goto recompute_grid;
    1648             :                 }
    1649             :         }
    1650             : 
    1651             :         memset(&props, 0, sizeof(props));
    1652             :         if (image_props)
    1653             :                 memcpy(&props, image_props, sizeof(props));
    1654           2 :         props.hidden = GF_FALSE;
    1655           2 :         props.width = nb_cols * w;
    1656           2 :         props.height = nb_rows * h;
    1657           2 :         props.num_grid_rows = nb_rows;
    1658           2 :         props.num_grid_columns = nb_cols;
    1659           2 :         GF_LOG(GF_LOG_INFO, GF_LOG_CONTAINER, ("Grid: %u rows %u cols - size %ux%u pixels\n", nb_cols, nb_rows, props.width, props.height));
    1660             : 
    1661           2 :         e = gf_isom_iff_create_image_grid_item_internal(movie, root_meta, meta_track_number, item_name, &item_id, &props);
    1662           2 :         if (e) {
    1663           0 :                 gf_free(imgs_ids);
    1664           0 :                 return e;
    1665             :         }
    1666             : 
    1667          12 :         for (i=0; i<nb_imgs; i++) {
    1668          12 :                 e = gf_isom_meta_add_item_ref(movie, root_meta, meta_track_number, item_id, imgs_ids[i], GF_4CC('d','i','m','g'), NULL);
    1669          12 :                 if (e) goto exit;
    1670             :         }
    1671             : 
    1672             :         //we might want an option to avoid this?
    1673             :         //if (image_props->hidden)
    1674             :         {
    1675           2 :                 GF_MetaBox *meta = gf_isom_get_meta(movie, root_meta, meta_track_number);
    1676          14 :                 for (i=0; i<nb_src_imgs; i++) {
    1677             :                         GF_ItemInfoEntryBox *iinf;
    1678          12 :                         u32 j=0;
    1679          54 :                         while ((iinf = (GF_ItemInfoEntryBox *)gf_list_enum(meta->item_infos->item_infos, &j))) {
    1680          42 :                                 if (iinf->item_ID == imgs_ids[i]) {
    1681          12 :                                         iinf->flags |= 0x1;
    1682          12 :                                         break;
    1683             :                                 }
    1684             :                         }
    1685             :                 }
    1686           2 :                 e = gf_isom_set_meta_primary_item(movie, root_meta, meta_track_number, item_id);
    1687             :         }
    1688             : 
    1689           2 : exit:
    1690           2 :         gf_free(imgs_ids);
    1691           2 :         return e;
    1692             : }
    1693             : 
    1694             : GF_EXPORT
    1695         104 : GF_Err gf_isom_iff_create_image_item_from_track(GF_ISOFile *movie, Bool root_meta, u32 meta_track_number, u32 imported_track, const char *item_name, u32 item_id, GF_ImageItemProperties *image_props, GF_List *item_extent_refs)
    1696             : {
    1697             : 
    1698         104 :         if (image_props && image_props->auto_grid)
    1699           2 :                 return iff_create_auto_grid(movie, root_meta, meta_track_number, item_name, item_id, image_props);
    1700             : 
    1701         102 :         return gf_isom_iff_create_image_item_from_track_internal(movie, root_meta, meta_track_number, imported_track, item_name, item_id, image_props, item_extent_refs, 1);
    1702             : }
    1703             : 
    1704             : 
    1705             : #endif /*GPAC_DISABLE_ISOM*/

Generated by: LCOV version 1.13