LCOV - code coverage report
Current view: top level - isomedia - media.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 419 554 75.6 %
Date: 2021-04-29 23:48:07 Functions: 16 18 88.9 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2019
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / ISO Media File Format sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/internal/isomedia_dev.h>
      27             : #include <gpac/constants.h>
      28             : #include <gpac/avparse.h>
      29             : 
      30             : #ifndef GPAC_DISABLE_ISOM
      31             : 
      32     2852800 : GF_Err Media_GetSampleDesc(GF_MediaBox *mdia, u32 SampleDescIndex, GF_SampleEntryBox **out_entry, u32 *dataRefIndex)
      33             : {
      34             :         GF_SampleDescriptionBox *stsd;
      35             :         GF_SampleEntryBox *entry = NULL;
      36             : 
      37     2852800 :         if (!mdia) return GF_ISOM_INVALID_FILE;
      38             : 
      39     2852800 :         stsd = mdia->information->sampleTable->SampleDescription;
      40     2852800 :         if (!stsd) return GF_ISOM_INVALID_FILE;
      41     2852800 :         if (!SampleDescIndex || (SampleDescIndex > gf_list_count(stsd->child_boxes)) ) return GF_BAD_PARAM;
      42             : 
      43     2852795 :         entry = (GF_SampleEntryBox*)gf_list_get(stsd->child_boxes, SampleDescIndex - 1);
      44     2852795 :         if (!entry) return GF_ISOM_INVALID_FILE;
      45             : 
      46     2852795 :         if (out_entry) *out_entry = entry;
      47     2852795 :         if (dataRefIndex) *dataRefIndex = entry->dataReferenceIndex;
      48             :         return GF_OK;
      49             : }
      50             : 
      51         187 : GF_Err Media_GetSampleDescIndex(GF_MediaBox *mdia, u64 DTS, u32 *sampleDescIndex)
      52             : {
      53             :         GF_Err e;
      54             :         u32 sampleNumber, prevSampleNumber, num;
      55             :         u64 offset;
      56         187 :         if (sampleDescIndex == NULL) return GF_BAD_PARAM;
      57             : 
      58             :         //find the sample for this time
      59         187 :         e = stbl_findEntryForTime(mdia->information->sampleTable, (u32) DTS, 0, &sampleNumber, &prevSampleNumber);
      60         187 :         if (e) return e;
      61             : 
      62         187 :         if (!sampleNumber && !prevSampleNumber) {
      63             :                 //we have to assume the track was created to be used... If we have a sampleDesc, OK
      64          60 :                 if (gf_list_count(mdia->information->sampleTable->SampleDescription->child_boxes)) {
      65          60 :                         (*sampleDescIndex) = 1;
      66          60 :                         return GF_OK;
      67             :                 }
      68             :                 return GF_BAD_PARAM;
      69             :         }
      70         127 :         return stbl_GetSampleInfos(mdia->information->sampleTable, ( sampleNumber ? sampleNumber : prevSampleNumber), &offset, &num, sampleDescIndex, NULL);
      71             : }
      72             : 
      73          13 : static GF_Err gf_isom_get_3gpp_audio_esd(GF_SampleTableBox *stbl, u32 type, GF_GenericAudioSampleEntryBox *entry, GF_ESD **out_esd)
      74             : {
      75          13 :         (*out_esd) = gf_odf_desc_esd_new(2);
      76          13 :         (*out_esd)->decoderConfig->streamType = GF_STREAM_AUDIO;
      77             :         /*official mapping to MPEG-4*/
      78          13 :         switch (type) {
      79           3 :         case GF_ISOM_SUBTYPE_3GP_EVRC:
      80           3 :                 (*out_esd)->decoderConfig->objectTypeIndication = GF_CODECID_EVRC;
      81             :                 return GF_OK;
      82           6 :         case GF_ISOM_SUBTYPE_3GP_QCELP:
      83             :         {
      84             :                 u32 block_size, sample_rate, sample_size, i;
      85             :                 GF_SttsEntry *ent;
      86             :                 GF_BitStream *bs;
      87             :                 char szName[80];
      88             :                 /*only map CBR*/
      89           6 :                 sample_size = stbl->SampleSize->sampleSize;
      90           6 :                 (*out_esd)->decoderConfig->objectTypeIndication = GF_CODECID_QCELP;
      91           6 :                 bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
      92           6 :                 gf_bs_write_data(bs, "QLCMfmt ", 8);
      93           6 :                 gf_bs_write_u32_le(bs, 150);/*fmt chunk size*/
      94           6 :                 gf_bs_write_u8(bs, 1);
      95           6 :                 gf_bs_write_u8(bs, 0);
      96             :                 /*QCELP GUID*/
      97           6 :                 gf_bs_write_data(bs, "\x41\x6D\x7F\x5E\x15\xB1\xD0\x11\xBA\x91\x00\x80\x5F\xB4\xB9\x7E", 16);
      98           6 :                 gf_bs_write_u16_le(bs, 1);
      99             :                 memset(szName, 0, 80);
     100             :                 strcpy(szName, "QCELP-13K(GPAC-emulated)");
     101           6 :                 gf_bs_write_data(bs, szName, 80);
     102           6 :                 ent = &stbl->TimeToSample->entries[0];
     103           6 :                 sample_rate = entry->samplerate_hi;
     104           6 :                 block_size = ent ? ent->sampleDelta : 160;
     105           6 :                 gf_bs_write_u16_le(bs, 8*sample_size*sample_rate/block_size);
     106           6 :                 gf_bs_write_u16_le(bs, sample_size);
     107           6 :                 gf_bs_write_u16_le(bs, block_size);
     108           6 :                 gf_bs_write_u16_le(bs, sample_rate);
     109           6 :                 gf_bs_write_u16_le(bs, entry->bitspersample);
     110           6 :                 gf_bs_write_u32_le(bs, sample_size ? 0 : 7);
     111             :                 /**/
     112          42 :                 for (i=0; i<7; i++) {
     113             :                         static const u32 qcelp_r2s [] = {0, 1, 1, 4, 2, 8, 3, 17, 4, 35, 5, 8, 14, 1};
     114          42 :                         if (sample_size) {
     115           0 :                                 gf_bs_write_u16(bs, 0);
     116             :                         } else {
     117          42 :                                 gf_bs_write_u8(bs, qcelp_r2s[2*i+1]);
     118          42 :                                 gf_bs_write_u8(bs, qcelp_r2s[2*i]);
     119             :                         }
     120             :                 }
     121           6 :                 gf_bs_write_u16(bs, 0);
     122             :                 memset(szName, 0, 80);
     123           6 :                 gf_bs_write_data(bs, szName, 20);/*reserved*/
     124           6 :                 gf_bs_get_content(bs, & (*out_esd)->decoderConfig->decoderSpecificInfo->data, & (*out_esd)->decoderConfig->decoderSpecificInfo->dataLength);
     125           6 :                 gf_bs_del(bs);
     126             :         }
     127             :         return GF_OK;
     128           0 :         case GF_ISOM_SUBTYPE_3GP_SMV:
     129           0 :                 (*out_esd)->decoderConfig->objectTypeIndication = GF_CODECID_SMV;
     130             :                 return GF_OK;
     131           2 :         case GF_ISOM_SUBTYPE_3GP_AMR:
     132           2 :                 (*out_esd)->decoderConfig->objectTypeIndication = GF_CODECID_AMR;
     133             :                 return GF_OK;
     134           2 :         case GF_ISOM_SUBTYPE_3GP_AMR_WB:
     135           2 :                 (*out_esd)->decoderConfig->objectTypeIndication = GF_CODECID_AMR_WB;
     136             :                 return GF_OK;
     137           0 :         default:
     138           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso file] unsupported sample description type %s\n", gf_4cc_to_str(entry->type)));
     139             :                 break;
     140             :         }
     141             :         return GF_OK;
     142             : }
     143             : 
     144        5081 : GF_Err Media_GetESD(GF_MediaBox *mdia, u32 sampleDescIndex, GF_ESD **out_esd, Bool true_desc_only)
     145             : {
     146             :         u32 type;
     147             :         GF_ESD *esd;
     148             :         GF_MPEGSampleEntryBox *entry = NULL;
     149             :         GF_ESDBox *ESDa;
     150             :         GF_ProtectionSchemeInfoBox *sinf;
     151        5081 :         GF_SampleDescriptionBox *stsd = mdia->information->sampleTable->SampleDescription;
     152             : 
     153        5081 :         *out_esd = NULL;
     154        5081 :         if (!stsd || !stsd->child_boxes || !sampleDescIndex || (sampleDescIndex > gf_list_count(stsd->child_boxes)) )
     155             :                 return GF_BAD_PARAM;
     156             : 
     157             :         esd = NULL;
     158        5079 :         entry = (GF_MPEGSampleEntryBox*)gf_list_get(stsd->child_boxes, sampleDescIndex - 1);
     159        5079 :         if (! entry) return GF_ISOM_INVALID_MEDIA;
     160             : 
     161        5079 :         *out_esd = NULL;
     162             :         ESDa = NULL;
     163        5079 :         type = entry->type;
     164        5079 :         switch (type) {
     165         505 :         case GF_ISOM_BOX_TYPE_ENCV:
     166             :         case GF_ISOM_BOX_TYPE_ENCA:
     167             :         case GF_ISOM_BOX_TYPE_ENCS:
     168             :         case GF_ISOM_BOX_TYPE_ENCF:
     169             :         case GF_ISOM_BOX_TYPE_ENCM:
     170             :         case GF_ISOM_BOX_TYPE_ENCT:
     171         505 :                 sinf = (GF_ProtectionSchemeInfoBox *) gf_isom_box_find_child(entry->child_boxes, GF_ISOM_BOX_TYPE_SINF);
     172         505 :                 if (sinf && sinf->original_format) {
     173         505 :                         type = sinf->original_format->data_format;
     174             :                 }
     175             :                 break;
     176           0 :         case GF_ISOM_BOX_TYPE_RESV:
     177           0 :                 sinf = (GF_ProtectionSchemeInfoBox *) gf_isom_box_find_child(entry->child_boxes, GF_ISOM_BOX_TYPE_RINF);
     178           0 :                 if (sinf && sinf->original_format) {
     179           0 :                         type = sinf->original_format->data_format;
     180             :                 }
     181             :                 break;
     182             :         }
     183             : 
     184             : 
     185        5079 :         switch (type) {
     186         394 :         case GF_ISOM_BOX_TYPE_MP4V:
     187         394 :                 if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
     188             :                         return GF_ISOM_INVALID_MEDIA;
     189         394 :                 ESDa = ((GF_MPEGVisualSampleEntryBox*)entry)->esd;
     190         394 :                 if (ESDa) esd = (GF_ESD *) ESDa->desc;
     191             :                 /*avc1 encrypted*/
     192           0 :                 else esd = ((GF_MPEGVisualSampleEntryBox*) entry)->emul_esd;
     193             :                 break;
     194        3166 :         case GF_ISOM_BOX_TYPE_AVC1:
     195             :         case GF_ISOM_BOX_TYPE_AVC2:
     196             :         case GF_ISOM_BOX_TYPE_AVC3:
     197             :         case GF_ISOM_BOX_TYPE_AVC4:
     198             :         case GF_ISOM_BOX_TYPE_HVC1:
     199             :         case GF_ISOM_BOX_TYPE_HEV1:
     200             :         case GF_ISOM_BOX_TYPE_HVC2:
     201             :         case GF_ISOM_BOX_TYPE_HEV2:
     202             :         case GF_ISOM_BOX_TYPE_HVT1:
     203             :         case GF_ISOM_BOX_TYPE_264B:
     204             :         case GF_ISOM_BOX_TYPE_265B:
     205             :         case GF_ISOM_BOX_TYPE_DVHE:
     206             :         case GF_ISOM_BOX_TYPE_VVC1:
     207             :         case GF_ISOM_BOX_TYPE_VVI1:
     208        3166 :                 if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
     209             :                         return GF_ISOM_INVALID_MEDIA;
     210        3166 :                 esd = ((GF_MPEGVisualSampleEntryBox*) entry)->emul_esd;
     211        3166 :                 break;
     212          33 :         case GF_ISOM_BOX_TYPE_SVC1:
     213             :         case GF_ISOM_BOX_TYPE_MVC1:
     214          33 :                 if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
     215             :                         return GF_ISOM_INVALID_MEDIA;
     216          33 :                 if ((mdia->mediaTrack->extractor_mode & 0x0000FFFF) != GF_ISOM_NALU_EXTRACT_INSPECT)
     217          33 :                         AVC_RewriteESDescriptorEx((GF_MPEGVisualSampleEntryBox*) entry, mdia);
     218             :                 else
     219           0 :                         AVC_RewriteESDescriptorEx((GF_MPEGVisualSampleEntryBox*) entry, NULL);
     220          33 :                 esd = ((GF_MPEGVisualSampleEntryBox*) entry)->emul_esd;
     221          33 :                 break;
     222           0 :         case GF_ISOM_BOX_TYPE_LHE1:
     223             :         case GF_ISOM_BOX_TYPE_LHV1:
     224           0 :                 if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
     225             :                         return GF_ISOM_INVALID_MEDIA;
     226           0 :                 if ((mdia->mediaTrack->extractor_mode & 0x0000FFFF) != GF_ISOM_NALU_EXTRACT_INSPECT)
     227           0 :                         HEVC_RewriteESDescriptorEx((GF_MPEGVisualSampleEntryBox*) entry, mdia);
     228             :                 else
     229           0 :                         HEVC_RewriteESDescriptorEx((GF_MPEGVisualSampleEntryBox*) entry, NULL);
     230           0 :                 esd = ((GF_MPEGVisualSampleEntryBox*) entry)->emul_esd;
     231           0 :                 break;
     232         148 :         case GF_ISOM_BOX_TYPE_AV01:
     233         148 :                 if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
     234             :                         return GF_ISOM_INVALID_MEDIA;
     235         148 :                 AV1_RewriteESDescriptorEx((GF_MPEGVisualSampleEntryBox*)entry, mdia);
     236         148 :                 esd = ((GF_MPEGVisualSampleEntryBox*)entry)->emul_esd;
     237         148 :                 break;
     238          38 :         case GF_ISOM_BOX_TYPE_VP08:
     239             :         case GF_ISOM_BOX_TYPE_VP09:
     240          38 :                 if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
     241             :                         return GF_ISOM_INVALID_MEDIA;
     242          38 :                 VP9_RewriteESDescriptorEx((GF_MPEGVisualSampleEntryBox*)entry, mdia);
     243          38 :                 esd = ((GF_MPEGVisualSampleEntryBox*)entry)->emul_esd;
     244          38 :                 break;
     245         750 :         case GF_ISOM_BOX_TYPE_MP4A:
     246         750 :                 if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_AUDIO)
     247             :                         return GF_ISOM_INVALID_MEDIA;
     248             :         {
     249             :             GF_MPEGAudioSampleEntryBox *ase = (GF_MPEGAudioSampleEntryBox*)entry;
     250         750 :             ESDa = ase->esd;
     251         750 :             if (ESDa) {
     252         750 :                                 esd = (GF_ESD *) ESDa->desc;
     253           0 :             } else if (!true_desc_only) {
     254             :                                 Bool make_mp4a = GF_FALSE;
     255           0 :                                 sinf = (GF_ProtectionSchemeInfoBox *) gf_isom_box_find_child(entry->child_boxes, GF_ISOM_BOX_TYPE_SINF);
     256             : 
     257           0 :                                 if (sinf && sinf->original_format) {
     258           0 :                                         if (sinf->original_format->data_format==GF_ISOM_BOX_TYPE_MP4A) {
     259             :                                                 make_mp4a = GF_TRUE;
     260             :                                         }
     261             :                                 } else {
     262             :                                         // Assuming that if no ESD is provided the stream is Basic MPEG-4 AAC LC
     263             :                                         make_mp4a = GF_TRUE;
     264             :                                 }
     265             :                                 if (make_mp4a) {
     266             :                                         GF_M4ADecSpecInfo aacinfo;
     267             :                                         memset(&aacinfo, 0, sizeof(GF_M4ADecSpecInfo));
     268           0 :                                         aacinfo.nb_chan = ase->channel_count;
     269           0 :                                         aacinfo.base_object_type = GF_M4A_AAC_LC;
     270           0 :                                         aacinfo.base_sr = ase->samplerate_hi;
     271           0 :                                         *out_esd = gf_odf_desc_esd_new(0);
     272           0 :                                         (*out_esd)->decoderConfig->streamType = GF_STREAM_AUDIO;
     273           0 :                                         (*out_esd)->decoderConfig->objectTypeIndication = GF_CODECID_AAC_MPEG4;
     274           0 :                                         gf_m4a_write_config(&aacinfo, &(*out_esd)->decoderConfig->decoderSpecificInfo->data, &(*out_esd)->decoderConfig->decoderSpecificInfo->dataLength);
     275             :                                 }
     276             :             }
     277             :         }
     278             :                 break;
     279         326 :         case GF_ISOM_BOX_TYPE_MP4S:
     280         326 :                 if (entry->internal_type==GF_ISOM_SAMPLE_ENTRY_MP4S) {
     281         326 :                         ESDa = entry->esd;
     282         326 :                         if (ESDa) esd = (GF_ESD *) ESDa->desc;
     283             :                 }
     284             :                 break;
     285             : #ifndef GPAC_DISABLE_TTXT
     286          30 :         case GF_ISOM_BOX_TYPE_TX3G:
     287             :         case GF_ISOM_BOX_TYPE_TEXT:
     288          30 :                 if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_MP4S)
     289             :                         return GF_ISOM_INVALID_MEDIA;
     290             : 
     291          30 :                 if (!true_desc_only && mdia->mediaTrack->moov->mov->convert_streaming_text) {
     292           3 :                         GF_Err e = gf_isom_get_ttxt_esd(mdia, out_esd);
     293           3 :                         if (e) return e;
     294             :                         break;
     295             :                 }
     296             :                 else
     297             :                         return GF_ISOM_INVALID_MEDIA;
     298             : #endif
     299             : #ifndef GPAC_DISABLE_VTT
     300           4 :         case GF_ISOM_BOX_TYPE_WVTT:
     301           4 :                 if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_MP4S)
     302             :                         return GF_ISOM_INVALID_MEDIA;
     303             :         {
     304             :                 GF_WebVTTSampleEntryBox*vtte = (GF_WebVTTSampleEntryBox*)entry;
     305           4 :                 esd =  gf_odf_desc_esd_new(2);
     306           4 :                 *out_esd = esd;
     307           4 :                 esd->decoderConfig->streamType = GF_STREAM_TEXT;
     308           4 :                 esd->decoderConfig->objectTypeIndication = GF_CODECID_WEBVTT;
     309           4 :                 if (vtte->config) {
     310           4 :                         esd->decoderConfig->decoderSpecificInfo->dataLength = (u32) strlen(vtte->config->string);
     311           4 :                         esd->decoderConfig->decoderSpecificInfo->data = gf_malloc(sizeof(char)*esd->decoderConfig->decoderSpecificInfo->dataLength);
     312           4 :                         memcpy(esd->decoderConfig->decoderSpecificInfo->data, vtte->config->string, esd->decoderConfig->decoderSpecificInfo->dataLength);
     313             :                 }
     314             :         }
     315             :                 break;
     316             :         case GF_ISOM_BOX_TYPE_STPP:
     317             :         case GF_ISOM_BOX_TYPE_SBTT:
     318             :         case GF_ISOM_BOX_TYPE_STXT:
     319             :                 break;
     320             : #endif
     321             : 
     322          14 :         case GF_ISOM_SUBTYPE_3GP_AMR:
     323             :         case GF_ISOM_SUBTYPE_3GP_AMR_WB:
     324             :         case GF_ISOM_SUBTYPE_3GP_EVRC:
     325             :         case GF_ISOM_SUBTYPE_3GP_QCELP:
     326             :         case GF_ISOM_SUBTYPE_3GP_SMV:
     327          14 :                 if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_AUDIO)
     328             :                         return GF_ISOM_INVALID_MEDIA;
     329          14 :                 if (!true_desc_only) {
     330          13 :                         GF_Err e = gf_isom_get_3gpp_audio_esd(mdia->information->sampleTable, type, (GF_GenericAudioSampleEntryBox*)entry, out_esd);
     331          13 :                         if (e) return e;
     332             :                         break;
     333             :                 } else return GF_ISOM_INVALID_MEDIA;
     334             : 
     335           3 :         case GF_ISOM_SUBTYPE_OPUS:
     336           3 :                 if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_AUDIO)
     337             :                         return GF_ISOM_INVALID_MEDIA;
     338             :         {
     339           3 :                 GF_OpusSpecificBox *e = ((GF_MPEGAudioSampleEntryBox*)entry)->cfg_opus;
     340             :                 GF_BitStream *bs_out;
     341           3 :                 if (!e) {
     342           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("ESD not found for Opus\n)"));
     343             :                         break;
     344             :                 }
     345             : 
     346           3 :                 *out_esd = gf_odf_desc_esd_new(2);
     347           3 :                 (*out_esd)->decoderConfig->streamType = GF_STREAM_AUDIO;
     348           3 :                 (*out_esd)->decoderConfig->objectTypeIndication = GF_CODECID_OPUS;
     349             : 
     350             :                 //serialize box with header - compatibility with ffmpeg
     351           3 :                 bs_out = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     352           3 :                 gf_isom_box_size((GF_Box *) e);
     353           3 :                 gf_isom_box_write((GF_Box *) e, bs_out);
     354           3 :                 gf_bs_get_content(bs_out, & (*out_esd)->decoderConfig->decoderSpecificInfo->data, & (*out_esd)->decoderConfig->decoderSpecificInfo->dataLength);
     355           3 :                 gf_bs_del(bs_out);
     356           3 :                 break;
     357             :         }
     358           3 :         case GF_ISOM_SUBTYPE_3GP_H263:
     359           3 :                 if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO)
     360             :                         return GF_ISOM_INVALID_MEDIA;
     361           3 :                 if (true_desc_only) {
     362             :                         return GF_ISOM_INVALID_MEDIA;
     363             :                 } else {
     364           2 :                         esd =  gf_odf_desc_esd_new(2);
     365           2 :                         *out_esd = esd;
     366           2 :                         esd->decoderConfig->streamType = GF_STREAM_VISUAL;
     367           2 :                         esd->decoderConfig->objectTypeIndication = GF_CODECID_H263;
     368           2 :                         break;
     369             :                 }
     370             : 
     371          14 :         case GF_ISOM_SUBTYPE_MP3:
     372          14 :                 if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_AUDIO)
     373             :                         return GF_ISOM_INVALID_MEDIA;
     374          14 :                 if (true_desc_only) {
     375             :                         return GF_ISOM_INVALID_MEDIA;
     376             :                 } else {
     377          14 :                         esd =  gf_odf_desc_esd_new(2);
     378          14 :                         *out_esd = esd;
     379          14 :                         esd->decoderConfig->streamType = GF_STREAM_AUDIO;
     380          14 :                         esd->decoderConfig->objectTypeIndication = GF_CODECID_MPEG_AUDIO;
     381          14 :                         break;
     382             :                 }
     383             : 
     384           9 :         case GF_ISOM_SUBTYPE_LSR1:
     385           9 :                 if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_MP4S)
     386             :                         return GF_ISOM_INVALID_MEDIA;
     387           9 :                 if (true_desc_only) {
     388             :                         return GF_ISOM_INVALID_MEDIA;
     389             :                 } else {
     390             :                         GF_LASeRSampleEntryBox*ptr = (GF_LASeRSampleEntryBox*)entry;
     391           9 :                         esd =  gf_odf_desc_esd_new(2);
     392           9 :                         *out_esd = esd;
     393           9 :                         esd->decoderConfig->streamType = GF_STREAM_SCENE;
     394           9 :                         esd->decoderConfig->objectTypeIndication = GF_CODECID_LASER;
     395           9 :                         esd->decoderConfig->decoderSpecificInfo->dataLength = ptr->lsr_config->hdr_size;
     396           9 :                         esd->decoderConfig->decoderSpecificInfo->data = gf_malloc(sizeof(char)*ptr->lsr_config->hdr_size);
     397           9 :                         if (!esd->decoderConfig->decoderSpecificInfo->data) return GF_OUT_OF_MEM;
     398           9 :                         memcpy(esd->decoderConfig->decoderSpecificInfo->data, ptr->lsr_config->hdr, sizeof(char)*ptr->lsr_config->hdr_size);
     399             :                         break;
     400             :                 }
     401           3 :         case GF_ISOM_SUBTYPE_MH3D_MHA1:
     402             :         case GF_ISOM_SUBTYPE_MH3D_MHA2:
     403             :         case GF_ISOM_SUBTYPE_MH3D_MHM1:
     404             :         case GF_ISOM_SUBTYPE_MH3D_MHM2:
     405           3 :                 if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_AUDIO)
     406             :                         return GF_ISOM_INVALID_MEDIA;
     407             : 
     408           3 :                 if (true_desc_only) {
     409             :                         return GF_ISOM_INVALID_MEDIA;
     410             :                 } else {
     411             :                         GF_MPEGAudioSampleEntryBox*ptr = (GF_MPEGAudioSampleEntryBox*)entry;
     412           3 :                         esd = gf_odf_desc_esd_new(2);
     413           3 :                         *out_esd = esd;
     414           3 :                         esd->decoderConfig->streamType = GF_STREAM_AUDIO;
     415           3 :                         if ((type==GF_ISOM_SUBTYPE_MH3D_MHA1) || (type==GF_ISOM_SUBTYPE_MH3D_MHA2))
     416           0 :                                 esd->decoderConfig->objectTypeIndication = GF_CODECID_MPHA;
     417             :                         else
     418           3 :                                 esd->decoderConfig->objectTypeIndication = GF_CODECID_MHAS;
     419           3 :                         if (ptr->cfg_mha) {
     420           0 :                                 GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     421             : 
     422           0 :                                 gf_bs_write_u8(bs, ptr->cfg_mha->configuration_version);
     423           0 :                                 gf_bs_write_u8(bs, ptr->cfg_mha->mha_pl_indication);
     424           0 :                                 gf_bs_write_u8(bs, ptr->cfg_mha->reference_channel_layout);
     425           0 :                                 gf_bs_write_u16(bs, ptr->cfg_mha->mha_config ? ptr->cfg_mha->mha_config_size : 0);
     426           0 :                                 if (ptr->cfg_mha->mha_config && ptr->cfg_mha->mha_config_size)
     427           0 :                                         gf_bs_write_data(bs, ptr->cfg_mha->mha_config, ptr->cfg_mha->mha_config_size);
     428             : 
     429           0 :                                 gf_bs_get_content(bs, &esd->decoderConfig->decoderSpecificInfo->data, &esd->decoderConfig->decoderSpecificInfo->dataLength);
     430           0 :                                 gf_bs_del(bs);
     431             :                         }
     432             :                 }
     433             :                 break;
     434             : 
     435             :         default:
     436             :                 return GF_ISOM_INVALID_MEDIA;
     437             :         }
     438             : 
     439        4912 :         if (true_desc_only) {
     440        3090 :                 if (!esd) return GF_ISOM_INVALID_MEDIA;
     441        3090 :                 *out_esd = esd;
     442        3090 :                 return GF_OK;
     443             :         } else {
     444        1822 :                 if (!esd && !*out_esd) return GF_ISOM_INVALID_MEDIA;
     445        1816 :                 if (*out_esd == NULL) return gf_odf_desc_copy((GF_Descriptor *)esd, (GF_Descriptor **)out_esd);
     446             :         }
     447             :         return GF_OK;
     448             : }
     449             : 
     450     1100156 : Bool Media_IsSampleSyncShadow(GF_ShadowSyncBox *stsh, u32 sampleNumber)
     451             : {
     452             :         u32 i;
     453             :         GF_StshEntry *ent;
     454     1100156 :         if (!stsh) return 0;
     455           6 :         i=0;
     456          21 :         while ((ent = (GF_StshEntry*)gf_list_enum(stsh->entries, &i))) {
     457           9 :                 if ((u32) ent->syncSampleNumber == sampleNumber) return 1;
     458           9 :                 else if ((u32) ent->syncSampleNumber > sampleNumber) return 0;
     459             :         }
     460             :         return 0;
     461             : }
     462             : 
     463     1371048 : GF_Err Media_GetSample(GF_MediaBox *mdia, u32 sampleNumber, GF_ISOSample **samp, u32 *sIDX, Bool no_data, u64 *out_offset)
     464             : {
     465             :         GF_Err e;
     466             :         u32 bytesRead;
     467             :         u32 dataRefIndex, chunkNumber;
     468             :         u64 offset, new_size;
     469             :         u32 sdesc_idx;
     470             :         GF_SampleEntryBox *entry;
     471             :         GF_StscEntry *stsc_entry;
     472             : 
     473     1371048 :         if (!mdia || !mdia->information->sampleTable) return GF_BAD_PARAM;
     474     1371048 :         if (!mdia->information->sampleTable->SampleSize)
     475             :                 return GF_ISOM_INVALID_FILE;
     476             : 
     477             :         //OK, here we go....
     478     1371048 :         if (sampleNumber > mdia->information->sampleTable->SampleSize->sampleCount) return GF_BAD_PARAM;
     479             : 
     480             :         //the data info
     481     1100163 :         if (!sIDX && !no_data) return GF_BAD_PARAM;
     482             : 
     483     1100163 :         e = stbl_GetSampleInfos(mdia->information->sampleTable, sampleNumber, &offset, &chunkNumber, &sdesc_idx, &stsc_entry);
     484     1100163 :         if (e) return e;
     485     1100159 :         if (sIDX) (*sIDX) = sdesc_idx;
     486             : 
     487     1100159 :         if (out_offset) *out_offset = offset;
     488     1100159 :         if (!samp ) return GF_OK;
     489             : 
     490     1100156 :         if (mdia->information->sampleTable->TimeToSample) {
     491             :                 //get the DTS
     492     1100156 :                 e = stbl_GetSampleDTS(mdia->information->sampleTable->TimeToSample, sampleNumber, &(*samp)->DTS);
     493     1100156 :                 if (e) return e;
     494             :         } else {
     495           0 :                 (*samp)->DTS=0;
     496             :         }
     497             :         //the CTS offset
     498     1100156 :         if (mdia->information->sampleTable->CompositionOffset) {
     499      436672 :                 e = stbl_GetSampleCTS(mdia->information->sampleTable->CompositionOffset , sampleNumber, &(*samp)->CTS_Offset);
     500      436672 :                 if (e) return e;
     501             :         } else {
     502      663484 :                 (*samp)->CTS_Offset = 0;
     503             :         }
     504             :         //the size
     505     1100156 :         e = stbl_GetSampleSize(mdia->information->sampleTable->SampleSize, sampleNumber, &(*samp)->dataLength);
     506     1100156 :         if (e) return e;
     507             :         //the RAP
     508     1100156 :         if (mdia->information->sampleTable->SyncSample) {
     509      743631 :                 e = stbl_GetSampleRAP(mdia->information->sampleTable->SyncSample, sampleNumber, &(*samp)->IsRAP, NULL, NULL);
     510      743631 :                 if (e) return e;
     511             :         } else {
     512             :                 //if no SyncSample, all samples are sync (cf spec)
     513      356525 :                 (*samp)->IsRAP = RAP;
     514             :         }
     515             : 
     516     1100156 :         if (mdia->information->sampleTable->SampleDep) {
     517             :                 u32 isLeading, dependsOn, dependedOn, redundant;
     518      118653 :                 e = stbl_GetSampleDepType(mdia->information->sampleTable->SampleDep, sampleNumber, &isLeading, &dependsOn, &dependedOn, &redundant);
     519      118653 :                 if (!e) {
     520      118653 :                         if (dependsOn==1) (*samp)->IsRAP = RAP_NO;
     521             :                         //commenting following code since it is wrong - an I frame is not always a SAP1, it can be a SAP2 or SAP3.
     522             :                         //Keeping this code breaks AVC / HEVC openGOP import when writing sample dependencies
     523             :                         //else if (dependsOn==2) (*samp)->IsRAP = RAP;
     524             : 
     525             :                         /*if not depended upon and redundant, mark as carousel sample*/
     526      118653 :                         if ((dependedOn==2) && (redundant==1)) (*samp)->IsRAP = RAP_REDUNDANT;
     527             :                         /*TODO FIXME - we must enhance the IsRAP semantics to carry disposable info ... */
     528             :                 }
     529             :         }
     530             : 
     531             :         /*get sync shadow*/
     532     1100156 :         if (Media_IsSampleSyncShadow(mdia->information->sampleTable->ShadowSync, sampleNumber)) (*samp)->IsRAP = RAP_REDUNDANT;
     533             : 
     534             :         //the data info
     535             :         if (!sIDX && !no_data) return GF_BAD_PARAM;
     536     1100156 :         if (!sIDX && !out_offset) return GF_OK;
     537     1033917 :         if (!sIDX) return GF_OK;
     538             : 
     539     1033913 :         (*sIDX) = sdesc_idx;
     540             : //      e = stbl_GetSampleInfos(mdia->information->sampleTable, sampleNumber, &offset, &chunkNumber, sIDX, &stsc_entry);
     541             : //      if (e) return e;
     542             : 
     543             :         //then get the DataRef
     544     1033913 :         e = Media_GetSampleDesc(mdia, sdesc_idx, &entry, &dataRefIndex);
     545     1033913 :         if (e) return e;
     546             : 
     547             :         //if moov is compressed, remove offset if sample is after moov in this file
     548     1033913 :         if (mdia->mediaTrack->moov->compressed_diff) {
     549         250 :                 GF_DataEntryBox *ent = (GF_DataEntryBox*)gf_list_get(mdia->information->dataInformation->dref->child_boxes, dataRefIndex - 1);
     550         250 :                 if (ent && (ent->flags&1) && (offset>=mdia->mediaTrack->moov->file_offset)) {
     551         250 :                         offset -= mdia->mediaTrack->moov->compressed_diff;
     552             :                 }
     553             :         }
     554             : 
     555             : 
     556     1033913 :         if (no_data) {
     557      521746 :                 if ( ((*samp)->dataLength != 0) && mdia->mediaTrack->pack_num_samples) {
     558           0 :                         u32 idx_in_chunk = sampleNumber - mdia->information->sampleTable->SampleToChunk->firstSampleInCurrentChunk;
     559           0 :                         u32 left_in_chunk = stsc_entry->samplesPerChunk - idx_in_chunk;
     560           0 :                         if (left_in_chunk > mdia->mediaTrack->pack_num_samples)
     561             :                                 left_in_chunk = mdia->mediaTrack->pack_num_samples;
     562           0 :                         (*samp)->dataLength *= left_in_chunk;
     563           0 :                         (*samp)->nb_pack = left_in_chunk;
     564             :                 }
     565             :                 return GF_OK;
     566             :         }
     567             : 
     568             :         // Open the data handler - check our mode, don't reopen in read only if this is
     569             :         //the same entry. In other modes we have no choice because the main data map is
     570             :         //divided into the original and the edition files
     571      512167 :         if (mdia->mediaTrack->moov->mov->openMode == GF_ISOM_OPEN_READ) {
     572             :                 //same as last call in read mode
     573      423592 :                 if (!mdia->information->dataHandler) {
     574         965 :                         e = gf_isom_datamap_open(mdia, dataRefIndex, stsc_entry->isEdited);
     575         965 :                         if (e) return e;
     576             :                 }
     577      423592 :                 mdia->information->dataEntryIndex = dataRefIndex;
     578             :         } else {
     579       88575 :                 e = gf_isom_datamap_open(mdia, dataRefIndex, stsc_entry->isEdited);
     580       88575 :                 if (e) return e;
     581             :         }
     582             : 
     583      512167 :         if ( mdia->mediaTrack->moov->mov->read_byte_offset || mdia->mediaTrack->moov->mov->bytes_removed) {
     584       30231 :                 GF_DataEntryBox *ent = (GF_DataEntryBox*)gf_list_get(mdia->information->dataInformation->dref->child_boxes, dataRefIndex - 1);
     585       30231 :                 if (ent && (ent->flags&1)) {
     586       30231 :                         u64 real_offset = mdia->mediaTrack->moov->mov->read_byte_offset + mdia->mediaTrack->moov->mov->bytes_removed;
     587       30231 :                         if (offset < real_offset)
     588             :                                 return GF_IO_ERR;
     589             : 
     590       30231 :                         if (mdia->information->dataHandler->last_read_offset != mdia->mediaTrack->moov->mov->read_byte_offset) {
     591           0 :                                 mdia->information->dataHandler->last_read_offset = mdia->mediaTrack->moov->mov->read_byte_offset;
     592           0 :                                 gf_bs_get_refreshed_size(mdia->information->dataHandler->bs);
     593             :                         }
     594             : 
     595       30231 :                         offset -= real_offset;
     596             :                 }
     597             :         }
     598      512167 :         if ((*samp)->dataLength != 0) {
     599      512167 :                 if (mdia->mediaTrack->pack_num_samples) {
     600         882 :                         u32 idx_in_chunk = sampleNumber - mdia->information->sampleTable->SampleToChunk->firstSampleInCurrentChunk;
     601         882 :                         u32 left_in_chunk = stsc_entry->samplesPerChunk - idx_in_chunk;
     602         882 :                         if (left_in_chunk > mdia->mediaTrack->pack_num_samples)
     603             :                                 left_in_chunk = mdia->mediaTrack->pack_num_samples;
     604         882 :                         (*samp)->dataLength *= left_in_chunk;
     605         882 :                         (*samp)->nb_pack = left_in_chunk;
     606             :                 }
     607             : 
     608             :                 /*and finally get the data, include padding if needed*/
     609      512167 :                 if ((*samp)->alloc_size) {
     610      397250 :                         if ((*samp)->alloc_size < (*samp)->dataLength + mdia->mediaTrack->padding_bytes) {
     611        4258 :                                 (*samp)->data = (char *) gf_realloc((*samp)->data, sizeof(char) * ( (*samp)->dataLength + mdia->mediaTrack->padding_bytes) );
     612        4258 :                                 if (! (*samp)->data) return GF_OUT_OF_MEM;
     613             : 
     614        4258 :                                 (*samp)->alloc_size = (*samp)->dataLength + mdia->mediaTrack->padding_bytes;
     615             :                         }
     616             :                 } else {
     617      114917 :                         (*samp)->data = (char *) gf_malloc(sizeof(char) * ( (*samp)->dataLength + mdia->mediaTrack->padding_bytes) );
     618      114917 :                         if (! (*samp)->data) return GF_OUT_OF_MEM;
     619             :                 }
     620      512167 :                 if (mdia->mediaTrack->padding_bytes)
     621           0 :                         memset((*samp)->data + (*samp)->dataLength, 0, sizeof(char) * mdia->mediaTrack->padding_bytes);
     622             : 
     623             :                 //check if we can get the sample (make sure we have enougth data...)
     624      512167 :                 new_size = gf_bs_get_size(mdia->information->dataHandler->bs);
     625      512167 :                 if (offset + (*samp)->dataLength > new_size) {
     626             :                         //always refresh the size to avoid wrong info on http/ftp
     627        1593 :                         new_size = gf_bs_get_refreshed_size(mdia->information->dataHandler->bs);
     628        1593 :                         if (offset + (*samp)->dataLength > new_size) {
     629        1527 :                                 mdia->BytesMissing = offset + (*samp)->dataLength - new_size;
     630        1527 :                                 return GF_ISOM_INCOMPLETE_FILE;
     631             :                         }
     632             :                 }
     633             : 
     634      510640 :                 bytesRead = gf_isom_datamap_get_data(mdia->information->dataHandler, (*samp)->data, (*samp)->dataLength, offset);
     635             :                 //if bytesRead != sampleSize, we have an IO err
     636      510640 :                 if (bytesRead < (*samp)->dataLength) {
     637             :                         return GF_IO_ERR;
     638             :                 }
     639      510640 :                 mdia->BytesMissing = 0;
     640             :         }
     641             : 
     642             :         //finally rewrite the sample if this is an OD Access Unit or NAL-based one
     643             :         //we do this even if sample size is zero because of sample implicit reconstruction rules (especially tile tracks)
     644      510640 :         if (mdia->handler->handlerType == GF_ISOM_MEDIA_OD) {
     645          98 :                 if (!mdia->mediaTrack->moov->mov->disable_odf_translate) {
     646          97 :                         e = Media_RewriteODFrame(mdia, *samp);
     647          97 :                         if (e) return e;
     648             :                 }
     649             :         }
     650      510542 :         else if (gf_isom_is_nalu_based_entry(mdia, entry)
     651      320123 :                 && !gf_isom_is_encrypted_entry(entry->type)
     652             :         ) {
     653      299941 :                 e = gf_isom_nalu_sample_rewrite(mdia, *samp, sampleNumber, (GF_MPEGVisualSampleEntryBox *)entry);
     654      299941 :                 if (e) return e;
     655             :         }
     656      210601 :         else if (mdia->mediaTrack->moov->mov->convert_streaming_text
     657         202 :                  && ((mdia->handler->handlerType == GF_ISOM_MEDIA_TEXT) || (mdia->handler->handlerType == GF_ISOM_MEDIA_SCENE) || (mdia->handler->handlerType == GF_ISOM_MEDIA_SUBT))
     658         202 :                  && (entry->type == GF_ISOM_BOX_TYPE_TX3G || entry->type == GF_ISOM_BOX_TYPE_TEXT)
     659             :                 ) {
     660             :                 u64 dur;
     661          11 :                 if (sampleNumber == mdia->information->sampleTable->SampleSize->sampleCount) {
     662           1 :                         dur = mdia->mediaHeader->duration - (*samp)->DTS;
     663             :                 } else {
     664          10 :                         stbl_GetSampleDTS(mdia->information->sampleTable->TimeToSample, sampleNumber+1, &dur);
     665          10 :                         dur -= (*samp)->DTS;
     666             :                 }
     667          11 :                 e = gf_isom_rewrite_text_sample(*samp, sdesc_idx, (u32) dur);
     668          11 :                 if (e) return e;
     669             :         }
     670             :         return GF_OK;
     671             : }
     672             : 
     673             : 
     674             : 
     675         219 : GF_Err Media_CheckDataEntry(GF_MediaBox *mdia, u32 dataEntryIndex)
     676             : {
     677             : 
     678             :         GF_DataEntryURLBox *entry;
     679             :         GF_DataMap *map;
     680             :         GF_Err e;
     681         219 :         if (!mdia || !dataEntryIndex || dataEntryIndex > gf_list_count(mdia->information->dataInformation->dref->child_boxes)) return GF_BAD_PARAM;
     682             : 
     683         219 :         entry = (GF_DataEntryURLBox*)gf_list_get(mdia->information->dataInformation->dref->child_boxes, dataEntryIndex - 1);
     684         219 :         if (!entry) return GF_ISOM_INVALID_FILE;
     685         219 :         if (entry->flags == 1) return GF_OK;
     686             : 
     687             :         //ok, not self contained, let's go for it...
     688             :         //we don't know what's a URN yet
     689           0 :         if (entry->type == GF_ISOM_BOX_TYPE_URN) return GF_NOT_SUPPORTED;
     690           0 :         if (mdia->mediaTrack->moov->mov->openMode == GF_ISOM_OPEN_WRITE) {
     691           0 :                 e = gf_isom_datamap_new(entry->location, NULL, GF_ISOM_DATA_MAP_READ, &map);
     692             :         } else {
     693           0 :                 e = gf_isom_datamap_new(entry->location, mdia->mediaTrack->moov->mov->fileName, GF_ISOM_DATA_MAP_READ, &map);
     694             :         }
     695           0 :         if (e) return e;
     696           0 :         gf_isom_datamap_del(map);
     697           0 :         return GF_OK;
     698             : }
     699             : 
     700             : 
     701      580864 : Bool Media_IsSelfContained(GF_MediaBox *mdia, u32 StreamDescIndex)
     702             : {
     703      580864 :         u32 drefIndex=0;
     704             :         GF_FullBox *a=NULL;
     705      580864 :         GF_SampleEntryBox *se = NULL;
     706             : 
     707      580864 :         Media_GetSampleDesc(mdia, StreamDescIndex, &se, &drefIndex);
     708      580864 :         if (!drefIndex) return 0;
     709      580864 :         if (mdia
     710      580864 :                 && mdia->information
     711      580864 :                 && mdia->information->dataInformation
     712      580864 :                 && mdia->information->dataInformation->dref
     713             :         ) {
     714      580864 :                 a = (GF_FullBox*)gf_list_get(mdia->information->dataInformation->dref->child_boxes, drefIndex - 1);
     715             :         }
     716      580864 :         if (!a) {
     717           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] broken file: Data reference index set to %d but no data reference entry found\n", drefIndex));
     718             :                 return 1;
     719             :         }
     720      580864 :         if (a->flags & 1) return 1;
     721             :         /*QT specific*/
     722        1548 :         if (a->type == GF_QT_BOX_TYPE_ALIS) return 1;
     723        1548 :         return 0;
     724             : }
     725             : 
     726        1817 : GF_ISOMDataRefAllType Media_SelfContainedType(GF_MediaBox *mdia)
     727             : {
     728             :         u32 nb_ext, nb_self;
     729             :         u32 i, count;
     730             : 
     731             :         nb_ext = nb_self = 0;
     732        1817 :         count = mdia->information->sampleTable->SampleDescription ? gf_list_count(mdia->information->sampleTable->SampleDescription->child_boxes) : 0;
     733        5461 :         for (i=0; i<count; i++) {
     734        1827 :                 if (Media_IsSelfContained(mdia, i+1)) nb_self++;
     735           3 :                 else nb_ext++;
     736             :         }
     737        1817 :         if (nb_ext==count) return ISOM_DREF_EXT;
     738        1814 :         if (nb_self==count) return ISOM_DREF_SELF;
     739           0 :         return ISOM_DREF_MIXED;
     740             : }
     741             : 
     742             : 
     743             : 
     744             : //look for a sync sample from a given point in media time
     745          99 : GF_Err Media_FindSyncSample(GF_SampleTableBox *stbl, u32 searchFromSample, u32 *sampleNumber, u8 mode)
     746             : {
     747             :         GF_ISOSAPType isRAP;
     748             :         u32 next, prev, next_in_sap, prev_in_sap;
     749          99 :         if (!stbl || !stbl->SyncSample) return GF_BAD_PARAM;
     750             : 
     751             :         //set to current sample if we don't find a RAP
     752          99 :         *sampleNumber = searchFromSample;
     753             : 
     754             :         //this is not the exact sample, but the prev move to next sample if enough samples....
     755          99 :         if ( (mode == GF_ISOM_SEARCH_SYNC_FORWARD) && (searchFromSample == stbl->SampleSize->sampleCount) ) {
     756             :                 return GF_OK;
     757             :         }
     758          99 :         if ( (mode == GF_ISOM_SEARCH_SYNC_BACKWARD) && !searchFromSample) {
     759           0 :                 *sampleNumber = 1;
     760           0 :                 return GF_OK;
     761             :         }
     762             :         //get the entry
     763          99 :         stbl_GetSampleRAP(stbl->SyncSample, searchFromSample, &isRAP, &prev, &next);
     764          99 :         if (isRAP) {
     765          42 :                 (*sampleNumber) = searchFromSample;
     766          42 :                 return GF_OK;
     767             :         }
     768             : 
     769             :         /*check sample groups - prev & next are overwritten if RAP group is found, but are not re-initialized otherwise*/
     770          57 :         stbl_SearchSAPs(stbl, searchFromSample, &isRAP, &prev_in_sap, &next_in_sap);
     771          57 :         if (isRAP) {
     772           0 :                 (*sampleNumber) = searchFromSample;
     773           0 :                 return GF_OK;
     774             :         }
     775             : 
     776          57 :         if (prev_in_sap > prev)
     777           0 :                 prev = prev_in_sap;
     778          57 :         if (next_in_sap && next_in_sap < next)
     779           0 :                 next = next_in_sap;
     780             : 
     781             :         //nothing yet, go for next time...
     782          57 :         if (mode == GF_ISOM_SEARCH_SYNC_FORWARD) {
     783          31 :                 if (next) *sampleNumber = next;
     784             :         } else {
     785          26 :                 if (prev) *sampleNumber = prev;
     786             :         }
     787             : 
     788             :         return GF_OK;
     789             : }
     790             : 
     791             : //create a DataReference if not existing (only for WRITE-edit mode)
     792        1580 : GF_Err Media_FindDataRef(GF_DataReferenceBox *dref, char *URLname, char *URNname, u32 *dataRefIndex)
     793             : {
     794             :         u32 i;
     795             :         GF_DataEntryURLBox *entry;
     796             : 
     797        1580 :         if (!dref) return GF_BAD_PARAM;
     798        1580 :         *dataRefIndex = 0;
     799        1580 :         i=0;
     800        3160 :         while ((entry = (GF_DataEntryURLBox*)gf_list_enum(dref->child_boxes, &i))) {
     801          29 :                 if (entry->type == GF_ISOM_BOX_TYPE_URL) {
     802             :                         //self-contained case
     803          29 :                         if (entry->flags == 1) {
     804             :                                 //if nothing specified, get the dataRef
     805          29 :                                 if (!URLname && !URNname) {
     806          29 :                                         *dataRefIndex = i;
     807          29 :                                         return GF_OK;
     808             :                                 }
     809             :                         } else {
     810             :                                 //OK, check if we have URL
     811           0 :                                 if (URLname && !strcmp(URLname, entry->location)) {
     812           0 :                                         *dataRefIndex = i;
     813           0 :                                         return GF_OK;
     814             :                                 }
     815             :                         }
     816             :                 } else {
     817             :                         //this is a URN one, only check the URN name (URL optional)
     818           0 :                         if (URNname && !strcmp(URNname, ((GF_DataEntryURNBox *)entry)->nameURN)) {
     819           0 :                                 *dataRefIndex = i;
     820           0 :                                 return GF_OK;
     821             :                         }
     822             :                 }
     823             :         }
     824             :         return GF_OK;
     825             : }
     826             : 
     827             : //Get the total media duration based on the TimeToSample table
     828      599556 : GF_Err Media_SetDuration(GF_TrackBox *trak)
     829             : {
     830             :         GF_Err e;
     831             :         GF_ESD *esd;
     832             :         u64 DTS;
     833             :         GF_SttsEntry *ent;
     834             :         u32 nbSamp;
     835             : 
     836      599556 :         if (!trak || !trak->Media || !trak->Media->information || !trak->Media->information->sampleTable)
     837             :                 return GF_ISOM_INVALID_FILE;
     838             : 
     839      599556 :         if (!trak->Media->information->sampleTable->SampleSize || !trak->Media->information->sampleTable->TimeToSample)
     840             :                 return GF_ISOM_INVALID_FILE;
     841             : 
     842      599556 :         nbSamp = trak->Media->information->sampleTable->SampleSize->sampleCount;
     843             : 
     844             :         //we need to check how many samples we have.
     845             :         // == 1 -> last sample duration == default duration
     846             :         // > 1 -> last sample duration == prev sample duration
     847      599556 :         switch (nbSamp) {
     848        3180 :         case 0:
     849        3180 :                 trak->Media->mediaHeader->duration = 0;
     850        3180 :                 if (Track_IsMPEG4Stream(trak->Media->handler->handlerType)) {
     851        3141 :                         Media_GetESD(trak->Media, 1, &esd, 1);
     852        3141 :                         if (esd && esd->URLString) trak->Media->mediaHeader->duration = (u64) -1;
     853             : 
     854             :                 }
     855             :                 return GF_OK;
     856             : 
     857             : //      case 1:
     858             : //              trak->Media->mediaHeader->duration = trak->Media->mediaHeader->timeScale;
     859             : //              return GF_OK;
     860             : 
     861      596376 :         default:
     862             :                 //we assume a constant frame rate for the media and assume the last sample
     863             :                 //will be hold the same time as the prev one
     864      596376 :                 e = stbl_GetSampleDTS(trak->Media->information->sampleTable->TimeToSample, nbSamp, &DTS);
     865      596376 :                 if (e < 0) {
     866             :                         return e;
     867             :                 }
     868      596376 :                 if (trak->Media->information->sampleTable->TimeToSample->nb_entries > 0) {
     869      596376 :                         ent = &trak->Media->information->sampleTable->TimeToSample->entries[trak->Media->information->sampleTable->TimeToSample->nb_entries-1];
     870             :                 } else {
     871             :                         ent = NULL;
     872             :                 }
     873      596376 :                 trak->Media->mediaHeader->duration = DTS;
     874             : 
     875             : 
     876             : #if 1
     877      596376 :                 if (ent) trak->Media->mediaHeader->duration += ent->sampleDelta;
     878             : #else
     879             :                 if (!ent) {
     880             :                         u64 DTSprev;
     881             :                         stbl_GetSampleDTS(trak->Media->information->sampleTable->TimeToSample, nbSamp-1, &DTSprev);
     882             :                         trak->Media->mediaHeader->duration += (DTS - DTSprev);
     883             :                 } else {
     884             : #ifndef GPAC_DISABLE_ISOM_WRITE
     885             :                         if (trak->moov->mov->editFileMap && trak->Media->information->sampleTable->CompositionOffset) {
     886             :                                 u32 count, i;
     887             :                                 u64 max_ts;
     888             :                                 GF_DttsEntry *cts_ent;
     889             :                                 GF_CompositionOffsetBox *ctts = trak->Media->information->sampleTable->CompositionOffset;
     890             :                                 if (ctts->w_LastSampleNumber==nbSamp) {
     891             :                                         count = gf_list_count(ctts->entryList);
     892             :                                         max_ts = trak->Media->mediaHeader->duration;
     893             :                                         while (count) {
     894             :                                                 count -= 1;
     895             :                                                 cts_ent = gf_list_get(ctts->entryList, count);
     896             :                                                 if (nbSamp<cts_ent->sampleCount) break;
     897             : 
     898             :                                                 for (i=0; i<cts_ent->sampleCount; i++) {
     899             :                                                         stbl_GetSampleDTS(trak->Media->information->sampleTable->TimeToSample, nbSamp-i, &DTS);
     900             :                                                         if ((s32) cts_ent->decodingOffset < 0) max_ts = DTS;
     901             :                                                         else max_ts = DTS + cts_ent->decodingOffset;
     902             :                                                         if (max_ts>=trak->Media->mediaHeader->duration) {
     903             :                                                                 trak->Media->mediaHeader->duration = max_ts;
     904             :                                                         } else {
     905             :                                                                 break;
     906             :                                                         }
     907             :                                                 }
     908             :                                                 if (max_ts<trak->Media->mediaHeader->duration) {
     909             :                                                         break;
     910             :                                                 }
     911             :                                                 nbSamp-=cts_ent->sampleCount;
     912             :                                         }
     913             :                                 }
     914             :                         }
     915             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     916             :                         trak->Media->mediaHeader->duration += ent->sampleDelta;
     917             :                 }
     918             : #endif
     919             :                 return GF_OK;
     920             :         }
     921             : }
     922             : 
     923             : 
     924             : 
     925             : 
     926             : #ifndef GPAC_DISABLE_ISOM_WRITE
     927             : 
     928           3 : GF_Err Media_SetDrefURL(GF_DataEntryURLBox *dref_entry, const char *origName, const char *finalName)
     929             : {
     930             :         //for now we only support dref created in same folder for relative URLs
     931           3 :         if (strstr(origName, "://") || ((origName[1]==':') && (origName[2]=='\\'))
     932           3 :                 || (origName[0]=='/') || (origName[0]=='\\')
     933             :         ) {
     934           0 :                 dref_entry->location = gf_strdup(origName);
     935             :         } else {
     936           3 :                 char *fname = strrchr(origName, '/');
     937           3 :                 if (!fname) fname = strrchr(origName, '\\');
     938           3 :                 if (fname) fname++;
     939             : 
     940           3 :                 if (!fname) {
     941           0 :                         dref_entry->location = gf_strdup(origName);
     942             :                 } else {
     943           3 :                         u32 len = (u32) (fname - origName);
     944           3 :                         if (!finalName || strncmp(origName, finalName, len)) {
     945           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("Concatenation of relative path %s with relative path %s not supported, use absolute URLs\n", origName, finalName));
     946             :                                 return GF_NOT_SUPPORTED;
     947             :                         } else {
     948           3 :                                 dref_entry->location = gf_strdup(fname);
     949             :                         }
     950             :                 }
     951             :         }
     952             :         return GF_OK;
     953             : }
     954             : 
     955             : 
     956        1726 : GF_Err Media_CreateDataRef(GF_ISOFile *movie, GF_DataReferenceBox *dref, char *URLname, char *URNname, u32 *dataRefIndex)
     957             : {
     958             :         GF_Err e;
     959             :         Bool use_alis=GF_FALSE;
     960             :         GF_DataEntryURLBox *entry;
     961             : 
     962        1726 :         if (URLname && !strcmp(URLname, "alis")) {
     963             :                 URLname = NULL;
     964             :                 use_alis=GF_TRUE;
     965             :         }
     966             : 
     967        1726 :         if (!URLname && !URNname) {
     968             :                 //THIS IS SELF CONTAIN, create a regular entry if needed
     969        1726 :                 entry = (GF_DataEntryURLBox *) gf_isom_box_new_parent(&dref->child_boxes, use_alis ? GF_QT_BOX_TYPE_ALIS : GF_ISOM_BOX_TYPE_URL);
     970        1726 :                 if (!entry) return GF_OUT_OF_MEM;
     971        1726 :                 entry->flags = 1;
     972        1726 :                 *dataRefIndex = gf_list_count(dref->child_boxes);
     973        1726 :                 return GF_OK;
     974           0 :         } else if (!URNname && URLname) {
     975             :                 //THIS IS URL
     976           0 :                 entry = (GF_DataEntryURLBox *) gf_isom_box_new_parent(&dref->child_boxes, GF_ISOM_BOX_TYPE_URL);
     977           0 :                 if (!entry) return GF_OUT_OF_MEM;
     978           0 :                 entry->flags = 0;
     979             : 
     980           0 :                 e = Media_SetDrefURL(entry, URLname, movie->fileName ? movie->fileName : movie->finalName);
     981           0 :                 if (! entry->location) {
     982           0 :                         gf_isom_box_del_parent(&dref->child_boxes, (GF_Box *)entry);
     983           0 :                         return e ? e : GF_OUT_OF_MEM;
     984             :                 }
     985           0 :                 *dataRefIndex = gf_list_count(dref->child_boxes);
     986           0 :                 return GF_OK;
     987             :         } else {
     988             :                 //THIS IS URN
     989           0 :                 entry = (GF_DataEntryURLBox *) gf_isom_box_new_parent(&dref->child_boxes, GF_ISOM_BOX_TYPE_URN);
     990           0 :                 if (!entry) return GF_OUT_OF_MEM;
     991           0 :                 ((GF_DataEntryURNBox *)entry)->flags = 0;
     992           0 :                 ((GF_DataEntryURNBox *)entry)->nameURN = (char*)gf_malloc(strlen(URNname)+1);
     993           0 :                 if (! ((GF_DataEntryURNBox *)entry)->nameURN) {
     994           0 :                         gf_isom_box_del_parent(&dref->child_boxes, (GF_Box *)entry);
     995           0 :                         return GF_OUT_OF_MEM;
     996             :                 }
     997             :                 strcpy(((GF_DataEntryURNBox *)entry)->nameURN, URNname);
     998             :                 //check for URL
     999           0 :                 if (URLname) {
    1000           0 :                         ((GF_DataEntryURNBox *)entry)->location = (char*)gf_malloc(strlen(URLname)+1);
    1001           0 :                         if (! ((GF_DataEntryURNBox *)entry)->location) {
    1002           0 :                                 gf_isom_box_del_parent(&dref->child_boxes, (GF_Box *)entry);
    1003           0 :                                 return GF_OUT_OF_MEM;
    1004             :                         }
    1005             :                         strcpy(((GF_DataEntryURNBox *)entry)->location, URLname);
    1006             :                 }
    1007           0 :                 *dataRefIndex = gf_list_count(dref->child_boxes);
    1008           0 :                 return GF_OK;
    1009             :         }
    1010             :         return GF_OK;
    1011             : }
    1012             : 
    1013             : 
    1014      556713 : GF_Err Media_AddSample(GF_MediaBox *mdia, u64 data_offset, const GF_ISOSample *sample, u32 StreamDescIndex, u32 syncShadowNumber)
    1015             : {
    1016             :         GF_Err e;
    1017             :         GF_SampleTableBox *stbl;
    1018             :         u32 sampleNumber, i;
    1019      556713 :         if (!mdia || !sample) return GF_BAD_PARAM;
    1020             : 
    1021      556713 :         stbl = mdia->information->sampleTable;
    1022             : 
    1023             :         //get a valid sampleNumber for this new guy
    1024      556713 :         e = stbl_AddDTS(stbl, sample->DTS, &sampleNumber, mdia->mediaHeader->timeScale, sample->nb_pack);
    1025      556713 :         if (e) return e;
    1026             : 
    1027             :         //add size
    1028      556713 :         e = stbl_AddSize(stbl->SampleSize, sampleNumber, sample->dataLength, sample->nb_pack);
    1029      556713 :         if (e) return e;
    1030             : 
    1031             :         //adds CTS offset
    1032      556713 :         if (sample->CTS_Offset) {
    1033             :                 //if we don't have a CTS table, add it...
    1034      116782 :                 if (!stbl->CompositionOffset) {
    1035         296 :                         stbl->CompositionOffset = (GF_CompositionOffsetBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_CTTS);
    1036         296 :                         if (!stbl->CompositionOffset) return GF_OUT_OF_MEM;
    1037             :                 }
    1038             :                 //then add our CTS (the prev samples with no CTS offset will be automatically added...
    1039      116782 :                 e = stbl_AddCTS(stbl, sampleNumber, sample->CTS_Offset);
    1040      116782 :                 if (e) return e;
    1041      439931 :         } else if (stbl->CompositionOffset) {
    1042       35220 :                 e = stbl_AddCTS(stbl, sampleNumber, sample->CTS_Offset);
    1043       35220 :                 if (e) return e;
    1044             :         }
    1045             : 
    1046             :         //The first non sync sample we see must create a syncTable
    1047      556713 :         if (sample->IsRAP) {
    1048             :                 //insert it only if we have a sync table and if we have an IDR slice
    1049      218642 :                 if (stbl->SyncSample && (sample->IsRAP == RAP)) {
    1050       11409 :                         e = stbl_AddRAP(stbl->SyncSample, sampleNumber);
    1051       11409 :                         if (e) return e;
    1052             :                 }
    1053             :         } else {
    1054             :                 //non-sync sample. Create a SyncSample table if needed
    1055      338071 :                 if (!stbl->SyncSample) {
    1056         708 :                         stbl->SyncSample = (GF_SyncSampleBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_STSS);
    1057         708 :                         if (!stbl->SyncSample) return GF_OUT_OF_MEM;
    1058             :                         //all the prev samples are sync
    1059        2108 :                         for (i=0; i<stbl->SampleSize->sampleCount; i++) {
    1060        1400 :                                 if (i+1 != sampleNumber) {
    1061         692 :                                         e = stbl_AddRAP(stbl->SyncSample, i+1);
    1062         692 :                                         if (e) return e;
    1063             :                                 }
    1064             :                         }
    1065             :                 }
    1066             :         }
    1067      556713 :         if (sample->IsRAP==RAP_REDUNDANT) {
    1068           0 :                 e = stbl_AddRedundant(stbl, sampleNumber);
    1069           0 :                 if (e) return e;
    1070             :         }
    1071             : 
    1072      556713 :         if (!mdia->mediaTrack->chunk_cache) {
    1073             :                 //and update the chunks
    1074      555707 :                 e = stbl_AddChunkOffset(mdia, sampleNumber, StreamDescIndex, data_offset, sample->nb_pack);
    1075      555707 :                 if (e) return e;
    1076             :         }
    1077             :         
    1078      556713 :         if (!syncShadowNumber) return GF_OK;
    1079          12 :         if (!stbl->ShadowSync) {
    1080           6 :                 stbl->ShadowSync = (GF_ShadowSyncBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_STSH);
    1081           6 :                 if (!stbl->ShadowSync) return GF_OUT_OF_MEM;
    1082             :         }
    1083          12 :         return stbl_AddShadow(mdia->information->sampleTable->ShadowSync, sampleNumber, syncShadowNumber);
    1084             : }
    1085             : 
    1086             : 
    1087           0 : static GF_Err UpdateSample(GF_MediaBox *mdia, u32 sampleNumber, u32 size, s32 CTS, u64 offset, u8 isRap)
    1088             : {
    1089             :         u32 i;
    1090           0 :         GF_SampleTableBox *stbl = mdia->information->sampleTable;
    1091             : 
    1092             :         //set size, offset, RAP, CTS ...
    1093           0 :         stbl_SetSampleSize(stbl->SampleSize, sampleNumber, size);
    1094           0 :         stbl_SetChunkOffset(mdia, sampleNumber, offset);
    1095             : 
    1096             :         //do we have a CTS?
    1097           0 :         if (stbl->CompositionOffset) {
    1098           0 :                 stbl_SetSampleCTS(stbl, sampleNumber, CTS);
    1099             :         } else {
    1100             :                 //do we need one ??
    1101           0 :                 if (CTS) {
    1102           0 :                         stbl->CompositionOffset = (GF_CompositionOffsetBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_CTTS);
    1103           0 :                         if (!stbl->CompositionOffset) return GF_OUT_OF_MEM;
    1104           0 :                         stbl_AddCTS(stbl, sampleNumber, CTS);
    1105             :                 }
    1106             :         }
    1107             :         //do we have a sync ???
    1108           0 :         if (stbl->SyncSample) {
    1109           0 :                 stbl_SetSampleRAP(stbl->SyncSample, sampleNumber, isRap);
    1110             :         } else {
    1111             :                 //do we need one
    1112           0 :                 if (! isRap) {
    1113           0 :                         stbl->SyncSample = (GF_SyncSampleBox *) gf_isom_box_new_parent(&stbl->child_boxes, GF_ISOM_BOX_TYPE_STSS);
    1114           0 :                         if (!stbl->SyncSample) return GF_OUT_OF_MEM;
    1115             :                         //what a pain: all the sample we had have to be sync ...
    1116           0 :                         for (i=0; i<stbl->SampleSize->sampleCount; i++) {
    1117           0 :                                 if (i+1 != sampleNumber) stbl_AddRAP(stbl->SyncSample, i+1);
    1118             :                         }
    1119             :                 }
    1120             :         }
    1121           0 :         if (isRap==2) {
    1122           0 :                 stbl_SetRedundant(stbl, sampleNumber);
    1123             :         }
    1124             :         return GF_OK;
    1125             : }
    1126             : 
    1127        4677 : GF_Err Media_UpdateSample(GF_MediaBox *mdia, u32 sampleNumber, GF_ISOSample *sample, Bool data_only)
    1128             : {
    1129             :         GF_Err e;
    1130             :         u32 drefIndex, chunkNum, descIndex;
    1131             :         u64 newOffset, DTS;
    1132             :         GF_DataEntryURLBox *Dentry;
    1133             :         GF_SampleTableBox *stbl;
    1134             : 
    1135        4677 :         if (!mdia || !sample || !sampleNumber || !mdia->mediaTrack->moov->mov->editFileMap)
    1136             :                 return GF_BAD_PARAM;
    1137             : 
    1138        4677 :         stbl = mdia->information->sampleTable;
    1139             : 
    1140        4677 :         if (!data_only) {
    1141             :                 //check we have the sampe dts
    1142           0 :                 e = stbl_GetSampleDTS(stbl->TimeToSample, sampleNumber, &DTS);
    1143           0 :                 if (e) return e;
    1144           0 :                 if (DTS != sample->DTS) return GF_BAD_PARAM;
    1145             :         }
    1146             : 
    1147             :         //get our infos
    1148        4677 :         stbl_GetSampleInfos(stbl, sampleNumber, &newOffset, &chunkNum, &descIndex, NULL);
    1149             : 
    1150             :         //then check the data ref
    1151        4677 :         e = Media_GetSampleDesc(mdia, descIndex, NULL, &drefIndex);
    1152        4677 :         if (e) return e;
    1153        4677 :         Dentry = (GF_DataEntryURLBox*)gf_list_get(mdia->information->dataInformation->dref->child_boxes, drefIndex - 1);
    1154        4677 :         if (!Dentry) return GF_ISOM_INVALID_FILE;
    1155             : 
    1156        4677 :         if (Dentry->flags != 1) return GF_BAD_PARAM;
    1157             : 
    1158             :         //MEDIA DATA EDIT: write this new sample to the edit temp file
    1159        4677 :         newOffset = gf_isom_datamap_get_offset(mdia->mediaTrack->moov->mov->editFileMap);
    1160        4677 :         if (sample->dataLength) {
    1161        4677 :                 e = gf_isom_datamap_add_data(mdia->mediaTrack->moov->mov->editFileMap, sample->data, sample->dataLength);
    1162        4677 :                 if (e) return e;
    1163             :         }
    1164             : 
    1165        4677 :         if (data_only) {
    1166        4677 :                 stbl_SetSampleSize(stbl->SampleSize, sampleNumber, sample->dataLength);
    1167        4677 :                 return stbl_SetChunkOffset(mdia, sampleNumber, newOffset);
    1168             :         }
    1169           0 :         return UpdateSample(mdia, sampleNumber, sample->dataLength, sample->CTS_Offset, newOffset, sample->IsRAP);
    1170             : }
    1171             : 
    1172           0 : GF_Err Media_UpdateSampleReference(GF_MediaBox *mdia, u32 sampleNumber, GF_ISOSample *sample, u64 data_offset)
    1173             : {
    1174             :         GF_Err e;
    1175             :         u32 drefIndex, chunkNum, descIndex;
    1176             :         u64 off, DTS;
    1177             :         GF_DataEntryURLBox *Dentry;
    1178             :         GF_SampleTableBox *stbl;
    1179             : 
    1180           0 :         if (!mdia) return GF_BAD_PARAM;
    1181           0 :         stbl = mdia->information->sampleTable;
    1182             : 
    1183             :         //check we have the sampe dts
    1184           0 :         e = stbl_GetSampleDTS(stbl->TimeToSample, sampleNumber, &DTS);
    1185           0 :         if (e) return e;
    1186           0 :         if (DTS != sample->DTS) return GF_BAD_PARAM;
    1187             : 
    1188             :         //get our infos
    1189           0 :         stbl_GetSampleInfos(stbl, sampleNumber, &off, &chunkNum, &descIndex, NULL);
    1190             : 
    1191             :         //then check the data ref
    1192           0 :         e = Media_GetSampleDesc(mdia, descIndex, NULL, &drefIndex);
    1193           0 :         if (e) return e;
    1194           0 :         Dentry = (GF_DataEntryURLBox*)gf_list_get(mdia->information->dataInformation->dref->child_boxes, drefIndex - 1);
    1195           0 :         if (!Dentry) return GF_ISOM_INVALID_FILE;
    1196             : 
    1197             :         //we only modify self-contained data
    1198           0 :         if (Dentry->flags == 1) return GF_ISOM_INVALID_MODE;
    1199             : 
    1200             :         //and we don't modify the media data
    1201           0 :         return UpdateSample(mdia, sampleNumber, sample->dataLength, sample->CTS_Offset, data_offset, sample->IsRAP);
    1202             : }
    1203             : 
    1204             : 
    1205             : #endif  /*GPAC_DISABLE_ISOM_WRITE*/
    1206             : 
    1207             : #endif /*GPAC_DISABLE_ISOM*/

Generated by: LCOV version 1.13