LCOV - code coverage report
Current view: top level - filters - isoffin_read_ch.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 311 441 70.5 %
Date: 2021-04-29 23:48:07 Functions: 10 10 100.0 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2021
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / ISOBMFF reader filter
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : 
      27             : #include "isoffin.h"
      28             : 
      29             : #ifndef GPAC_DISABLE_ISOM
      30             : #include <gpac/network.h>
      31             : #include <gpac/avparse.h>
      32             : 
      33             : 
      34        2676 : void isor_reset_reader(ISOMChannel *ch)
      35             : {
      36        2676 :         ch->last_state = GF_OK;
      37             :         isor_reader_release_sample(ch);
      38             : 
      39        2676 :         if (ch->static_sample) {
      40        1190 :                 ch->static_sample->dataLength = ch->static_sample->alloc_size;
      41        1190 :                 gf_isom_sample_del(&ch->static_sample);
      42             :         }
      43        2676 :         ch->sample = NULL;
      44        2676 :         ch->sample_num = 0;
      45        2676 :         ch->speed = 1.0;
      46        2676 :         ch->start = ch->end = 0;
      47        2676 :         ch->to_init = 1;
      48        2676 :         ch->playing = GF_FALSE;
      49        2676 :         if (ch->sai_buffer) gf_free(ch->sai_buffer);
      50        2676 :         ch->sai_buffer = NULL;
      51        2676 :         ch->sai_alloc_size = 0;
      52        2676 :         ch->dts = ch->cts = 0;
      53        2676 :         ch->seek_flag = 0;
      54        2676 : }
      55             : 
      56        6379 : void isor_check_producer_ref_time(ISOMReader *read)
      57             : {
      58             :         GF_ISOTrackID trackID;
      59             :         u64 ntp;
      60             :         u64 timestamp;
      61             : 
      62        6379 :         if (gf_sys_is_test_mode()) {
      63        6110 :                 return;
      64             :         }
      65             : 
      66         269 :         if (gf_isom_get_last_producer_time_box(read->mov, &trackID, &ntp, &timestamp, GF_TRUE)) {
      67             : #if !defined(_WIN32_WCE) && !defined(GPAC_DISABLE_LOG)
      68             : 
      69           0 :                 if (gf_log_tool_level_on(GF_LOG_DASH, GF_LOG_DEBUG)) {
      70             :                         time_t secs;
      71             :                         struct tm t;
      72             : 
      73           0 :                         s32 diff = gf_net_get_ntp_diff_ms(ntp);
      74             : 
      75           0 :                         secs = (ntp>>32) - GF_NTP_SEC_1900_TO_1970;
      76           0 :                         t = *gf_gmtime(&secs);
      77             : 
      78           0 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] TrackID %d: Timestamp "LLU" matches sender NTP time %d-%02d-%02dT%02d:%02d:%02dZ - NTP clock diff (local - remote): %d ms\n", trackID, timestamp, 1900+t.tm_year, t.tm_mon+1, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec, diff));
      79             :                 }
      80             : #endif
      81           0 :                 read->last_sender_ntp = ntp;
      82           0 :                 read->cts_for_last_sender_ntp = timestamp;
      83           0 :                 read->ntp_at_last_sender_ntp = gf_net_get_ntp_ts();
      84             :         }
      85             : }
      86             : 
      87             : 
      88        1185 : static void init_reader(ISOMChannel *ch)
      89             : {
      90        1185 :         u32 sample_desc_index=0;
      91             : 
      92        1185 :         ch->au_seq_num = 1;
      93             : 
      94             :         assert(ch->sample==NULL);
      95        1185 :         if (!ch->static_sample) {
      96        1144 :                 ch->static_sample = gf_isom_sample_new();
      97             :         }
      98             : 
      99        1185 :         if (ch->streamType==GF_STREAM_OCR) {
     100             :                 assert(!ch->sample);
     101           0 :                 ch->sample = gf_isom_sample_new();
     102           0 :                 ch->sample->IsRAP = RAP;
     103           0 :                 ch->sample->DTS = ch->start;
     104           0 :                 ch->last_state=GF_OK;
     105        1185 :         } else if (ch->sample_num) {
     106          10 :                 ch->sample = gf_isom_get_sample_ex(ch->owner->mov, ch->track, ch->sample_num, &sample_desc_index, ch->static_sample, &ch->sample_data_offset);
     107          10 :                 ch->disable_seek = GF_TRUE;
     108          10 :                 ch->au_seq_num = ch->sample_num;
     109             :         } else {
     110             :                 //if seek is disabled, get the next closest sample for this time; otherwise, get the previous RAP sample for this time
     111        1175 :                 u32 mode = ch->disable_seek ? GF_ISOM_SEARCH_BACKWARD : GF_ISOM_SEARCH_SYNC_BACKWARD;
     112             : 
     113             :                 /*take care of seeking out of the track range*/
     114        1175 :                 if (!ch->owner->frag_type && (ch->duration<=ch->start)) {
     115          10 :                         ch->last_state = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->duration-1, &sample_desc_index, mode, &ch->static_sample, &ch->sample_num, &ch->sample_data_offset);
     116        1165 :                 } else if (ch->start || ch->has_edit_list) {
     117          50 :                         ch->last_state = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->start, &sample_desc_index, mode, &ch->static_sample, &ch->sample_num, &ch->sample_data_offset);
     118             :                 } else {
     119        1115 :                         ch->sample_num = 1;
     120        1115 :                         if (ch->owner->nodata) {
     121           0 :                                 ch->sample = gf_isom_get_sample_info_ex(ch->owner->mov, ch->track, ch->sample_num, &sample_desc_index, &ch->sample_data_offset, ch->static_sample);
     122             :                         } else {
     123        1115 :                                 ch->sample = gf_isom_get_sample_ex(ch->owner->mov, ch->track, ch->sample_num, &sample_desc_index, ch->static_sample, &ch->sample_data_offset);
     124             :                         }
     125        1115 :                         if (!ch->sample) ch->last_state = GF_EOS;
     126             :                 }
     127        1175 :                 if (ch->last_state) {
     128         287 :                         ch->sample = NULL;
     129         287 :                         ch->last_state = GF_OK;
     130             :                 } else {
     131         888 :                         ch->sample = ch->static_sample;
     132             :                 }
     133             : 
     134        1175 :                 if (ch->has_rap && ch->has_edit_list) {
     135           0 :                         ch->edit_sync_frame = ch->sample_num;
     136             :                 }
     137             : 
     138        1175 :                 if (ch->sample && !ch->sample->data && ch->owner->frag_type && !ch->has_edit_list) {
     139           0 :                         ch->sample = NULL;
     140           0 :                         ch->sample_num = 1;
     141           0 :                         ch->sample = gf_isom_get_sample_ex(ch->owner->mov, ch->track, ch->sample_num, &sample_desc_index, ch->static_sample, &ch->sample_data_offset);
     142             :                 }
     143             :         }
     144             : 
     145             : 
     146             :         /*no sample means we're not in the track range - stop*/
     147        1185 :         if (!ch->sample) {
     148             :                 /*incomplete file - check if we're still downloading or not*/
     149         287 :                 if (gf_isom_get_missing_bytes(ch->owner->mov, ch->track)) {
     150          28 :                         if (!ch->owner->input_loaded) {
     151          20 :                                 ch->last_state = GF_OK;
     152         307 :                                 return;
     153             :                         }
     154           8 :                         ch->last_state = GF_ISOM_INCOMPLETE_FILE;
     155         259 :                 } else if (ch->sample_num) {
     156         246 :                         ch->last_state = (ch->owner->frag_type==1) ? GF_OK : GF_EOS;
     157         246 :                         ch->to_init = 0;
     158             :                 }
     159             :                 return;
     160             :         }
     161             : 
     162         898 :         ch->sample_time = ch->sample->DTS;
     163             : 
     164         898 :         ch->to_init = GF_FALSE;
     165             : 
     166         898 :         ch->seek_flag = 0;
     167         898 :         if (ch->disable_seek) {
     168          20 :                 ch->dts = ch->sample->DTS;
     169          20 :                 ch->cts = ch->sample->DTS + ch->sample->CTS_Offset;
     170          20 :                 ch->start = 0;
     171             :         } else {
     172             :                 s64 cts;
     173         878 :                 ch->dts = ch->start;
     174         878 :                 ch->cts = ch->start;
     175             : 
     176         878 :                 cts = ch->sample->DTS + ch->sample->CTS_Offset;
     177         878 :                 if (ch->ts_offset<0)
     178         204 :                         cts += ch->ts_offset;
     179             : 
     180             :                 //TODO - we need to notify scene decoder how many secs elapsed between RAP and seek point
     181         878 :                 if (ch->cts != cts) {
     182          21 :                         ch->seek_flag = 1;
     183             :                 }
     184             :         }
     185         898 :         if (!sample_desc_index) sample_desc_index = 1;
     186         898 :         ch->last_sample_desc_index = sample_desc_index;
     187         898 :         ch->owner->no_order_check = ch->speed < 0 ? GF_TRUE : GF_FALSE;
     188             : }
     189             : 
     190             : 
     191       37940 : static void isor_update_cenc_info(ISOMChannel *ch, Bool for_item)
     192             : {
     193             :         GF_Err e;
     194             :         Bool Is_Encrypted;
     195             :         u32 out_size;
     196             :         u8 crypt_byte_block, skip_byte_block;
     197             :         u8 piff_info[20];
     198       37940 :         u8 *key_info = NULL;
     199       37940 :         u32 key_info_size = 0;
     200             :         u8 item_mkey = 0;
     201             : 
     202             :         //this will be skipped anyways, don't fectch ...
     203       37940 :         if (ch->owner->stsd && (ch->last_sample_desc_index != ch->owner->stsd) && ch->sample) {
     204           0 :                 return;
     205             :         }
     206             : 
     207             : 
     208       37940 :         out_size = ch->sai_alloc_size;
     209       37940 :         if (for_item) {
     210          13 :                 u32 aux_info_param=0;
     211          13 :                 e = gf_isom_extract_meta_item_get_cenc_info(ch->owner->mov, GF_TRUE, 0, ch->item_id, &Is_Encrypted, &skip_byte_block, &crypt_byte_block, (const u8 **) &key_info, &key_info_size, &aux_info_param, &ch->sai_buffer, &out_size, &ch->sai_alloc_size);
     212             : 
     213             :                 /*The ienc property is always exposed as a multiple key info in GPAC
     214             :                 However the type of SAI may be single-key (aux_info_param==0) or multiple-key (aux_info_param==1) for the same ienc used
     215             :                 We therefore temporary force the key info type to single key if v0 SAI CENC are used
     216             :                 Note that this is thread safe as this filter is the only one using the opened file
     217             :                 */
     218          13 :                 if (aux_info_param==0) {
     219          10 :                         item_mkey = key_info[0];
     220             :                 }
     221             :         } else {
     222       37927 :                 e = gf_isom_get_sample_cenc_info(ch->owner->mov, ch->track, ch->sample_num, &Is_Encrypted, &crypt_byte_block, &skip_byte_block, (const u8 **) &key_info, &key_info_size);
     223             :         }
     224       37940 :         if (!key_info) {
     225           0 :                 piff_info[0] = 0;
     226           0 :                 piff_info[1] = 0;
     227           0 :                 piff_info[2] = 0;
     228           0 :                 piff_info[3] = key_info_size;
     229             :                 memset(piff_info + 4, 0, 16);
     230           0 :                 key_info_size = 20;
     231           0 :                 key_info = (u8 *) piff_info;
     232             :         }
     233             : 
     234             : 
     235       37940 :         if (!for_item && (e==GF_OK) && Is_Encrypted) {
     236       33661 :                 e = gf_isom_cenc_get_sample_aux_info(ch->owner->mov, ch->track, ch->sample_num, ch->last_sample_desc_index, NULL, &ch->sai_buffer, &out_size);
     237             :         }
     238             : 
     239       37940 :         if (out_size > ch->sai_alloc_size) ch->sai_alloc_size = out_size;
     240       37940 :         ch->sai_buffer_size = out_size;
     241             : 
     242       37940 :         if (e) {
     243           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[IsoMedia] Failed to fetch CENC auxiliary info for %s %d: %s\n", for_item ? "item" : "track", for_item ? ch->item_id : ch->track, gf_error_to_string(e) ));
     244             :                 return;
     245             :         }
     246             : 
     247       37940 :         ch->pck_encrypted = Is_Encrypted;
     248             : 
     249             :         /*notify change of IV/KID only when packet is encrypted
     250             :         1- these info are ignored when packet is not encrypted
     251             :         2- this allows us to define the initial CENC state for multi-stsd cases*/
     252       37940 :         if (Is_Encrypted) {
     253             :                 u32 ki_crc;
     254             : 
     255       33674 :                 if ((ch->crypt_byte_block != crypt_byte_block) || (ch->skip_byte_block != skip_byte_block)) {
     256           4 :                         ch->crypt_byte_block = crypt_byte_block;
     257           4 :                         ch->skip_byte_block = skip_byte_block;
     258             : 
     259           4 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_CENC_PATTERN, &PROP_FRAC_INT(ch->skip_byte_block, ch->crypt_byte_block) );
     260             :                 }
     261       33674 :                 if (item_mkey)
     262          10 :                         key_info[0] = 0;
     263             : 
     264       33674 :                 ki_crc = gf_crc_32(key_info, key_info_size);
     265       33674 :                 if (ch->key_info_crc != ki_crc) {
     266         343 :                         ch->key_info_crc = ki_crc;
     267         343 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_CENC_KEY_INFO, &PROP_DATA((u8 *)key_info, key_info_size) );
     268             :                 }
     269             : 
     270       33674 :                 if (item_mkey)
     271          10 :                         key_info[0] = item_mkey;
     272             :         }
     273             : }
     274             : 
     275         118 : void isor_reader_get_sample_from_item(ISOMChannel *ch)
     276             : {
     277         118 :         if (ch->au_seq_num) {
     278          72 :                 if (!ch->owner->itt || !isor_declare_item_properties(ch->owner, ch, 1+ch->au_seq_num)) {
     279          46 :                         ch->last_state = GF_EOS;
     280          46 :                         return;
     281             :                 }
     282             :         }
     283          72 :         ch->sample_time = 0;
     284          72 :         ch->last_state = GF_OK;
     285          72 :         if (!ch->static_sample) {
     286          46 :                 ch->static_sample = gf_isom_sample_new();
     287             :         }
     288             : 
     289          72 :         ch->sample = ch->static_sample;
     290          72 :         ch->sample->IsRAP = RAP;
     291          72 :         ch->au_duration = 1000;
     292          72 :         ch->dts = ch->cts = 1000 * ch->au_seq_num;
     293          72 :         gf_isom_extract_meta_item_mem(ch->owner->mov, GF_TRUE, 0, ch->item_id, &ch->sample->data, &ch->sample->dataLength, &ch->static_sample->alloc_size, NULL, GF_FALSE);
     294             : 
     295          72 :         if (ch->is_encrypted && ch->is_cenc) {
     296          13 :                 isor_update_cenc_info(ch, GF_TRUE);
     297             :         }
     298             : }
     299             : 
     300      642314 : void isor_reader_get_sample(ISOMChannel *ch)
     301             : {
     302             :         GF_Err e;
     303             :         u32 sample_desc_index;
     304      887782 :         if (ch->sample) return;
     305             : 
     306      642314 :         if (ch->next_track) {
     307           0 :                 ch->track = ch->next_track;
     308           0 :                 ch->next_track = 0;
     309             :         }
     310             : 
     311      642314 :         if (ch->to_init) {
     312        1185 :                 init_reader(ch);
     313        1185 :                 sample_desc_index = ch->last_sample_desc_index;
     314      641129 :         } else if (ch->speed < 0) {
     315          47 :                 if (ch->last_state == GF_EOS) {
     316           2 :                         ch->sample = NULL;
     317           2 :                         return;
     318             :                 }
     319             : 
     320          45 :                 if (ch->static_sample->IsRAP) {
     321          20 :                         ch->last_rap_sample_time = ch->sample_time;
     322             :                 }
     323             : 
     324          45 :                 e = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->sample_time + 1, &sample_desc_index, GF_ISOM_SEARCH_FORWARD, &ch->static_sample, &ch->sample_num, NULL);
     325             : 
     326          45 :                 if ((e==GF_EOS) || (ch->static_sample->IsRAP)) {
     327          20 :                         if (!ch->last_rap_sample_time) {
     328             :                                 e = GF_EOS;
     329             :                         } else {
     330          18 :                                 e = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->last_rap_sample_time - 1, &sample_desc_index, GF_ISOM_SEARCH_SYNC_BACKWARD, &ch->static_sample, &ch->sample_num, NULL);
     331             :                         }
     332             :                 }
     333             : 
     334          43 :                 if (e) {
     335           2 :                         if ((e==GF_EOS) && !ch->owner->frag_type) {
     336           2 :                                 ch->last_state = GF_EOS;
     337             :                         }
     338           2 :                         ch->sample = NULL;
     339           2 :                         return;
     340             :                 }
     341          43 :                 ch->sample = ch->static_sample;
     342             : 
     343          43 :                 if (ch->sample->DTS == ch->sample_time) {
     344           0 :                         if (!ch->owner->frag_type) {
     345           0 :                                 ch->last_state = GF_EOS;
     346             :                         }
     347             :                 }
     348             :                 if (ch->sample) {
     349          43 :                         ch->sample_time = ch->sample->DTS;
     350             :                 }
     351             : 
     352      641082 :         } else if (ch->has_edit_list) {
     353           0 :                 u32 prev_sample = ch->sample_num;
     354           0 :                 e = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->sample_time + 1, &sample_desc_index, GF_ISOM_SEARCH_FORWARD, &ch->static_sample, &ch->sample_num, &ch->sample_data_offset);
     355             : 
     356           0 :                 if (e == GF_OK) {
     357           0 :                         ch->sample = ch->static_sample;
     358             : 
     359             :                         /*we are in forced seek mode: fetch all samples before the one matching the sample time*/
     360           0 :                         if (ch->edit_sync_frame) {
     361           0 :                                 ch->edit_sync_frame++;
     362           0 :                                 if (ch->edit_sync_frame < ch->sample_num) {
     363           0 :                                         ch->sample = gf_isom_get_sample_ex(ch->owner->mov, ch->track, ch->edit_sync_frame, &sample_desc_index, ch->static_sample, &ch->sample_data_offset);
     364           0 :                                         ch->sample->DTS = ch->sample_time;
     365           0 :                                         ch->sample->CTS_Offset = 0;
     366             :                                 } else {
     367           0 :                                         ch->edit_sync_frame = 0;
     368           0 :                                         if (ch->sample) ch->sample_time = ch->sample->DTS;
     369             :                                 }
     370             :                         } else {
     371             :                                 /*if we get the same sample, figure out next interesting time (current sample + DTS gap to next sample should be a good bet)*/
     372           0 :                                 if (prev_sample == ch->sample_num) {
     373           0 :                                         if (ch->owner->frag_type && (ch->sample_num==gf_isom_get_sample_count(ch->owner->mov, ch->track))) {
     374           0 :                                                 ch->sample = NULL;
     375             :                                         } else {
     376           0 :                                                 u32 sample_num = ch->sample_num ? ch->sample_num : 1;
     377             : 
     378           0 :                                                 if (sample_num >= gf_isom_get_sample_count(ch->owner->mov, ch->track) ) {
     379             :                                                         //e = GF_EOS;
     380             :                                                 } else {
     381           0 :                                                         u32 time_diff = gf_isom_get_sample_duration(ch->owner->mov, ch->track, sample_num);
     382           0 :                                                         e = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->sample_time + time_diff, &sample_desc_index, GF_ISOM_SEARCH_FORWARD, &ch->static_sample, &ch->sample_num, &ch->sample_data_offset);
     383           0 :                                                         if (e==GF_OK) {
     384           0 :                                                                 if (ch->sample_num == prev_sample) {
     385           0 :                                                                         ch->sample_time += time_diff;
     386           0 :                                                                         ch->sample = NULL;
     387           0 :                                                                         return;
     388             :                                                                 } else {
     389           0 :                                                                         ch->sample = ch->static_sample;
     390             :                                                                 }
     391             :                                                         }
     392             :                                                 }
     393             :                                         }
     394             :                                 }
     395             : 
     396             :                                 /*we jumped to another segment - if RAP is needed look for closest rap in decoding order and
     397             :                                 force seek mode*/
     398           0 :                                 if (ch->sample && !ch->sample->IsRAP && ch->has_rap && (ch->sample_num != prev_sample+1)) {
     399           0 :                                         GF_ISOSample *found = ch->static_sample;
     400             :                                         u32 samp_num = ch->sample_num;
     401           0 :                                         ch->sample = NULL;
     402           0 :                                         e = gf_isom_get_sample_for_movie_time(ch->owner->mov, ch->track, ch->sample_time + 1, &sample_desc_index, GF_ISOM_SEARCH_SYNC_BACKWARD, &ch->static_sample, &ch->sample_num, &ch->sample_data_offset);
     403             : 
     404           0 :                                         if (e == GF_OK) ch->sample = ch->static_sample;
     405             : 
     406             :                                         /*if no sync point in the past, use the first non-sync for the given time*/
     407           0 :                                         if (!ch->sample || !ch->sample->data) {
     408           0 :                                                 ch->sample = ch->static_sample = found;
     409           0 :                                                 ch->sample_time = ch->sample->DTS;
     410           0 :                                                 ch->sample_num = samp_num;
     411             :                                         } else {
     412           0 :                                                 ch->sample = ch->static_sample;
     413           0 :                                                 ch->edit_sync_frame = ch->sample_num;
     414           0 :                                                 ch->sample->DTS = ch->sample_time;
     415           0 :                                                 ch->sample->CTS_Offset = 0;
     416             :                                         }
     417             :                                 } else {
     418           0 :                                         if (ch->sample) ch->sample_time = ch->sample->DTS;
     419             :                                 }
     420             :                         }
     421             :                 }
     422             :         } else {
     423             :                 Bool do_fetch = GF_TRUE;
     424      641082 :                 ch->sample_num++;
     425             : 
     426      641082 :                 if (ch->sap_only) {
     427          72 :                         Bool is_rap = gf_isom_get_sample_sync(ch->owner->mov, ch->track, ch->sample_num);
     428          72 :                         if (!is_rap) {
     429             :                                 GF_ISOSampleRollType roll_type;
     430           6 :                                 gf_isom_get_sample_rap_roll_info(ch->owner->mov, ch->track, ch->sample_num, &is_rap, &roll_type, NULL);
     431           6 :                                 if (roll_type) is_rap = GF_TRUE;
     432             :                         }
     433             : 
     434          72 :                         if (!is_rap) {
     435             :                                 do_fetch = GF_FALSE;
     436          66 :                         } else if (ch->sap_only==2) {
     437           0 :                                 ch->sap_only = 0;
     438             :                         }
     439             :                 }
     440             :                 if (do_fetch) {
     441      641076 :                         if (ch->owner->nodata) {
     442           0 :                                 ch->sample = gf_isom_get_sample_info_ex(ch->owner->mov, ch->track, ch->sample_num, &sample_desc_index, &ch->sample_data_offset, ch->static_sample);
     443             :                         } else {
     444      641076 :                                 ch->sample = gf_isom_get_sample_ex(ch->owner->mov, ch->track, ch->sample_num, &sample_desc_index, ch->static_sample, &ch->sample_data_offset);
     445             :                         }
     446             :                         /*if sync shadow / carousel RAP skip*/
     447      641076 :                         if (ch->sample && (ch->sample->IsRAP==RAP_REDUNDANT)) {
     448           0 :                                 ch->sample = NULL;
     449           0 :                                 ch->sample_num++;
     450           0 :                                 isor_reader_get_sample(ch);
     451           0 :                                 return;
     452             :                         }
     453             :                 }
     454             :         }
     455             : 
     456             :         //check scalable track change
     457      642310 :         if (ch->sample && ch->sample->IsRAP && ch->next_track) {
     458           0 :                 ch->track = ch->next_track;
     459           0 :                 ch->next_track = 0;
     460           0 :                 ch->sample = NULL;
     461           0 :                 isor_reader_get_sample(ch);
     462           0 :                 return;
     463             :         }
     464             : 
     465      642310 :         if (!ch->sample) {
     466      245464 :                 u32 sample_count = gf_isom_get_sample_count(ch->owner->mov, ch->track);
     467      245464 :                 ch->sample_data_offset = 0;
     468             :                 /*incomplete file - check if we're still downloading or not*/
     469      245464 :                 if (gf_isom_get_missing_bytes(ch->owner->mov, ch->track)) {
     470        1527 :                         ch->last_state = GF_ISOM_INCOMPLETE_FILE;
     471        1527 :                         if (ch->owner->mem_load_mode==2)
     472         418 :                                 ch->owner->force_fetch = GF_TRUE;
     473             : 
     474        1527 :                         if (!ch->owner->input_loaded) {
     475        1467 :                                 ch->last_state = GF_OK;
     476        1467 :                                 if (!ch->has_edit_list && ch->sample_num)
     477        1450 :                                         ch->sample_num--;
     478             :                         } else {
     479          60 :                                 if (ch->sample_num >= gf_isom_get_sample_count(ch->owner->mov, ch->track)) {
     480           0 :                                         ch->last_state = GF_EOS;
     481             :                                 }
     482             :                         }
     483             :                 }
     484      243937 :                 else if (!ch->sample_num
     485      243924 :                          || ((ch->speed >= 0) && (ch->sample_num >= sample_count))
     486           6 :                          || ((ch->speed < 0) && (ch->sample_time == gf_isom_get_current_tfdt(ch->owner->mov, ch->track) ))
     487             :                         ) {
     488             : 
     489      243931 :                         if (ch->owner->frag_type==1) {
     490             :                                 /*if sample cannot be found and file is fragmented, rewind sample*/
     491      230279 :                                 if (ch->sample_num) ch->sample_num--;
     492      230279 :                                 ch->last_state = GF_EOS;
     493       13652 :                         } else if (ch->last_state != GF_EOS) {
     494         782 :                                 GF_LOG(GF_LOG_DEBUG, GF_LOG_CONTAINER, ("[IsoMedia] Track #%d end of stream reached\n", ch->track));
     495         782 :                                 ch->last_state = GF_EOS;
     496         782 :                                 if (ch->sample_num>sample_count) ch->sample_num = sample_count;
     497             :                         } else {
     498       12870 :                                 if (ch->sample_num>sample_count) ch->sample_num = sample_count;
     499             :                         }
     500             :                 } else {
     501           6 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] Track #%d fail to fetch sample %d / %d: %s\n", ch->track, ch->sample_num, gf_isom_get_sample_count(ch->owner->mov, ch->track), gf_error_to_string(gf_isom_last_error(ch->owner->mov)) ));
     502             :                 }
     503             :                 return;
     504             :         }
     505             : 
     506      396846 :         if (sample_desc_index != ch->last_sample_desc_index) {
     507         247 :                 if (!ch->owner->stsd) {
     508             :                         //we used sample entry 1 by default to setup, if no active prev sample (edit list might trigger this)
     509             :                         //and new sample desc is 1, do not reconfigure
     510         247 :                         if (!ch->last_sample_desc_index && (sample_desc_index==1)) {
     511             : 
     512             :                         } else {
     513           5 :                                 ch->needs_pid_reconfig = GF_TRUE;
     514             :                         }
     515             :                 }
     516         247 :                 ch->last_sample_desc_index = sample_desc_index;
     517             :         }
     518             : 
     519      396846 :         ch->last_state = GF_OK;
     520      396846 :         ch->au_duration = gf_isom_get_sample_duration(ch->owner->mov, ch->track, ch->sample_num);
     521             : 
     522      396846 :         ch->sap_3 = GF_FALSE;
     523      396846 :         ch->sap_4_type = 0;
     524      396846 :         ch->roll = 0;
     525      396846 :         ch->set_disc = ch->owner->clock_discontinuity ? 2 : 0;
     526      396846 :         ch->owner->clock_discontinuity = 0;
     527             : 
     528      396846 :         if (ch->sample) {
     529      396846 :                 gf_isom_get_sample_rap_roll_info(ch->owner->mov, ch->track, ch->sample_num, &ch->sap_3, &ch->sap_4_type, &ch->roll);
     530             : 
     531             :                 /*still seeking or not ?
     532             :                  1- when speed is negative, the RAP found is "after" the seek point in playback order since we used backward RAP search: nothing to do
     533             :                  2- otherwise set DTS+CTS to start value
     534             :                  */
     535      396846 :                 if ((ch->speed < 0) || (ch->start <= ch->sample->DTS + ch->sample->CTS_Offset)) {
     536      396807 :                         ch->dts = ch->sample->DTS;
     537      396807 :                         ch->cts = ch->sample->DTS + ch->sample->CTS_Offset;
     538      396807 :                         ch->seek_flag = 0;
     539             :                 } else {
     540          39 :                         ch->cts = ch->start;
     541          39 :                         ch->seek_flag = 1;
     542          39 :                         ch->dts = ch->start;
     543             :                 }
     544             : 
     545      396846 :                 if (ch->end && (ch->end < ch->sample->DTS + ch->sample->CTS_Offset + ch->au_duration)) {
     546           0 :                         GF_LOG(GF_LOG_DEBUG, GF_LOG_DASH, ("[IsoMedia] End of Channel "LLD" (CTS "LLD")\n", ch->end, ch->sample->DTS + ch->sample->CTS_Offset));
     547           0 :                         ch->sample = NULL;
     548           0 :                         ch->last_state = GF_EOS;
     549           0 :                         ch->playing = 2;
     550           0 :                         return;
     551             :                 }
     552             :         }
     553             : 
     554      396846 :         if (ch->owner->last_sender_ntp && ch->cts==ch->owner->cts_for_last_sender_ntp) {
     555           0 :                 ch->sender_ntp = ch->owner->last_sender_ntp;
     556           0 :                 ch->ntp_at_server_ntp = ch->owner->ntp_at_last_sender_ntp;
     557      396846 :         } else if (ch->owner->last_sender_ntp && ch->dts==ch->owner->cts_for_last_sender_ntp) {
     558           0 :                 ch->sender_ntp = ch->owner->last_sender_ntp;
     559           0 :                 ch->ntp_at_server_ntp = ch->owner->ntp_at_last_sender_ntp;
     560             :         } else {
     561      396846 :                 ch->sender_ntp = ch->ntp_at_server_ntp = 0;
     562             :         }
     563             : 
     564      396846 :         if (!ch->sample_num) return;
     565             : 
     566      396846 :         gf_isom_get_sample_flags(ch->owner->mov, ch->track, ch->sample_num, &ch->isLeading, &ch->dependsOn, &ch->dependedOn, &ch->redundant);
     567             : 
     568      396846 :         if (ch->is_encrypted) {
     569             :                 /*in case of CENC: we write sample auxiliary information to slh->sai; its size is in saiz*/
     570       42342 :                 if (gf_isom_is_cenc_media(ch->owner->mov, ch->track, ch->last_sample_desc_index)) {
     571       37927 :                         isor_update_cenc_info(ch, GF_FALSE);
     572             : 
     573        4415 :                 } else if (gf_isom_is_media_encrypted(ch->owner->mov, ch->track, ch->last_sample_desc_index)) {
     574        3869 :                         ch->pck_encrypted = GF_TRUE;
     575             :                 } else {
     576         546 :                         ch->pck_encrypted = GF_FALSE;
     577             :                 }
     578             :         }
     579      396846 :         if (ch->sample && ch->sample->nb_pack)
     580         482 :                 ch->sample_num += ch->sample->nb_pack-1;
     581             : }
     582             : 
     583      396918 : void isor_reader_release_sample(ISOMChannel *ch)
     584             : {
     585      399594 :         if (ch->sample)
     586      396918 :                 ch->au_seq_num++;
     587      399594 :         ch->sample = NULL;
     588      399594 :         ch->sai_buffer_size = 0;
     589      396918 : }
     590             : 
     591          40 : static void isor_reset_seq_list(GF_List *list)
     592             : {
     593         106 :         while (gf_list_count(list)) {
     594          26 :                 GF_NALUFFParam *sl = gf_list_pop_back(list);
     595          26 :                 gf_free(sl->data);
     596          26 :                 gf_free(sl);
     597             :         }
     598          40 : }
     599             : 
     600             : enum
     601             : {
     602             :         RESET_STATE_VPS=1,
     603             :         RESET_STATE_SPS=1<<1,
     604             :         RESET_STATE_PPS=1<<2,
     605             :         RESET_STATE_SPS_EXT=1<<3,
     606             :         RESET_STATE_DCI=1<<4,
     607             : };
     608             : 
     609        2070 : static void isor_replace_nal(GF_AVCConfig *avcc, GF_HEVCConfig *hvcc, GF_VVCConfig *vvcc, u8 *data, u32 size, u8 nal_type, u32 *reset_state)
     610             : {
     611             :         u32 i, count, state=0;
     612             :         GF_NALUFFParam *sl;
     613             :         GF_List *list=NULL;
     614        2070 :         if (avcc) {
     615        2022 :                 if (nal_type==GF_AVC_NALU_PIC_PARAM) {
     616        1992 :                         list = avcc->pictureParameterSets;
     617             :                         state=RESET_STATE_PPS;
     618          30 :                 } else if (nal_type==GF_AVC_NALU_SEQ_PARAM) {
     619          30 :                         list = avcc->sequenceParameterSets;
     620             :                         state=RESET_STATE_SPS;
     621           0 :                 } else if (nal_type==GF_AVC_NALU_SEQ_PARAM_EXT) {
     622           0 :                         list = avcc->sequenceParameterSetExtensions;
     623             :                         state=RESET_STATE_SPS_EXT;
     624             :                 } else return;
     625             :         }
     626          48 :         else if (hvcc) {
     627             :                 GF_NALUFFParamArray *hvca=NULL;
     628          48 :                 count = gf_list_count(hvcc->param_array);
     629          96 :                 for (i=0; i<count; i++) {
     630          90 :                         hvca = gf_list_get(hvcc->param_array, i);
     631          90 :                         if (hvca->type==nal_type) {
     632          42 :                                 list = hvca->nalus;
     633          42 :                                 break;
     634             :                         }
     635             :                         hvca = NULL;
     636             :                 }
     637          48 :                 if (!hvca) {
     638           6 :                         GF_SAFEALLOC(hvca, GF_NALUFFParamArray);
     639           6 :                         if (hvca) {
     640           6 :                                 list = hvca->nalus = gf_list_new();
     641           6 :                                 hvca->type = nal_type;
     642           6 :                                 gf_list_add(hvcc->param_array, hvca);
     643             :                         }
     644             :                 }
     645          48 :                 switch (nal_type) {
     646          16 :                 case GF_HEVC_NALU_VID_PARAM:
     647             :                         state = RESET_STATE_VPS;
     648          16 :                         break;
     649          16 :                 case GF_HEVC_NALU_SEQ_PARAM:
     650             :                         state = RESET_STATE_SPS;
     651          16 :                         break;
     652          16 :                 case GF_HEVC_NALU_PIC_PARAM:
     653             :                         state = RESET_STATE_PPS;
     654          16 :                         break;
     655             :                 }
     656             :         }
     657           0 :         else if (vvcc) {
     658             :                 GF_NALUFFParamArray *vvca=NULL;
     659           0 :                 count = gf_list_count(vvcc->param_array);
     660           0 :                 for (i=0; i<count; i++) {
     661           0 :                         vvca = gf_list_get(vvcc->param_array, i);
     662           0 :                         if (vvca->type==nal_type) {
     663           0 :                                 list = vvca->nalus;
     664           0 :                                 break;
     665             :                         }
     666             :                         vvca = NULL;
     667             :                 }
     668           0 :                 if (!vvca) {
     669           0 :                         GF_SAFEALLOC(vvca, GF_NALUFFParamArray);
     670           0 :                         if (vvca) {
     671           0 :                                 list = vvca->nalus = gf_list_new();
     672           0 :                                 vvca->type = nal_type;
     673           0 :                                 gf_list_add(vvcc->param_array, vvca);
     674             :                         }
     675             :                 }
     676           0 :                 switch (nal_type) {
     677           0 :                 case GF_VVC_NALU_VID_PARAM:
     678             :                         state = RESET_STATE_VPS;
     679           0 :                         break;
     680           0 :                 case GF_VVC_NALU_SEQ_PARAM:
     681             :                         state = RESET_STATE_SPS;
     682           0 :                         break;
     683           0 :                 case GF_VVC_NALU_PIC_PARAM:
     684             :                         state = RESET_STATE_PPS;
     685           0 :                         break;
     686           0 :                 case GF_VVC_NALU_DEC_PARAM:
     687             :                         state = RESET_STATE_DCI;
     688           0 :                         break;
     689             :                 }
     690             :         }
     691             : 
     692        2070 :         count = gf_list_count(list);
     693        2322 :         for (i=0; i<count; i++) {
     694        2278 :                 sl = gf_list_get(list, i);
     695        2278 :                 if ((sl->size==size) && !memcmp(sl->data, data, size)) return;
     696             :         }
     697          44 :         if (! (*reset_state & state))  {
     698          40 :                 isor_reset_seq_list(list);
     699          40 :                 *reset_state |= state;
     700             :         }
     701          44 :         GF_SAFEALLOC(sl, GF_NALUFFParam);
     702          44 :         if (!sl) return;
     703          44 :         sl->data = gf_malloc(sizeof(char)*size);
     704             :         memcpy(sl->data, data, size);
     705          44 :         sl->size = size;
     706          44 :         gf_list_add(list, sl);
     707             : }
     708             : 
     709      396918 : void isor_reader_check_config(ISOMChannel *ch)
     710             : {
     711             :         u32 nalu_len, reset_state;
     712      621806 :         if (!ch->check_hevc_ps && !ch->check_avc_ps && !ch->check_vvc_ps && !ch->check_mhas_pl) return;
     713             : 
     714      185450 :         if (!ch->sample) return;
     715             :         //we cannot touch the payload if encrypted !!
     716             :         //TODO, in CENC try to remove non-encrypted NALUs and update saiz accordingly
     717      185450 :         if (ch->is_encrypted) return;
     718             : 
     719      172030 :         if (ch->check_mhas_pl) {
     720           0 :                 u64 ch_layout = 0;
     721           0 :                 s32 PL = gf_mpegh_get_mhas_pl(ch->sample->data, ch->sample->dataLength, &ch_layout);
     722           0 :                 if (PL>0) {
     723           0 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_PROFILE_LEVEL, &PROP_UINT((u32) PL));
     724           0 :                         ch->check_mhas_pl = GF_FALSE;
     725           0 :                         if (ch_layout)
     726           0 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_CHANNEL_LAYOUT, &PROP_LONGUINT(ch_layout));
     727             :                 }
     728             :                 return;
     729             :         }
     730             : 
     731      172030 :         if (ch->owner->analyze) return;
     732             :         
     733             :         nalu_len = 4;
     734      172030 :         if (ch->avcc) nalu_len = ch->avcc->nal_unit_size;
     735       12067 :         else if (ch->hvcc) nalu_len = ch->hvcc->nal_unit_size;
     736           0 :         else if (ch->vvcc) nalu_len = ch->vvcc->nal_unit_size;
     737             : 
     738      172030 :         reset_state = 0;
     739             : 
     740      172030 :         if (!ch->nal_bs) ch->nal_bs = gf_bs_new(ch->sample->data, ch->sample->dataLength, GF_BITSTREAM_READ);
     741      171750 :         else gf_bs_reassign_buffer(ch->nal_bs, ch->sample->data, ch->sample->dataLength);
     742             : 
     743      393251 :         while (gf_bs_available(ch->nal_bs)) {
     744             :                 Bool replace_nal = GF_FALSE;
     745             :                 u8 nal_type=0;
     746      221221 :                 u32 pos = (u32) gf_bs_get_position(ch->nal_bs);
     747      221221 :                 u32 size = gf_bs_read_int(ch->nal_bs, nalu_len*8);
     748             :                 //this takes care of size + pos + nalu_len > 0 but (s32) size < 0 ...
     749      221221 :                 if (ch->sample->dataLength < size) break;
     750      221221 :                 if (ch->sample->dataLength < size + pos + nalu_len) break;
     751      221221 :                 if (ch->check_avc_ps) {
     752      166766 :                         u8 hdr = gf_bs_peek_bits(ch->nal_bs, 8, 0);
     753      166766 :                         nal_type = hdr & 0x1F;
     754             :                         switch (nal_type) {
     755             :                         case GF_AVC_NALU_SEQ_PARAM:
     756             :                         case GF_AVC_NALU_SEQ_PARAM_EXT:
     757             :                         case GF_AVC_NALU_PIC_PARAM:
     758             :                                 replace_nal = GF_TRUE;
     759             :                                 break;
     760             :                         }
     761             :                 }
     762       54455 :                 else if (ch->check_hevc_ps) {
     763       54455 :                         u8 hdr = gf_bs_peek_bits(ch->nal_bs, 8, 0);
     764       54455 :                         nal_type = (hdr & 0x7E) >> 1;
     765       54455 :                         switch (nal_type) {
     766          48 :                         case GF_HEVC_NALU_VID_PARAM:
     767             :                         case GF_HEVC_NALU_SEQ_PARAM:
     768             :                         case GF_HEVC_NALU_PIC_PARAM:
     769             :                                 replace_nal = GF_TRUE;
     770          48 :                                 break;
     771             :                         }
     772             :                 }
     773           0 :                 else if (ch->check_vvc_ps) {
     774           0 :                         u8 hdr = gf_bs_peek_bits(ch->nal_bs, 8, 1);
     775           0 :                         nal_type = hdr >> 3;
     776           0 :                         switch (nal_type) {
     777           0 :                         case GF_VVC_NALU_VID_PARAM:
     778             :                         case GF_VVC_NALU_SEQ_PARAM:
     779             :                         case GF_VVC_NALU_PIC_PARAM:
     780             :                         case GF_VVC_NALU_DEC_PARAM:
     781             :                                 replace_nal = GF_TRUE;
     782           0 :                                 break;
     783             :                         }
     784             :                 }
     785      221221 :                 gf_bs_skip_bytes(ch->nal_bs, size);
     786             : 
     787      221221 :                 if (replace_nal) {
     788        2070 :                         u32 move_size = ch->sample->dataLength - size - pos - nalu_len;
     789        2070 :                         isor_replace_nal(ch->avcc, ch->hvcc, ch->vvcc, ch->sample->data + pos + nalu_len, size, nal_type, &reset_state);
     790        2070 :                         if (move_size)
     791         108 :                                 memmove(ch->sample->data + pos, ch->sample->data + pos + size + nalu_len, ch->sample->dataLength - size - pos - nalu_len);
     792             : 
     793        2070 :                         ch->sample->dataLength -= size + nalu_len;
     794        2070 :                         gf_bs_reassign_buffer(ch->nal_bs, ch->sample->data, ch->sample->dataLength);
     795        2070 :                         gf_bs_seek(ch->nal_bs, pos);
     796             :                 }
     797             :         }
     798             : 
     799      172030 :         if (reset_state) {
     800          22 :                 u8 *dsi=NULL;
     801          22 :                 u32 dsi_size=0;
     802          22 :                 if (ch->check_avc_ps) {
     803          14 :                         gf_odf_avc_cfg_write(ch->avcc, &dsi, &dsi_size);
     804             :                 }
     805           8 :                 else if (ch->check_hevc_ps) {
     806           8 :                         gf_odf_hevc_cfg_write(ch->hvcc, &dsi, &dsi_size);
     807             :                 }
     808           0 :                 else if (ch->check_vvc_ps) {
     809           0 :                         gf_odf_vvc_cfg_write(ch->vvcc, &dsi, &dsi_size);
     810             :                 }
     811          22 :                 if (dsi && dsi_size) {
     812          22 :                         u32 dsi_crc = gf_crc_32(dsi, dsi_size);
     813          22 :                         if (ch->dsi_crc == dsi_crc) {
     814           0 :                                 gf_free(dsi);
     815             :                         } else {
     816          22 :                                 ch->dsi_crc = dsi_crc;
     817          22 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(dsi, dsi_size) );
     818             :                         }
     819             :                 }
     820             :         }
     821             : }
     822             : 
     823             : #endif /*GPAC_DISABLE_ISOM*/

Generated by: LCOV version 1.13