LCOV - code coverage report
Current view: top level - isomedia - sample_descs.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 711 842 84.4 %
Date: 2021-04-29 23:48:07 Functions: 40 44 90.9 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       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             : 
      28             : #ifndef GPAC_DISABLE_ISOM
      29             : 
      30             : 
      31        3722 : GF_Err gf_isom_base_sample_entry_read(GF_SampleEntryBox *ptr, GF_BitStream *bs)
      32             : {
      33        3722 :         gf_bs_read_data(bs, ptr->reserved, 6);
      34        3722 :         ptr->dataReferenceIndex = gf_bs_read_u16(bs);
      35        3722 :         if (!ptr->dataReferenceIndex) {
      36         112 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[ISO file] dataReferenceIndex set to 0 in sample entry, overriding to 1\n"));
      37         112 :                 ptr->dataReferenceIndex = 1;
      38             :         }
      39        3722 :         return GF_OK;
      40             : }
      41             : 
      42        5591 : void gf_isom_sample_entry_predestroy(GF_SampleEntryBox *ptr)
      43             : {
      44        5591 : }
      45             : 
      46         897 : void gf_isom_sample_entry_init(GF_SampleEntryBox *ent)
      47             : {
      48         897 :         ent->internal_type = GF_ISOM_SAMPLE_ENTRY_MP4S;
      49         897 : }
      50             : 
      51        3326 : void gf_isom_video_sample_entry_init(GF_VisualSampleEntryBox *ent)
      52             : {
      53             :         gf_isom_sample_entry_init((GF_SampleEntryBox*)ent);
      54        3326 :         ent->internal_type = GF_ISOM_SAMPLE_ENTRY_VIDEO;
      55        3326 :         ent->horiz_res = ent->vert_res = 0x00480000;
      56        3326 :         ent->frames_per_sample = 1;
      57        3326 :         ent->bit_depth = 0x18;
      58        3326 :         ent->color_table_index = -1;
      59        3326 : }
      60             : 
      61        2233 : GF_Err gf_isom_video_sample_entry_read(GF_VisualSampleEntryBox *ptr, GF_BitStream *bs)
      62             : {
      63             :         GF_Err e;
      64        2233 :         ISOM_DECREASE_SIZE(ptr, 78)
      65             : 
      66        2233 :         e = gf_isom_base_sample_entry_read((GF_SampleEntryBox *)ptr, bs);
      67        2233 :         if (e) return e;
      68             : 
      69        2233 :         ptr->version = gf_bs_read_u16(bs);
      70        2233 :         ptr->revision = gf_bs_read_u16(bs);
      71        2233 :         ptr->vendor = gf_bs_read_u32(bs);
      72        2233 :         ptr->temporal_quality  = gf_bs_read_u32(bs);
      73        2233 :         ptr->spatial_quality = gf_bs_read_u32(bs);
      74        2233 :         ptr->Width = gf_bs_read_u16(bs);
      75        2233 :         ptr->Height = gf_bs_read_u16(bs);
      76        2233 :         ptr->horiz_res = gf_bs_read_u32(bs);
      77        2233 :         ptr->vert_res = gf_bs_read_u32(bs);
      78        2233 :         ptr->entry_data_size = gf_bs_read_u32(bs);
      79        2233 :         ptr->frames_per_sample = gf_bs_read_u16(bs);
      80        2233 :         gf_bs_read_data(bs, ptr->compressor_name, 32);
      81        2233 :         ptr->compressor_name[32] = 0;
      82        2233 :         ptr->bit_depth = gf_bs_read_u16(bs);
      83        2233 :         ptr->color_table_index = gf_bs_read_u16(bs);
      84        2233 :         return GF_OK;
      85             : }
      86             : 
      87             : #ifndef GPAC_DISABLE_ISOM_WRITE
      88        2016 : void gf_isom_video_sample_entry_write(GF_VisualSampleEntryBox *ptr, GF_BitStream *bs)
      89             : {
      90        2016 :         gf_bs_write_data(bs, ptr->reserved, 6);
      91        2016 :         gf_bs_write_u16(bs, ptr->dataReferenceIndex);
      92             : 
      93        2016 :         gf_bs_write_u16(bs, ptr->version);
      94        2016 :         gf_bs_write_u16(bs, ptr->revision);
      95        2016 :         gf_bs_write_u32(bs, ptr->vendor);
      96        2016 :         gf_bs_write_u32(bs, ptr->temporal_quality);
      97        2016 :         gf_bs_write_u32(bs, ptr->spatial_quality);
      98        2016 :         gf_bs_write_u16(bs, ptr->Width);
      99        2016 :         gf_bs_write_u16(bs, ptr->Height);
     100        2016 :         gf_bs_write_u32(bs, ptr->horiz_res);
     101        2016 :         gf_bs_write_u32(bs, ptr->vert_res);
     102        2016 :         gf_bs_write_u32(bs, ptr->entry_data_size);
     103        2016 :         gf_bs_write_u16(bs, ptr->frames_per_sample);
     104        2016 :         gf_bs_write_data(bs, ptr->compressor_name, 32);
     105        2016 :         gf_bs_write_u16(bs, ptr->bit_depth);
     106        2016 :         gf_bs_write_u16(bs, ptr->color_table_index);
     107             : 
     108             : 
     109        2016 :         if (gf_sys_old_arch_compat()) {
     110             :                 //patch for old export
     111        1973 :                 GF_Box *clap = gf_isom_box_find_child(ptr->child_boxes, GF_ISOM_BOX_TYPE_CLAP);
     112        1973 :                 GF_Box *pasp = gf_isom_box_find_child(ptr->child_boxes, GF_ISOM_BOX_TYPE_PASP);
     113        1973 :                 GF_Box *colr = gf_isom_box_find_child(ptr->child_boxes, GF_ISOM_BOX_TYPE_COLR);
     114        1973 :                 GF_Box *mdcv = gf_isom_box_find_child(ptr->child_boxes, GF_ISOM_BOX_TYPE_MDCV);
     115        1973 :                 GF_Box *clli = gf_isom_box_find_child(ptr->child_boxes, GF_ISOM_BOX_TYPE_CLLI);
     116        1973 :                 GF_Box *ccst = gf_isom_box_find_child(ptr->child_boxes, GF_ISOM_BOX_TYPE_CCST);
     117        1973 :                 GF_Box *auxi = gf_isom_box_find_child(ptr->child_boxes, GF_ISOM_BOX_TYPE_AUXI);
     118        1973 :                 GF_Box *rvcc = gf_isom_box_find_child(ptr->child_boxes, GF_ISOM_BOX_TYPE_RVCC);
     119        1973 :                 GF_Box *sinf = gf_isom_box_find_child(ptr->child_boxes, GF_ISOM_BOX_TYPE_SINF);
     120        1973 :                 GF_Box *btrt = gf_isom_box_find_child(ptr->child_boxes, GF_ISOM_BOX_TYPE_BTRT);
     121        1973 :                 GF_Box *fiel = gf_isom_box_find_child(ptr->child_boxes, GF_QT_BOX_TYPE_FIEL);
     122        1973 :                 GF_Box *gamma = gf_isom_box_find_child(ptr->child_boxes, GF_QT_BOX_TYPE_GAMA);
     123             : 
     124        1973 :                 if (clap) {
     125           1 :                         gf_list_del_item(ptr->child_boxes, clap);
     126           1 :                         gf_list_add(ptr->child_boxes, clap);
     127             :                 }
     128        1973 :                 if (pasp) {
     129         109 :                         gf_list_del_item(ptr->child_boxes, pasp);
     130         109 :                         gf_list_add(ptr->child_boxes, pasp);
     131             :                 }
     132        1973 :                 if (colr) {
     133         227 :                         gf_list_del_item(ptr->child_boxes, colr);
     134         227 :                         gf_list_add(ptr->child_boxes, colr);
     135             :                 }
     136        1973 :                 if (fiel) {
     137          17 :                         gf_list_del_item(ptr->child_boxes, fiel);
     138          17 :                         gf_list_add(ptr->child_boxes, fiel);
     139             :                 }
     140        1973 :                 if (gamma) {
     141           9 :                         gf_list_del_item(ptr->child_boxes, gamma);
     142           9 :                         gf_list_add(ptr->child_boxes, gamma);
     143             :                 }
     144        1973 :                 if (mdcv) {
     145           1 :                         gf_list_del_item(ptr->child_boxes, mdcv);
     146           1 :                         gf_list_add(ptr->child_boxes, mdcv);
     147             :                 }
     148        1973 :                 if (clli) {
     149           1 :                         gf_list_del_item(ptr->child_boxes, clli);
     150           1 :                         gf_list_add(ptr->child_boxes, clli);
     151             :                 }
     152        1973 :                 if (ccst) {
     153           1 :                         gf_list_del_item(ptr->child_boxes, ccst);
     154           1 :                         gf_list_add(ptr->child_boxes, ccst);
     155             :                 }
     156        1973 :                 if (auxi) {
     157           1 :                         gf_list_del_item(ptr->child_boxes, auxi);
     158           1 :                         gf_list_add(ptr->child_boxes, auxi);
     159             :                 }
     160        1973 :                 if (rvcc) {
     161           1 :                         gf_list_del_item(ptr->child_boxes, rvcc);
     162           1 :                         gf_list_add(ptr->child_boxes, rvcc);
     163             :                 }
     164        1973 :                 if (sinf) {
     165         377 :                         gf_list_del_item(ptr->child_boxes, sinf);
     166         377 :                         gf_list_add(ptr->child_boxes, sinf);
     167             :                 }
     168        1973 :                 if (btrt) {
     169        1508 :                         gf_list_del_item(ptr->child_boxes, btrt);
     170        1508 :                         gf_list_add(ptr->child_boxes, btrt);
     171             :                 }
     172             :         }
     173             : 
     174        2016 : }
     175             : 
     176        3521 : void gf_isom_video_sample_entry_size(GF_VisualSampleEntryBox *ent)
     177             : {
     178        3521 :         ent->size += 78;
     179        3521 : }
     180             : 
     181             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     182             : 
     183             : 
     184             : 
     185        1368 : void gf_isom_audio_sample_entry_init(GF_AudioSampleEntryBox *ptr)
     186             : {
     187             :         gf_isom_sample_entry_init((GF_SampleEntryBox*)ptr);
     188        1368 :         ptr->internal_type = GF_ISOM_SAMPLE_ENTRY_AUDIO;
     189             : 
     190        1368 :         ptr->channel_count = 2;
     191        1368 :         ptr->bitspersample = 16;
     192        1368 : }
     193             : 
     194         974 : GF_Err gf_isom_audio_sample_entry_read(GF_AudioSampleEntryBox *ptr, GF_BitStream *bs)
     195             : {
     196             :         GF_Err e;
     197         974 :         ISOM_DECREASE_SIZE(ptr, 28)
     198             : 
     199         974 :         e = gf_isom_base_sample_entry_read((GF_SampleEntryBox *)ptr, bs);
     200         974 :         if (e) return e;
     201             : 
     202         974 :         ptr->version = gf_bs_read_u16(bs);
     203         974 :         ptr->revision = gf_bs_read_u16(bs);
     204         974 :         ptr->vendor = gf_bs_read_u32(bs);
     205         974 :         ptr->channel_count = gf_bs_read_u16(bs);
     206         974 :         ptr->bitspersample = gf_bs_read_u16(bs);
     207         974 :         ptr->compression_id = gf_bs_read_u16(bs);
     208         974 :         ptr->packet_size = gf_bs_read_u16(bs);
     209         974 :         ptr->samplerate_hi = gf_bs_read_u16(bs);
     210         974 :         ptr->samplerate_lo = gf_bs_read_u16(bs);
     211             : 
     212         974 :         if (!ptr->qtff_mode) return GF_OK;
     213             :         //QT only
     214          89 :         if (ptr->version==1) {
     215          89 :                 ISOM_DECREASE_SIZE(ptr, 16)
     216          89 :                 gf_bs_read_data(bs, (char *) ptr->extensions, 16);
     217           0 :         } else if (ptr->version==2) {
     218           0 :                 ISOM_DECREASE_SIZE(ptr, 36)
     219           0 :                 gf_bs_read_data(bs,  (char *) ptr->extensions, 36);
     220             :         }
     221             :         return GF_OK;
     222             : }
     223             : 
     224             : #ifndef GPAC_DISABLE_ISOM_WRITE
     225             : 
     226          17 : GF_Box *gf_isom_audio_sample_get_audio_codec_cfg_box(GF_AudioSampleEntryBox *ptr)
     227             : {
     228             :         GF_MPEGAudioSampleEntryBox *mpga = (GF_MPEGAudioSampleEntryBox *) ptr;
     229          18 :         switch (ptr->type) {
     230           2 :         case GF_ISOM_BOX_TYPE_MP4A:
     231           2 :                 return (GF_Box *)mpga->esd;
     232           0 :         case GF_ISOM_BOX_TYPE_AC3:
     233             :         case GF_ISOM_BOX_TYPE_EC3:
     234           0 :                 return (GF_Box *)mpga->cfg_ac3;
     235           0 :         case GF_ISOM_BOX_TYPE_OPUS:
     236           0 :                 return (GF_Box *)mpga->cfg_opus;
     237           0 :         case GF_ISOM_BOX_TYPE_MHA1:
     238             :         case GF_ISOM_BOX_TYPE_MHA2:
     239           0 :                 return (GF_Box *)mpga->cfg_mha;
     240           0 :         case GF_ISOM_BOX_TYPE_MLPA:
     241           0 :                 return (GF_Box *)mpga->cfg_mlp;
     242             :         }
     243             :         return NULL;
     244             : }
     245         810 : void gf_isom_audio_sample_entry_write(GF_AudioSampleEntryBox *ptr, GF_BitStream *bs)
     246             : {
     247         810 :         gf_bs_write_data(bs, ptr->reserved, 6);
     248         810 :         gf_bs_write_u16(bs, ptr->dataReferenceIndex);
     249             : 
     250         810 :         gf_bs_write_u16(bs, ptr->version);
     251         810 :         gf_bs_write_u16(bs, ptr->revision);
     252         810 :         gf_bs_write_u32(bs, ptr->vendor);
     253         810 :         gf_bs_write_u16(bs, ptr->channel_count);
     254         810 :         gf_bs_write_u16(bs, ptr->bitspersample);
     255         810 :         gf_bs_write_u16(bs, ptr->compression_id);
     256         810 :         gf_bs_write_u16(bs, ptr->packet_size);
     257         810 :         gf_bs_write_u16(bs, ptr->samplerate_hi);
     258         810 :         gf_bs_write_u16(bs, ptr->samplerate_lo);
     259             : 
     260         810 :         if (ptr->qtff_mode) {
     261             :                 GF_Box *codec_ext = NULL;
     262          65 :                 if (ptr->qtff_mode==GF_ISOM_AUDIO_QTFF_ON_NOEXT) {
     263             :                         codec_ext = gf_isom_audio_sample_get_audio_codec_cfg_box(ptr);
     264             :                 }
     265             : 
     266          65 :                 if (ptr->version==1) {
     267             :                         //direct copy of data
     268          65 :                         if (ptr->qtff_mode==GF_ISOM_AUDIO_QTFF_ON_EXT_VALID) {
     269          64 :                                 gf_bs_write_data(bs,  (char *) ptr->extensions, 16);
     270             :                         } else {
     271           1 :                                 gf_bs_write_u32(bs, codec_ext ? 1024 : 1);
     272           1 :                                 gf_bs_write_u32(bs, codec_ext ? 0 : ptr->bitspersample/8);
     273           1 :                                 gf_bs_write_u32(bs, codec_ext ? 0 : ptr->bitspersample/8*ptr->channel_count);
     274           1 :                                 gf_bs_write_u32(bs, codec_ext ? 0 : ptr->bitspersample <= 16 ? ptr->bitspersample/8 : 2);
     275             :                         }
     276           0 :                 } else if (ptr->version==2) {
     277           0 :                         gf_bs_write_data(bs,  (char *) ptr->extensions, 36);
     278             :                 }
     279             :         }
     280         810 : }
     281             : 
     282        1522 : void gf_isom_audio_sample_entry_size(GF_AudioSampleEntryBox *ptr)
     283             : {
     284        1522 :         ptr->size += 28;
     285        1522 :         if (ptr->qtff_mode) {
     286         115 :                 if (ptr->version==1) {
     287         115 :                         ptr->size+=16;
     288           0 :                 } else if (ptr->version==2) {
     289           0 :                         ptr->size += 36;
     290             :                 }
     291             :         }
     292        1522 : }
     293             : 
     294             : 
     295             : #endif  /*GPAC_DISABLE_ISOM_WRITE*/
     296             : 
     297             : 
     298             : 
     299             : GF_EXPORT
     300           0 : GF_3GPConfig *gf_isom_3gp_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex)
     301             : {
     302             :         GF_3GPConfig *config, *res;
     303             :         GF_TrackBox *trak;
     304             :         GF_SampleEntryBox *entry;
     305           0 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
     306           0 :         if (!trak || !StreamDescriptionIndex) return NULL;
     307             : 
     308             :         config = NULL;
     309           0 :         entry = (GF_SampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, StreamDescriptionIndex-1);
     310           0 :         if (!entry) return NULL;
     311           0 :         switch (entry->type) {
     312           0 :         case GF_ISOM_SUBTYPE_3GP_AMR:
     313             :         case GF_ISOM_SUBTYPE_3GP_AMR_WB:
     314             :         case GF_ISOM_SUBTYPE_3GP_EVRC:
     315             :         case GF_ISOM_SUBTYPE_3GP_QCELP:
     316             :         case GF_ISOM_SUBTYPE_3GP_SMV:
     317           0 :                 if (! ((GF_MPEGAudioSampleEntryBox*)entry)->cfg_3gpp) return NULL;
     318           0 :                 config = & ((GF_MPEGAudioSampleEntryBox*)entry)->cfg_3gpp->cfg;
     319           0 :                 break;
     320           0 :         case GF_ISOM_SUBTYPE_3GP_H263:
     321           0 :                 if (! ((GF_MPEGVisualSampleEntryBox*)entry)->cfg_3gpp) return NULL;
     322           0 :                 config = & ((GF_MPEGVisualSampleEntryBox*)entry)->cfg_3gpp->cfg;
     323           0 :                 break;
     324             :         default:
     325             :                 return NULL;
     326             :         }
     327             :         if (!config) return NULL;
     328             : 
     329           0 :         res = (GF_3GPConfig*)gf_malloc(sizeof(GF_3GPConfig));
     330           0 :         if (res)
     331             :                 memcpy(res, config, sizeof(GF_3GPConfig));
     332             :         return res;
     333             : }
     334             : 
     335             : GF_EXPORT
     336          12 : GF_AC3Config *gf_isom_ac3_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex)
     337             : {
     338             :         GF_AC3Config *res;
     339             :         GF_TrackBox *trak;
     340             :         GF_MPEGAudioSampleEntryBox *entry;
     341          12 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
     342          12 :         if (!trak || !StreamDescriptionIndex) return NULL;
     343             : 
     344          12 :         entry = (GF_MPEGAudioSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, StreamDescriptionIndex-1);
     345          12 :         if (!entry || !entry->cfg_ac3) return NULL;
     346             :         if (!entry->cfg_ac3) return NULL;
     347          12 :         if ( (entry->cfg_ac3->type!=GF_ISOM_BOX_TYPE_DAC3) && (entry->cfg_ac3->type!=GF_ISOM_BOX_TYPE_DEC3) ) return NULL;
     348             : 
     349          12 :         res = (GF_AC3Config*)gf_malloc(sizeof(GF_AC3Config));
     350          12 :         if (res)
     351          12 :                 memcpy(res, &entry->cfg_ac3->cfg, sizeof(GF_AC3Config));
     352             :         return res;
     353             : }
     354             : 
     355             : GF_EXPORT
     356           2 : GF_Err gf_isom_flac_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex, u8 **dsi, u32 *dsi_size)
     357             : {
     358             :         u32 type;
     359             :         GF_TrackBox *trak;
     360             :         GF_MPEGAudioSampleEntryBox *entry;
     361           2 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
     362           2 :         if (dsi) *dsi = NULL;
     363           2 :         if (dsi_size) *dsi_size = 0;
     364           2 :         if (!trak || !StreamDescriptionIndex) return GF_BAD_PARAM;
     365             : 
     366           2 :         entry = (GF_MPEGAudioSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, StreamDescriptionIndex-1);
     367             : 
     368           2 :         type = entry->type;
     369           2 :         if (type==GF_ISOM_BOX_TYPE_ENCA) {
     370           0 :                 gf_isom_get_original_format_type(the_file, trackNumber, StreamDescriptionIndex, &type);
     371             :         }
     372             : 
     373           2 :         if (type!=GF_ISOM_BOX_TYPE_FLAC) return GF_BAD_PARAM;
     374           2 :         if (!entry->cfg_flac) return GF_OK;
     375           2 :         if (dsi) {
     376           2 :                 *dsi = gf_malloc(sizeof(u8)*entry->cfg_flac->dataSize);
     377           2 :                 memcpy(*dsi, entry->cfg_flac->data, entry->cfg_flac->dataSize);
     378             :         }
     379           2 :         if (dsi_size) *dsi_size = entry->cfg_flac->dataSize;
     380             :         return GF_OK;
     381             : }
     382             : 
     383             : GF_EXPORT
     384           2 : GF_Err gf_isom_truehd_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex, u32 *format_info, u32 *peak_data_rate)
     385             : {
     386             :         GF_TrackBox *trak;
     387             :         GF_MPEGAudioSampleEntryBox *entry;
     388           2 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
     389           2 :         if (!trak || !StreamDescriptionIndex) return GF_BAD_PARAM;
     390             : 
     391           2 :         entry = (GF_MPEGAudioSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, StreamDescriptionIndex-1);
     392           2 :         if (!entry) return GF_BAD_PARAM;
     393           2 :         if (entry->type != GF_ISOM_SUBTYPE_MLPA) return GF_BAD_PARAM;
     394             : 
     395           2 :         if (!entry->cfg_mlp) return GF_ISOM_INVALID_FILE;
     396           2 :         if (format_info) *format_info = entry->cfg_mlp->format_info;
     397           2 :         if (peak_data_rate) *peak_data_rate = entry->cfg_mlp->peak_data_rate;
     398             :         return GF_OK;
     399             : }
     400             : 
     401             : #ifndef GPAC_DISABLE_ISOM_WRITE
     402           1 : GF_Err gf_isom_truehd_config_new(GF_ISOFile *the_file, u32 trackNumber, char *URLname, char *URNname, u32 format, u32 peak_rate, u32 *outDescriptionIndex)
     403             : {
     404             :         GF_TrackBox *trak;
     405             :         GF_Err e;
     406             :         u32 dataRefIndex;
     407             :         GF_MPEGAudioSampleEntryBox *entry;
     408             :         GF_SampleDescriptionBox *stsd;
     409             : 
     410           1 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
     411           1 :         if (e) return e;
     412             : 
     413           1 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
     414           1 :         if (!trak || !trak->Media) return GF_BAD_PARAM;
     415             : 
     416             :         //get or create the data ref
     417           1 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
     418           1 :         if (e) return e;
     419           1 :         if (!dataRefIndex) {
     420           1 :                 e = Media_CreateDataRef(the_file, trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
     421           1 :                 if (e) return e;
     422             :         }
     423           1 :         if (!the_file->keep_utc)
     424           1 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
     425             : 
     426           1 :         stsd = trak->Media->information->sampleTable->SampleDescription;
     427             :         //create a new entry
     428           1 :         entry = (GF_MPEGAudioSampleEntryBox *)gf_isom_box_new_parent(&stsd->child_boxes, GF_ISOM_BOX_TYPE_MLPA);
     429           1 :         if (!entry) return GF_OUT_OF_MEM;
     430           1 :         entry->cfg_mlp = (GF_TrueHDConfigBox *)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_DMLP);
     431           1 :         if (!entry->cfg_mlp) return GF_OUT_OF_MEM;
     432           1 :         entry->cfg_mlp->format_info = format;
     433           1 :         entry->cfg_mlp->peak_data_rate = (u16) peak_rate;
     434           1 :         entry->dataReferenceIndex = dataRefIndex;
     435           1 :         *outDescriptionIndex = gf_list_count(stsd->child_boxes);
     436           1 :         return e;
     437             : }
     438             : #endif
     439             : 
     440             : #ifndef GPAC_DISABLE_ISOM_WRITE
     441             : GF_EXPORT
     442           2 : GF_Err gf_isom_opus_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_OpusSpecificBox *cfg, char *URLname, char *URNname, u32 *outDescriptionIndex)
     443             : {
     444             :         GF_TrackBox *trak;
     445             :         GF_Err e;
     446             :         u32 dataRefIndex;
     447             :         GF_MPEGAudioSampleEntryBox *entry;
     448             :         GF_SampleDescriptionBox *stsd;
     449             :         ptrdiff_t offset;
     450             : 
     451           2 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
     452           2 :         if (e) return e;
     453             : 
     454           2 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
     455           2 :         if (!trak || !trak->Media || !cfg) return GF_BAD_PARAM;
     456             : 
     457             :         //get or create the data ref
     458           2 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
     459           2 :         if (e) return e;
     460           2 :         if (!dataRefIndex) {
     461           2 :                 e = Media_CreateDataRef(the_file, trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
     462           2 :                 if (e) return e;
     463             :         }
     464           2 :         if (!the_file->keep_utc)
     465           2 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
     466             : 
     467           2 :         stsd = trak->Media->information->sampleTable->SampleDescription;
     468             :         //create a new entry
     469           2 :         entry = (GF_MPEGAudioSampleEntryBox *)gf_isom_box_new_parent(&stsd->child_boxes, GF_ISOM_BOX_TYPE_OPUS);
     470           2 :         if (!entry) return GF_OUT_OF_MEM;
     471           2 :         entry->cfg_opus = (GF_OpusSpecificBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_DOPS);
     472           2 :         if (!entry->cfg_opus) return GF_OUT_OF_MEM;
     473             :         //skip box header
     474             :         offset = (ptrdiff_t)&cfg->version - (ptrdiff_t)cfg;
     475           2 :         memcpy((char*)entry->cfg_opus + offset, (char*)cfg + offset, sizeof(GF_OpusSpecificBox) - (size_t)offset);
     476             : 
     477           2 :         entry->dataReferenceIndex = dataRefIndex;
     478           2 :         *outDescriptionIndex = gf_list_count(stsd->child_boxes);
     479           2 :         return e;
     480             : }
     481             : #endif
     482             : 
     483             : GF_EXPORT
     484           0 : GF_Err gf_isom_opus_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex, u8 **dsi, u32 *dsi_size)
     485             : {
     486             :         u32 type;
     487             :         GF_TrackBox *trak;
     488             :         GF_MPEGAudioSampleEntryBox *entry;
     489           0 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
     490           0 :         if (dsi) *dsi = NULL;
     491           0 :         if (dsi_size) *dsi_size = 0;
     492           0 :         if (!trak || !StreamDescriptionIndex) return GF_BAD_PARAM;
     493             : 
     494           0 :         entry = (GF_MPEGAudioSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, StreamDescriptionIndex-1);
     495             : 
     496           0 :         type = entry->type;
     497           0 :         if (type==GF_ISOM_BOX_TYPE_ENCA) {
     498           0 :                 gf_isom_get_original_format_type(the_file, trackNumber, StreamDescriptionIndex, &type);
     499             :         }
     500           0 :         if (type != GF_ISOM_SUBTYPE_OPUS)
     501             :                 return GF_BAD_PARAM;
     502             : 
     503           0 :         if (!entry->cfg_opus)
     504             :                 return GF_BAD_PARAM;
     505             : 
     506           0 :         if (dsi && dsi_size) {
     507           0 :                 GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     508           0 :                 gf_isom_box_size((GF_Box *)entry->cfg_opus);
     509           0 :                 gf_isom_box_write((GF_Box *)entry->cfg_opus, bs);
     510           0 :                 gf_bs_get_content(bs, dsi, dsi_size);
     511           0 :                 gf_bs_del(bs);
     512             :         }
     513             :         return GF_OK;
     514             : }
     515             : 
     516             : #ifndef GPAC_DISABLE_ISOM_WRITE
     517             : 
     518             : GF_EXPORT
     519          21 : GF_Err gf_isom_3gp_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_3GPConfig *cfg, const char *URLname, const char *URNname, u32 *outDescriptionIndex)
     520             : {
     521             :         GF_TrackBox *trak;
     522             :         GF_Err e;
     523             :         u32 dataRefIndex;
     524             :         u32 cfg_type;
     525             :         GF_SampleDescriptionBox *stsd;
     526             : 
     527          21 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
     528          21 :         if (e) return e;
     529             : 
     530          21 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
     531          21 :         if (!trak || !trak->Media || !cfg) return GF_BAD_PARAM;
     532             : 
     533          21 :         switch (cfg->type) {
     534          12 :         case GF_ISOM_SUBTYPE_3GP_AMR:
     535             :         case GF_ISOM_SUBTYPE_3GP_AMR_WB:
     536          12 :                 if (trak->Media->handler->handlerType!=GF_ISOM_MEDIA_AUDIO) return GF_BAD_PARAM;
     537             :                 cfg_type = GF_ISOM_BOX_TYPE_DAMR;
     538             :                 break;
     539           1 :         case GF_ISOM_SUBTYPE_3GP_EVRC:
     540           1 :                 if (trak->Media->handler->handlerType!=GF_ISOM_MEDIA_AUDIO) return GF_BAD_PARAM;
     541             :                 cfg_type = GF_ISOM_BOX_TYPE_DEVC;
     542             :                 break;
     543           3 :         case GF_ISOM_SUBTYPE_3GP_QCELP:
     544           3 :                 if (trak->Media->handler->handlerType!=GF_ISOM_MEDIA_AUDIO) return GF_BAD_PARAM;
     545             :                 cfg_type = GF_ISOM_BOX_TYPE_DQCP;
     546             :                 break;
     547           0 :         case GF_ISOM_SUBTYPE_3GP_SMV:
     548           0 :                 if (trak->Media->handler->handlerType!=GF_ISOM_MEDIA_AUDIO) return GF_BAD_PARAM;
     549             :                 cfg_type = GF_ISOM_BOX_TYPE_DSMV;
     550             :                 break;
     551           5 :         case GF_ISOM_SUBTYPE_3GP_H263:
     552           5 :                 if (!gf_isom_is_video_handler_type(trak->Media->handler->handlerType)) return GF_BAD_PARAM;
     553             :                 cfg_type = GF_ISOM_BOX_TYPE_D263;
     554             :                 break;
     555             :         case 0:
     556             :                 return GF_BAD_PARAM;
     557           0 :         default:
     558           0 :                 return GF_NOT_SUPPORTED;
     559             :         }
     560             : 
     561             :         //get or create the data ref
     562          21 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
     563          21 :         if (e) return e;
     564          21 :         if (!dataRefIndex) {
     565          16 :                 e = Media_CreateDataRef(the_file, trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
     566          16 :                 if (e) return e;
     567             :         }
     568          21 :         if (!the_file->keep_utc)
     569          21 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
     570             : 
     571          21 :         stsd = trak->Media->information->sampleTable->SampleDescription;
     572             : 
     573          21 :         switch (cfg->type) {
     574          16 :         case GF_ISOM_SUBTYPE_3GP_AMR:
     575             :         case GF_ISOM_SUBTYPE_3GP_AMR_WB:
     576             :         case GF_ISOM_SUBTYPE_3GP_EVRC:
     577             :         case GF_ISOM_SUBTYPE_3GP_QCELP:
     578             :         case GF_ISOM_SUBTYPE_3GP_SMV:
     579             :         {
     580          16 :                 GF_MPEGAudioSampleEntryBox *entry = (GF_MPEGAudioSampleEntryBox *) gf_isom_box_new_parent(&stsd->child_boxes, cfg->type);
     581          16 :                 if (!entry) return GF_OUT_OF_MEM;
     582          16 :                 entry->cfg_3gpp = (GF_3GPPConfigBox *) gf_isom_box_new_parent(&entry->child_boxes, cfg_type);
     583          16 :                 if (!entry->cfg_3gpp) {
     584           0 :                         gf_isom_box_del((GF_Box *) entry);
     585           0 :                         return GF_OUT_OF_MEM;
     586             :                 }
     587          16 :                 memcpy(&entry->cfg_3gpp->cfg, cfg, sizeof(GF_3GPConfig));
     588          16 :                 entry->samplerate_hi = trak->Media->mediaHeader->timeScale;
     589          16 :                 entry->dataReferenceIndex = dataRefIndex;
     590          16 :                 *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
     591             :         }
     592          16 :         break;
     593           5 :         case GF_ISOM_SUBTYPE_3GP_H263:
     594             :         {
     595           5 :                 GF_MPEGVisualSampleEntryBox *entry = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new_parent(&stsd->child_boxes, cfg->type);
     596           5 :                 if (!entry) return GF_OUT_OF_MEM;
     597           5 :                 entry->cfg_3gpp = (GF_3GPPConfigBox *) gf_isom_box_new_parent(&entry->child_boxes, cfg_type);
     598           5 :                 if (!entry->cfg_3gpp) {
     599           0 :                         gf_isom_box_del((GF_Box *) entry);
     600           0 :                         return GF_OUT_OF_MEM;
     601             :                 }
     602           5 :                 memcpy(&entry->cfg_3gpp->cfg, cfg, sizeof(GF_3GPConfig));
     603           5 :                 entry->dataReferenceIndex = dataRefIndex;
     604           5 :                 *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
     605             :         }
     606           5 :         break;
     607             :         }
     608             :         return e;
     609             : }
     610             : 
     611             : GF_EXPORT
     612           0 : GF_Err gf_isom_3gp_config_update(GF_ISOFile *the_file, u32 trackNumber, GF_3GPConfig *param, u32 DescriptionIndex)
     613             : {
     614             :         GF_TrackBox *trak;
     615             :         GF_Err e;
     616             :         GF_3GPConfig *cfg;
     617             :         GF_MPEGAudioSampleEntryBox *a_entry;
     618             :         GF_MPEGVisualSampleEntryBox *v_entry;
     619             : 
     620           0 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
     621           0 :         if (e) return e;
     622             : 
     623           0 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
     624           0 :         if (!trak || !trak->Media || !param || !DescriptionIndex) return GF_BAD_PARAM;
     625             : 
     626             :         cfg = NULL;
     627           0 :         a_entry = (GF_MPEGAudioSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
     628           0 :         if (!a_entry) return GF_BAD_PARAM;
     629             :         v_entry = (GF_MPEGVisualSampleEntryBox *) a_entry;
     630             : 
     631           0 :         switch (a_entry->type) {
     632           0 :         case GF_ISOM_SUBTYPE_3GP_AMR:
     633             :         case GF_ISOM_SUBTYPE_3GP_AMR_WB:
     634             :         case GF_ISOM_SUBTYPE_3GP_EVRC:
     635             :         case GF_ISOM_SUBTYPE_3GP_QCELP:
     636             :         case GF_ISOM_SUBTYPE_3GP_SMV:
     637           0 :                 cfg = &a_entry->cfg_3gpp->cfg;
     638           0 :                 break;
     639           0 :         case GF_ISOM_SUBTYPE_3GP_H263:
     640           0 :                 cfg = & v_entry->cfg_3gpp->cfg;
     641           0 :                 break;
     642             :         default:
     643             :                 break;
     644             :         }
     645           0 :         if (!cfg || (cfg->type != param->type)) return GF_BAD_PARAM;
     646             :         memcpy(cfg, param, sizeof(GF_3GPConfig));
     647           0 :         return GF_OK;
     648             : }
     649             : 
     650             : GF_EXPORT
     651          11 : GF_Err gf_isom_ac3_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_AC3Config *cfg, const char *URLname, const char *URNname, u32 *outDescriptionIndex)
     652             : {
     653             :         GF_TrackBox *trak;
     654             :         GF_Err e;
     655             :         u32 dataRefIndex;
     656             :         GF_MPEGAudioSampleEntryBox *entry;
     657             : 
     658          11 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
     659          11 :         if (e) return e;
     660             : 
     661          11 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
     662          11 :         if (!trak || !trak->Media || !cfg) return GF_BAD_PARAM;
     663             : 
     664             :         //get or create the data ref
     665          11 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
     666          11 :         if (e) return e;
     667          11 :         if (!dataRefIndex) {
     668          10 :                 e = Media_CreateDataRef(the_file, trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
     669          10 :                 if (e) return e;
     670             :         }
     671          11 :         if (!the_file->keep_utc)
     672          11 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
     673             : 
     674          11 :         if (cfg->is_ec3) {
     675           2 :                 entry = (GF_MPEGAudioSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_EC3);
     676           2 :                 if (!entry) return GF_OUT_OF_MEM;
     677           2 :                 entry->cfg_ac3 = (GF_AC3ConfigBox *) gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_DEC3);
     678             :         } else {
     679           9 :                 entry = (GF_MPEGAudioSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_AC3);
     680           9 :                 if (!entry) return GF_OUT_OF_MEM;
     681           9 :                 entry->cfg_ac3 = (GF_AC3ConfigBox *) gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_DAC3);
     682             :         }
     683          11 :         if (!entry->cfg_ac3) {
     684           0 :                 gf_isom_box_del((GF_Box *) entry);
     685           0 :                 return GF_OUT_OF_MEM;
     686             :         }
     687          11 :         memcpy(&entry->cfg_ac3->cfg, cfg, sizeof(GF_AC3Config));
     688          11 :         entry->samplerate_hi = trak->Media->mediaHeader->timeScale;
     689          11 :         entry->dataReferenceIndex = dataRefIndex;
     690          11 :         e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->child_boxes, entry);
     691          11 :         *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
     692          11 :         return e;
     693             : }
     694             : 
     695             : GF_EXPORT
     696           2 : GF_Err gf_isom_flac_config_new(GF_ISOFile *the_file, u32 trackNumber, u8 *metadata, u32 metadata_size, const char *URLname, const char *URNname, u32 *outDescriptionIndex)
     697             : {
     698             :         GF_TrackBox *trak;
     699             :         GF_Err e;
     700             :         u32 dataRefIndex;
     701             :         GF_MPEGAudioSampleEntryBox *entry;
     702             : 
     703           2 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
     704           2 :         if (e) return e;
     705             : 
     706           2 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
     707           2 :         if (!trak || !trak->Media) return GF_BAD_PARAM;
     708             : 
     709             :         //get or create the data ref
     710           2 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
     711           2 :         if (e) return e;
     712           2 :         if (!dataRefIndex) {
     713           2 :                 e = Media_CreateDataRef(the_file, trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
     714           2 :                 if (e) return e;
     715             :         }
     716           2 :         if (!the_file->keep_utc)
     717           2 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
     718             : 
     719           2 :         entry = (GF_MPEGAudioSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_FLAC);
     720           2 :         if (!entry) return GF_OUT_OF_MEM;
     721           2 :         entry->cfg_flac = (GF_FLACConfigBox *) gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_DFLA);
     722             : 
     723           2 :         if (!entry->cfg_flac) {
     724           0 :                 gf_isom_box_del((GF_Box *) entry);
     725           0 :                 return GF_OUT_OF_MEM;
     726             :         }
     727           2 :         entry->cfg_flac->dataSize = metadata_size;
     728           2 :         entry->cfg_flac->data = gf_malloc(sizeof(u8)*metadata_size);
     729           2 :         memcpy(entry->cfg_flac->data, metadata, sizeof(u8)*metadata_size);
     730           2 :         entry->samplerate_hi = trak->Media->mediaHeader->timeScale;
     731           2 :         entry->dataReferenceIndex = dataRefIndex;
     732           2 :         e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->child_boxes, entry);
     733           2 :         *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
     734           2 :         return e;
     735             : }
     736             : 
     737             : 
     738             : 
     739             : GF_EXPORT
     740           7 : GF_Err gf_isom_new_mj2k_description(GF_ISOFile *the_file, u32 trackNumber, const char *URLname, const char *URNname, u32 *outDescriptionIndex, u8 *dsi, u32 dsi_len)
     741             : {
     742             :         GF_TrackBox *trak;
     743             :         GF_Err e;
     744           7 :         u32 dataRefIndex=0;
     745             : 
     746           7 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
     747           7 :         if (e) return e;
     748             : 
     749           7 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
     750           7 :         if (!trak || !trak->Media) return GF_BAD_PARAM;
     751             : 
     752             :         //get or create the data ref
     753           7 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
     754           7 :         if (e) return e;
     755           7 :         if (!dataRefIndex) {
     756           5 :                 e = Media_CreateDataRef(the_file, trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
     757           5 :                 if (e) return e;
     758             :         }
     759           7 :         if (!the_file->keep_utc)
     760           7 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
     761             : 
     762           7 :         GF_MPEGVisualSampleEntryBox *entry = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new_parent(&trak->Media->information->sampleTable->SampleDescription->child_boxes, GF_ISOM_BOX_TYPE_MJP2);
     763           7 :         if (!entry) return GF_OUT_OF_MEM;
     764           7 :         entry->jp2h = (GF_J2KHeaderBox *) gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_JP2H);
     765           7 :         if (!entry->jp2h) {
     766           0 :                 gf_isom_box_del_parent(&trak->Media->information->sampleTable->SampleDescription->child_boxes, (GF_Box *) entry);
     767           0 :                 return GF_OUT_OF_MEM;
     768             :         }
     769           7 :         if (dsi && dsi_len) {
     770           5 :                 GF_BitStream *bs = gf_bs_new(dsi, dsi_len, GF_BITSTREAM_READ);
     771           5 :                 entry->jp2h->size = dsi_len;
     772           5 :                 gf_isom_box_read((GF_Box *)entry->jp2h, bs);
     773           5 :                 gf_bs_del(bs);
     774             :         }
     775           7 :         entry->dataReferenceIndex = dataRefIndex;
     776           7 :         *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
     777           7 :         return e;
     778             : }
     779             : 
     780             : #endif  /*GPAC_DISABLE_ISOM_WRITE*/
     781             : 
     782             : 
     783             : 
     784             : GF_EXPORT
     785           5 : GF_Err gf_isom_get_dims_description(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex, GF_DIMSDescription *desc)
     786             : {
     787             :         GF_DIMSSampleEntryBox *dims;
     788             :         GF_TrackBox *trak;
     789           5 :         trak = gf_isom_get_track_from_file(movie, trackNumber);
     790           5 :         if (!trak || !descriptionIndex || !desc) return GF_BAD_PARAM;
     791             : 
     792           5 :         dims = (GF_DIMSSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, descriptionIndex-1);
     793           5 :         if (!dims) return GF_BAD_PARAM;
     794           5 :         if (dims->type != GF_ISOM_BOX_TYPE_DIMS) return GF_BAD_PARAM;
     795             : 
     796             :         memset(desc, 0, sizeof(GF_DIMSDescription));
     797           5 :         if (dims->config) {
     798           5 :                 desc->profile = dims->config->profile;
     799           5 :                 desc->level = dims->config->level;
     800           5 :                 desc->pathComponents = dims->config->pathComponents;
     801           5 :                 desc->fullRequestHost = dims->config->fullRequestHost;
     802           5 :                 desc->containsRedundant = dims->config->containsRedundant;
     803           5 :                 desc->streamType = dims->config->streamType;
     804           5 :                 desc->textEncoding = dims->config->textEncoding;
     805           5 :                 desc->contentEncoding = dims->config->contentEncoding;
     806             :         }
     807           5 :         if (dims->scripts) {
     808           0 :                 desc->content_script_types = dims->scripts->content_script_types;
     809             :         }
     810             :         return GF_OK;
     811             : }
     812             : 
     813             : #ifndef GPAC_DISABLE_ISOM_WRITE
     814             : 
     815             : GF_EXPORT
     816           2 : GF_Err gf_isom_new_dims_description(GF_ISOFile *movie, u32 trackNumber, GF_DIMSDescription *desc, const char *URLname, const char *URNname, u32 *outDescriptionIndex)
     817             : {
     818             :         GF_TrackBox *trak;
     819             :         GF_Err e;
     820             :         u32 dataRefIndex;
     821             :         GF_DIMSSampleEntryBox *dims;
     822             : 
     823           2 :         e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
     824           2 :         if (e) return e;
     825             : 
     826           2 :         trak = gf_isom_get_track_from_file(movie, trackNumber);
     827           2 :         if (!trak || !trak->Media) return GF_BAD_PARAM;
     828             : 
     829           2 :         if (trak->Media->handler->handlerType != GF_ISOM_MEDIA_SCENE) return GF_BAD_PARAM;
     830             : 
     831             :         //get or create the data ref
     832           2 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
     833           2 :         if (e) return e;
     834           2 :         if (!dataRefIndex) {
     835           2 :                 e = Media_CreateDataRef(movie, trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
     836           2 :                 if (e) return e;
     837             :         }
     838           2 :         if (!movie->keep_utc)
     839           2 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
     840             : 
     841           2 :         dims = (GF_DIMSSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_DIMS);
     842           2 :         if (!dims) return GF_OUT_OF_MEM;
     843           2 :         dims->dataReferenceIndex = dataRefIndex;
     844           2 :         gf_list_add(trak->Media->information->sampleTable->SampleDescription->child_boxes, dims);
     845           2 :         if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
     846             : 
     847           2 :         dims->config = (GF_DIMSSceneConfigBox*) gf_isom_box_new_parent(&dims->child_boxes, GF_ISOM_BOX_TYPE_DIMC);
     848           2 :         if (!dims->config) return GF_OUT_OF_MEM;
     849             : 
     850           2 :         dims->config->profile = desc->profile;
     851           2 :         dims->config->level = desc->level;
     852           2 :         dims->config->pathComponents = desc->pathComponents;
     853           2 :         dims->config->fullRequestHost = desc->fullRequestHost;
     854           2 :         dims->config->containsRedundant = desc->containsRedundant;
     855           2 :         if (!dims->config->containsRedundant) dims->config->containsRedundant = 1;
     856           2 :         dims->config->streamType = desc->streamType;
     857           2 :         dims->config->textEncoding = gf_strdup(desc->textEncoding ? desc->textEncoding : "");
     858           2 :         dims->config->contentEncoding = gf_strdup(desc->contentEncoding ? desc->contentEncoding : "");
     859             : 
     860           2 :         if (desc->content_script_types) {
     861           0 :                 dims->scripts = (GF_DIMSScriptTypesBox*) gf_isom_box_new_parent(&dims->child_boxes, GF_ISOM_BOX_TYPE_DIST);
     862           0 :                 if (!dims->scripts) return GF_OUT_OF_MEM;
     863           0 :                 dims->scripts->content_script_types = gf_strdup(desc->content_script_types);
     864             :         }
     865             :         return e;
     866             : }
     867             : 
     868             : #if 0 //unused
     869             : GF_Err gf_isom_update_dims_description(GF_ISOFile *movie, u32 trackNumber, GF_DIMSDescription *desc, char *URLname, char *URNname, u32 DescriptionIndex)
     870             : {
     871             :         GF_TrackBox *trak;
     872             :         GF_Err e;
     873             :         GF_DIMSSampleEntryBox *dims;
     874             : 
     875             :         e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
     876             :         if (e) return e;
     877             : 
     878             :         trak = gf_isom_get_track_from_file(movie, trackNumber);
     879             :         if (!trak || !trak->Media || !desc || !DescriptionIndex) return GF_BAD_PARAM;
     880             : 
     881             :         dims = (GF_DIMSSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
     882             :         if (!dims) return GF_BAD_PARAM;
     883             :         if (dims->type != GF_ISOM_BOX_TYPE_DIMS) return GF_BAD_PARAM;
     884             :         if (!dims->config) {
     885             :                 dims->config = (GF_DIMSSceneConfigBox*) gf_isom_box_new_parent(&dims->child_boxes, GF_ISOM_BOX_TYPE_DIMC);
     886             :                 if (!dims->config) return GF_OUT_OF_MEM;
     887             :         }
     888             : 
     889             :         if (!movie->keep_utc)
     890             :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
     891             : 
     892             :         dims->config->profile = desc->profile;
     893             :         dims->config->level = desc->level;
     894             :         dims->config->pathComponents = desc->pathComponents;
     895             :         dims->config->fullRequestHost = desc->fullRequestHost;
     896             :         dims->config->containsRedundant = desc->containsRedundant;
     897             :         dims->config->streamType = desc->streamType;
     898             : 
     899             :         if (dims->config->textEncoding) gf_free(dims->config->textEncoding);
     900             :         dims->config->textEncoding = gf_strdup(desc->textEncoding ? desc->textEncoding : "");
     901             : 
     902             :         if (dims->config->contentEncoding) gf_free(dims->config->contentEncoding);
     903             :         dims->config->contentEncoding = gf_strdup(desc->contentEncoding ? desc->contentEncoding : "");
     904             : 
     905             :         if (desc->content_script_types) {
     906             :                 if (!dims->scripts) {
     907             :                         dims->scripts = (GF_DIMSScriptTypesBox*) gf_isom_box_new_parent(&dims->child_boxes, GF_ISOM_BOX_TYPE_DIST);
     908             :                         if (!dims->scripts) return GF_OUT_OF_MEM;
     909             :                 }
     910             :                 if (dims->scripts->content_script_types) gf_free(dims->scripts->content_script_types);
     911             :                 dims->scripts->content_script_types = gf_strdup(desc->content_script_types ? desc->content_script_types  :"");
     912             :         } else if (dims->scripts) {
     913             :                 gf_isom_box_del_parent(&dims->child_boxes, (GF_Box *) dims->scripts);
     914             :                 dims->scripts = NULL;
     915             :         }
     916             :         return GF_OK;
     917             : }
     918             : #endif
     919             : 
     920             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     921             : 
     922           5 : GF_Err LSR_UpdateESD(GF_LASeRSampleEntryBox *lsr, GF_ESD *esd)
     923             : {
     924           5 :         GF_BitRateBox *btrt = gf_isom_sample_entry_get_bitrate((GF_SampleEntryBox *)lsr, GF_TRUE);
     925             : 
     926           5 :         if (lsr->descr) gf_isom_box_del_parent(&lsr->child_boxes, (GF_Box *) lsr->descr);
     927           5 :         lsr->descr = NULL;
     928           5 :         btrt->avgBitrate = esd->decoderConfig->avgBitrate;
     929           5 :         btrt->maxBitrate = esd->decoderConfig->maxBitrate;
     930           5 :         btrt->bufferSizeDB = esd->decoderConfig->bufferSizeDB;
     931             : 
     932           5 :         if (gf_list_count(esd->IPIDataSet)
     933           5 :                 || gf_list_count(esd->IPMPDescriptorPointers)
     934           5 :                 || esd->langDesc
     935           5 :                 || gf_list_count(esd->extensionDescriptors)
     936           5 :                 || esd->ipiPtr || esd->qos || esd->RegDescriptor) {
     937             : 
     938           0 :                 lsr->descr = (GF_MPEG4ExtensionDescriptorsBox *)gf_isom_box_new_parent(&lsr->child_boxes, GF_ISOM_BOX_TYPE_M4DS);
     939           0 :                 if (!lsr->descr) return GF_OUT_OF_MEM;
     940           0 :                 if (esd->RegDescriptor) {
     941           0 :                         gf_list_add(lsr->descr->descriptors, esd->RegDescriptor);
     942           0 :                         esd->RegDescriptor = NULL;
     943             :                 }
     944           0 :                 if (esd->qos) {
     945           0 :                         gf_list_add(lsr->descr->descriptors, esd->qos);
     946           0 :                         esd->qos = NULL;
     947             :                 }
     948           0 :                 if (esd->ipiPtr) {
     949           0 :                         gf_list_add(lsr->descr->descriptors, esd->ipiPtr);
     950           0 :                         esd->ipiPtr= NULL;
     951             :                 }
     952             : 
     953           0 :                 while (gf_list_count(esd->IPIDataSet)) {
     954           0 :                         GF_Descriptor *desc = (GF_Descriptor *)gf_list_get(esd->IPIDataSet, 0);
     955           0 :                         gf_list_rem(esd->IPIDataSet, 0);
     956           0 :                         gf_list_add(lsr->descr->descriptors, desc);
     957             :                 }
     958           0 :                 while (gf_list_count(esd->IPMPDescriptorPointers)) {
     959           0 :                         GF_Descriptor *desc = (GF_Descriptor *)gf_list_get(esd->IPMPDescriptorPointers, 0);
     960           0 :                         gf_list_rem(esd->IPMPDescriptorPointers, 0);
     961           0 :                         gf_list_add(lsr->descr->descriptors, desc);
     962             :                 }
     963           0 :                 if (esd->langDesc) {
     964           0 :                         gf_list_add(lsr->descr->descriptors, esd->langDesc);
     965           0 :                         esd->langDesc = NULL;
     966             :                 }
     967           0 :                 while (gf_list_count(esd->extensionDescriptors)) {
     968           0 :                         GF_Descriptor *desc = (GF_Descriptor *)gf_list_get(esd->extensionDescriptors, 0);
     969           0 :                         gf_list_rem(esd->extensionDescriptors, 0);
     970           0 :                         gf_list_add(lsr->descr->descriptors, desc);
     971             :                 }
     972             :         }
     973             : 
     974             :         /*update GF_AVCConfig*/
     975           5 :         if (!lsr->lsr_config) {
     976           3 :                 lsr->lsr_config = (GF_LASERConfigurationBox *)gf_isom_box_new_parent(&lsr->child_boxes,  GF_ISOM_BOX_TYPE_LSRC);
     977           3 :                 if (!lsr->lsr_config) return GF_OUT_OF_MEM;
     978             :         }
     979           5 :         if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) {
     980           5 :                 lsr->lsr_config->hdr = gf_realloc(lsr->lsr_config->hdr, sizeof(char) * esd->decoderConfig->decoderSpecificInfo->dataLength);
     981           5 :                 lsr->lsr_config->hdr_size = esd->decoderConfig->decoderSpecificInfo->dataLength;
     982           5 :                 memcpy(lsr->lsr_config->hdr, esd->decoderConfig->decoderSpecificInfo->data, sizeof(char)*esd->decoderConfig->decoderSpecificInfo->dataLength);
     983             :         }
     984           5 :         gf_odf_desc_del((GF_Descriptor *)esd);
     985           5 :         return GF_OK;
     986             : }
     987             : 
     988             : /* MetadataSampleEntry */
     989             : GF_EXPORT
     990           1 : GF_Err gf_isom_get_xml_metadata_description(GF_ISOFile *file, u32 track, u32 sampleDescription,
     991             :         const char **_namespace, const char **schema_loc, const char **content_encoding)
     992             : {
     993             :         GF_TrackBox *trak;
     994             :         GF_MetaDataSampleEntryBox *ptr;
     995           1 :         if (_namespace) *_namespace = NULL;
     996           1 :         if (content_encoding) *content_encoding = NULL;
     997           1 :         if (schema_loc) *schema_loc = NULL;
     998           1 :         trak = gf_isom_get_track_from_file(file, track);
     999           1 :         if (!trak || !sampleDescription) return GF_BAD_PARAM;
    1000           1 :         ptr = (GF_MetaDataSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, sampleDescription-1);
    1001           1 :         if (!ptr) return GF_BAD_PARAM;
    1002             : 
    1003           1 :         if (schema_loc) *schema_loc = ptr->xml_schema_loc;
    1004           1 :         if (_namespace) *_namespace = ptr->xml_namespace;
    1005           1 :         if (content_encoding) *content_encoding = ptr->content_encoding;
    1006             :         return GF_OK;
    1007             : }
    1008             : 
    1009             : #ifndef GPAC_DISABLE_ISOM_WRITE
    1010             : 
    1011           3 : GF_Err gf_isom_new_xml_metadata_description(GF_ISOFile *movie, u32 trackNumber,
    1012             :         const char *_namespace, const char *schema_loc, const char *content_encoding,
    1013             :         u32 *outDescriptionIndex)
    1014             : {
    1015             :         GF_TrackBox *trak;
    1016             :         GF_Err e;
    1017             :         u32 dataRefIndex;
    1018             :         GF_MetaDataSampleEntryBox *metad;
    1019             :         char *URLname = NULL;
    1020             :         char *URNname = NULL;
    1021             : 
    1022           3 :         e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
    1023           3 :         if (e) return e;
    1024             : 
    1025           3 :         trak = gf_isom_get_track_from_file(movie, trackNumber);
    1026           3 :         if (!trak || !trak->Media || !_namespace)
    1027             :                 return GF_BAD_PARAM;
    1028             : 
    1029           2 :         switch (trak->Media->handler->handlerType) {
    1030             :         case GF_ISOM_MEDIA_MPEG_SUBT:
    1031             :         case GF_ISOM_MEDIA_META:
    1032             :         case GF_ISOM_MEDIA_TEXT:
    1033             :                 break;
    1034             :         default:
    1035             :                 return GF_BAD_PARAM;
    1036             :         }
    1037             : 
    1038             :         //get or create the data ref
    1039           2 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
    1040           2 :         if (e) return e;
    1041           2 :         if (!dataRefIndex) {
    1042           2 :                 e = Media_CreateDataRef(movie, trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
    1043           2 :                 if (e) return e;
    1044             :         }
    1045           2 :         if (!movie->keep_utc)
    1046           2 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
    1047             : 
    1048           2 :         metad = (GF_MetaDataSampleEntryBox*) gf_isom_box_new(GF_ISOM_BOX_TYPE_METX);
    1049           2 :         if (!metad) return GF_OUT_OF_MEM;
    1050             : 
    1051           2 :         metad->dataReferenceIndex = dataRefIndex;
    1052           2 :         metad->xml_namespace = gf_strdup(_namespace);
    1053           2 :         if (content_encoding) metad->content_encoding = gf_strdup(content_encoding);
    1054           2 :         if (schema_loc) metad->xml_schema_loc = gf_strdup(schema_loc);
    1055             : 
    1056           2 :         e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->child_boxes, metad);
    1057           2 :         if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
    1058             :         return e;
    1059             : }
    1060             : 
    1061             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
    1062             : 
    1063             : /* XMLSubtitleSampleEntry */
    1064             : GF_EXPORT
    1065          23 : GF_Err gf_isom_xml_subtitle_get_description(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex,
    1066             :         const char **xmlnamespace, const char **xml_schema_loc, const char **mimes)
    1067             : {
    1068             :         GF_TrackBox *trak;
    1069             :         GF_MetaDataSampleEntryBox *entry;
    1070          23 :         if (xmlnamespace) *xmlnamespace = NULL;
    1071          23 :         if (xml_schema_loc) *xml_schema_loc = NULL;
    1072          23 :         if (mimes) *mimes = NULL;
    1073          23 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    1074          23 :         if (!trak || !StreamDescriptionIndex) return GF_BAD_PARAM;
    1075             : 
    1076          23 :         entry = (GF_MetaDataSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, StreamDescriptionIndex-1);
    1077          23 :         if (!entry) return GF_BAD_PARAM;
    1078             :  
    1079          23 :         if ((entry->type!=GF_ISOM_BOX_TYPE_STPP) && (entry->type!=GF_ISOM_BOX_TYPE_METX)) {
    1080             :                 return GF_BAD_PARAM;
    1081             :         }
    1082             : 
    1083          23 :         if (entry->mime_type) {
    1084           0 :                 if (mimes) *mimes = entry->mime_type;
    1085             :         }
    1086          23 :         if (entry->xml_schema_loc) {
    1087           7 :                 if (xml_schema_loc) *xml_schema_loc = entry->xml_schema_loc;
    1088             :         }
    1089          23 :         if (xmlnamespace)
    1090          23 :                 *xmlnamespace = entry->xml_namespace;
    1091             :         return GF_OK;
    1092             : }
    1093             : 
    1094             : 
    1095             : GF_EXPORT
    1096        1195 : const char *gf_isom_subtitle_get_mime(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex)
    1097             : {
    1098             :         GF_TrackBox *trak;
    1099             :         GF_TextConfigBox *mime;
    1100             :         GF_MetaDataSampleEntryBox *entry;
    1101        1195 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    1102        1195 :         if (!trak || !StreamDescriptionIndex) return NULL;
    1103             : 
    1104        1195 :         entry = (GF_MetaDataSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, StreamDescriptionIndex-1);
    1105        1195 :         if (!entry) return NULL;
    1106             : 
    1107        1195 :         mime = (GF_TextConfigBox *) gf_isom_box_find_child(entry->child_boxes, GF_ISOM_BOX_TYPE_MIME);
    1108        1195 :         if (!mime) return NULL;
    1109           0 :         return mime->config;
    1110             : }
    1111             : 
    1112             : 
    1113             : #ifndef GPAC_DISABLE_ISOM_WRITE
    1114             : 
    1115             : GF_EXPORT
    1116           0 : GF_Err gf_isom_subtitle_set_mime(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex, const char *codec_params)
    1117             : {
    1118             :         GF_TrackBox *trak;
    1119             :         GF_Err e;
    1120             :         GF_TextConfigBox *mime;
    1121             :         GF_MetaDataSampleEntryBox *entry;
    1122             : 
    1123           0 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
    1124           0 :         if (e) return e;
    1125             : 
    1126           0 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    1127           0 :         if (!trak || !StreamDescriptionIndex) return GF_BAD_PARAM;
    1128             : 
    1129           0 :         entry = (GF_MetaDataSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, StreamDescriptionIndex-1);
    1130           0 :         if (!entry) return GF_BAD_PARAM;
    1131             : 
    1132           0 :         mime = (GF_TextConfigBox *) gf_isom_box_find_child(entry->child_boxes, GF_ISOM_BOX_TYPE_MIME);
    1133           0 :         if (!mime) {
    1134           0 :                 if (!codec_params) return GF_OK;
    1135           0 :                 mime = (GF_TextConfigBox *) gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_MIME);
    1136           0 :                 if (!mime) return GF_OUT_OF_MEM;
    1137             :         }
    1138           0 :         if (!codec_params) {
    1139           0 :                 gf_isom_box_del_parent(&entry->child_boxes, (GF_Box *)mime);
    1140           0 :                 return GF_OK;
    1141             :         }
    1142           0 :         if (mime->config) gf_free(mime->config);
    1143           0 :         mime->config = gf_strdup(codec_params);
    1144           0 :         return GF_OK;
    1145             : }
    1146             : 
    1147             : GF_EXPORT
    1148          21 : GF_Err gf_isom_new_xml_subtitle_description(GF_ISOFile  *movie, u32 trackNumber,
    1149             :         const char *xmlnamespace, const char *xml_schema_loc, const char *mimes,
    1150             :         u32 *outDescriptionIndex)
    1151             : {
    1152             :         GF_TrackBox                 *trak;
    1153             :         GF_Err                      e;
    1154             :         u32                         dataRefIndex;
    1155             :         GF_MetaDataSampleEntryBox *stpp;
    1156             :         char *URLname = NULL;
    1157             :         char *URNname = NULL;
    1158             : 
    1159          21 :         e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
    1160          21 :         if (e) return e;
    1161             : 
    1162          21 :         trak = gf_isom_get_track_from_file(movie, trackNumber);
    1163          21 :         if (!trak || !trak->Media) return GF_BAD_PARAM;
    1164             : 
    1165          21 :         switch (trak->Media->handler->handlerType) {
    1166             :         case GF_ISOM_MEDIA_MPEG_SUBT:
    1167             :         case GF_ISOM_MEDIA_META:
    1168             :         case GF_ISOM_MEDIA_TEXT:
    1169             :                 break;
    1170             :         default:
    1171             :                 return GF_BAD_PARAM;
    1172             :         }
    1173             : 
    1174          21 :         if (!xmlnamespace) {
    1175           1 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("XML (Subtitle, Metadata or Text) SampleEntry: namespace is mandatory. Abort.\n"));
    1176             :                 return GF_BAD_PARAM;
    1177             :         }
    1178             : 
    1179             :         //get or create the data ref
    1180          20 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
    1181          20 :         if (e) return e;
    1182          20 :         if (!dataRefIndex) {
    1183          20 :                 e = Media_CreateDataRef(movie, trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
    1184          20 :                 if (e) return e;
    1185             :         }
    1186          20 :         if (!movie->keep_utc)
    1187          20 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
    1188             : 
    1189          20 :         stpp = (GF_MetaDataSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STPP);
    1190          20 :         if (!stpp) return GF_OUT_OF_MEM;
    1191          20 :         stpp->dataReferenceIndex = dataRefIndex;
    1192          20 :         gf_list_add(trak->Media->information->sampleTable->SampleDescription->child_boxes, stpp);
    1193          20 :         if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
    1194             : 
    1195          20 :         stpp->xml_namespace = gf_strdup(xmlnamespace);
    1196          20 :         if (xml_schema_loc) stpp->xml_schema_loc = gf_strdup(xml_schema_loc); //optional
    1197          20 :         if (mimes) stpp->mime_type = gf_strdup(mimes); //optional
    1198             :         return e;
    1199             : }
    1200             : 
    1201             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
    1202             : 
    1203             : 
    1204             : /* SimpleTextSampleEntry: also used for MetadataTextSampleEntry and SubtitleTextSampleEntry */
    1205             : GF_EXPORT
    1206          36 : GF_Err gf_isom_stxt_get_description(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex,
    1207             :                                     const char **mime, const char **encoding, const char **config)
    1208             : {
    1209             :         GF_TrackBox *trak;
    1210             :         GF_MetaDataSampleEntryBox *entry;
    1211          36 :         if (mime) *mime = NULL;
    1212          36 :         if (config) *config = NULL;
    1213          36 :         if (encoding) *encoding = NULL;
    1214          36 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    1215          36 :         if (!trak || !StreamDescriptionIndex) return GF_BAD_PARAM;
    1216             : 
    1217          36 :         entry = (GF_MetaDataSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, StreamDescriptionIndex-1);
    1218          72 :         if (!entry ||
    1219          36 :                 ((entry->type!=GF_ISOM_BOX_TYPE_STXT) &&
    1220           8 :                  (entry->type!=GF_ISOM_BOX_TYPE_METT) &&
    1221             :                  (entry->type!=GF_ISOM_BOX_TYPE_SBTT))) {
    1222             :                 return GF_BAD_PARAM;
    1223             :         }
    1224             : 
    1225          36 :         if (entry->config) {
    1226           8 :                 if (config) *config = entry->config->config;
    1227             :         }
    1228          36 :         if (entry->mime_type) {
    1229          36 :                 if (mime) *mime = entry->mime_type;
    1230             :         }
    1231          36 :         if (entry->content_encoding) {
    1232          16 :                 if (encoding) *encoding = entry->content_encoding;
    1233             :         }
    1234             :         return GF_OK;
    1235             : }
    1236             : 
    1237             : #ifndef GPAC_DISABLE_ISOM_WRITE
    1238          25 : GF_Err gf_isom_new_stxt_description(GF_ISOFile *movie, u32 trackNumber, u32 type,
    1239             :                                     const char *mime, const char *encoding, const char * config,
    1240             :                                     u32 *outDescriptionIndex)
    1241             : {
    1242             :         GF_TrackBox *trak;
    1243             :         GF_Err e;
    1244             :         u32 dataRefIndex;
    1245             :         GF_MetaDataSampleEntryBox *sample_entry;
    1246             :         char *URLname = NULL;
    1247             :         char *URNname = NULL;
    1248             : 
    1249          25 :         e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
    1250          25 :         if (e) return e;
    1251             : 
    1252          25 :         trak = gf_isom_get_track_from_file(movie, trackNumber);
    1253          25 :         if (!trak || !trak->Media) return GF_BAD_PARAM;
    1254             : 
    1255          25 :         switch (trak->Media->handler->handlerType) {
    1256             :         case GF_ISOM_MEDIA_MPEG_SUBT:
    1257             :         case GF_ISOM_MEDIA_META:
    1258             :         case GF_ISOM_MEDIA_SCENE:
    1259             :         case GF_ISOM_MEDIA_TEXT:
    1260             :         case GF_ISOM_MEDIA_SUBT:
    1261             :                 break;
    1262             :         default:
    1263             :                 return GF_BAD_PARAM;
    1264             :         }
    1265          25 :         switch (type) {
    1266             :         case GF_ISOM_SUBTYPE_SBTT:
    1267             :         case GF_ISOM_SUBTYPE_STXT:
    1268             :         case GF_ISOM_SUBTYPE_METT:
    1269             :                 break;
    1270           0 :         default:
    1271           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("SampleEntry shall be either Metadata, Subtitle or SimpleText. Abort.\n"));
    1272             :                 return GF_BAD_PARAM;
    1273             :         }
    1274             : 
    1275          25 :         if (!mime) {
    1276           4 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("Text (Metadata, Subtitle or SimpleText) SampleEntry: mime is mandatory. Using text/plain.\n"));
    1277             :                 mime = "text/plain";
    1278             :         }
    1279             : 
    1280             :         //get or create the data ref
    1281          25 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
    1282          25 :         if (e) return e;
    1283          25 :         if (!dataRefIndex) {
    1284          25 :                 e = Media_CreateDataRef(movie, trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex);
    1285          25 :                 if (e) return e;
    1286             :         }
    1287          25 :         if (!movie->keep_utc)
    1288          25 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
    1289             : 
    1290          25 :         sample_entry = (GF_MetaDataSampleEntryBox *) gf_isom_box_new(type);
    1291          25 :         if (!sample_entry) return GF_OUT_OF_MEM;
    1292          25 :         sample_entry->dataReferenceIndex = dataRefIndex;
    1293          25 :         gf_list_add(trak->Media->information->sampleTable->SampleDescription->child_boxes, sample_entry);
    1294          25 :         if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
    1295             : 
    1296          25 :         sample_entry->mime_type = gf_strdup(mime);
    1297          25 :         if (encoding) sample_entry->content_encoding = gf_strdup(encoding);
    1298          25 :         if (config) {
    1299          10 :                 sample_entry->config = (GF_TextConfigBox*) gf_isom_box_new_parent(&sample_entry->child_boxes, GF_ISOM_BOX_TYPE_TXTC);
    1300          10 :                 if (!sample_entry->config) return GF_OUT_OF_MEM;
    1301          10 :                 sample_entry->config->config = gf_strdup(config);
    1302          10 :                 if (!sample_entry->config->config) return GF_OUT_OF_MEM;
    1303             :         }
    1304             :         return e;
    1305             : }
    1306             : 
    1307             : #if 0 //unused
    1308             : 
    1309             : /*! updates simple streaming text config
    1310             : \param isom_file the target ISO file
    1311             : \param trackNumber the target track
    1312             : \param encoding the text encoding, if any
    1313             : \param config the configuration string, if any
    1314             : \param sampleDescriptionIndex the target sample description index
    1315             : \return error if any
    1316             : */
    1317             : GF_Err gf_isom_update_stxt_description(GF_ISOFile *movie, u32 trackNumber,
    1318             :                                        const char *encoding, const char *config,
    1319             :                                        u32 DescriptionIndex)
    1320             : {
    1321             :         GF_TrackBox *trak;
    1322             :         GF_Err e;
    1323             :         GF_MetaDataSampleEntryBox *sample_entry;
    1324             : 
    1325             :         e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
    1326             :         if (e) return e;
    1327             : 
    1328             :         trak = gf_isom_get_track_from_file(movie, trackNumber);
    1329             :         if (!trak || !trak->Media || !DescriptionIndex) return GF_BAD_PARAM;
    1330             : 
    1331             :         sample_entry = (GF_MetaDataSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
    1332             :         if (!sample_entry) return GF_BAD_PARAM;
    1333             :         if (sample_entry->type != GF_ISOM_BOX_TYPE_METT &&
    1334             :                 sample_entry->type != GF_ISOM_BOX_TYPE_SBTT &&
    1335             :                 sample_entry->type != GF_ISOM_BOX_TYPE_STXT) {
    1336             :                 return GF_BAD_PARAM;
    1337             :         }
    1338             : 
    1339             :         if (!sample_entry->config) {
    1340             :                 sample_entry->config = (GF_TextConfigBox*) gf_isom_box_new_parent(&sample_entry->child_boxes, GF_ISOM_BOX_TYPE_TXTC);
    1341             :                 if (!sample_entry->config) return GF_OUT_OF_MEM;
    1342             :         }
    1343             :         if (!movie->keep_utc)
    1344             :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
    1345             : 
    1346             :         if (sample_entry->config->config) {
    1347             :                 gf_free(sample_entry->config->config);
    1348             :         }
    1349             :         sample_entry->config->config = gf_strdup(config);
    1350             : 
    1351             :         if (sample_entry->content_encoding) {
    1352             :                 gf_free(sample_entry->content_encoding);
    1353             :         }
    1354             :         if (encoding) {
    1355             :                 sample_entry->content_encoding = gf_strdup(encoding);
    1356             :         }
    1357             :         return GF_OK;
    1358             : }
    1359             : #endif
    1360             : 
    1361             : 
    1362             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
    1363             : 
    1364             : #ifndef GPAC_DISABLE_VTT
    1365             : 
    1366           6 : GF_WebVTTSampleEntryBox *gf_webvtt_isom_get_description(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex)
    1367             : {
    1368             :         GF_WebVTTSampleEntryBox *wvtt;
    1369             :         GF_TrackBox *trak;
    1370             : 
    1371           6 :         if (!descriptionIndex) return NULL;
    1372             : 
    1373           6 :         trak = gf_isom_get_track_from_file(movie, trackNumber);
    1374           6 :         if (!trak || !trak->Media) return NULL;
    1375             : 
    1376           6 :         switch (trak->Media->handler->handlerType) {
    1377             :         case GF_ISOM_MEDIA_TEXT:
    1378             :                 break;
    1379             :         default:
    1380             :                 return NULL;
    1381             :         }
    1382             : 
    1383           6 :         wvtt = (GF_WebVTTSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, descriptionIndex - 1);
    1384           6 :         if (!wvtt) return NULL;
    1385           6 :         switch (wvtt->type) {
    1386             :         case GF_ISOM_BOX_TYPE_WVTT:
    1387             :                 break;
    1388             :         default:
    1389             :                 return NULL;
    1390             :         }
    1391           6 :         return wvtt;
    1392             : }
    1393             : 
    1394             : GF_EXPORT
    1395           4 : const char *gf_isom_get_webvtt_config(GF_ISOFile *file, u32 track, u32 index)
    1396             : {
    1397           4 :         GF_WebVTTSampleEntryBox *wvtt = gf_webvtt_isom_get_description(file, track, index);
    1398           4 :         if (!wvtt) return NULL;
    1399           4 :         return wvtt->config ? wvtt->config->string : NULL;
    1400             : }
    1401             : 
    1402             : #endif /*GPAC_DISABLE_VTT*/
    1403             : 
    1404             : #ifndef GPAC_DISABLE_ISOM_WRITE
    1405             : 
    1406             : #ifndef GPAC_DISABLE_VTT
    1407             : 
    1408             : #if 0 //unused
    1409             : /*! updates a WebVTT sample description
    1410             : \param isom_file the target ISO file
    1411             : \param trackNumber the target track
    1412             : \param sampleDescriptionIndex the target sample description index to update
    1413             : \param config the WebVTT configuration string
    1414             : \return error if any
    1415             : */
    1416             : GF_Err gf_isom_update_webvtt_description(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex, const char *config)
    1417             : {
    1418             :         GF_Err e;
    1419             :         GF_WebVTTSampleEntryBox *wvtt;
    1420             :         GF_TrackBox *trak;
    1421             : 
    1422             :         e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
    1423             :         if (e) return GF_BAD_PARAM;
    1424             : 
    1425             :         trak = gf_isom_get_track_from_file(movie, trackNumber);
    1426             :         if (!trak || !trak->Media) return GF_BAD_PARAM;
    1427             : 
    1428             :         switch (trak->Media->handler->handlerType) {
    1429             :         case GF_ISOM_MEDIA_TEXT:
    1430             :         case GF_ISOM_MEDIA_SUBT:
    1431             :         case GF_ISOM_MEDIA_MPEG_SUBT:
    1432             :                 break;
    1433             :         default:
    1434             :                 return GF_BAD_PARAM;
    1435             :         }
    1436             : 
    1437             :         wvtt = (GF_WebVTTSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, descriptionIndex - 1);
    1438             :         if (!wvtt) return GF_BAD_PARAM;
    1439             :         switch (wvtt->type) {
    1440             :         case GF_ISOM_BOX_TYPE_WVTT:
    1441             :                 break;
    1442             :         default:
    1443             :                 return GF_BAD_PARAM;
    1444             :         }
    1445             :         if (!movie->keep_utc)
    1446             :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
    1447             : 
    1448             :         if (wvtt->config) gf_isom_box_del_parent(&wvtt->child_boxes, (GF_Box *)wvtt->config);
    1449             :         wvtt->config = (GF_StringBox *)boxstring_new_with_data(GF_ISOM_BOX_TYPE_VTTC_CONFIG, config, &wvtt->child_boxes);
    1450             :         return GF_OK;
    1451             : }
    1452             : #endif
    1453             : 
    1454             : 
    1455          42 : GF_Err gf_isom_new_webvtt_description(GF_ISOFile *movie, u32 trackNumber, const char *URLname, const char *URNname, u32 *outDescriptionIndex, const char *config)
    1456             : {
    1457             :         GF_TrackBox *trak;
    1458             :         GF_Err e;
    1459             :         u32 dataRefIndex;
    1460             :         GF_WebVTTSampleEntryBox *wvtt;
    1461             : 
    1462          42 :         e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
    1463          42 :         if (e) return e;
    1464             : 
    1465          42 :         trak = gf_isom_get_track_from_file(movie, trackNumber);
    1466          42 :         if (!trak || !trak->Media) return GF_BAD_PARAM;
    1467             : 
    1468          42 :         switch (trak->Media->handler->handlerType) {
    1469             :         case GF_ISOM_MEDIA_TEXT:
    1470             :         case GF_ISOM_MEDIA_SUBT:
    1471             :         case GF_ISOM_MEDIA_MPEG_SUBT:
    1472             :                 break;
    1473             :         default:
    1474             :                 return GF_BAD_PARAM;
    1475             :         }
    1476             : 
    1477             :         //get or create the data ref
    1478          42 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
    1479          42 :         if (e) return e;
    1480          42 :         if (!dataRefIndex) {
    1481          42 :                 e = Media_CreateDataRef(movie, trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
    1482          42 :                 if (e) return e;
    1483             :         }
    1484          42 :         if (!movie->keep_utc)
    1485          42 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
    1486             : 
    1487          42 :         wvtt = (GF_WebVTTSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_WVTT);
    1488          42 :         if (!wvtt) return GF_OUT_OF_MEM;
    1489          42 :         wvtt->dataReferenceIndex = dataRefIndex;
    1490          42 :         gf_list_add(trak->Media->information->sampleTable->SampleDescription->child_boxes, wvtt);
    1491          42 :         if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
    1492             : 
    1493          42 :         if (config) {
    1494          42 :                 wvtt->config = (GF_StringBox *)boxstring_new_with_data(GF_ISOM_BOX_TYPE_VTTC_CONFIG, config, &wvtt->child_boxes);
    1495             :         }
    1496             :         return e;
    1497             : }
    1498             : 
    1499             : #endif /*GPAC_DISABLE_VTT*/
    1500             : 
    1501        5405 : GF_BitRateBox *gf_isom_sample_entry_get_bitrate(GF_SampleEntryBox *ent, Bool create)
    1502             : {
    1503        5405 :         u32 i=0;
    1504             :         GF_BitRateBox *a;
    1505       17563 :         while ((a = (GF_BitRateBox *)gf_list_enum(ent->child_boxes, &i))) {
    1506        9895 :                 if (a->type==GF_ISOM_BOX_TYPE_BTRT) return a;
    1507             :         }
    1508        2263 :         if (!create) return NULL;
    1509         822 :         a = (GF_BitRateBox *) gf_isom_box_new_parent(&ent->child_boxes, GF_ISOM_BOX_TYPE_BTRT);
    1510         822 :         return a;
    1511             : }
    1512             : 
    1513             : GF_EXPORT
    1514        1624 : GF_Err gf_isom_update_bitrate(GF_ISOFile *movie, u32 trackNumber, u32 sampleDescriptionIndex, u32 average_bitrate, u32 max_bitrate, u32 decode_buffer_size)
    1515             : {
    1516             :         GF_BitRateBox *a;
    1517             :         GF_Err e;
    1518             :         GF_SampleEntryBox *ent;
    1519             :         u32 i, count;
    1520             :         GF_TrackBox *trak;
    1521             : 
    1522        1624 :         e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
    1523        1624 :         if (e) return GF_BAD_PARAM;
    1524             : 
    1525        1624 :         trak = gf_isom_get_track_from_file(movie, trackNumber);
    1526             : 
    1527        1624 :         if (!trak || !trak->Media) return GF_BAD_PARAM;
    1528             : 
    1529        1624 :         count = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
    1530        3255 :         for (i=0; i<count; i++) {
    1531             :                 u32 ent_type;
    1532             :                 GF_ProtectionSchemeInfoBox *sinf;
    1533             :                 GF_ESDBox *esds=NULL;
    1534        1631 :                 if (sampleDescriptionIndex && (sampleDescriptionIndex!=i+1)) continue;
    1535             : 
    1536        1623 :                 ent = (GF_SampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, i);
    1537        1623 :                 if (!ent) return GF_BAD_PARAM;
    1538             : 
    1539        1623 :                 ent_type = ent->type;
    1540             :                 switch (ent_type) {
    1541         105 :                 case GF_ISOM_BOX_TYPE_ENCV:
    1542             :                 case GF_ISOM_BOX_TYPE_ENCA:
    1543             :                 case GF_ISOM_BOX_TYPE_ENCS:
    1544         105 :                         sinf = (GF_ProtectionSchemeInfoBox *) gf_isom_box_find_child(ent->child_boxes, GF_ISOM_BOX_TYPE_SINF);
    1545         105 :                         if (sinf && sinf->original_format)
    1546         105 :                                 ent_type = sinf->original_format->data_format;
    1547             :                         break;
    1548             :                 }
    1549        1623 :                 switch (ent_type) {
    1550         173 :                 case GF_ISOM_BOX_TYPE_MP4V:
    1551         173 :                         esds = ((GF_MPEGVisualSampleEntryBox *)ent)->esd;
    1552         173 :                         break;
    1553         253 :                 case GF_ISOM_BOX_TYPE_MP4A:
    1554         253 :                         esds = ((GF_MPEGAudioSampleEntryBox *)ent)->esd;
    1555         253 :                         break;
    1556           2 :                 case GF_ISOM_BOX_TYPE_MP4S:
    1557           2 :                         esds = ((GF_MPEGSampleEntryBox *) ent)->esd;
    1558           2 :                         break;
    1559             :                 }
    1560             :                 //using mpeg4 esd
    1561         428 :                 if (esds) {
    1562         428 :                         if (esds->desc && esds->desc->decoderConfig) {
    1563         428 :                                 esds->desc->decoderConfig->avgBitrate = average_bitrate;
    1564         428 :                                 esds->desc->decoderConfig->maxBitrate = max_bitrate;
    1565         428 :                                 if (decode_buffer_size)
    1566         416 :                                         esds->desc->decoderConfig->bufferSizeDB = decode_buffer_size;
    1567             :                         }
    1568         428 :                         continue;
    1569             :                 }
    1570             :                 
    1571             :                 //using BTRT
    1572        1195 :                 if (!max_bitrate && average_bitrate) max_bitrate = average_bitrate;
    1573        1195 :                 a = gf_isom_sample_entry_get_bitrate(ent, max_bitrate ? GF_TRUE : GF_FALSE);
    1574             : 
    1575        1195 :                 if (!max_bitrate) {
    1576         132 :                         if (a) {
    1577          10 :                                 gf_isom_box_del_parent(&ent->child_boxes, (GF_Box *) a);
    1578             :                         }
    1579             :                 } else {
    1580        1063 :                         a->avgBitrate = average_bitrate;
    1581        1063 :                         a->maxBitrate = max_bitrate;
    1582        1063 :                         if (decode_buffer_size)
    1583        1023 :                                 a->bufferSizeDB = decode_buffer_size;
    1584             :                 }
    1585             :         }
    1586             :         return GF_OK;
    1587             : }
    1588             : 
    1589             : 
    1590             : GF_EXPORT
    1591           3 : GF_Err gf_isom_tmcd_config_new(GF_ISOFile *the_file, u32 trackNumber, u32 fps_num, u32 fps_den, s32 frames_per_counter_tick, Bool is_drop, Bool is_counter, u32 *outDescriptionIndex)
    1592             : {
    1593             :         GF_TrackBox *trak;
    1594             :         GF_Err e;
    1595             :         u32 dataRefIndex;
    1596             :         GF_Box *tmcd;
    1597             :         GF_GenericMediaHeaderInfoBox *gmin;
    1598             :         GF_TimeCodeMediaInformationBox *tcmi;
    1599             :         GF_TimeCodeSampleEntryBox *entry;
    1600             : 
    1601           3 :         e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE);
    1602           3 :         if (e) return e;
    1603             : 
    1604           3 :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    1605           3 :         if (!trak || !trak->Media) return GF_BAD_PARAM;
    1606             : 
    1607             :         //get or create the data ref
    1608           3 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, NULL, NULL, &dataRefIndex);
    1609           3 :         if (e) return e;
    1610           3 :         if (!dataRefIndex) {
    1611           3 :                 e = Media_CreateDataRef(the_file, trak->Media->information->dataInformation->dref, NULL, NULL, &dataRefIndex);
    1612           3 :                 if (e) return e;
    1613             :         }
    1614           3 :         if (!the_file->keep_utc)
    1615           3 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
    1616             : 
    1617           3 :         gmin = (GF_GenericMediaHeaderInfoBox *) gf_isom_box_find_child(trak->Media->information->InfoHeader->child_boxes, GF_QT_BOX_TYPE_GMIN);
    1618           3 :         if (!gmin) {
    1619           3 :                 gmin = (GF_GenericMediaHeaderInfoBox *) gf_isom_box_new_parent(&trak->Media->information->InfoHeader->child_boxes, GF_QT_BOX_TYPE_GMIN);
    1620           3 :                 if (!gmin) return GF_OUT_OF_MEM;
    1621             :         }
    1622             : 
    1623           3 :         tmcd = gf_isom_box_find_child(trak->Media->information->InfoHeader->child_boxes, GF_QT_BOX_TYPE_TMCD);
    1624           3 :         if (!tmcd) {
    1625             :                 //default container box, use GMHD to create it
    1626           3 :                 tmcd = gf_isom_box_new_parent(&trak->Media->information->InfoHeader->child_boxes, GF_ISOM_BOX_TYPE_GMHD);
    1627           3 :                 if (!tmcd) return GF_OUT_OF_MEM;
    1628           3 :                 tmcd->type = GF_QT_BOX_TYPE_TMCD;
    1629             :         }
    1630           3 :         tcmi = (GF_TimeCodeMediaInformationBox *) gf_isom_box_find_child(tmcd->child_boxes, GF_QT_BOX_TYPE_TCMI);
    1631           3 :         if (!tcmi) {
    1632           3 :                 tcmi = (GF_TimeCodeMediaInformationBox *) gf_isom_box_new_parent(&tmcd->child_boxes, GF_QT_BOX_TYPE_TCMI);
    1633           3 :                 if (!tcmi) return GF_OUT_OF_MEM;
    1634             :         }
    1635             : 
    1636           3 :         entry = (GF_TimeCodeSampleEntryBox *) gf_isom_box_new_ex(GF_QT_BOX_TYPE_TMCD, GF_ISOM_BOX_TYPE_STSD, GF_FALSE, GF_FALSE);
    1637           3 :         if (!entry) return GF_OUT_OF_MEM;
    1638           3 :         entry->flags = 0;
    1639           3 :         if (is_drop) entry->flags |= 0x00000001;
    1640           3 :         if (is_counter) entry->flags |= 0x00000008;
    1641             : 
    1642           3 :         entry->timescale = fps_num;
    1643           3 :         entry->frame_duration = fps_den;
    1644           3 :         entry->frames_per_counter_tick = (u8) frames_per_counter_tick;
    1645             :         
    1646           3 :         entry->dataReferenceIndex = dataRefIndex;
    1647           3 :         e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->child_boxes, entry);
    1648           3 :         *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
    1649           3 :         return e;
    1650             : }
    1651             : 
    1652           1 : GF_Err gf_isom_new_mpha_description(GF_ISOFile *movie, u32 trackNumber, const char *URLname, const char *URNname, u32 *outDescriptionIndex, u8 *dsi, u32 dsi_size)
    1653             : {
    1654             :         GF_TrackBox *trak;
    1655             :         GF_Err e;
    1656             :         u32 dataRefIndex;
    1657             :         GF_MPEGAudioSampleEntryBox *mpa;
    1658             : 
    1659           1 :         e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE);
    1660           1 :         if (e) return e;
    1661           1 :         if (dsi_size<6) return GF_BAD_PARAM;
    1662             : 
    1663           1 :         trak = gf_isom_get_track_from_file(movie, trackNumber);
    1664           1 :         if (!trak || !trak->Media) return GF_BAD_PARAM;
    1665             : 
    1666           1 :         switch (trak->Media->handler->handlerType) {
    1667             :         case GF_ISOM_MEDIA_AUDIO:
    1668             :                 break;
    1669             :         default:
    1670             :                 return GF_BAD_PARAM;
    1671             :         }
    1672             : 
    1673             :         //get or create the data ref
    1674           1 :         e = Media_FindDataRef(trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
    1675           1 :         if (e) return e;
    1676           1 :         if (!dataRefIndex) {
    1677           1 :                 e = Media_CreateDataRef(movie, trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
    1678           1 :                 if (e) return e;
    1679             :         }
    1680           1 :         if (!movie->keep_utc)
    1681           1 :                 trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();
    1682             : 
    1683           1 :         mpa = (GF_MPEGAudioSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_MHA1);
    1684           1 :         if (!mpa) return GF_OUT_OF_MEM;
    1685           1 :         mpa->dataReferenceIndex = dataRefIndex;
    1686           1 :         gf_list_add(trak->Media->information->sampleTable->SampleDescription->child_boxes, mpa);
    1687           1 :         if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->child_boxes);
    1688             : 
    1689           1 :         mpa->cfg_mha = (GF_MHAConfigBox *) gf_isom_box_new_parent(&mpa->child_boxes, GF_ISOM_BOX_TYPE_MHAC);
    1690           1 :         if (!mpa->cfg_mha) return GF_OUT_OF_MEM;
    1691           1 :         mpa->cfg_mha->configuration_version = dsi[0];
    1692           1 :         mpa->cfg_mha->mha_pl_indication = dsi[1];
    1693           1 :         mpa->cfg_mha->reference_channel_layout = dsi[2];
    1694           1 :         mpa->cfg_mha->mha_config_size = dsi[3];
    1695           1 :         mpa->cfg_mha->mha_config_size <<= 8;
    1696           1 :         mpa->cfg_mha->mha_config_size |= dsi[4];
    1697           1 :         mpa->cfg_mha->mha_config = gf_malloc(sizeof(u8) * mpa->cfg_mha->mha_config_size);
    1698           1 :         if (!mpa->cfg_mha->mha_config) return GF_OUT_OF_MEM;
    1699           1 :         memcpy(mpa->cfg_mha->mha_config, dsi+5, dsi_size-5);
    1700           1 :         return GF_OK;
    1701             : }
    1702             : 
    1703             : #endif  /*GPAC_DISABLE_ISOM_WRITE*/
    1704             : 
    1705             : GF_EXPORT
    1706           4 : GF_Err gf_isom_get_tmcd_config(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex, u32 *tmcd_flags, u32 *tmcd_fps_num, u32 *tmcd_fps_den, u32 *tmcd_fpt)
    1707             : {
    1708             :         GF_TimeCodeSampleEntryBox *tmcd;
    1709             :         GF_TrackBox *trak;
    1710           4 :         trak = gf_isom_get_track_from_file(movie, trackNumber);
    1711           4 :         if (!trak || !descriptionIndex) return GF_BAD_PARAM;
    1712             : 
    1713           4 :         tmcd = (GF_TimeCodeSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, descriptionIndex-1);
    1714           4 :         if (!tmcd) return GF_BAD_PARAM;
    1715           4 :         if (tmcd->type != GF_QT_BOX_TYPE_TMCD) return GF_BAD_PARAM;
    1716             : 
    1717           4 :         if (tmcd_flags) *tmcd_flags = tmcd->flags;
    1718           4 :         if (tmcd_fps_num) *tmcd_fps_num = tmcd->timescale;
    1719           4 :         if (tmcd_fps_den) *tmcd_fps_den = tmcd->frame_duration;
    1720           4 :         if (tmcd_fpt) *tmcd_fpt = tmcd->frames_per_counter_tick;
    1721             :         return GF_OK;
    1722             : }
    1723             : 
    1724             : GF_EXPORT
    1725           5 : GF_Err gf_isom_get_pcm_config(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex, u32 *flags, u32 *pcm_size)
    1726             : {
    1727             :         GF_AudioSampleEntryBox *aent;
    1728             :         GF_PCMConfigBox *pcmC;
    1729             :         GF_TrackBox *trak;
    1730           5 :         trak = gf_isom_get_track_from_file(movie, trackNumber);
    1731           5 :         if (!trak || !descriptionIndex) return GF_BAD_PARAM;
    1732             : 
    1733           5 :         aent = (GF_AudioSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, descriptionIndex-1);
    1734           5 :         if (!aent) return GF_BAD_PARAM;
    1735           5 :         if ((aent->type != GF_ISOM_BOX_TYPE_IPCM) && (aent->type != GF_ISOM_BOX_TYPE_FPCM))
    1736             :                 return GF_BAD_PARAM;
    1737             : 
    1738           5 :         pcmC = (GF_PCMConfigBox *) gf_isom_box_find_child(aent->child_boxes, GF_ISOM_BOX_TYPE_PCMC);
    1739           5 :         if (!pcmC) return GF_NON_COMPLIANT_BITSTREAM;
    1740             : 
    1741           5 :         if (flags) *flags = pcmC->format_flags;
    1742           5 :         if (pcm_size) *pcm_size = pcmC->PCM_sample_size;
    1743             :         return GF_OK;
    1744             : }
    1745             : 
    1746             : 
    1747             : 
    1748             : #endif /*GPAC_DISABLE_ISOM*/

Generated by: LCOV version 1.13