LCOV - code coverage report
Current view: top level - isomedia - hinting.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 322 411 78.3 %
Date: 2021-04-29 23:48:07 Functions: 32 36 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-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             : #if !defined(GPAC_DISABLE_ISOM) && !defined(GPAC_DISABLE_ISOM_HINTING)
      29             : 
      30         135 : GF_Box *ghnt_box_new()
      31             : {
      32             :         GF_HintSampleEntryBox *tmp;
      33         135 :         GF_SAFEALLOC(tmp, GF_HintSampleEntryBox);
      34         135 :         if (!tmp) return NULL;
      35         135 :         gf_isom_sample_entry_init((GF_SampleEntryBox *)tmp);
      36             : 
      37             :         //this type is used internally for protocols that share the same base entry
      38             :         //currently only RTP uses this, but a flexMux could use this entry too...
      39         135 :         tmp->type = GF_ISOM_BOX_TYPE_GHNT;
      40         135 :         tmp->HintTrackVersion = 1;
      41         135 :         tmp->LastCompatibleVersion = 1;
      42         135 :         return (GF_Box *)tmp;
      43             : }
      44             : 
      45         135 : void ghnt_box_del(GF_Box *s)
      46             : {
      47             :         GF_HintSampleEntryBox *ptr;
      48             : 
      49         135 :         gf_isom_sample_entry_predestroy((GF_SampleEntryBox *)s);
      50             :         ptr = (GF_HintSampleEntryBox *)s;
      51         135 :         if (ptr->hint_sample) gf_isom_hint_sample_del(ptr->hint_sample);
      52         135 :         gf_free(ptr);
      53         135 : }
      54             : 
      55          51 : GF_Err ghnt_box_read(GF_Box *s, GF_BitStream *bs)
      56             : {
      57             :         GF_Err e;
      58             :         GF_HintSampleEntryBox *ptr = (GF_HintSampleEntryBox *)s;
      59          51 :         if (ptr == NULL) return GF_BAD_PARAM;
      60             : 
      61             :         //sample entry + 4 bytes in box
      62          51 :         ISOM_DECREASE_SIZE(ptr, 12)
      63             : 
      64          51 :         e = gf_isom_base_sample_entry_read((GF_SampleEntryBox *)ptr, bs);
      65          51 :         if (e) return e;
      66             : 
      67          51 :         ptr->HintTrackVersion = gf_bs_read_u16(bs);
      68          51 :         ptr->LastCompatibleVersion = gf_bs_read_u16(bs);
      69             : 
      70          51 :         if ((s->type == GF_ISOM_BOX_TYPE_RTP_STSD) || (s->type == GF_ISOM_BOX_TYPE_SRTP_STSD) || (s->type == GF_ISOM_BOX_TYPE_RRTP_STSD) || (s->type == GF_ISOM_BOX_TYPE_RTCP_STSD)) {
      71          50 :                 ISOM_DECREASE_SIZE(ptr, 4)
      72          50 :                 ptr->MaxPacketSize = gf_bs_read_u32(bs);
      73           1 :         } else if (s->type == GF_ISOM_BOX_TYPE_FDP_STSD) {
      74           1 :                 ISOM_DECREASE_SIZE(ptr, 4)
      75           1 :                 ptr->partition_entry_ID = gf_bs_read_u16(bs);
      76           1 :                 ptr->FEC_overhead = gf_bs_read_u16(bs);
      77             : 
      78             :         }
      79          51 :         return gf_isom_box_array_read(s, bs);
      80             : }
      81             : 
      82             : #ifndef GPAC_DISABLE_ISOM_WRITE
      83             : 
      84          79 : GF_Err ghnt_box_write(GF_Box *s, GF_BitStream *bs)
      85             : {
      86             :         GF_Err e;
      87             :         GF_HintSampleEntryBox *ptr = (GF_HintSampleEntryBox *)s;
      88             : 
      89          79 :         e = gf_isom_box_write_header(s, bs);
      90          79 :         if (e) return e;
      91          79 :         gf_bs_write_data(bs, ptr->reserved, 6);
      92          79 :         gf_bs_write_u16(bs, ptr->dataReferenceIndex);
      93          79 :         gf_bs_write_u16(bs, ptr->HintTrackVersion);
      94          79 :         gf_bs_write_u16(bs, ptr->LastCompatibleVersion);
      95          79 :         gf_bs_write_u32(bs, ptr->MaxPacketSize);
      96          79 :         return GF_OK;
      97             : }
      98             : 
      99         225 : GF_Err ghnt_box_size(GF_Box *s)
     100             : {
     101             :         GF_HintSampleEntryBox *ptr = (GF_HintSampleEntryBox *)s;
     102         225 :         ptr->size += 16;
     103         225 :         return GF_OK;
     104             : }
     105             : 
     106             : 
     107             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     108             : 
     109             : 
     110       59555 : GF_HintSample *gf_isom_hint_sample_new(u32 ProtocolType)
     111             : {
     112             :         GF_HintSample *tmp;
     113       59555 :         switch (ProtocolType) {
     114             :         case GF_ISOM_BOX_TYPE_RTP_STSD:
     115             :         case GF_ISOM_BOX_TYPE_SRTP_STSD:
     116             :         case GF_ISOM_BOX_TYPE_RRTP_STSD:
     117             :         case GF_ISOM_BOX_TYPE_RTCP_STSD:
     118             :                 break;
     119           0 :         case GF_ISOM_BOX_TYPE_FDP_STSD:
     120           0 :                 return (GF_HintSample *) gf_isom_box_new(GF_ISOM_BOX_TYPE_FDSA);
     121             :                 break;
     122             :         default:
     123             :                 return NULL;
     124             :         }
     125       59555 :         GF_SAFEALLOC(tmp, GF_HintSample);
     126       59555 :         if (!tmp) return NULL;
     127       59555 :         tmp->packetTable = gf_list_new();
     128       59555 :         tmp->hint_subtype = ProtocolType;
     129       59555 :         return tmp;
     130             : }
     131             : 
     132       59555 : void gf_isom_hint_sample_del(GF_HintSample *ptr)
     133             : {
     134       59555 :         if (ptr->hint_subtype==GF_ISOM_BOX_TYPE_FDP_STSD) {
     135           0 :                 gf_isom_box_del((GF_Box*)ptr);
     136           0 :                 return;
     137             :         }
     138             : 
     139      128077 :         while (gf_list_count(ptr->packetTable)) {
     140       68522 :                 GF_HintPacket *pck = (GF_HintPacket *)gf_list_get(ptr->packetTable, 0);
     141       68522 :                 gf_isom_hint_pck_del(pck);
     142       68522 :                 gf_list_rem(ptr->packetTable, 0);
     143             :         }
     144       59555 :         gf_list_del(ptr->packetTable);
     145       59555 :         if (ptr->AdditionalData) gf_free(ptr->AdditionalData);
     146             : 
     147       59555 :         if (ptr->sample_cache) {
     148           0 :                 while (gf_list_count(ptr->sample_cache)) {
     149           0 :                         GF_HintDataCache *hdc = (GF_HintDataCache *)gf_list_get(ptr->sample_cache, 0);
     150           0 :                         gf_list_rem(ptr->sample_cache, 0);
     151           0 :                         if (hdc->samp) gf_isom_sample_del(&hdc->samp);
     152           0 :                         gf_free(hdc);
     153             :                 }
     154           0 :                 gf_list_del(ptr->sample_cache);
     155             :         }
     156       59555 :         if (ptr->extra_data)
     157           0 :                 gf_isom_box_del((GF_Box*)ptr->extra_data);
     158       59555 :         if (ptr->child_boxes)
     159           0 :                 gf_isom_box_array_del(ptr->child_boxes);
     160             : 
     161       59555 :         gf_free(ptr);
     162             : }
     163             : 
     164         385 : GF_Err gf_isom_hint_sample_read(GF_HintSample *ptr, GF_BitStream *bs, u32 sampleSize)
     165             : {
     166             :         u16 i;
     167             :         u32 type;
     168             :         GF_Err e;
     169             : #ifndef GPAC_DISABLE_LOG
     170         385 :         char *szName = (ptr->hint_subtype==GF_ISOM_BOX_TYPE_RTCP_STSD) ? "RTCP" : "RTP";
     171             : #endif
     172             :         u64 sizeIn, sizeOut;
     173             : 
     174         385 :         sizeIn = gf_bs_available(bs);
     175             : 
     176         385 :         switch (ptr->hint_subtype) {
     177             :         case GF_ISOM_BOX_TYPE_RTP_STSD:
     178             :         case GF_ISOM_BOX_TYPE_SRTP_STSD:
     179             :         case GF_ISOM_BOX_TYPE_RRTP_STSD:
     180             :         case GF_ISOM_BOX_TYPE_RTCP_STSD:
     181             :                 break;
     182           0 :         case GF_ISOM_BOX_TYPE_FDP_STSD:
     183           0 :                 ptr->size = gf_bs_read_u32(bs);
     184           0 :                 type = gf_bs_read_u32(bs);
     185           0 :                 if (type != GF_ISOM_BOX_TYPE_FDSA) {
     186           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso] invalid FDT sample, top box type %s not fdsa\n", gf_4cc_to_str(type) ));
     187             :                         return GF_ISOM_INVALID_MEDIA;
     188             :                 }
     189           0 :                 return gf_isom_box_read((GF_Box*)ptr, bs);
     190             :         default:
     191             :                 return GF_NOT_SUPPORTED;
     192             :         }
     193             : 
     194         385 :         ptr->packetCount = gf_bs_read_u16(bs);
     195         385 :         ptr->reserved = gf_bs_read_u16(bs);
     196         385 :         if (ptr->packetCount>=sampleSize) {
     197           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso] broken %s sample: %d packet_count indicated but only %d bytes in samples\n", szName, ptr->packetCount, sampleSize));
     198             :                 return GF_ISOM_INVALID_MEDIA;
     199             :         }
     200             :         
     201         385 :         for (i = 0; i < ptr->packetCount; i++) {
     202             :                 GF_HintPacket *pck;
     203         385 :                 if (! gf_bs_available(bs) ) {
     204           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso] %s hint sample has no more data but still %d entries to read\n", szName, ptr->packetCount-i));
     205             :                         return GF_ISOM_INVALID_MEDIA;
     206             :                 }
     207         385 :                 pck = gf_isom_hint_pck_new(ptr->hint_subtype);
     208         385 :                 pck->trackID = ptr->trackID;
     209         385 :                 pck->sampleNumber = ptr->sampleNumber;
     210         385 :                 gf_list_add(ptr->packetTable, pck);
     211             : 
     212         385 :                 e = gf_isom_hint_pck_read(pck, bs);
     213         385 :                 if (e) return e;
     214             :         }
     215             : 
     216         385 :         if (ptr->hint_subtype==GF_ISOM_BOX_TYPE_RTCP_STSD) return GF_OK;
     217             : 
     218             : 
     219         385 :         sizeOut = gf_bs_available(bs) - sizeIn;
     220             : 
     221             :         //do we have some more data after the packets ??
     222         385 :         if ((u32)sizeOut < sampleSize) {
     223           0 :                 ptr->dataLength = sampleSize - (u32)sizeOut;
     224           0 :                 ptr->AdditionalData = (char*)gf_malloc(sizeof(char) * ptr->dataLength);
     225           0 :                 if (!ptr->AdditionalData) return GF_OUT_OF_MEM;
     226           0 :                 gf_bs_read_data(bs, ptr->AdditionalData, ptr->dataLength);
     227             :         }
     228             :         return GF_OK;
     229             : }
     230             : 
     231             : 
     232             : #ifndef GPAC_DISABLE_ISOM_WRITE
     233             : 
     234       59170 : GF_Err gf_isom_hint_sample_write(GF_HintSample *ptr, GF_BitStream *bs)
     235             : {
     236             :         u32 count, i;
     237             :         GF_Err e;
     238             : 
     239       59170 :         if (ptr->hint_subtype==GF_ISOM_BOX_TYPE_FDP_STSD) {
     240           0 :                 e = gf_isom_box_size((GF_Box*)ptr);
     241           0 :                 if (!e) e = gf_isom_box_write((GF_Box*)ptr, bs);
     242             :                 return e;
     243             :         }
     244             : 
     245       59170 :         count = gf_list_count(ptr->packetTable);
     246       59170 :         gf_bs_write_u16(bs, count);
     247       59170 :         gf_bs_write_u16(bs, ptr->reserved);
     248             :         //write the packet table
     249      127307 :         for (i=0; i<count; i++) {
     250       68137 :                 GF_HintPacket *pck = (GF_HintPacket *)gf_list_get(ptr->packetTable, i);
     251       68137 :                 e = gf_isom_hint_pck_write(pck, bs);
     252       68137 :                 if (e) return e;
     253             :         }
     254             :         //write additional data
     255       59170 :         if (ptr->AdditionalData) {
     256          83 :                 gf_bs_write_data(bs, ptr->AdditionalData, ptr->dataLength);
     257             :         }
     258             :         return GF_OK;
     259             : }
     260             : 
     261             : 
     262       59170 : u32 gf_isom_hint_sample_size(GF_HintSample *ptr)
     263             : {
     264             :         u32 size, count, i;
     265       59170 :         if (ptr->hint_subtype==GF_ISOM_BOX_TYPE_FDP_STSD) {
     266           0 :                 gf_isom_box_size((GF_Box*)ptr);
     267           0 :                 size = (u32) ptr->size;
     268             :         } else {
     269             :                 size = 4;
     270       59170 :                 count = gf_list_count(ptr->packetTable);
     271      127307 :                 for (i=0; i<count; i++) {
     272       68137 :                         GF_HintPacket *pck = (GF_HintPacket *)gf_list_get(ptr->packetTable, i);
     273       68137 :                         size += gf_isom_hint_pck_size(pck);
     274             :                 }
     275       59170 :                 size += ptr->dataLength;
     276             :         }
     277       59170 :         return size;
     278             : }
     279             : 
     280             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     281             : 
     282             : 
     283             : GF_EXPORT
     284       68523 : GF_HintPacket *gf_isom_hint_pck_new(u32 HintType)
     285             : {
     286             :         GF_HintPacket *pck;
     287       68523 :         switch (HintType) {
     288       68522 :         case GF_ISOM_BOX_TYPE_RTP_STSD:
     289             :         case GF_ISOM_BOX_TYPE_SRTP_STSD:
     290             :         case GF_ISOM_BOX_TYPE_RRTP_STSD:
     291       68522 :                 pck = (GF_HintPacket *) gf_isom_hint_rtp_new();
     292       68522 :                 if (pck) pck->hint_subtype = HintType;
     293             :                 return pck;
     294           1 :         case GF_ISOM_BOX_TYPE_RTCP_STSD:
     295           1 :                 pck = (GF_HintPacket *) gf_isom_hint_rtcp_new();
     296           1 :                 if (pck) pck->hint_subtype = HintType;
     297             :                 return pck;
     298             :         default:
     299             :                 return NULL;
     300             :         }
     301             : }
     302             : 
     303             : GF_EXPORT
     304       68523 : void gf_isom_hint_pck_del(GF_HintPacket *ptr)
     305             : {
     306       68523 :         if (!ptr) return;
     307       68523 :         switch (ptr->hint_subtype) {
     308       68522 :         case GF_ISOM_BOX_TYPE_RTP_STSD:
     309             :         case GF_ISOM_BOX_TYPE_SRTP_STSD:
     310             :         case GF_ISOM_BOX_TYPE_RRTP_STSD:
     311       68522 :                 gf_isom_hint_rtp_del((GF_RTPPacket *)ptr);
     312       68522 :                 break;
     313           1 :         case GF_ISOM_BOX_TYPE_RTCP_STSD:
     314           1 :                 gf_isom_hint_rtcp_del((GF_RTCPPacket *)ptr);
     315           1 :                 break;
     316             :         default:
     317             :                 break;
     318             :         }
     319             : }
     320             : 
     321             : GF_EXPORT
     322         386 : GF_Err gf_isom_hint_pck_read(GF_HintPacket *ptr, GF_BitStream *bs)
     323             : {
     324         386 :         if (!ptr) return GF_BAD_PARAM;
     325         386 :         switch (ptr->hint_subtype) {
     326         385 :         case GF_ISOM_BOX_TYPE_RTP_STSD:
     327             :         case GF_ISOM_BOX_TYPE_SRTP_STSD:
     328             :         case GF_ISOM_BOX_TYPE_RRTP_STSD:
     329         385 :                 return gf_isom_hint_rtp_read((GF_RTPPacket *)ptr, bs);
     330           1 :         case GF_ISOM_BOX_TYPE_RTCP_STSD:
     331           1 :                 return gf_isom_hint_rtcp_read((GF_RTCPPacket *)ptr, bs);
     332             :         default:
     333             :                 return GF_NOT_SUPPORTED;
     334             :         }
     335             : }
     336             : 
     337             : #ifndef GPAC_DISABLE_ISOM_WRITE
     338             : 
     339             : GF_EXPORT
     340       68138 : GF_Err gf_isom_hint_pck_write(GF_HintPacket *ptr, GF_BitStream *bs)
     341             : {
     342       68138 :         if (!ptr) return GF_BAD_PARAM;
     343       68138 :         switch (ptr->hint_subtype) {
     344       68137 :         case GF_ISOM_BOX_TYPE_RTP_STSD:
     345             :         case GF_ISOM_BOX_TYPE_SRTP_STSD:
     346             :         case GF_ISOM_BOX_TYPE_RRTP_STSD:
     347       68137 :                 return gf_isom_hint_rtp_write((GF_RTPPacket *)ptr, bs);
     348           1 :         case GF_ISOM_BOX_TYPE_RTCP_STSD:
     349           1 :                 return gf_isom_hint_rtcp_write((GF_RTCPPacket *)ptr, bs);
     350             :         default:
     351             :                 return GF_NOT_SUPPORTED;
     352             :         }
     353             : }
     354             : 
     355             : GF_EXPORT
     356       68138 : u32 gf_isom_hint_pck_size(GF_HintPacket *ptr)
     357             : {
     358       68138 :         if (!ptr) return GF_BAD_PARAM;
     359       68138 :         switch (ptr->hint_subtype) {
     360       68137 :         case GF_ISOM_BOX_TYPE_RTP_STSD:
     361             :         case GF_ISOM_BOX_TYPE_SRTP_STSD:
     362             :         case GF_ISOM_BOX_TYPE_RRTP_STSD:
     363       68137 :                 return gf_isom_hint_rtp_size((GF_RTPPacket *)ptr);
     364             :         case GF_ISOM_BOX_TYPE_RTCP_STSD:
     365           1 :                 return gf_isom_hint_rtcp_size((GF_RTCPPacket *)ptr);
     366             :         default:
     367             :                 return 0;
     368             :         }
     369             : }
     370             : 
     371         159 : GF_Err gf_isom_hint_pck_offset(GF_HintPacket *ptr, u32 offset, u32 HintSampleNumber)
     372             : {
     373         159 :         if (!ptr) return GF_BAD_PARAM;
     374         159 :         switch (ptr->hint_subtype) {
     375         159 :         case GF_ISOM_BOX_TYPE_RTP_STSD:
     376             :         case GF_ISOM_BOX_TYPE_SRTP_STSD:
     377             :         case GF_ISOM_BOX_TYPE_RRTP_STSD:
     378         159 :                 return gf_isom_hint_rtp_offset((GF_RTPPacket *)ptr, offset, HintSampleNumber);
     379             :         case GF_ISOM_BOX_TYPE_RTCP_STSD:
     380             :                 return GF_BAD_PARAM;
     381           0 :         default:
     382           0 :                 return GF_NOT_SUPPORTED;
     383             :         }
     384             : }
     385             : 
     386      124334 : GF_Err gf_isom_hint_pck_add_dte(GF_HintPacket *ptr, GF_GenericDTE *dte, u8 AtBegin)
     387             : {
     388      124334 :         if (!ptr) return GF_BAD_PARAM;
     389      124334 :         switch (ptr->hint_subtype) {
     390      124334 :         case GF_ISOM_BOX_TYPE_RTP_STSD:
     391             :         case GF_ISOM_BOX_TYPE_SRTP_STSD:
     392             :         case GF_ISOM_BOX_TYPE_RRTP_STSD:
     393      124334 :                 if (AtBegin)
     394       34278 :                         return gf_list_insert( ((GF_RTPPacket *)ptr)->DataTable, dte, 0);
     395             :                 else
     396       90056 :                         return gf_list_add( ((GF_RTPPacket *)ptr)->DataTable, dte);
     397             : 
     398             :         case GF_ISOM_BOX_TYPE_RTCP_STSD:
     399             :                 return GF_BAD_PARAM;
     400           0 :         default:
     401           0 :                 return GF_NOT_SUPPORTED;
     402             :         }
     403             : }
     404             : 
     405             : GF_EXPORT
     406       68138 : u32 gf_isom_hint_pck_length(GF_HintPacket *ptr)
     407             : {
     408       68138 :         if (!ptr) return 0;
     409       68138 :         switch (ptr->hint_subtype) {
     410       68137 :         case GF_ISOM_BOX_TYPE_RTP_STSD:
     411             :         case GF_ISOM_BOX_TYPE_SRTP_STSD:
     412             :         case GF_ISOM_BOX_TYPE_RRTP_STSD:
     413       68137 :                 return gf_isom_hint_rtp_length((GF_RTPPacket *)ptr);
     414             :         case GF_ISOM_BOX_TYPE_RTCP_STSD:
     415           1 :                 return gf_isom_hint_rtcp_length((GF_RTCPPacket *)ptr);
     416             :         default:
     417             :                 return 0;
     418             :         }
     419             : }
     420             : 
     421             : 
     422             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     423             : 
     424             : 
     425             : 
     426             : /********************************************************************
     427             :                 Creation of DataTable entries in the RTP sample
     428             : ********************************************************************/
     429             : 
     430             : //creation of DTEs
     431      125104 : GF_GenericDTE *NewDTE(u8 type)
     432             : {
     433      125104 :         switch (type) {
     434           0 :         case 0:
     435             :         {
     436             :                 GF_EmptyDTE *dte;
     437           0 :                 GF_SAFEALLOC(dte, GF_EmptyDTE);
     438             :                 return (GF_GenericDTE *)dte;
     439             :         }
     440       49407 :         case 1:
     441             :         {
     442             :                 GF_ImmediateDTE *dte;
     443       49407 :                 GF_SAFEALLOC(dte, GF_ImmediateDTE);
     444       49407 :                 if (dte) dte->source = 1;
     445             :                 return (GF_GenericDTE *)dte;
     446             :         }
     447       75697 :         case 2:
     448             :         {
     449             :                 GF_SampleDTE *dte;
     450       75697 :                 GF_SAFEALLOC(dte, GF_SampleDTE);
     451       75697 :                 if (!dte) return NULL;
     452       75697 :                 dte->source = 2;
     453             :                 //can be -1 in QT , so init at -2
     454       75697 :                 dte->trackRefIndex = (s8) -2;
     455       75697 :                 dte->samplesPerComp = 1;
     456       75697 :                 dte->bytesPerComp = 1;
     457       75697 :                 return (GF_GenericDTE *)dte;
     458             :         }
     459           0 :         case 3:
     460             :         {
     461             :                 GF_StreamDescDTE *dte;
     462           0 :                 GF_SAFEALLOC(dte, GF_StreamDescDTE);
     463           0 :                 if (!dte) return NULL;
     464           0 :                 dte->source = 3;
     465             :                 //can be -1 in QT , so init at -2
     466           0 :                 dte->trackRefIndex = (s8) -2;
     467           0 :                 return (GF_GenericDTE *)dte;
     468             :         }
     469             :         default:
     470             :                 return NULL;
     471             :         }
     472             : }
     473             : 
     474             : /********************************************************************
     475             :                 Deletion of DataTable entries in the RTP sample
     476             : ********************************************************************/
     477             : 
     478             : //deletion of DTEs
     479           0 : void DelDTE(GF_GenericDTE *dte)
     480             : {
     481      125104 :         switch (dte->source) {
     482      125104 :         case 0:
     483             :         case 1:
     484             :         case 2:
     485             :         case 3:
     486      125104 :                 gf_free(dte);
     487           0 :                 break;
     488             :         default:
     489             :                 return;
     490             :         }
     491             : }
     492             : 
     493             : 
     494             : 
     495             : /********************************************************************
     496             :                 Reading of DataTable entries in the RTP sample
     497             : ********************************************************************/
     498             : 
     499         770 : GF_Err ReadDTE(GF_GenericDTE *_dte, GF_BitStream *bs)
     500             : {
     501         770 :         switch (_dte->source) {
     502           0 :         case 0:
     503             :                 //empty but always 15 bytes !!!
     504           0 :                 gf_bs_skip_bytes(bs, 15);
     505           0 :                 return GF_OK;
     506         385 :         case 1:
     507             :         {
     508             :                 GF_ImmediateDTE *dte = (GF_ImmediateDTE *)_dte;
     509         385 :                 dte->dataLength = gf_bs_read_u8(bs);
     510         385 :                 if (dte->dataLength > 14) return GF_ISOM_INVALID_FILE;
     511         385 :                 gf_bs_read_data(bs, dte->data, dte->dataLength);
     512         385 :                 if (dte->dataLength < 14) gf_bs_skip_bytes(bs, 14 - dte->dataLength);
     513             :                 return GF_OK;
     514             :         }
     515         385 :         case 2:
     516             :         {
     517             :                 GF_SampleDTE *dte = (GF_SampleDTE *)_dte;
     518         385 :                 dte->trackRefIndex = (s8) gf_bs_read_u8(bs);
     519         385 :                 dte->dataLength = gf_bs_read_u16(bs);
     520         385 :                 dte->sampleNumber = gf_bs_read_u32(bs);
     521         385 :                 dte->byteOffset = gf_bs_read_u32(bs);
     522         385 :                 dte->bytesPerComp = gf_bs_read_u16(bs);
     523         385 :                 dte->samplesPerComp = gf_bs_read_u16(bs);
     524         385 :                 if (dte->bytesPerComp != 1) {
     525           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso] hint packet constructor with bytesperblock %d, not 1\n", dte->bytesPerComp));
     526             :                 }
     527         385 :                 if (dte->samplesPerComp != 1) {
     528           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso] hint packet constructor with samplesperblock %d, not 1\n", dte->bytesPerComp));
     529             :                 }
     530             :                 return GF_OK;
     531             :         }
     532           0 :         case 3:
     533             :         {
     534             :                 GF_StreamDescDTE *dte = (GF_StreamDescDTE *)_dte;
     535           0 :                 dte->trackRefIndex = gf_bs_read_u8(bs);
     536           0 :                 dte->dataLength = gf_bs_read_u16(bs);
     537           0 :                 dte->streamDescIndex = gf_bs_read_u32(bs);
     538           0 :                 dte->byteOffset = gf_bs_read_u32(bs);
     539           0 :                 dte->reserved = gf_bs_read_u32(bs);
     540           0 :                 return GF_OK;
     541             :         }
     542             :         default:
     543             :                 return GF_ISOM_INVALID_FILE;
     544             :         }
     545             : }
     546             : 
     547             : /********************************************************************
     548             :                 Writing of DataTable entries in the RTP sample
     549             : ********************************************************************/
     550             : 
     551             : 
     552      124334 : GF_Err WriteDTE(GF_GenericDTE *_dte, GF_BitStream *bs)
     553             : {
     554      124334 :         switch (_dte->source) {
     555           0 :         case 0:
     556             :         {
     557             :                 GF_EmptyDTE *dte = (GF_EmptyDTE *)_dte;
     558           0 :                 gf_bs_write_u8(bs, dte->source);
     559             :                 //empty but always 15 bytes !!!
     560           0 :                 gf_bs_write_data(bs, "empty hint DTE", 15);
     561           0 :                 return GF_OK;
     562             :         }
     563       49022 :         case 1:
     564             :         {
     565             :                 GF_ImmediateDTE *dte = (GF_ImmediateDTE *)_dte;
     566       49022 :                 gf_bs_write_u8(bs, dte->source);
     567       49022 :                 gf_bs_write_u8(bs, dte->dataLength);
     568       49022 :                 gf_bs_write_data(bs, dte->data, dte->dataLength);
     569       49022 :                 if (dte->dataLength < 14) {
     570             :                         char data[14];
     571             :                         memset(data, 0, 14);
     572       48965 :                         gf_bs_write_data(bs, data, 14 - dte->dataLength);
     573             :                 }
     574             :                 return GF_OK;
     575             :         }
     576       75312 :         case 2:
     577             :         {
     578             :                 GF_SampleDTE *dte = (GF_SampleDTE *)_dte;
     579       75312 :                 gf_bs_write_u8(bs, dte->source);
     580       75312 :                 gf_bs_write_u8(bs, dte->trackRefIndex);
     581       75312 :                 gf_bs_write_u16(bs, dte->dataLength);
     582       75312 :                 gf_bs_write_u32(bs, dte->sampleNumber);
     583       75312 :                 gf_bs_write_u32(bs, dte->byteOffset);
     584       75312 :                 gf_bs_write_u16(bs, dte->bytesPerComp);
     585       75312 :                 gf_bs_write_u16(bs, dte->samplesPerComp);
     586       75312 :                 return GF_OK;
     587             :         }
     588           0 :         case 3:
     589             :         {
     590             :                 GF_StreamDescDTE *dte = (GF_StreamDescDTE *)_dte;
     591           0 :                 gf_bs_write_u8(bs, dte->source);
     592             : 
     593           0 :                 gf_bs_write_u8(bs, dte->trackRefIndex);
     594           0 :                 gf_bs_write_u16(bs, dte->dataLength);
     595           0 :                 gf_bs_write_u32(bs, dte->streamDescIndex);
     596           0 :                 gf_bs_write_u32(bs, dte->byteOffset);
     597           0 :                 gf_bs_write_u32(bs, dte->reserved);
     598           0 :                 return GF_OK;
     599             :         }
     600             :         default:
     601             :                 return GF_ISOM_INVALID_FILE;
     602             :         }
     603             : }
     604             : 
     605           0 : GF_Err OffsetDTE(GF_GenericDTE *dte, u32 offset, u32 HintSampleNumber)
     606             : {
     607             :         GF_SampleDTE *sDTE;
     608             :         //offset shifting is only true for intra sample reference
     609         911 :         switch (dte->source) {
     610             :         case 2:
     611             :                 break;
     612             :         default:
     613             :                 return GF_OK;
     614             :         }
     615             : 
     616             :         sDTE = (GF_SampleDTE *)dte;
     617             :         //we only adjust for intra HintTrack reference
     618         911 :         if (sDTE->trackRefIndex != (s8) -1) return GF_OK;
     619             :         //and in the same sample
     620          83 :         if (sDTE->sampleNumber != HintSampleNumber) return GF_OK;
     621          83 :         sDTE->byteOffset += offset;
     622           0 :         return GF_OK;
     623             : }
     624             : 
     625       68522 : GF_RTPPacket *gf_isom_hint_rtp_new()
     626             : {
     627             :         GF_RTPPacket *tmp;
     628       68522 :         GF_SAFEALLOC(tmp, GF_RTPPacket);
     629       68522 :         if (!tmp) return NULL;
     630       68522 :         tmp->TLV = gf_list_new();
     631       68522 :         tmp->DataTable = gf_list_new();
     632       68522 :         return tmp;
     633             : }
     634             : 
     635       68522 : void gf_isom_hint_rtp_del(GF_RTPPacket *ptr)
     636             : {
     637             :         //the DTE
     638      262148 :         while (gf_list_count(ptr->DataTable)) {
     639      125104 :                 GF_GenericDTE *p = (GF_GenericDTE *)gf_list_get(ptr->DataTable, 0);
     640             :                 DelDTE(p);
     641      125104 :                 gf_list_rem(ptr->DataTable, 0);
     642             :         }
     643       68522 :         gf_list_del(ptr->DataTable);
     644             :         //the TLV
     645       68522 :         gf_isom_box_array_del(ptr->TLV);
     646       68522 :         gf_free(ptr);
     647       68522 : }
     648             : 
     649         385 : GF_Err gf_isom_hint_rtp_read(GF_RTPPacket *ptr, GF_BitStream *bs)
     650             : {
     651             :         GF_Err e;
     652             :         u8 hasTLV, type;
     653             :         u16 i, count;
     654             :         u32 TLVsize, tempSize;
     655             :         GF_Box *a;
     656             : 
     657         385 :         ptr->relativeTransTime = gf_bs_read_u32(bs);
     658             :         //RTP Header
     659             :         //1- reserved fields
     660         385 :         gf_bs_read_int(bs, 2);
     661         385 :         ptr->P_bit = gf_bs_read_int(bs, 1);
     662         385 :         ptr->X_bit = gf_bs_read_int(bs, 1);
     663         385 :         gf_bs_read_int(bs, 4);
     664         385 :         ptr->M_bit = gf_bs_read_int(bs, 1);
     665         385 :         ptr->payloadType = gf_bs_read_int(bs, 7);
     666             : 
     667         385 :         ptr->SequenceNumber = gf_bs_read_u16(bs);
     668         385 :         gf_bs_read_int(bs, 13);
     669         385 :         hasTLV = gf_bs_read_int(bs, 1);
     670         385 :         ptr->B_bit = gf_bs_read_int(bs, 1);
     671         385 :         ptr->R_bit = gf_bs_read_int(bs, 1);
     672         385 :         count = gf_bs_read_u16(bs);
     673             : 
     674             :         //read the TLV
     675         385 :         if (hasTLV) {
     676             :                 tempSize = 4;   //TLVsize includes its field length
     677           0 :                 TLVsize = gf_bs_read_u32(bs);
     678           0 :                 while (tempSize < TLVsize) {
     679           0 :                         e = gf_isom_box_parse(&a, bs);
     680           0 :                         if (e) return e;
     681           0 :                         gf_list_add(ptr->TLV, a);
     682           0 :                         tempSize += (u32) a->size;
     683             :                 }
     684           0 :                 if (tempSize != TLVsize) return GF_ISOM_INVALID_FILE;
     685             :         }
     686             : 
     687             :         //read the DTEs
     688         770 :         for (i=0; i<count; i++) {
     689             :                 GF_GenericDTE *dte;
     690             :                 Bool add_it = 0;
     691         770 :                 type = gf_bs_read_u8(bs);
     692         770 :                 dte = NewDTE(type);
     693         770 :                 if (!dte) {
     694           0 :                         GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso] invalid DTE code %d in hint sample %d of trackID %d\n", type, ptr->sampleNumber, ptr->trackID));
     695             :                         return GF_ISOM_INVALID_FILE;
     696             :                 }
     697         770 :                 e = ReadDTE(dte, bs);
     698         770 :                 if (e) return e;
     699             :                 /*little opt, remove empty dte*/
     700         770 :                 switch (type) {
     701         385 :                 case 1:
     702         385 :                         if ( ((GF_ImmediateDTE *)dte)->dataLength) add_it = 1;
     703             :                         break;
     704         385 :                 case 2:
     705         385 :                         if ( ((GF_SampleDTE *)dte)->dataLength) add_it = 1;
     706             :                         break;
     707           0 :                 case 3:
     708           0 :                         if ( ((GF_StreamDescDTE *)dte)->dataLength) add_it = 1;
     709             :                         break;
     710             :                 }
     711             :                 if (add_it)
     712         770 :                         gf_list_add(ptr->DataTable, dte);
     713             :                 else
     714             :                         DelDTE(dte);
     715             :         }
     716             :         return GF_OK;
     717             : }
     718             : 
     719         159 : GF_Err gf_isom_hint_rtp_offset(GF_RTPPacket *ptr, u32 offset, u32 HintSampleNumber)
     720             : {
     721             :         u32 count, i;
     722             :         GF_Err e;
     723             : 
     724         159 :         count = gf_list_count(ptr->DataTable);
     725        1070 :         for (i=0; i<count; i++) {
     726         911 :                 GF_GenericDTE *dte = (GF_GenericDTE *)gf_list_get(ptr->DataTable, i);
     727             :                 e = OffsetDTE(dte, offset, HintSampleNumber);
     728             :                 if (e) return e;
     729             :         }
     730             :         return GF_OK;
     731             : }
     732             : 
     733             : //Gets the REAL size of the packet once rebuild, but without CSRC fields in the
     734             : //header
     735       68522 : u32 gf_isom_hint_rtp_length(GF_RTPPacket *ptr)
     736             : {
     737             :         u32 size, count, i;
     738             : 
     739             :         //64 bit header
     740             :         size = 8;
     741             :         //32 bit SSRC
     742             :         size += 4;
     743       68522 :         count = gf_list_count(ptr->DataTable);
     744      193626 :         for (i=0; i<count; i++) {
     745      125104 :                 GF_GenericDTE *dte = (GF_GenericDTE *)gf_list_get(ptr->DataTable, i);
     746      125104 :                 switch (dte->source) {
     747             :                 case 0:
     748             :                         break;
     749       49407 :                 case 1:
     750       49407 :                         size += ((GF_ImmediateDTE *)dte)->dataLength;
     751       49407 :                         break;
     752       75697 :                 case 2:
     753       75697 :                         size += ((GF_SampleDTE *)dte)->dataLength;
     754       75697 :                         break;
     755           0 :                 case 3:
     756           0 :                         size += ((GF_StreamDescDTE *)dte)->dataLength;
     757           0 :                         break;
     758             :                 }
     759             :         }
     760       68522 :         return size;
     761             : }
     762             : 
     763             : 
     764             : #ifndef GPAC_DISABLE_ISOM_WRITE
     765             : 
     766       68137 : u32 gf_isom_hint_rtp_size(GF_RTPPacket *ptr)
     767             : {
     768             :         GF_Box none;
     769             :         u32 size, count;
     770             :         //the RTP Header size and co
     771             :         size = 12;
     772             :         //the extra table size
     773       68137 :         count = gf_list_count(ptr->TLV);
     774       68137 :         if (count) {
     775        9737 :                 none.size = 4;  //WE INCLUDE THE SIZE FIELD LENGTH
     776        9737 :                 none.type = 0;
     777             :                 //REMEMBER THAT TLV ENTRIES ARE 4-BYTES ALIGNED !!!
     778        9737 :                 gf_isom_box_array_size(&none, ptr->TLV);
     779        9737 :                 size += (u32) none.size;
     780             :         }
     781             :         //the DTE (each entry is 16 bytes)
     782       68137 :         count = gf_list_count(ptr->DataTable);
     783       68137 :         size += count * 16;
     784       68137 :         return size;
     785             : }
     786             : 
     787       68137 : GF_Err gf_isom_hint_rtp_write(GF_RTPPacket *ptr, GF_BitStream *bs)
     788             : {
     789             :         GF_Err e;
     790             :         u32 TLVcount, DTEcount, i;
     791             :         GF_Box none;
     792             : 
     793       68137 :         gf_bs_write_u32(bs, ptr->relativeTransTime);
     794             :         //RTP Header
     795             : //      gf_bs_write_int(bs, 2, 2);
     796             :         //version is 2
     797       68137 :         gf_bs_write_int(bs, 2, 2);
     798       68137 :         gf_bs_write_int(bs, ptr->P_bit, 1);
     799       68137 :         gf_bs_write_int(bs, ptr->X_bit, 1);
     800       68137 :         gf_bs_write_int(bs, 0, 4);
     801       68137 :         gf_bs_write_int(bs, ptr->M_bit, 1);
     802       68137 :         gf_bs_write_int(bs, ptr->payloadType, 7);
     803             : 
     804       68137 :         gf_bs_write_u16(bs, ptr->SequenceNumber);
     805       68137 :         gf_bs_write_int(bs, 0, 13);
     806       68137 :         TLVcount = gf_list_count(ptr->TLV);
     807       68137 :         DTEcount = gf_list_count(ptr->DataTable);
     808       68137 :         gf_bs_write_int(bs, TLVcount ? 1 : 0, 1);
     809       68137 :         gf_bs_write_int(bs, ptr->B_bit, 1);
     810       68137 :         gf_bs_write_int(bs, ptr->R_bit, 1);
     811             : 
     812       68137 :         gf_bs_write_u16(bs, DTEcount);
     813             : 
     814       68137 :         if (TLVcount) {
     815             :                 //first write the size of the table ...
     816        9737 :                 none.size = 4;  //WE INCLUDE THE SIZE FIELD LENGTH
     817        9737 :                 none.type = 0;
     818        9737 :                 gf_isom_box_array_size(&none, ptr->TLV);
     819        9737 :                 gf_bs_write_u32(bs, (u32) none.size);
     820        9737 :                 e = gf_isom_box_array_write(&none, ptr->TLV, bs);
     821        9737 :                 if (e) return e;
     822             :         }
     823             :         //write the DTE...
     824      124334 :         for (i = 0; i < DTEcount; i++) {
     825      124334 :                 GF_GenericDTE *dte = (GF_GenericDTE *)gf_list_get(ptr->DataTable, i);
     826      124334 :                 e = WriteDTE(dte, bs);
     827      124334 :                 if (e) return e;
     828             :         }
     829             :         return GF_OK;
     830             : }
     831             : 
     832             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     833             : 
     834             : 
     835             : 
     836           1 : GF_RTCPPacket *gf_isom_hint_rtcp_new()
     837             : {
     838             :         GF_RTCPPacket *tmp;
     839           1 :         GF_SAFEALLOC(tmp, GF_RTCPPacket);
     840           1 :         return tmp;
     841             : }
     842             : 
     843           1 : void gf_isom_hint_rtcp_del(GF_RTCPPacket *ptr)
     844             : {
     845           1 :         if(ptr->data) gf_free(ptr->data);
     846           1 :         gf_free(ptr);
     847           1 : }
     848             : 
     849           1 : GF_Err gf_isom_hint_rtcp_read(GF_RTCPPacket *ptr, GF_BitStream *bs)
     850             : {
     851             :         //RTCP Header
     852             : 
     853           1 :         ptr->Version = gf_bs_read_int(bs, 2);
     854           1 :         ptr->Padding = gf_bs_read_int(bs, 1);
     855           1 :         ptr->Count = gf_bs_read_int(bs, 5);
     856           1 :         ptr->PayloadType = gf_bs_read_u8(bs);
     857           1 :         ptr->length = 4 * gf_bs_read_u16(bs);
     858           1 :         if (ptr->length<4) return GF_ISOM_INVALID_MEDIA;
     859             : 
     860             :         //remove header size
     861           0 :         if (gf_bs_available(bs) < ptr->length) {
     862           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[iso] RTCP hint packet has more data (%d) than available\n", ptr->length ));
     863             :                 return GF_ISOM_INVALID_MEDIA;
     864             :         }
     865           0 :         ptr->data = gf_malloc(sizeof(char) * ptr->length);
     866           0 :         if (!ptr->data) return GF_OUT_OF_MEM;
     867           0 :         gf_bs_read_data(bs, ptr->data, ptr->length);
     868           0 :         return GF_OK;
     869             : }
     870             : 
     871             : 
     872             : //Gets the REAL size of the packet once rebuild, but without CSRC fields in the
     873             : //header
     874           0 : u32 gf_isom_hint_rtcp_length(GF_RTCPPacket *ptr)
     875             : {
     876           1 :         return 4 * (ptr->length + 1);
     877             : }
     878             : 
     879             : 
     880             : #ifndef GPAC_DISABLE_ISOM_WRITE
     881             : 
     882           0 : u32 gf_isom_hint_rtcp_size(GF_RTCPPacket *ptr)
     883             : {
     884           1 :         return 4 * (ptr->length + 1);
     885             : }
     886             : 
     887           1 : GF_Err gf_isom_hint_rtcp_write(GF_RTCPPacket *ptr, GF_BitStream *bs)
     888             : {
     889             :         //RTP Header
     890           1 :         gf_bs_write_int(bs, ptr->Version, 2);
     891           1 :         gf_bs_write_int(bs, ptr->Padding, 1);
     892           1 :         gf_bs_write_int(bs, ptr->Count, 5);
     893           1 :         gf_bs_write_u8(bs, ptr->PayloadType);
     894           1 :         gf_bs_write_u16(bs, 4*ptr->length);
     895           1 :         gf_bs_write_data(bs, ptr->data, ptr->length);
     896           1 :         return GF_OK;
     897             : }
     898             : 
     899             : #endif /*GPAC_DISABLE_ISOM_WRITE*/
     900             : 
     901             : 
     902             : 
     903             : #if 0 //unused
     904             : 
     905             : /*small hint reader - performs data caching*/
     906             : 
     907             : /*resets hint reading parameters, returns an error if the hint type is not supported for reading
     908             : packet sequence number is always reseted to 0
     909             : @sample_start: indicates from where the packets should be read (regular 1-based sample number)
     910             : @ts_offset: constant offset for timestamps, must be expressed in media timescale (which is the hint timescale).
     911             :         usually 0 (no offset)
     912             : @sn_offset: offset for packet sequence number (first packet will have a SN of 1 + sn_offset)
     913             :         usually 0
     914             : @ssrc: sync source identifier for RTP
     915             : */
     916             : 
     917             : GF_Err gf_isom_reset_hint_reader(GF_ISOFile *the_file, u32 trackNumber, u32 sample_start, u32 ts_offset, u32 sn_offset, u32 ssrc)
     918             : {
     919             :         GF_Err e;
     920             :         GF_TrackBox *trak;
     921             :         GF_HintSampleEntryBox *entry;
     922             : 
     923             :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
     924             :         if (!trak) return GF_BAD_PARAM;
     925             : 
     926             :         if (!sample_start) return GF_BAD_PARAM;
     927             :         if (sample_start>=trak->Media->information->sampleTable->SampleSize->sampleCount) return GF_BAD_PARAM;
     928             : 
     929             :         e = Media_GetSampleDesc(trak->Media, 1, (GF_SampleEntryBox **) &entry, NULL);
     930             :         if (e) return e;
     931             :         switch (entry->type) {
     932             :         case GF_ISOM_BOX_TYPE_RTP_STSD:
     933             :         case GF_ISOM_BOX_TYPE_SRTP_STSD:
     934             :         case GF_ISOM_BOX_TYPE_RRTP_STSD:
     935             :                 break;
     936             :         default:
     937             :                 return GF_NOT_SUPPORTED;
     938             :         }
     939             : 
     940             :         entry->hint_ref = NULL;
     941             :         e = Track_FindRef(trak, GF_ISOM_REF_HINT, &entry->hint_ref);
     942             :         if (e) return e;
     943             : 
     944             :         entry->cur_sample = sample_start;
     945             :         entry->pck_sn = 1 + sn_offset;
     946             :         entry->ssrc = ssrc;
     947             :         entry->ts_offset = ts_offset;
     948             :         if (entry->hint_sample) gf_isom_hint_sample_del(entry->hint_sample);
     949             :         entry->hint_sample = NULL;
     950             :         return GF_OK;
     951             : }
     952             : 
     953             : static GF_Err gf_isom_load_next_hint_sample(GF_ISOFile *the_file, u32 trackNumber, GF_TrackBox *trak, GF_HintSampleEntryBox *entry)
     954             : {
     955             :         GF_BitStream *bs;
     956             :         u32 descIdx;
     957             :         GF_ISOSample *samp;
     958             : 
     959             :         if (!entry->cur_sample) return GF_BAD_PARAM;
     960             :         if (entry->cur_sample>trak->Media->information->sampleTable->SampleSize->sampleCount) return GF_EOS;
     961             : 
     962             :         samp = gf_isom_get_sample(the_file, trackNumber, entry->cur_sample, &descIdx);
     963             :         if (!samp) return GF_IO_ERR;
     964             :         entry->cur_sample++;
     965             : 
     966             :         if (entry->hint_sample) gf_isom_hint_sample_del(entry->hint_sample);
     967             : 
     968             :         bs = gf_bs_new(samp->data, samp->dataLength, GF_BITSTREAM_READ);
     969             :         entry->hint_sample = gf_isom_hint_sample_new(entry->type);
     970             :         gf_isom_hint_sample_read(entry->hint_sample, bs, samp->dataLength);
     971             :         gf_bs_del(bs);
     972             :         entry->hint_sample->TransmissionTime = samp->DTS;
     973             :         gf_isom_sample_del(&samp);
     974             :         entry->hint_sample->sample_cache = gf_list_new();
     975             :         return GF_OK;
     976             : }
     977             : 
     978             : static GF_ISOSample *gf_isom_get_data_sample(GF_HintSample *hsamp, GF_TrackBox *trak, u32 sample_num)
     979             : {
     980             :         GF_ISOSample *samp;
     981             :         GF_HintDataCache *hdc;
     982             :         u32 i, count;
     983             :         count = gf_list_count(hsamp->sample_cache);
     984             :         for (i=0; i<count; i++) {
     985             :                 hdc = (GF_HintDataCache *)gf_list_get(hsamp->sample_cache, i);
     986             :                 if ((hdc->sample_num==sample_num) && (hdc->trak==trak)) return hdc->samp;
     987             :         }
     988             : 
     989             :         samp = gf_isom_sample_new();
     990             :         Media_GetSample(trak->Media, sample_num, &samp, &i, 0, NULL);
     991             :         if (!samp) return NULL;
     992             :         GF_SAFEALLOC(hdc, GF_HintDataCache);
     993             :         if (!hdc) return NULL;
     994             :         hdc->samp = samp;
     995             :         hdc->sample_num = sample_num;
     996             :         hdc->trak = trak;
     997             :         /*we insert all new samples, since they're more likely to be fetched next (except for audio
     998             :         interleaving and other multiplex)*/
     999             :         gf_list_insert(hsamp->sample_cache, hdc, 0);
    1000             :         return samp;
    1001             : }
    1002             : 
    1003             : /*reads next hint packet. ALl packets are read in transmission (decoding) order
    1004             : returns an error if not supported, or GF_EOS when no more packets are available
    1005             : currently only RTP reader is supported
    1006             : @pck_data, @pck_size: output packet data (must be freed by caller) - contains all info to be sent
    1007             :         on the wire, eg for RTP contains the RTP header and the data
    1008             : @disposable (optional): indicates that the packet can be dropped when late (B-frames & co)
    1009             : @repeated (optional): indicates this is a repeated packet (same one has already been sent)
    1010             : @trans_ts (optional): indicates the transmission time of the packet, expressed in hint timescale, taking into account
    1011             : the ts_offset specified in gf_isom_reset_hint_reader. Depending on packets this may not be the same
    1012             : as the hint sample timestamp + ts_offset, some packets may need to be sent earlier (B-frames)
    1013             : @sample_num (optional): indicates hint sample number the packet belongs to
    1014             : */
    1015             : GF_Err gf_isom_next_hint_packet(GF_ISOFile *the_file, u32 trackNumber, char **pck_data, u32 *pck_size, Bool *disposable, Bool *repeated, u32 *trans_ts, u32 *sample_num)
    1016             : {
    1017             :         GF_RTPPacket *pck;
    1018             :         GF_Err e;
    1019             :         GF_BitStream *bs;
    1020             :         GF_TrackBox *trak, *ref_trak;
    1021             :         GF_HintSampleEntryBox *entry;
    1022             :         u32 i, count, ts;
    1023             :         s32 cts_off;
    1024             : 
    1025             :         *pck_data = NULL;
    1026             :         *pck_size = 0;
    1027             :         if (trans_ts) *trans_ts = 0;
    1028             :         if (disposable) *disposable = 0;
    1029             :         if (repeated) *repeated = 0;
    1030             :         if (sample_num) *sample_num = 0;
    1031             : 
    1032             :         trak = gf_isom_get_track_from_file(the_file, trackNumber);
    1033             :         if (!trak) return GF_BAD_PARAM;
    1034             :         e = Media_GetSampleDesc(trak->Media, 1, (GF_SampleEntryBox **) &entry, NULL);
    1035             :         if (e) return e;
    1036             :         switch (entry->type) {
    1037             :         case GF_ISOM_BOX_TYPE_RTP_STSD:
    1038             :         case GF_ISOM_BOX_TYPE_SRTP_STSD:
    1039             :         case GF_ISOM_BOX_TYPE_RRTP_STSD:
    1040             :                 break;
    1041             :         default:
    1042             :                 return GF_NOT_SUPPORTED;
    1043             :         }
    1044             : 
    1045             :         if (!entry->hint_sample) {
    1046             :                 e = gf_isom_load_next_hint_sample(the_file, trackNumber, trak, entry);
    1047             :                 if (e) return e;
    1048             :         }
    1049             :         pck = (GF_RTPPacket *)gf_list_get(entry->hint_sample->packetTable, 0);
    1050             :         gf_list_rem(entry->hint_sample->packetTable, 0);
    1051             :         if (!pck) return GF_BAD_PARAM;
    1052             : 
    1053             :         bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
    1054             :         /*write RTP header*/
    1055             :         gf_bs_write_int(bs, 2, 2);      /*version*/
    1056             :         gf_bs_write_int(bs, pck->P_bit, 1);  /*P bit*/
    1057             :         gf_bs_write_int(bs, pck->X_bit, 1);  /*X bit*/
    1058             :         gf_bs_write_int(bs, 0, 4);      /*CSRC count*/
    1059             :         gf_bs_write_int(bs, pck->M_bit, 1);  /*M bit*/
    1060             :         gf_bs_write_int(bs, pck->payloadType, 7);    /*payt*/
    1061             :         gf_bs_write_u16(bs, entry->pck_sn);  /*seq num*/
    1062             :         entry->pck_sn++;
    1063             : 
    1064             :         /*look for CTS offset in TLV*/
    1065             :         cts_off = 0;
    1066             :         count = gf_list_count(pck->TLV);
    1067             :         for (i=0; i<count; i++) {
    1068             :                 GF_RTPOBox *rtpo = (GF_RTPOBox *)gf_list_get(pck->TLV, i);
    1069             :                 if (rtpo->type == GF_ISOM_BOX_TYPE_RTPO) {
    1070             :                         cts_off = rtpo->timeOffset;
    1071             :                         break;
    1072             :                 }
    1073             :         }
    1074             :         /*TS - TODO check TS wrapping*/
    1075             :         ts = (u32) (entry->hint_sample->TransmissionTime + pck->relativeTransTime + entry->ts_offset + cts_off);
    1076             :         gf_bs_write_u32(bs, ts );
    1077             :         gf_bs_write_u32(bs, entry->ssrc);    /*SSRC*/
    1078             : 
    1079             :         /*then build all data*/
    1080             :         count = gf_list_count(pck->DataTable);
    1081             :         for (i=0; i<count; i++) {
    1082             :                 GF_GenericDTE *dte = (GF_GenericDTE *)gf_list_get(pck->DataTable, i);
    1083             :                 switch (dte->source) {
    1084             :                 /*empty*/
    1085             :                 case 0:
    1086             :                         break;
    1087             :                 /*immediate data*/
    1088             :                 case 1:
    1089             :                         gf_bs_write_data(bs, ((GF_ImmediateDTE *)dte)->data, ((GF_ImmediateDTE *)dte)->dataLength);
    1090             :                         break;
    1091             :                 /*sample data*/
    1092             :                 case 2:
    1093             :                 {
    1094             :                         GF_ISOSample *samp;
    1095             :                         GF_SampleDTE *sdte = (GF_SampleDTE *)dte;
    1096             :                         /*get track if not this one*/
    1097             :                         if (sdte->trackRefIndex != (s8) -1) {
    1098             :                                 if (!entry->hint_ref || !entry->hint_ref->trackIDs) {
    1099             :                                         gf_isom_hint_rtp_del(pck);
    1100             :                                         gf_bs_del(bs);
    1101             :                                         return GF_ISOM_INVALID_FILE;
    1102             :                                 }
    1103             :                                 ref_trak = gf_isom_get_track_from_id(trak->moov, entry->hint_ref->trackIDs[(u32)sdte->trackRefIndex]);
    1104             :                         } else {
    1105             :                                 ref_trak = trak;
    1106             :                         }
    1107             :                         samp = gf_isom_get_data_sample(entry->hint_sample, ref_trak, sdte->sampleNumber);
    1108             :                         if (!samp) {
    1109             :                                 gf_isom_hint_rtp_del(pck);
    1110             :                                 gf_bs_del(bs);
    1111             :                                 return GF_IO_ERR;
    1112             :                         }
    1113             :                         gf_bs_write_data(bs, samp->data + sdte->byteOffset, sdte->dataLength);
    1114             :                 }
    1115             :                 break;
    1116             :                 /*sample desc data - currently NOT SUPPORTED !!!*/
    1117             :                 case 3:
    1118             :                         break;
    1119             :                 }
    1120             :         }
    1121             :         if (trans_ts) *trans_ts = ts;
    1122             :         if (disposable) *disposable = pck->B_bit;
    1123             :         if (repeated) *repeated = pck->R_bit;
    1124             :         if (sample_num) *sample_num = entry->cur_sample-1;
    1125             : 
    1126             :         gf_bs_get_content(bs, pck_data, pck_size);
    1127             :         gf_bs_del(bs);
    1128             :         gf_isom_hint_rtp_del(pck);
    1129             :         if (!gf_list_count(entry->hint_sample->packetTable)) {
    1130             :                 gf_isom_hint_sample_del(entry->hint_sample);
    1131             :                 entry->hint_sample = NULL;
    1132             :         }
    1133             :         return GF_OK;
    1134             : }
    1135             : 
    1136             : #endif
    1137             : 
    1138             : 
    1139             : #endif /* !defined(GPAC_DISABLE_ISOM) && !defined(GPAC_DISABLE_ISOM_HINTING)*/

Generated by: LCOV version 1.13