LCOV - code coverage report
Current view: top level - odf - odf_codec.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 244 313 78.0 %
Date: 2021-04-29 23:48:07 Functions: 24 24 100.0 %

          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             : #include <gpac/internal/odf_dev.h>
      27             : 
      28             : /************************************************************
      29             :                 Object GF_Descriptor Codec Functions
      30             : ************************************************************/
      31             : 
      32             : GF_EXPORT
      33         417 : GF_ODCodec *gf_odf_codec_new()
      34             : {
      35             :         GF_ODCodec *codec;
      36             :         GF_List *comList;
      37             : 
      38         417 :         comList = gf_list_new();
      39         417 :         if (!comList) return NULL;
      40             : 
      41         417 :         codec = (GF_ODCodec *) gf_malloc(sizeof(GF_ODCodec));
      42         417 :         if (!codec) {
      43           0 :                 gf_list_del(comList);
      44           0 :                 return NULL;
      45             :         }
      46             :         //the bitstream is always NULL. It is created on the fly for access unit processing only
      47         417 :         codec->bs = NULL;
      48         417 :         codec->CommandList = comList;
      49         417 :         return codec;
      50             : }
      51             : 
      52             : GF_EXPORT
      53         417 : void gf_odf_codec_del(GF_ODCodec *codec)
      54             : {
      55         417 :         if (!codec) return;
      56             : 
      57         424 :         while (gf_list_count(codec->CommandList)) {
      58           7 :                 GF_ODCom *com = (GF_ODCom *)gf_list_get(codec->CommandList, 0);
      59           7 :                 gf_odf_delete_command(com);
      60           7 :                 gf_list_rem(codec->CommandList, 0);
      61             :         }
      62         417 :         gf_list_del(codec->CommandList);
      63         417 :         if (codec->bs) gf_bs_del(codec->bs);
      64         417 :         gf_free(codec);
      65             : }
      66             : 
      67             : 
      68             : /************************************************************
      69             :                 Codec Encoder Functions
      70             : ************************************************************/
      71             : 
      72             : GF_EXPORT
      73         231 : GF_Err gf_odf_codec_add_com(GF_ODCodec *codec, GF_ODCom *command)
      74             : {
      75         231 :         if (!codec || !command) return GF_BAD_PARAM;
      76         231 :         return gf_list_add(codec->CommandList, command);
      77             : }
      78             : 
      79             : GF_EXPORT
      80         238 : GF_Err gf_odf_codec_encode(GF_ODCodec *codec, u32 cleanup_type)
      81             : {
      82             :         GF_ODCom *com;
      83             :         GF_Err e = GF_OK;
      84             :         u32 i;
      85             : 
      86         238 :         if (!codec) return GF_BAD_PARAM;
      87             : 
      88             :         //check our bitstream: if existing, this means the previous encoded AU was not retrieved
      89             :         //we DON'T allow that
      90         238 :         if (codec->bs) return GF_BAD_PARAM;
      91         238 :         codec->bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
      92         238 :         if (!codec->bs) return GF_OUT_OF_MEM;
      93             : 
      94             :         /*encode each command*/
      95         238 :         i = 0;
      96         714 :         while ((com = (GF_ODCom *)gf_list_enum(codec->CommandList, &i))) {
      97         238 :                 e = gf_odf_write_command(codec->bs, com);
      98         238 :                 if (e) goto err_exit;
      99             :                 //don't forget OD Commands are aligned...
     100         238 :                 gf_bs_align(codec->bs);
     101             :         }
     102             : 
     103             : //if an error occurs, delete the GF_BitStream and empty the codec
     104         238 : err_exit:
     105         238 :         if (e) {
     106           0 :                 gf_bs_del(codec->bs);
     107           0 :                 codec->bs = NULL;
     108             :         }
     109         238 :         if (cleanup_type==1) {
     110         356 :                 while (gf_list_count(codec->CommandList)) {
     111         178 :                         com = (GF_ODCom *)gf_list_get(codec->CommandList, 0);
     112         178 :                         gf_odf_delete_command(com);
     113         178 :                         gf_list_rem(codec->CommandList, 0);
     114             :                 }
     115             :         }
     116         238 :         if (cleanup_type==0) {
     117          54 :                 gf_list_reset(codec->CommandList);
     118             :         }
     119             :         return e;
     120             : }
     121             : 
     122             : GF_EXPORT
     123         238 : GF_Err gf_odf_codec_get_au(GF_ODCodec *codec, u8 **outAU, u32 *au_length)
     124             : {
     125         238 :         if (!codec || !codec->bs || !outAU || *outAU) return GF_BAD_PARAM;
     126         238 :         gf_bs_get_content(codec->bs, outAU, au_length);
     127         238 :         gf_bs_del(codec->bs);
     128         238 :         codec->bs = NULL;
     129         238 :         return GF_OK;
     130             : }
     131             : 
     132             : 
     133             : 
     134             : /************************************************************
     135             :                 Codec Decoder Functions
     136             : ************************************************************/
     137             : 
     138             : GF_EXPORT
     139         249 : GF_Err gf_odf_codec_set_au(GF_ODCodec *codec, const u8 *au, u32 au_length)
     140             : {
     141         249 :         if (!codec ) return GF_BAD_PARAM;
     142         249 :         if (!au || !au_length) return GF_OK;
     143             : 
     144             :         //if the command list is not empty, this is an error
     145         249 :         if (gf_list_count(codec->CommandList)) return GF_BAD_PARAM;
     146             : 
     147             :         //the bitStream should not be here
     148         249 :         if (codec->bs) return GF_BAD_PARAM;
     149             : 
     150         249 :         codec->bs = gf_bs_new(au, (u64) au_length, (unsigned char)GF_BITSTREAM_READ);
     151         249 :         if (!codec->bs) return GF_OUT_OF_MEM;
     152         249 :         return GF_OK;
     153             : }
     154             : 
     155             : 
     156             : GF_EXPORT
     157         249 : GF_Err gf_odf_codec_decode(GF_ODCodec *codec)
     158             : {
     159             :         GF_Err e = GF_OK;
     160             :         u32 size = 0, comSize, bufSize;
     161             :         GF_ODCom *com;
     162             : 
     163         249 :         if (!codec || !codec->bs) return GF_BAD_PARAM;
     164             : 
     165         249 :         bufSize = (u32) gf_bs_available(codec->bs);
     166         747 :         while (size < bufSize) {
     167         249 :                 e =     gf_odf_parse_command(codec->bs, &com, &comSize);
     168         249 :                 if (e) goto err_exit;
     169         249 :                 gf_list_add(codec->CommandList, com);
     170         249 :                 size += comSize + gf_odf_size_field_size(comSize);
     171             :                 //OD Commands are aligned
     172         249 :                 gf_bs_align(codec->bs);
     173             :         }
     174             :         //then delete our bitstream
     175         249 :         gf_bs_del(codec->bs);
     176         249 :         codec->bs = NULL;
     177         249 :         if (size != bufSize) {
     178             :                 e = GF_ODF_INVALID_COMMAND;
     179             :                 goto err_exit;
     180             :         }
     181             :         return e;
     182             : 
     183           0 : err_exit:
     184           0 :         if (codec->bs) {
     185           0 :                 gf_bs_del(codec->bs);
     186           0 :                 codec->bs = NULL;
     187             :         }
     188           0 :         while (gf_list_count(codec->CommandList)) {
     189           0 :                 com = (GF_ODCom*)gf_list_get(codec->CommandList, 0);
     190           0 :                 gf_odf_delete_command(com);
     191           0 :                 gf_list_rem(codec->CommandList, 0);
     192             :         }
     193             :         return e;
     194             : }
     195             : 
     196             : //get the first command in the codec and remove the entry
     197             : GF_EXPORT
     198         490 : GF_ODCom *gf_odf_codec_get_com(GF_ODCodec *codec)
     199             : {
     200             :         GF_ODCom *com;
     201         490 :         if (!codec || codec->bs) return NULL;
     202         490 :         com = (GF_ODCom*)gf_list_get(codec->CommandList, 0);
     203         490 :         if (com) gf_list_rem(codec->CommandList, 0);
     204             :         return com;
     205             : }
     206             : 
     207             : 
     208             : 
     209             : /************************************************************
     210             :                 OD Commands Functions
     211             : ************************************************************/
     212             : 
     213             : //some easy way to get an OD GF_ODCom...
     214             : GF_EXPORT
     215         354 : GF_ODCom *gf_odf_com_new(u8 tag)
     216             : {
     217             :         GF_ODCom *newcom;
     218             : 
     219         354 :         newcom = gf_odf_create_command(tag);
     220         354 :         newcom->tag = tag;
     221         354 :         return (GF_ODCom *)newcom;
     222             : }
     223             : 
     224             : //      ... and to delete it
     225             : GF_EXPORT
     226         418 : GF_Err gf_odf_com_del(GF_ODCom **com)
     227             : {
     228             :         GF_Err e;
     229         418 :         e = gf_odf_delete_command(*com);
     230         418 :         *com = NULL;
     231         418 :         return e;
     232             : }
     233             : 
     234             : 
     235             : /************************************************************
     236             :                 Object Descriptors Functions
     237             : ************************************************************/
     238             : 
     239             : //some easy way to get an mpeg4 descriptor ...
     240             : GF_EXPORT
     241       14774 : GF_Descriptor *gf_odf_desc_new(u8 tag)
     242             : {
     243             :         GF_Descriptor *newdesc;
     244       14774 :         newdesc = gf_odf_create_descriptor(tag);
     245       14774 :         newdesc->tag = tag;
     246       14774 :         return (GF_Descriptor *)newdesc;
     247             : }
     248             : 
     249             : //      ... and to delete it
     250             : GF_EXPORT
     251       10992 : void gf_odf_desc_del(GF_Descriptor *desc)
     252             : {
     253       10992 :         if (desc) gf_odf_delete_descriptor(desc);
     254       10992 : }
     255             : 
     256             : //this functions will destroy the descriptors in a list but not the list
     257             : GF_EXPORT
     258          12 : GF_Err gf_odf_desc_list_del(GF_List *descList)
     259             : {
     260             :         GF_Err e;
     261             : 
     262          12 :         if (! descList) return GF_BAD_PARAM;
     263             : 
     264          18 :         while (gf_list_count(descList)) {
     265           6 :                 GF_Descriptor *tmp = (GF_Descriptor*)gf_list_get(descList, 0);
     266           6 :                 gf_list_rem(descList, 0);
     267           6 :                 e = gf_odf_delete_descriptor(tmp);
     268           6 :                 if (e) return e;
     269             :         }
     270             :         return GF_OK;
     271             : }
     272             : 
     273             : 
     274             : 
     275             : GF_EXPORT
     276        3580 : GF_ESD *gf_odf_desc_esd_new(u32 sl_predefined)
     277             : {
     278             :         GF_ESD *esd;
     279        3580 :         esd = (GF_ESD *) gf_odf_desc_new(GF_ODF_ESD_TAG);
     280        3580 :         esd->decoderConfig = (GF_DecoderConfig *) gf_odf_desc_new(GF_ODF_DCD_TAG);
     281        3580 :         esd->decoderConfig->decoderSpecificInfo = (GF_DefaultDescriptor *) gf_odf_desc_new(GF_ODF_DSI_TAG);
     282        3580 :         esd->slConfig = (GF_SLConfig *) gf_odf_new_slc((u8) sl_predefined);
     283        3580 :         return esd;
     284             : }
     285             : 
     286             : 
     287             : //use this function to decode a standalone descriptor
     288             : //the desc MUST be formatted with tag and size field!!!
     289             : GF_EXPORT
     290        5288 : GF_Err gf_odf_desc_read(u8 *raw_desc, u32 descSize, GF_Descriptor **outDesc)
     291             : {
     292             :         GF_Err e;
     293             :         u32 size;
     294             :         GF_BitStream *bs;
     295        5288 :         if (!raw_desc || !descSize) return GF_BAD_PARAM;
     296             : 
     297        5288 :         bs = gf_bs_new(raw_desc, (u64) descSize, GF_BITSTREAM_READ);
     298        5288 :         if (!bs) return GF_OUT_OF_MEM;
     299             : 
     300        5288 :         size = 0;
     301        5288 :         e = gf_odf_parse_descriptor(bs, outDesc, &size);
     302             :         //the size dosn't have the header in it
     303        5288 :         size += gf_odf_size_field_size(size);
     304             :         /*
     305             :                 if (size != descSize) {
     306             :                         if (*outDesc) gf_odf_delete_descriptor(*outDesc);
     307             :                         *outDesc = NULL;
     308             :                         e = GF_ODF_INVALID_DESCRIPTOR;
     309             :                 }
     310             :         */
     311             : 
     312        5288 :         gf_bs_del(bs);
     313        5288 :         return e;
     314             : }
     315             : 
     316             : //use this function to encode a standalone descriptor
     317             : //the desc will be formatted with tag and size field
     318             : GF_EXPORT
     319        4979 : GF_Err gf_odf_desc_write_bs(GF_Descriptor *desc, GF_BitStream *bs)
     320             : {
     321             :         GF_Err e;
     322        4979 :         if (!desc || !bs) return GF_BAD_PARAM;
     323             : 
     324             :         //then encode our desc...
     325        4979 :         e = gf_odf_write_descriptor(bs, desc);
     326        4979 :         if (e) return e;
     327             :         
     328        4979 :         return GF_OK;
     329             : }
     330             : 
     331             : GF_EXPORT
     332        4981 : GF_Err gf_odf_desc_write(GF_Descriptor *desc, u8 **outEncDesc, u32 *outSize)
     333             : {
     334             :         GF_Err e;
     335             :         GF_BitStream *bs;
     336        4981 :         if (!desc || !outEncDesc || !outSize) return GF_BAD_PARAM;
     337        4979 :         *outEncDesc = NULL;
     338        4979 :         *outSize = 0;
     339             : 
     340        4979 :         bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     341        4979 :         if (!bs) return GF_OUT_OF_MEM;
     342             : 
     343        4979 :         e = gf_odf_desc_write_bs(desc, bs);
     344             :         
     345             :         //then get the content from our bitstream
     346        4979 :         gf_bs_get_content(bs, outEncDesc, outSize);
     347        4979 :         gf_bs_del(bs);
     348        4979 :         return e;
     349             : }
     350             : 
     351             : 
     352             : //use this function to get the size of a standalone descriptor
     353             : GF_EXPORT
     354        3808 : u32 gf_odf_desc_size(GF_Descriptor *desc)
     355             : {
     356             :         u32 descSize;
     357             :         GF_Err e;
     358             : 
     359        3808 :         if (!desc) return GF_BAD_PARAM;
     360             :         //get the descriptor length
     361        3806 :         e = gf_odf_size_descriptor(desc, &descSize);
     362        3806 :         if (e) return 0;
     363             :         //add the header length
     364        3806 :         descSize += gf_odf_size_field_size(descSize);
     365        3806 :         return descSize;
     366             : 
     367             : }
     368             : 
     369             : //this is useful to duplicate on the fly a descriptor (mainly for authoring purposes)
     370             : GF_EXPORT
     371        3435 : GF_Err gf_odf_desc_copy(GF_Descriptor *inDesc, GF_Descriptor **outDesc)
     372             : {
     373             :         GF_Err e;
     374             :         u8 *desc;
     375             :         u32 size, oti=0;
     376             : 
     377             :         //patch for esd copy, we now signal codecid (32 bit) in OTI (8 bits)
     378        3435 :         if (inDesc->tag == GF_ODF_ESD_TAG) {
     379             :                 GF_ESD *esd = (GF_ESD *)inDesc;
     380        2377 :                 if (esd->decoderConfig) {
     381        2377 :                         oti = esd->decoderConfig->objectTypeIndication;
     382        2377 :                         esd->decoderConfig->objectTypeIndication = 0;
     383             :                 }
     384             :         }
     385             : 
     386             :         //warning: here we get some data allocated
     387        3435 :         e = gf_odf_desc_write(inDesc, &desc, &size);
     388        3435 :         if (e) return e;
     389        3435 :         e = gf_odf_desc_read(desc, size, outDesc);
     390        3435 :         gf_free(desc);
     391        3435 :         if (oti && !e) {
     392             :                 GF_ESD *esd = (GF_ESD *)inDesc;
     393        2305 :                 GF_ESD *out_esd = (GF_ESD *)*outDesc;
     394        2305 :                 if (esd->decoderConfig) esd->decoderConfig->objectTypeIndication = oti;
     395        2305 :                 if (out_esd->decoderConfig) out_esd->decoderConfig->objectTypeIndication = oti;
     396             :         }
     397             :         return e;
     398             : }
     399             : 
     400             : /************************************************************
     401             :                 Object Descriptors Edit Functions
     402             : ************************************************************/
     403             : 
     404             : //This functions handles internally what desc can be added to another desc
     405             : //and adds it. NO DUPLICATION of the descriptor, so
     406             : //once a desc is added to its parent, destroying the parent WILL destroy this desc
     407             : GF_EXPORT
     408        2243 : GF_Err gf_odf_desc_add_desc(GF_Descriptor *parentDesc, GF_Descriptor *newDesc)
     409             : {
     410             :         GF_DecoderConfig *dcd;
     411             : 
     412             :         //our ADD definition
     413             :         GF_Err AddDescriptorToOD(GF_ObjectDescriptor *od, GF_Descriptor *desc);
     414             :         GF_Err AddDescriptorToIOD(GF_InitialObjectDescriptor *iod, GF_Descriptor *desc);
     415             :         GF_Err AddDescriptorToESD(GF_ESD *esd, GF_Descriptor *desc);
     416             :         GF_Err AddDescriptorToIsomIOD(GF_IsomInitialObjectDescriptor *iod, GF_Descriptor *desc);
     417             :         GF_Err AddDescriptorToIsomOD(GF_IsomObjectDescriptor *od, GF_Descriptor *desc);
     418             : 
     419        2243 :         if (!parentDesc || !newDesc) return GF_BAD_PARAM;
     420             : 
     421        2243 :         switch (parentDesc->tag) {
     422             :         //these are container descriptors
     423         315 :         case GF_ODF_OD_TAG:
     424         315 :                 return AddDescriptorToOD((GF_ObjectDescriptor *)parentDesc, newDesc);
     425         521 :         case GF_ODF_IOD_TAG:
     426         521 :                 return AddDescriptorToIOD((GF_InitialObjectDescriptor *)parentDesc, newDesc);
     427         780 :         case GF_ODF_ESD_TAG:
     428         780 :                 return AddDescriptorToESD((GF_ESD *)parentDesc, newDesc);
     429         415 :         case GF_ODF_DCD_TAG:
     430             :                 dcd = (GF_DecoderConfig *)parentDesc;
     431         830 :                 if ((newDesc->tag == GF_ODF_DSI_TAG)
     432         415 :                         || (newDesc->tag == GF_ODF_BIFS_CFG_TAG)
     433          33 :                         || (newDesc->tag == GF_ODF_UI_CFG_TAG)
     434           0 :                         || (newDesc->tag == GF_ODF_TEXT_CFG_TAG)
     435             :                    ) {
     436         415 :                         if (dcd->decoderSpecificInfo) return GF_ODF_FORBIDDEN_DESCRIPTOR;
     437         415 :                         dcd->decoderSpecificInfo = (GF_DefaultDescriptor *) newDesc;
     438         415 :                         return GF_OK;
     439           0 :                 } else if (newDesc->tag == GF_ODF_EXT_PL_TAG) {
     440           0 :                         return gf_list_add(dcd->profileLevelIndicationIndexDescriptor, newDesc);
     441             :                 }
     442             :                 return GF_ODF_FORBIDDEN_DESCRIPTOR;
     443             : 
     444           0 :         case GF_ODF_TEXT_CFG_TAG:
     445           0 :                 if (newDesc->tag != GF_ODF_TX3G_TAG) return GF_ODF_FORBIDDEN_DESCRIPTOR;
     446           0 :                 return gf_list_add(((GF_TextConfig *)parentDesc)->sample_descriptions, newDesc);
     447             : 
     448             :         case GF_ODF_QOS_TAG:
     449             :                 return GF_BAD_PARAM;
     450             : 
     451             :         //MP4 File Format tags
     452          64 :         case GF_ODF_ISOM_IOD_TAG:
     453          64 :                 return AddDescriptorToIsomIOD((GF_IsomInitialObjectDescriptor *)parentDesc, newDesc);
     454         148 :         case GF_ODF_ISOM_OD_TAG:
     455         148 :                 return AddDescriptorToIsomOD((GF_IsomObjectDescriptor *)parentDesc, newDesc);
     456             : 
     457           0 :         case GF_ODF_IPMP_TL_TAG:
     458           0 :                 if (newDesc->tag!=GF_ODF_IPMP_TOOL_TAG) return GF_BAD_PARAM;
     459           0 :                 return gf_list_add(((GF_IPMP_ToolList *)parentDesc)->ipmp_tools, newDesc);
     460             : 
     461           0 :         case GF_ODF_BIFS_CFG_TAG:
     462             :         {
     463             :                 GF_BIFSConfig *cfg = (GF_BIFSConfig *)parentDesc;
     464           0 :                 if (newDesc->tag!=GF_ODF_ELEM_MASK_TAG) return GF_BAD_PARAM;
     465           0 :                 if (!cfg->elementaryMasks) cfg->elementaryMasks = gf_list_new();
     466           0 :                 return gf_list_add(cfg->elementaryMasks, newDesc);
     467             :         }
     468           0 :         default:
     469           0 :                 return GF_ODF_FORBIDDEN_DESCRIPTOR;
     470             :         }
     471             : }
     472             : 
     473             : 
     474             : 
     475             : /*****************************************************************************************
     476             :                 Since IPMP V2, we introduce a new set of functions to read / write a list of
     477             :         descriptors that have no containers (a bit like an OD command, but for descriptors)
     478             :                 This is useful for IPMPv2 DecoderSpecificInfo which contains a set of
     479             :         IPMP_Declarators.
     480             :                 As it could be used for other purposes we keep it generic
     481             :         You must create the list yourself, the functions just encode/decode from/to the list
     482             : 
     483             :         These functions are also used in mp4 for extension descriptor in LASeR and AVC sample descriptions
     484             : *****************************************************************************************/
     485             : 
     486             : GF_EXPORT
     487           5 : GF_Err gf_odf_desc_list_read(u8 *raw_list, u32 raw_size, GF_List *descList)
     488             : {
     489             :         GF_BitStream *bs;
     490             :         u32 size, desc_size;
     491             :         GF_Descriptor *desc;
     492             :         GF_Err e = GF_OK;
     493             : 
     494           5 :         if (!descList || !raw_list || !raw_size) return GF_BAD_PARAM;
     495             : 
     496           5 :         bs = gf_bs_new(raw_list, raw_size, GF_BITSTREAM_READ);
     497           5 :         if (!bs) return GF_OUT_OF_MEM;
     498             : 
     499             :         size = 0;
     500          10 :         while (size < raw_size) {
     501           5 :                 e =     gf_odf_parse_descriptor(bs, &desc, &desc_size);
     502           5 :                 if (e) goto exit;
     503           5 :                 gf_list_add(descList, desc);
     504           5 :                 size += desc_size + gf_odf_size_field_size(desc_size);
     505             :         }
     506             : 
     507           5 : exit:
     508             :         //then delete our bitstream
     509           5 :         gf_bs_del(bs);
     510           5 :         if (size != raw_size) e = GF_ODF_INVALID_DESCRIPTOR;
     511             :         return e;
     512             : }
     513             : 
     514             : 
     515             : GF_EXPORT
     516           2 : GF_Err gf_odf_desc_list_write(GF_List *descList, u8 **outEncList, u32 *outSize)
     517             : {
     518             :         GF_BitStream *bs;
     519             :         GF_Err e;
     520             : 
     521           2 :         if (!descList || !outEncList || *outEncList || !outSize) return GF_BAD_PARAM;
     522             : 
     523           2 :         *outSize = 0;
     524             : 
     525           2 :         bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     526           2 :         if (!bs) return GF_OUT_OF_MEM;
     527             : 
     528           2 :         e = gf_odf_write_descriptor_list(bs, descList);
     529           2 :         if (e) {
     530           0 :                 gf_bs_del(bs);
     531           0 :                 return e;
     532             :         }
     533             : 
     534           2 :         gf_bs_get_content(bs, outEncList, outSize);
     535           2 :         gf_bs_del(bs);
     536           2 :         return GF_OK;
     537             : }
     538             : 
     539             : GF_EXPORT
     540           4 : GF_Err gf_odf_desc_list_size(GF_List *descList, u32 *outSize)
     541             : {
     542           4 :         return gf_odf_size_descriptor_list(descList, outSize);
     543             : }
     544             : 
     545             : 
     546             : 
     547          26 : GF_Err gf_odf_codec_apply_com(GF_ODCodec *codec, GF_ODCom *command)
     548             : {
     549             :         GF_ODCom *com;
     550             :         GF_ODUpdate *odU, *odU_o;
     551             :         u32 i, count;
     552          26 :         count = gf_list_count(codec->CommandList);
     553             : 
     554          26 :         switch (command->tag) {
     555             :         case GF_ODF_OD_REMOVE_TAG:
     556           6 :                 for (i=0; i<count; i++) {
     557           6 :                         com = (GF_ODCom *)gf_list_get(codec->CommandList, i);
     558             :                         /*process OD updates*/
     559           6 :                         if (com->tag==GF_ODF_OD_UPDATE_TAG) {
     560             :                                 u32 count2, j, k;
     561             :                                 GF_ODRemove *odR = (GF_ODRemove *) command;
     562             :                                 odU = (GF_ODUpdate *)com;
     563           6 :                                 count2 = gf_list_count(odU->objectDescriptors);
     564             :                                 /*remove all descs*/
     565          24 :                                 for (k=0; k<count2; k++) {
     566          18 :                                         GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, k);
     567          30 :                                         for (j=0; j<odR->NbODs; j++) {
     568          18 :                                                 if (od->objectDescriptorID==odR->OD_ID[j]) {
     569           6 :                                                         gf_list_rem(odU->objectDescriptors, k);
     570           6 :                                                         k--;
     571           6 :                                                         count2--;
     572           6 :                                                         gf_odf_desc_del((GF_Descriptor *)od);
     573           6 :                                                         break;
     574             :                                                 }
     575             :                                         }
     576             :                                 }
     577           6 :                                 if (!gf_list_count(odU->objectDescriptors)) {
     578           0 :                                         gf_list_rem(codec->CommandList, i);
     579           0 :                                         i--;
     580           0 :                                         count--;
     581             :                                 }
     582             :                         }
     583             :                         /*process ESD updates*/
     584           0 :                         else if (com->tag==GF_ODF_ESD_UPDATE_TAG) {
     585             :                                 u32 j;
     586             :                                 GF_ODRemove *odR = (GF_ODRemove *) command;
     587           0 :                                 GF_ESDUpdate *esdU = (GF_ESDUpdate*)com;
     588           0 :                                 for (j=0; j<odR->NbODs; j++) {
     589           0 :                                         if (esdU->ODID==odR->OD_ID[j]) {
     590           0 :                                                 gf_list_rem(codec->CommandList, i);
     591           0 :                                                 i--;
     592           0 :                                                 count--;
     593           0 :                                                 gf_odf_com_del((GF_ODCom**)&esdU);
     594           0 :                                                 break;
     595             :                                         }
     596             :                                 }
     597             :                         }
     598             :                         /*process ESD remove*/
     599           0 :                         else if (com->tag==GF_ODF_ESD_REMOVE_TAG) {
     600             :                                 u32 j;
     601             :                                 GF_ODRemove *odR = (GF_ODRemove *) command;
     602           0 :                                 GF_ESDRemove *esdR = (GF_ESDRemove*)com;
     603           0 :                                 for (j=0; j<odR->NbODs; j++) {
     604           0 :                                         if (esdR->ODID==odR->OD_ID[j]) {
     605           0 :                                                 gf_list_rem(codec->CommandList, i);
     606           0 :                                                 i--;
     607           0 :                                                 count--;
     608           0 :                                                 gf_odf_com_del((GF_ODCom**)&esdR);
     609           0 :                                                 break;
     610             :                                         }
     611             :                                 }
     612             :                         }
     613             :                 }
     614             :                 return GF_OK;
     615             :         case GF_ODF_OD_UPDATE_TAG:
     616             :                 odU_o = NULL;
     617           0 :                 for (i=0; i<count; i++) {
     618           6 :                         odU_o = (GF_ODUpdate*)gf_list_get(codec->CommandList, i);
     619             :                         /*process OD updates*/
     620           6 :                         if (odU_o->tag==GF_ODF_OD_UPDATE_TAG) break;
     621             :                         odU_o = NULL;
     622             :                 }
     623          12 :                 if (!odU_o) {
     624           6 :                         odU_o = (GF_ODUpdate *)gf_odf_com_new(GF_ODF_OD_UPDATE_TAG);
     625           6 :                         gf_list_add(codec->CommandList, odU_o);
     626             :                 }
     627             :                 odU = (GF_ODUpdate*)command;
     628          12 :                 count = gf_list_count(odU->objectDescriptors);
     629          36 :                 for (i=0; i<count; i++) {
     630             :                         Bool found = GF_FALSE;
     631          24 :                         GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, i);
     632          24 :                         u32 j, count2 = gf_list_count(odU_o->objectDescriptors);
     633          42 :                         for (j=0; j<count2; j++) {
     634          24 :                                 GF_ObjectDescriptor *od2 = (GF_ObjectDescriptor *)gf_list_get(odU_o->objectDescriptors, j);
     635          24 :                                 if (od2->objectDescriptorID==od->objectDescriptorID) {
     636             :                                         found = GF_TRUE;
     637             :                                         break;
     638             :                                 }
     639             :                         }
     640          24 :                         if (!found) {
     641             :                                 GF_ObjectDescriptor *od_new;
     642          18 :                                 GF_Err e = gf_odf_desc_copy((GF_Descriptor*)od, (GF_Descriptor**)&od_new);
     643          18 :                                 if (e==GF_OK)
     644          18 :                                         gf_list_add(odU_o->objectDescriptors, od_new);
     645             :                         }
     646             : 
     647             :                 }
     648             :                 return GF_OK;
     649             :         case GF_ODF_ESD_REMOVE_TAG:
     650           6 :                 for (i=0; i<count; i++) {
     651           6 :                         com = (GF_ODCom *)gf_list_get(codec->CommandList, i);
     652             :                         /*process OD updates*/
     653           6 :                         if (com->tag==GF_ODF_OD_UPDATE_TAG) {
     654             :                                 u32 count2, j, k, l;
     655             :                                 GF_ESDRemove *esdR = (GF_ESDRemove *) command;
     656             :                                 odU = (GF_ODUpdate *)com;
     657           6 :                                 count2 = gf_list_count(odU->objectDescriptors);
     658             :                                 /*remove all descs*/
     659          24 :                                 for (k=0; k<count2; k++) {
     660          18 :                                         GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, k);
     661          36 :                                         for (j=0; j<gf_list_count(od->ESDescriptors); j++) {
     662          18 :                                                 GF_ESD *esd = gf_list_get(od->ESDescriptors, j);
     663          30 :                                                 for (l=0; l<esdR->NbESDs; l++) {
     664          18 :                                                         if (esdR->ES_ID[l] == esd->ESID) {
     665           6 :                                                                 gf_list_rem(od->ESDescriptors, j);
     666           6 :                                                                 j--;
     667           6 :                                                                 gf_odf_desc_del((GF_Descriptor *)esd);
     668           6 :                                                                 break;
     669             :                                                         }
     670             :                                                 }
     671             :                                         }
     672             :                                 }
     673             :                         }
     674             :                         /*process ESD updates*/
     675           0 :                         else if (com->tag==GF_ODF_ESD_UPDATE_TAG) {
     676             :                                 u32 j, k;
     677             :                                 GF_ESDRemove *esdR = (GF_ESDRemove *) command;
     678           0 :                                 GF_ESDUpdate *esdU = (GF_ESDUpdate*)com;
     679           0 :                                 for (j=0; j<gf_list_count(esdU->ESDescriptors); j++) {
     680           0 :                                         GF_ESD *esd = gf_list_get(esdU->ESDescriptors, j);
     681           0 :                                         for (k=0; k<esdR->NbESDs; k++) {
     682           0 :                                                 if (esd->ESID == esdR->ES_ID[k]) {
     683           0 :                                                         gf_list_rem(codec->CommandList, j);
     684           0 :                                                         j--;
     685           0 :                                                         gf_odf_desc_del((GF_Descriptor *)esd);
     686             :                                                 }
     687             :                                         }
     688             :                                 }
     689           0 :                                 if (!gf_list_count(esdU->ESDescriptors)) {
     690           0 :                                         gf_list_rem(codec->CommandList, i);
     691           0 :                                         i--;
     692           0 :                                         count--;
     693           0 :                                         gf_odf_com_del((GF_ODCom**)&esdU);
     694             :                                 }
     695             :                         }
     696             :                 }
     697             :                 return GF_OK;
     698             :         case GF_ODF_ESD_UPDATE_TAG:
     699           2 :                 for (i=0; i<count; i++) {
     700           2 :                         com = (GF_ODCom *)gf_list_get(codec->CommandList, i);
     701             :                         /*process OD updates*/
     702           2 :                         if (com->tag==GF_ODF_OD_UPDATE_TAG) {
     703             :                                 u32 count2, k, l;
     704             :                                 GF_ESDUpdate *esdU = (GF_ESDUpdate *) command;
     705             :                                 odU = (GF_ODUpdate *)com;
     706           2 :                                 count2 = gf_list_count(odU->objectDescriptors);
     707             :                                 /*remove all descs*/
     708           2 :                                 for (k=0; k<count2; k++) {
     709           2 :                                         GF_ObjectDescriptor *od = (GF_ObjectDescriptor *)gf_list_get(odU->objectDescriptors, k);
     710           2 :                                         if (od->objectDescriptorID==esdU->ODID) {
     711             :                                                 GF_ESD *esd;
     712           4 :                                                 while (gf_list_count(od->ESDescriptors)) {
     713           2 :                                                         esd = gf_list_pop_back(od->ESDescriptors);
     714           2 :                                                         gf_odf_desc_del((GF_Descriptor *)esd);
     715             :                                                 }
     716           2 :                                                 gf_list_transfer(od->ESDescriptors, esdU->ESDescriptors);
     717           2 :                                                 l = 0;
     718           4 :                                                 while ((esd = gf_list_enum(esdU->ESDescriptors, &l))) {
     719             :                                                         GF_ESD *new_esd;
     720           0 :                                                         GF_Err e = gf_odf_desc_copy((GF_Descriptor*)esd, (GF_Descriptor**)&new_esd);
     721           0 :                                                         if (e==GF_OK)
     722           0 :                                                                 gf_list_add(od->ESDescriptors, new_esd);
     723             :                                                 }
     724             :                                                 break;
     725             :                                         }
     726             :                                 }
     727             :                         }
     728             :                         /*process ESD updates*/
     729           0 :                         else if (com->tag==GF_ODF_ESD_UPDATE_TAG) {
     730             :                                 return GF_NOT_SUPPORTED;
     731             :                         }
     732             :                 }
     733             :                 return GF_OK;
     734             :         }
     735             :         return GF_NOT_SUPPORTED;
     736             : }

Generated by: LCOV version 1.13