LCOV - code coverage report
Current view: top level - odf - odf_command.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 203 226 89.8 %
Date: 2021-04-29 23:48:07 Functions: 21 23 91.3 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2012
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / MPEG-4 ObjectDescriptor sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : 
      27             : #include <gpac/internal/odf_dev.h>
      28             : 
      29             : 
      30         249 : GF_Err gf_odf_parse_command(GF_BitStream *bs, GF_ODCom **com, u32 *com_size)
      31             : {
      32             :         u32 val, size, sizeHeader;
      33             :         u8 tag;
      34             :         GF_Err err;
      35             :         GF_ODCom *newCom;
      36         249 :         if (!bs) return GF_BAD_PARAM;
      37             : 
      38         249 :         *com_size = 0;
      39             : 
      40             :         //tag
      41         249 :         tag = gf_bs_read_int(bs, 8);
      42             :         sizeHeader = 1;
      43             : 
      44             :         //size
      45             :         size = 0;
      46             :         do {
      47         278 :                 val = gf_bs_read_int(bs, 8);
      48         278 :                 sizeHeader++;
      49         278 :                 size <<= 7;
      50         278 :                 size |= val & 0x7F;
      51         278 :         } while ( val & 0x80 );
      52         249 :         *com_size = size;
      53             : 
      54         249 :         newCom = gf_odf_create_command(tag);
      55         249 :         if (! newCom) {
      56           0 :                 *com = NULL;
      57           0 :                 return GF_OUT_OF_MEM;
      58             :         }
      59             : 
      60         249 :         newCom->tag = tag;
      61             : 
      62         249 :         err = gf_odf_read_command(bs, newCom, *com_size);
      63             :         //little trick to handle lazy bitstreams that encode
      64             :         //SizeOfInstance on a fix number of bytes
      65             :         //This nb of bytes is added in Read methods
      66         249 :         *com_size += sizeHeader - gf_odf_size_field_size(*com_size);
      67         249 :         *com = newCom;
      68         249 :         if (err) {
      69           0 :                 gf_odf_delete_command(newCom);
      70           0 :                 *com = NULL;
      71             :         }
      72             :         return err;
      73             : }
      74             : 
      75             : #ifndef GPAC_MINIMAL_ODF
      76             : 
      77             : GF_ODCom *gf_odf_new_base_command()
      78             : {
      79             :         GF_BaseODCom *newCom = (GF_BaseODCom *) gf_malloc(sizeof(GF_BaseODCom));
      80             :         if (!newCom) return NULL;
      81             :         newCom->dataSize = 0;
      82             :         newCom->data = NULL;
      83             :         return (GF_ODCom *)newCom;
      84             : }
      85             : GF_Err gf_odf_del_base_command(GF_BaseODCom *bcRemove)
      86             : {
      87             :         if (! bcRemove) return GF_BAD_PARAM;
      88             :         if (bcRemove->data) gf_free(bcRemove->data);
      89             :         gf_free(bcRemove);
      90             :         return GF_OK;
      91             : }
      92             : 
      93             : GF_Err gf_odf_read_base_command(GF_BitStream *bs, GF_BaseODCom *bcRem, u32 gf_odf_size_command)
      94             : {
      95             :         if (! bcRem) return GF_BAD_PARAM;
      96             : 
      97             :         bcRem->dataSize = gf_odf_size_command;
      98             :         bcRem->data = (char *) gf_malloc(sizeof(char) * bcRem->dataSize);
      99             :         if (! bcRem->data) return GF_OUT_OF_MEM;
     100             :         gf_bs_read_data(bs, bcRem->data, bcRem->dataSize);
     101             :         return GF_OK;
     102             : }
     103             : GF_Err gf_odf_size_base_command(GF_BaseODCom *bcRem, u32 *outSize)
     104             : {
     105             :         if (!bcRem) return GF_BAD_PARAM;
     106             :         *outSize = bcRem->dataSize;
     107             :         return GF_OK;
     108             : }
     109             : GF_Err gf_odf_write_base_command(GF_BitStream *bs, GF_BaseODCom *bcRem)
     110             : {
     111             :         u32 size;
     112             :         GF_Err e;
     113             :         if (! bcRem) return GF_BAD_PARAM;
     114             : 
     115             :         e = gf_odf_size_base_command(bcRem, &size);
     116             :         if (e) return e;
     117             :         e = gf_odf_write_base_descriptor(bs, bcRem->tag, size);
     118             :         if (e) return e;
     119             :         gf_bs_write_data(bs, bcRem->data, bcRem->dataSize);
     120             :         return GF_OK;
     121             : }
     122             : #endif
     123             : 
     124          58 : GF_ODCom *gf_odf_new_od_remove()
     125             : {
     126          58 :         GF_ODRemove *newCom = (GF_ODRemove *) gf_malloc(sizeof(GF_ODRemove));
     127          58 :         if (!newCom) return NULL;
     128          58 :         newCom->NbODs = 0;
     129          58 :         newCom->OD_ID = NULL;
     130          58 :         newCom->tag = GF_ODF_OD_REMOVE_TAG;
     131          58 :         return (GF_ODCom *)newCom;
     132             : }
     133          58 : GF_Err gf_odf_del_od_remove(GF_ODRemove *ODRemove)
     134             : {
     135          58 :         if (! ODRemove) return GF_BAD_PARAM;
     136          58 :         if (ODRemove->OD_ID) gf_free(ODRemove->OD_ID);
     137          58 :         gf_free(ODRemove);
     138          58 :         return GF_OK;
     139             : }
     140          42 : GF_Err gf_odf_read_od_remove(GF_BitStream *bs, GF_ODRemove *odRem, u32 gf_odf_size_command)
     141             : {
     142             :         u32 i = 0, nbBits;
     143          42 :         if (! odRem) return GF_BAD_PARAM;
     144             : 
     145          42 :         odRem->NbODs = (u32 ) (gf_odf_size_command * 8) / 10;
     146          42 :         odRem->OD_ID = (u16 *) gf_malloc(sizeof(u16) * odRem->NbODs);
     147          42 :         if (! odRem->OD_ID) return GF_OUT_OF_MEM;
     148             : 
     149          42 :         for (i = 0; i < odRem->NbODs ; i++) {
     150          42 :                 odRem->OD_ID[i] = gf_bs_read_int(bs, 10);
     151             :         }
     152          42 :         nbBits = odRem->NbODs * 10;
     153             :         //now we need to align !!!
     154          42 :         nbBits += gf_bs_align(bs);
     155          42 :         if (nbBits != (gf_odf_size_command * 8)) return GF_ODF_INVALID_COMMAND;
     156          42 :         return GF_OK;
     157             : }
     158             : 
     159           0 : GF_Err gf_odf_size_od_remove(GF_ODRemove *odRem, u32 *outSize)
     160             : {
     161             :         u32 size;
     162           0 :         if (!odRem) return GF_BAD_PARAM;
     163             : 
     164          36 :         size = 10 * odRem->NbODs;
     165          36 :         *outSize = size/8;
     166          36 :         if (*outSize * 8 != size) *outSize += 1;
     167             :         return GF_OK;
     168             : }
     169             : 
     170          36 : GF_Err gf_odf_write_od_remove(GF_BitStream *bs, GF_ODRemove *odRem)
     171             : {
     172             :         GF_Err e;
     173             :         u32 size, i;
     174          36 :         if (! odRem) return GF_BAD_PARAM;
     175             : 
     176             :         e = gf_odf_size_od_remove(odRem, &size);
     177             :         if (e) return e;
     178          36 :         e = gf_odf_write_base_descriptor(bs, odRem->tag, size);
     179          36 :         if (e) return e;
     180             : 
     181          36 :         for (i = 0; i < odRem->NbODs; i++) {
     182          36 :                 gf_bs_write_int(bs, odRem->OD_ID[i], 10);
     183             :         }
     184             :         //OD commands are aligned
     185          36 :         gf_bs_align(bs);
     186          36 :         return GF_OK;
     187             : }
     188             : 
     189             : 
     190             : 
     191         432 : GF_ODCom *gf_odf_new_od_update()
     192             : {
     193         432 :         GF_ODUpdate *newCom = (GF_ODUpdate *) gf_malloc(sizeof(GF_ODUpdate));
     194         432 :         if (!newCom) return NULL;
     195             : 
     196         432 :         newCom->objectDescriptors = gf_list_new();
     197         432 :         if (! newCom->objectDescriptors) {
     198           0 :                 gf_free(newCom);
     199           0 :                 return NULL;
     200             :         }
     201         432 :         newCom->tag = GF_ODF_OD_UPDATE_TAG;
     202         432 :         return (GF_ODCom *)newCom;
     203             : }
     204             : 
     205         432 : GF_Err gf_odf_del_od_update(GF_ODUpdate *ODUpdate)
     206             : {
     207             :         GF_Err e;
     208         432 :         if (! ODUpdate) return GF_BAD_PARAM;
     209        1047 :         while (gf_list_count(ODUpdate->objectDescriptors)) {
     210         615 :                 GF_Descriptor *tmp = (GF_Descriptor*)gf_list_get(ODUpdate->objectDescriptors, 0);
     211         615 :                 e = gf_odf_delete_descriptor(tmp);
     212         615 :                 if (e) return e;
     213         615 :                 e = gf_list_rem(ODUpdate->objectDescriptors, 0);
     214         615 :                 if (e) return e;
     215             :         }
     216         432 :         gf_list_del(ODUpdate->objectDescriptors);
     217         432 :         gf_free(ODUpdate);
     218         432 :         return GF_OK;
     219             : }
     220             : 
     221             : 
     222             : 
     223         288 : GF_Err AddToODUpdate(GF_ODUpdate *odUp, GF_Descriptor *desc)
     224             : {
     225         288 :         if (! odUp) return GF_BAD_PARAM;
     226         288 :         if (! desc) return GF_OK;
     227             : 
     228         288 :         switch (desc->tag) {
     229         288 :         case GF_ODF_OD_TAG:
     230             :         case GF_ODF_IOD_TAG:
     231             :         case GF_ODF_ISOM_IOD_TAG:
     232             :         case GF_ODF_ISOM_OD_TAG:
     233         288 :                 return gf_list_add(odUp->objectDescriptors, desc);
     234             : 
     235           0 :         default:
     236           0 :                 gf_odf_delete_descriptor(desc);
     237           0 :                 return GF_OK;
     238             :         }
     239             : }
     240             : 
     241         151 : GF_Err gf_odf_read_od_update(GF_BitStream *bs, GF_ODUpdate *odUp, u32 gf_odf_size_command)
     242             : {
     243             :         GF_Descriptor *tmp;
     244             :         GF_Err e = GF_OK;
     245         151 :         u32 tmpSize = 0, nbBytes = 0;
     246         151 :         if (! odUp) return GF_BAD_PARAM;
     247             : 
     248         439 :         while (nbBytes < gf_odf_size_command) {
     249         288 :                 e = gf_odf_parse_descriptor(bs, &tmp, &tmpSize);
     250         288 :                 if (e) return e;
     251         288 :                 e = AddToODUpdate(odUp, tmp);
     252         288 :                 if (e) return e;
     253         288 :                 nbBytes += tmpSize + gf_odf_size_field_size(tmpSize);
     254             :         }
     255             :         //OD commands are aligned
     256         151 :         gf_bs_align(bs);
     257         151 :         if (nbBytes != gf_odf_size_command) return GF_ODF_INVALID_COMMAND;
     258         151 :         return e;
     259             : }
     260         154 : GF_Err gf_odf_size_od_update(GF_ODUpdate *odUp, u32 *outSize)
     261             : {
     262             :         GF_Descriptor *tmp;
     263             :         u32 i, tmpSize;
     264         154 :         if (!odUp) return GF_BAD_PARAM;
     265             : 
     266         154 :         *outSize = 0;
     267         154 :         i=0;
     268         625 :         while ((tmp = (GF_Descriptor *)gf_list_enum(odUp->objectDescriptors, &i))) {
     269         317 :                 gf_odf_size_descriptor(tmp, &tmpSize);
     270         317 :                 *outSize += tmpSize + gf_odf_size_field_size(tmpSize);
     271             :         }
     272             :         return GF_OK;
     273             : }
     274         154 : GF_Err gf_odf_write_od_update(GF_BitStream *bs, GF_ODUpdate *odUp)
     275             : {
     276             :         GF_Err e;
     277             :         GF_Descriptor *tmp;
     278             :         u32 size, i;
     279         154 :         if (! odUp) return GF_BAD_PARAM;
     280             : 
     281         154 :         e = gf_odf_size_od_update(odUp, &size);
     282         154 :         if (e) return e;
     283         154 :         e = gf_odf_write_base_descriptor(bs, odUp->tag, size);
     284         154 :         if (e) return e;
     285             : 
     286         154 :         i=0;
     287         625 :         while ((tmp = (GF_Descriptor *)gf_list_enum(odUp->objectDescriptors, &i))) {
     288         317 :                 e = gf_odf_write_descriptor(bs, tmp);
     289         317 :                 if (e) return e;
     290             :         }
     291             :         //OD commands are aligned
     292         154 :         gf_bs_align(bs);
     293         154 :         return GF_OK;
     294             : }
     295             : 
     296             : 
     297          28 : GF_ODCom *gf_odf_new_esd_update()
     298             : {
     299          28 :         GF_ESDUpdate *newCom = (GF_ESDUpdate *) gf_malloc(sizeof(GF_ESDUpdate));
     300          28 :         if (!newCom) return NULL;
     301             : 
     302          28 :         newCom->ESDescriptors = gf_list_new();
     303          28 :         if (! newCom->ESDescriptors) {
     304           0 :                 gf_free(newCom);
     305           0 :                 return NULL;
     306             :         }
     307          28 :         newCom->tag = GF_ODF_ESD_UPDATE_TAG;
     308          28 :         return (GF_ODCom *)newCom;
     309             : }
     310             : 
     311          28 : GF_Err gf_odf_del_esd_update(GF_ESDUpdate *ESDUpdate)
     312             : {
     313             :         GF_Err e;
     314          28 :         if (! ESDUpdate) return GF_BAD_PARAM;
     315          54 :         while (gf_list_count(ESDUpdate->ESDescriptors)) {
     316          26 :                 GF_Descriptor *tmp = (GF_Descriptor*)gf_list_get(ESDUpdate->ESDescriptors, 0);
     317          26 :                 e = gf_odf_delete_descriptor(tmp);
     318          26 :                 if (e) return e;
     319          26 :                 e = gf_list_rem(ESDUpdate->ESDescriptors, 0);
     320          26 :                 if (e) return e;
     321             :         }
     322          28 :         gf_list_del(ESDUpdate->ESDescriptors);
     323          28 :         gf_free(ESDUpdate);
     324          28 :         return GF_OK;
     325             : }
     326             : 
     327          14 : GF_Err AddToESDUpdate(GF_ESDUpdate *esdUp, GF_Descriptor *desc)
     328             : {
     329          14 :         if (! esdUp) return GF_BAD_PARAM;
     330          14 :         if (!desc) return GF_OK;
     331             : 
     332          14 :         switch (desc->tag) {
     333          14 :         case GF_ODF_ESD_TAG:
     334             :         case GF_ODF_ESD_REF_TAG:
     335          14 :                 return gf_list_add(esdUp->ESDescriptors, desc);
     336             : 
     337           0 :         default:
     338           0 :                 gf_odf_delete_descriptor(desc);
     339           0 :                 return GF_OK;
     340             :         }
     341             : }
     342             : 
     343          14 : GF_Err gf_odf_read_esd_update(GF_BitStream *bs, GF_ESDUpdate *esdUp, u32 gf_odf_size_command)
     344             : {
     345             :         GF_Descriptor *tmp;
     346          14 :         u32 tmpSize = 0, nbBits = 0;
     347             :         GF_Err e = GF_OK;
     348          14 :         if (! esdUp) return GF_BAD_PARAM;
     349             : 
     350          14 :         esdUp->ODID = gf_bs_read_int(bs, 10);
     351             :         nbBits += 10;
     352             :         //very tricky, we're at the bit level here...
     353             :         while (1) {
     354          14 :                 e = gf_odf_parse_descriptor(bs, &tmp, &tmpSize);
     355          14 :                 if (e) return e;
     356          14 :                 e = AddToESDUpdate(esdUp, tmp);
     357          14 :                 if (e) return e;
     358          14 :                 nbBits += ( tmpSize + gf_odf_size_field_size(tmpSize) ) * 8;
     359             :                 //our com is aligned, so nbBits is between (gf_odf_size_command-1)*8 and gf_odf_size_command*8
     360          14 :                 if ( ( (nbBits >(gf_odf_size_command-1)*8) && (nbBits <= gf_odf_size_command * 8))
     361           0 :                         || (nbBits > gf_odf_size_command*8) ) {      //this one is a security break
     362             :                         break;
     363             :                 }
     364             :         }
     365          14 :         if (nbBits > gf_odf_size_command * 8) return GF_ODF_INVALID_COMMAND;
     366             :         //Align our bitstream
     367          14 :         nbBits += gf_bs_align(bs);
     368          14 :         if (nbBits != gf_odf_size_command *8) return GF_ODF_INVALID_COMMAND;
     369          14 :         return e;
     370             : }
     371             : 
     372             : 
     373             : 
     374          12 : GF_Err gf_odf_size_esd_update(GF_ESDUpdate *esdUp, u32 *outSize)
     375             : {
     376             :         u32 i, BitSize, tmpSize;
     377             :         GF_Descriptor *tmp;
     378          12 :         if (!esdUp) return GF_BAD_PARAM;
     379             : 
     380          12 :         *outSize = 0;
     381             :         BitSize = 10;
     382          12 :         i=0;
     383          36 :         while ((tmp = (GF_Descriptor *)gf_list_enum(esdUp->ESDescriptors, &i))) {
     384          12 :                 gf_odf_size_descriptor(tmp, &tmpSize);
     385          12 :                 BitSize += ( tmpSize + gf_odf_size_field_size(tmpSize) ) * 8;
     386             :         }
     387         420 :         while ((s32) BitSize > 0) {
     388         408 :                 BitSize -= 8;
     389         408 :                 *outSize += 1;
     390             :         }
     391             :         return GF_OK;
     392             : }
     393          12 : GF_Err gf_odf_write_esd_update(GF_BitStream *bs, GF_ESDUpdate *esdUp)
     394             : {
     395             :         GF_Descriptor *tmp;
     396             :         GF_Err e;
     397             :         u32 size, i;
     398          12 :         if (! esdUp) return GF_BAD_PARAM;
     399             : 
     400          12 :         e = gf_odf_size_esd_update(esdUp, &size);
     401          12 :         if (e) return e;
     402          12 :         e = gf_odf_write_base_descriptor(bs, esdUp->tag, size);
     403          12 :         if (e) return e;
     404             : 
     405          12 :         gf_bs_write_int(bs, esdUp->ODID, 10);
     406          12 :         i=0;
     407          36 :         while ((tmp = (GF_Descriptor *)gf_list_enum(esdUp->ESDescriptors, &i))) {
     408          12 :                 e = gf_odf_write_descriptor(bs, tmp);
     409          12 :                 if (e) return e;
     410             :         }
     411             :         //OD commands are aligned
     412          12 :         gf_bs_align(bs);
     413          12 :         return GF_OK;
     414             : }
     415             : 
     416             : 
     417          85 : GF_ODCom *gf_odf_new_esd_remove()
     418             : {
     419          85 :         GF_ESDRemove *newCom = (GF_ESDRemove *) gf_malloc(sizeof(GF_ESDRemove));
     420          85 :         if (!newCom) return NULL;
     421          85 :         newCom->NbESDs = 0;
     422          85 :         newCom->ES_ID = NULL;
     423          85 :         newCom->tag = GF_ODF_ESD_REMOVE_TAG;
     424          85 :         return (GF_ODCom *)newCom;
     425             : }
     426             : 
     427          85 : GF_Err gf_odf_del_esd_remove(GF_ESDRemove *ESDRemove)
     428             : {
     429          85 :         if (! ESDRemove) return GF_BAD_PARAM;
     430          85 :         if (ESDRemove->ES_ID) gf_free(ESDRemove->ES_ID);
     431          85 :         gf_free(ESDRemove);
     432          85 :         return GF_OK;
     433             : }
     434             : 
     435             : 
     436          42 : GF_Err gf_odf_read_esd_remove(GF_BitStream *bs, GF_ESDRemove *esdRem, u32 gf_odf_size_command)
     437             : {
     438             :         u32 i = 0;
     439          42 :         if (! esdRem) return GF_BAD_PARAM;
     440             : 
     441          42 :         esdRem->ODID = gf_bs_read_int(bs, 10);
     442          42 :         /*aligned = */gf_bs_read_int(bs, 6);            //aligned
     443             : 
     444             :         //we have gf_odf_size_command - 2 bytes left, and this is our ES_ID[1...255]
     445             :         //this works because OD commands are aligned
     446          42 :         if (gf_odf_size_command < 2) return GF_ODF_INVALID_DESCRIPTOR;
     447          42 :         if (gf_odf_size_command == 2) {
     448           0 :                 esdRem->NbESDs = 0;
     449           0 :                 esdRem->ES_ID = NULL;
     450           0 :                 return GF_OK;
     451             :         }
     452          42 :         esdRem->NbESDs = (gf_odf_size_command - 2) / 2;
     453          42 :         esdRem->ES_ID = (u16 *) gf_malloc(sizeof(u16) * esdRem->NbESDs);
     454          42 :         if (! esdRem->ES_ID) return GF_OUT_OF_MEM;
     455          42 :         for (i = 0; i < esdRem->NbESDs ; i++) {
     456          42 :                 esdRem->ES_ID[i] = gf_bs_read_int(bs, 16);
     457             :         }
     458             :         //OD commands are aligned (but we should already be aligned....
     459          42 :         /*nbBits = */gf_bs_align(bs);
     460          42 :         return GF_OK;
     461             : }
     462             : 
     463           0 : GF_Err gf_odf_size_esd_remove(GF_ESDRemove *esdRem, u32 *outSize)
     464             : {
     465           0 :         if (!esdRem) return GF_BAD_PARAM;
     466          36 :         *outSize = 2 + 2 * esdRem->NbESDs;
     467           0 :         return GF_OK;
     468             : }
     469          36 : GF_Err gf_odf_write_esd_remove(GF_BitStream *bs, GF_ESDRemove *esdRem)
     470             : {
     471             :         GF_Err e;
     472             :         u32 size, i;
     473          36 :         if (! esdRem) return GF_BAD_PARAM;
     474             : 
     475             :         e = gf_odf_size_esd_remove(esdRem, &size);
     476             :         if (e) return e;
     477          36 :         e = gf_odf_write_base_descriptor(bs, esdRem->tag, size);
     478          36 :         if (e) return e;
     479             : 
     480          36 :         gf_bs_write_int(bs, esdRem->ODID, 10);
     481          36 :         gf_bs_write_int(bs, 0, 6);              //aligned
     482          72 :         for (i = 0; i < esdRem->NbESDs ; i++) {
     483          36 :                 gf_bs_write_int(bs, esdRem->ES_ID[i], 16);
     484             :         }
     485             :         //OD commands are aligned (but we are already aligned....
     486          36 :         gf_bs_align(bs);
     487          36 :         return GF_OK;
     488             : }
     489             : 
     490             : #ifndef GPAC_MINIMAL_ODF
     491             : 
     492             : GF_ODCom *gf_odf_new_ipmp_remove()
     493             : {
     494             :         GF_IPMPRemove *newCom = (GF_IPMPRemove *) gf_malloc(sizeof(GF_IPMPRemove));
     495             :         if (!newCom) return NULL;
     496             :         newCom->IPMPDescID  =NULL;
     497             :         newCom->NbIPMPDs = 0;
     498             :         newCom->tag = GF_ODF_IPMP_REMOVE_TAG;
     499             :         return (GF_ODCom *)newCom;
     500             : }
     501             : 
     502             : GF_Err gf_odf_del_ipmp_remove(GF_IPMPRemove *IPMPDRemove)
     503             : {
     504             :         if (! IPMPDRemove) return GF_BAD_PARAM;
     505             :         if (IPMPDRemove->IPMPDescID) gf_free(IPMPDRemove->IPMPDescID);
     506             :         gf_free(IPMPDRemove);
     507             :         return GF_OK;
     508             : }
     509             : 
     510             : GF_Err gf_odf_read_ipmp_remove(GF_BitStream *bs, GF_IPMPRemove *ipmpRem, u32 gf_odf_size_command)
     511             : {
     512             :         u32 i;
     513             :         if (! ipmpRem) return GF_BAD_PARAM;
     514             : 
     515             :         //we have gf_odf_size_command bytes left, and this is our IPMPD_ID[1...255]
     516             :         //this works because OD commands are aligned
     517             :         if (!gf_odf_size_command) return GF_OK;
     518             : 
     519             :         ipmpRem->NbIPMPDs = gf_odf_size_command;
     520             :         ipmpRem->IPMPDescID = (u8 *) gf_malloc(sizeof(u8) * ipmpRem->NbIPMPDs);
     521             :         if (! ipmpRem->IPMPDescID) return GF_OUT_OF_MEM;
     522             : 
     523             :         for (i = 0; i < ipmpRem->NbIPMPDs; i++) {
     524             :                 ipmpRem->IPMPDescID[i] = gf_bs_read_int(bs, 8);
     525             :         }
     526             :         //OD commands are aligned
     527             :         gf_bs_align(bs);
     528             :         return GF_OK;
     529             : }
     530             : 
     531             : GF_Err gf_odf_size_ipmp_remove(GF_IPMPRemove *ipmpRem, u32 *outSize)
     532             : {
     533             :         if (!ipmpRem) return GF_BAD_PARAM;
     534             : 
     535             :         *outSize = ipmpRem->NbIPMPDs;
     536             :         return GF_OK;
     537             : }
     538             : GF_Err gf_odf_write_ipmp_remove(GF_BitStream *bs, GF_IPMPRemove *ipmpRem)
     539             : {
     540             :         GF_Err e;
     541             :         u32 size, i;
     542             :         if (! ipmpRem) return GF_BAD_PARAM;
     543             : 
     544             :         e = gf_odf_size_ipmp_remove(ipmpRem, &size);
     545             :         if (e) return e;
     546             :         e = gf_odf_write_base_descriptor(bs, ipmpRem->tag, size);
     547             :         if (e) return e;
     548             : 
     549             :         for (i = 0; i < ipmpRem->NbIPMPDs; i++) {
     550             :                 gf_bs_write_int(bs, ipmpRem->IPMPDescID[i], 8);
     551             :         }
     552             :         //OD commands are aligned
     553             :         gf_bs_align(bs);
     554             :         return GF_OK;
     555             : }
     556             : 
     557             : GF_ODCom *gf_odf_new_ipmp_update()
     558             : {
     559             :         GF_IPMPUpdate *newCom = (GF_IPMPUpdate *) gf_malloc(sizeof(GF_IPMPUpdate));
     560             :         if (!newCom) return NULL;
     561             :         newCom->IPMPDescList = gf_list_new();
     562             :         if (! newCom->IPMPDescList) {
     563             :                 gf_free(newCom);
     564             :                 return NULL;
     565             :         }
     566             :         newCom->tag = GF_ODF_IPMP_UPDATE_TAG;
     567             :         return (GF_ODCom *)newCom;
     568             : }
     569             : 
     570             : GF_Err gf_odf_del_ipmp_update(GF_IPMPUpdate *IPMPDUpdate)
     571             : {
     572             :         GF_Err e;
     573             :         if (! IPMPDUpdate) return GF_BAD_PARAM;
     574             :         while (gf_list_count(IPMPDUpdate->IPMPDescList)) {
     575             :                 GF_Descriptor *tmp = (GF_Descriptor*)gf_list_get(IPMPDUpdate->IPMPDescList, 0);
     576             :                 e = gf_odf_delete_descriptor(tmp);
     577             :                 if (e) return e;
     578             :                 e = gf_list_rem(IPMPDUpdate->IPMPDescList, 0);
     579             :                 if (e) return e;
     580             :         }
     581             :         gf_list_del(IPMPDUpdate->IPMPDescList);
     582             :         gf_free(IPMPDUpdate);
     583             :         return GF_OK;
     584             : }
     585             : 
     586             : GF_Err AddToIPMPDUpdate(GF_IPMPUpdate *ipmpUp, GF_Descriptor *desc)
     587             : {
     588             :         if (! ipmpUp) return GF_BAD_PARAM;
     589             :         if (!desc) return GF_OK;
     590             : 
     591             :         switch (desc->tag) {
     592             :         case GF_ODF_IPMP_TAG:
     593             :                 return gf_list_add(ipmpUp->IPMPDescList, desc);
     594             :         default:
     595             :                 gf_odf_delete_descriptor(desc);
     596             :                 return GF_OK;
     597             :         }
     598             : }
     599             : 
     600             : GF_Err gf_odf_read_ipmp_update(GF_BitStream *bs, GF_IPMPUpdate *ipmpUp, u32 gf_odf_size_command)
     601             : {
     602             :         GF_Descriptor *tmp;
     603             :         u32 tmpSize = 0, nbBytes = 0;
     604             :         GF_Err e = GF_OK;
     605             :         if (! ipmpUp) return GF_BAD_PARAM;
     606             : 
     607             :         while (nbBytes < gf_odf_size_command) {
     608             :                 e = gf_odf_parse_descriptor(bs, &tmp, &tmpSize);
     609             :                 if (e) return e;
     610             :                 e = AddToIPMPDUpdate(ipmpUp, tmp);
     611             :                 if (e) return e;
     612             :                 nbBytes += tmpSize + gf_odf_size_field_size(tmpSize);
     613             :         }
     614             :         //OD commands are aligned
     615             :         gf_bs_align(bs);
     616             :         if (nbBytes != gf_odf_size_command) return GF_ODF_INVALID_COMMAND;
     617             :         return e;
     618             : }
     619             : 
     620             : 
     621             : GF_Err gf_odf_size_ipmp_update(GF_IPMPUpdate *ipmpUp, u32 *outSize)
     622             : {
     623             :         GF_Descriptor *tmp;
     624             :         u32 i, tmpSize;
     625             :         if (!ipmpUp) return GF_BAD_PARAM;
     626             : 
     627             :         *outSize = 0;
     628             :         i=0;
     629             :         while ((tmp = (GF_Descriptor *)gf_list_enum(ipmpUp->IPMPDescList, &i))) {
     630             :                 gf_odf_size_descriptor(tmp, &tmpSize);
     631             :                 *outSize += tmpSize + gf_odf_size_field_size(tmpSize);
     632             :         }
     633             :         return GF_OK;
     634             : }
     635             : GF_Err gf_odf_write_ipmp_update(GF_BitStream *bs, GF_IPMPUpdate *ipmpUp)
     636             : {
     637             :         GF_Err e;
     638             :         GF_Descriptor *tmp;
     639             :         u32 size, i;
     640             :         if (! ipmpUp) return GF_BAD_PARAM;
     641             : 
     642             :         e = gf_odf_size_ipmp_update(ipmpUp, &size);
     643             :         if (e) return e;
     644             :         e = gf_odf_write_base_descriptor(bs, ipmpUp->tag, size);
     645             :         if (e) return e;
     646             : 
     647             :         i=0;
     648             :         while ((tmp = (GF_Descriptor *)gf_list_enum(ipmpUp->IPMPDescList, &i))) {
     649             :                 e = gf_odf_write_descriptor(bs, tmp);
     650             :                 if (e) return e;
     651             :         }
     652             :         //OD commands are aligned
     653             :         gf_bs_align(bs);
     654             :         return GF_OK;
     655             : }
     656             : #endif
     657             : 

Generated by: LCOV version 1.13