LCOV - code coverage report
Current view: top level - filters - isoffin_load.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 592 757 78.2 %
Date: 2021-04-29 23:48:07 Functions: 4 4 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             : #include "isoffin.h"
      27             : #include <gpac/iso639.h>
      28             : #include <gpac/base_coding.h>
      29             : #include <gpac/media_tools.h>
      30             : 
      31             : #ifndef GPAC_DISABLE_ISOM
      32             : 
      33             : #if 0   //deprecated - we need to rework chapter information to deal with static chapters and chapter tracks
      34             : void isor_emulate_chapters(GF_ISOFile *file, GF_InitialObjectDescriptor *iod)
      35             : {
      36             :         GF_Segment *prev_seg;
      37             :         u64 prev_start;
      38             :         u64 start;
      39             :         u32 i, count;
      40             :         if (!iod || gf_list_count(iod->OCIDescriptors)) return;
      41             :         count = gf_isom_get_chapter_count(file, 0);
      42             :         if (!count) return;
      43             : 
      44             :         prev_seg = NULL;
      45             :         start = prev_start = 0;
      46             :         for (i=0; i<count; i++) {
      47             :                 const char *name;
      48             :                 GF_Segment *seg;
      49             :                 gf_isom_get_chapter(file, 0, i+1, &start, &name);
      50             :                 seg = (GF_Segment *) gf_odf_desc_new(GF_ODF_SEGMENT_TAG);
      51             :                 seg->startTime = (Double) (s64) start;
      52             :                 seg->startTime /= 1000;
      53             :                 seg->SegmentName = gf_strdup(name);
      54             :                 gf_list_add(iod->OCIDescriptors, seg);
      55             :                 if (prev_seg) {
      56             :                         prev_seg->Duration = (Double) (s64) (start - prev_start);
      57             :                         prev_seg->Duration /= 1000;
      58             :                 } else if (start) {
      59             :                         prev_seg = (GF_Segment *) gf_odf_desc_new(GF_ODF_SEGMENT_TAG);
      60             :                         prev_seg->startTime = 0;
      61             :                         prev_seg->Duration = (Double) (s64) (start);
      62             :                         prev_seg->Duration /= 1000;
      63             :                         gf_list_insert(iod->OCIDescriptors, prev_seg, 0);
      64             :                 }
      65             :                 prev_seg = seg;
      66             :                 prev_start = start;
      67             :         }
      68             :         if (prev_seg) {
      69             :                 start = 1000*gf_isom_get_duration(file);
      70             :                 start /= gf_isom_get_timescale(file);
      71             :                 if (start>prev_start) {
      72             :                         prev_seg->Duration = (Double) (s64) (start - prev_start);
      73             :                         prev_seg->Duration /= 1000;
      74             :                 }
      75             :         }
      76             : }
      77             : #endif
      78             : 
      79        1199 : static void isor_declare_track(ISOMReader *read, ISOMChannel *ch, u32 track, u32 stsd_idx, u32 streamtype, Bool use_iod)
      80             : {
      81             :         u32 w, h, sr, nb_ch, nb_bps, codec_id, depends_on_id, esid, avg_rate, max_rate, buffer_size, sample_count, max_size, nb_refs, exp_refs, base_track, audio_fmt, pix_fmt;
      82             :         GF_ESD *an_esd;
      83             :         const char *mime, *encoding, *stxtcfg, *namespace, *schemaloc, *mime_cfg;
      84             : #if !defined(GPAC_DISABLE_ISOM_WRITE)
      85             :         u8 *tk_template;
      86             :         u32 tk_template_size;
      87             : #endif
      88             :         GF_Language *lang_desc = NULL;
      89             :         Bool external_base=GF_FALSE;
      90             :         Bool has_scalable_layers = GF_FALSE;
      91        1199 :         u8 *dsi = NULL, *enh_dsi = NULL;
      92        1199 :         u32 dsi_size = 0, enh_dsi_size = 0;
      93             :         Double track_dur=0;
      94        1199 :         u32 srd_id=0, srd_indep=0, srd_x=0, srd_y=0, srd_w=0, srd_h=0;
      95        1199 :         u32 base_tile_track=0;
      96        1199 :         Bool srd_full_frame=GF_FALSE;
      97             :         u32 mtype, m_subtype;
      98             :         GF_GenericSampleDescription *udesc = NULL;
      99             :         GF_Err e;
     100             :         u32 ocr_es_id;
     101             :         Bool first_config = GF_FALSE;
     102             : 
     103             : 
     104        1199 :         depends_on_id = avg_rate = max_rate = buffer_size = 0;
     105        1199 :         mime = encoding = stxtcfg = namespace = schemaloc = mime_cfg = NULL;
     106             : 
     107        1199 :         if ( gf_isom_is_media_encrypted(read->mov, track, stsd_idx)) {
     108         217 :                 gf_isom_get_original_format_type(read->mov, track, stsd_idx, &m_subtype);
     109             :         } else {
     110         982 :                 m_subtype = gf_isom_get_media_subtype(read->mov, track, stsd_idx);
     111             :         }
     112             :         
     113             :         audio_fmt = 0;
     114             :         pix_fmt = 0;
     115             :         ocr_es_id = 0;
     116        1199 :         an_esd = gf_media_map_esd(read->mov, track, stsd_idx);
     117        1199 :         if (an_esd && an_esd->decoderConfig) {
     118         921 :                 if (an_esd->decoderConfig->streamType==GF_STREAM_INTERACT) {
     119           4 :                         gf_odf_desc_del((GF_Descriptor *)an_esd);
     120           4 :                         return;
     121             :                 }
     122         917 :                 streamtype = an_esd->decoderConfig->streamType;
     123         917 :                 if (an_esd->decoderConfig->objectTypeIndication < GF_CODECID_LAST_MPEG4_MAPPING) {
     124         782 :                         codec_id = gf_codecid_from_oti(streamtype, an_esd->decoderConfig->objectTypeIndication);
     125             :                 } else {
     126             :                         codec_id = an_esd->decoderConfig->objectTypeIndication;
     127             :                 }
     128         917 :                 ocr_es_id = an_esd->OCRESID;
     129         917 :                 depends_on_id = an_esd->dependsOnESID;
     130         917 :                 lang_desc = an_esd->langDesc;
     131         917 :                 an_esd->langDesc = NULL;
     132         917 :                 esid = an_esd->ESID;
     133             : 
     134         917 :                 if (an_esd->decoderConfig->decoderSpecificInfo && an_esd->decoderConfig->decoderSpecificInfo->data) {
     135         894 :                         dsi = an_esd->decoderConfig->decoderSpecificInfo->data;
     136         894 :                         dsi_size = an_esd->decoderConfig->decoderSpecificInfo->dataLength;
     137         894 :                         an_esd->decoderConfig->decoderSpecificInfo->data = NULL;
     138         894 :                         an_esd->decoderConfig->decoderSpecificInfo->dataLength = 0;
     139             :                 }
     140             : 
     141         917 :                 gf_odf_desc_del((GF_Descriptor *)an_esd);
     142             : 
     143             : #ifndef GPAC_DISABLE_AV_PARSERS
     144         917 :                 if (dsi && (codec_id==GF_CODECID_AAC_MPEG4)) {
     145             :                         GF_M4ADecSpecInfo acfg;
     146         198 :                         gf_m4a_get_config(dsi, dsi_size, &acfg);
     147         198 :                         if (acfg.base_object_type == GF_M4A_USAC)
     148             :                                 codec_id = GF_CODECID_USAC;
     149             :                 }
     150             : #endif
     151             : 
     152             :         } else {
     153             :                 u32 pcm_flags, pcm_size;
     154             :                 Bool load_default = GF_FALSE;
     155             : 
     156         278 :                 if (an_esd)
     157           0 :                         gf_odf_desc_del((GF_Descriptor *)an_esd);
     158             : 
     159         278 :                 lang_desc = (GF_Language *) gf_odf_desc_new(GF_ODF_LANG_TAG);
     160         278 :                 gf_isom_get_media_language(read->mov, track, &lang_desc->full_lang_code);
     161         278 :                 esid = gf_isom_get_track_id(read->mov, track);
     162             : 
     163         278 :                 if (!streamtype) streamtype = gf_codecid_type(m_subtype);
     164             :                 codec_id = 0;
     165             : 
     166         278 :                 switch (m_subtype) {
     167          27 :                 case GF_ISOM_SUBTYPE_STXT:
     168             :                 case GF_ISOM_SUBTYPE_METT:
     169             :                 case GF_ISOM_SUBTYPE_SBTT:
     170             :                 case GF_ISOM_MEDIA_SUBT:
     171             : 
     172             :                         codec_id = GF_CODECID_SIMPLE_TEXT;
     173          27 :                         gf_isom_stxt_get_description(read->mov, track, stsd_idx, &mime, &encoding, &stxtcfg);
     174          27 :                         break;
     175          13 :                 case GF_ISOM_SUBTYPE_STPP:
     176             :                         codec_id = GF_CODECID_SUBS_XML;
     177          13 :                         gf_isom_xml_subtitle_get_description(read->mov, track, stsd_idx, &namespace, &schemaloc, &mime);
     178          13 :                         break;
     179           3 :                 case GF_ISOM_SUBTYPE_METX:
     180             :                         codec_id = GF_CODECID_META_XML;
     181           3 :                         gf_isom_xml_subtitle_get_description(read->mov, track, stsd_idx, &namespace, &schemaloc, &mime);
     182           3 :                         break;
     183           4 :                 case GF_ISOM_SUBTYPE_WVTT:
     184             :                         codec_id = GF_CODECID_WEBVTT;
     185           4 :                         stxtcfg = gf_isom_get_webvtt_config(read->mov, track, stsd_idx);
     186           4 :                         break;
     187           7 :                 case GF_ISOM_SUBTYPE_MJP2:
     188             :                         codec_id = GF_CODECID_J2K;
     189           7 :                         gf_isom_get_jp2_config(read->mov, track, stsd_idx, &dsi, &dsi_size);
     190           7 :                         break;
     191         105 :                 case GF_ISOM_SUBTYPE_HVT1:
     192             :                         codec_id = GF_CODECID_HEVC_TILES;
     193         105 :                         gf_isom_get_reference(read->mov, track, GF_ISOM_REF_TBAS, 1, &base_tile_track);
     194         105 :                         if (base_tile_track) {
     195         105 :                                 depends_on_id = gf_isom_get_track_id(read->mov, base_tile_track);
     196             :                         }
     197         105 :                         gf_isom_get_tile_info(read->mov, track, 1, NULL, &srd_id, &srd_indep, &srd_full_frame, &srd_x, &srd_y, &srd_w, &srd_h);
     198         105 :                         break;
     199          24 :                 case GF_ISOM_SUBTYPE_TEXT:
     200             :                 case GF_ISOM_SUBTYPE_TX3G:
     201             :                 {
     202          24 :                         GF_TextSampleDescriptor *txtcfg = NULL;
     203             :                         codec_id = GF_CODECID_TX3G;
     204          24 :                         e = gf_isom_get_text_description(read->mov, track, stsd_idx, &txtcfg);
     205          24 :                         if (e) {
     206           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[IsoMedia] Track %d unable to fetch TX3G config\n", track));
     207             :                         }
     208          24 :                         if (txtcfg) {
     209          24 :                                 gf_odf_tx3g_write(txtcfg, &dsi, &dsi_size);
     210          24 :                                 gf_odf_desc_del((GF_Descriptor *) txtcfg);
     211             :                         }
     212             :                 }
     213          24 :                         break;
     214             : 
     215           2 :                 case GF_ISOM_SUBTYPE_FLAC:
     216             :                         codec_id = GF_CODECID_FLAC;
     217           2 :                         gf_isom_flac_config_get(read->mov, track, stsd_idx, &dsi, &dsi_size);
     218           2 :                         break;
     219           0 :                 case GF_ISOM_SUBTYPE_OPUS:
     220             :                         codec_id = GF_CODECID_OPUS;
     221           0 :                         gf_isom_opus_config_get(read->mov, track, stsd_idx, &dsi, &dsi_size);
     222           0 :                         break;
     223             : 
     224          24 :                 case GF_QT_SUBTYPE_TWOS:
     225             :                 case GF_QT_SUBTYPE_SOWT:
     226             :                 case GF_QT_SUBTYPE_FL32:
     227             :                 case GF_QT_SUBTYPE_FL64:
     228             :                 case GF_QT_SUBTYPE_IN24:
     229             :                 case GF_QT_SUBTYPE_IN32:
     230             :                         codec_id = GF_CODECID_RAW;
     231          24 :                         audio_fmt = gf_audio_fmt_from_isobmf(m_subtype);
     232          24 :                         break;
     233             :                 case GF_ISOM_MEDIA_TIMECODE:
     234             :                         codec_id = GF_CODECID_TMCD;
     235             :                         streamtype = GF_STREAM_METADATA;
     236             :                         break;
     237             : 
     238           0 :                 case GF_QT_SUBTYPE_RAW:
     239             :                         codec_id = GF_CODECID_RAW;
     240           0 :                         if (streamtype==GF_STREAM_AUDIO)
     241             :                                 audio_fmt = GF_AUDIO_FMT_U8;
     242             :                         else
     243             :                                 pix_fmt = GF_PIXEL_RGB;
     244             :                         break;
     245           0 :                 case GF_QT_SUBTYPE_YUV422_10:
     246             :                         codec_id = GF_CODECID_V210;
     247           0 :                         break;
     248             : 
     249           3 :                 case GF_ISOM_SUBTYPE_IPCM:
     250           3 :                         if (gf_isom_get_pcm_config(read->mov, track, stsd_idx, &pcm_flags, &pcm_size) == GF_OK) {
     251             :                                 codec_id = GF_CODECID_RAW;
     252           3 :                                 if (pcm_size==16) audio_fmt = GF_AUDIO_FMT_S16;
     253           2 :                                 else if (pcm_size==24) audio_fmt = GF_AUDIO_FMT_S24;
     254           1 :                                 else if (pcm_size==32) audio_fmt = GF_AUDIO_FMT_S32;
     255             :                         }
     256             :                         break;
     257           2 :                 case GF_ISOM_SUBTYPE_FPCM:
     258           2 :                         if (gf_isom_get_pcm_config(read->mov, track, stsd_idx, &pcm_flags, &pcm_size) == GF_OK) {
     259             :                                 codec_id = GF_CODECID_RAW;
     260           2 :                                 audio_fmt = (pcm_size==64) ? GF_AUDIO_FMT_DBL : GF_AUDIO_FMT_FLT;
     261             :                         }
     262             :                         break;
     263             : 
     264           0 :                 case GF_ISOM_SUBTYPE_VVC1:
     265             :                 case GF_ISOM_SUBTYPE_VVI1:
     266             :                 {
     267           0 :                         GF_VVCConfig *vvccfg = gf_isom_vvc_config_get(read->mov, track, stsd_idx);
     268           0 :                         if (vvccfg) {
     269           0 :                                 gf_odf_vvc_cfg_write(vvccfg, &dsi, &dsi_size);
     270           0 :                                 gf_odf_vvc_cfg_del(vvccfg);
     271             :                         }
     272             :                         codec_id = GF_CODECID_VVC;
     273             :                 }
     274             :                         break;
     275             : 
     276           9 :                 case GF_ISOM_SUBTYPE_AC3:
     277             :                 case GF_ISOM_SUBTYPE_EC3:
     278             :                 {
     279           9 :                         GF_AC3Config *ac3cfg = gf_isom_ac3_config_get(read->mov, track, stsd_idx);
     280           9 :                         codec_id = (m_subtype==GF_ISOM_SUBTYPE_AC3) ? GF_CODECID_AC3 : GF_CODECID_EAC3;
     281           9 :                         if (ac3cfg) {
     282           9 :                                 gf_odf_ac3_cfg_write(ac3cfg, &dsi, &dsi_size);
     283           9 :                                 gf_free(ac3cfg);
     284             :                         }
     285             :                 }
     286             :                         break;
     287             : 
     288           1 :                 case GF_ISOM_SUBTYPE_MLPA:
     289             :                 {
     290             :                         u32 fmt, prate;
     291           1 :                         if (gf_isom_truehd_config_get(read->mov, track, stsd_idx, &fmt, &prate) == GF_OK) {
     292           1 :                                 GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     293           1 :                                 gf_bs_write_u32(bs, fmt);
     294           1 :                                 gf_bs_write_int(bs, prate, 15);
     295           1 :                                 gf_bs_write_int(bs, 0, 1);
     296           1 :                                 gf_bs_write_u32(bs, 0);
     297           1 :                                 gf_bs_get_content(bs, &dsi, &dsi_size);
     298           1 :                                 gf_bs_del(bs);
     299             :                                 codec_id = GF_CODECID_TRUEHD;
     300             :                         }
     301             :                         break;
     302             :                 }
     303             : 
     304             : 
     305          51 :                 default:
     306          51 :                         codec_id = gf_codec_id_from_isobmf(m_subtype);
     307          51 :                         if (!codec_id) {
     308           3 :                                 pix_fmt = gf_pixel_fmt_from_qt_type(m_subtype);
     309           3 :                                 if (pix_fmt) {
     310             :                                         codec_id = GF_CODECID_RAW;
     311             :                                 } else {
     312             :                                         load_default = GF_TRUE;
     313             :                                 }
     314             :                         }
     315             :                         break;
     316             :                 }
     317             : 
     318         278 :                 if (load_default) {
     319           3 :                         if (!codec_id) {
     320           3 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[IsoMedia] Track %d type %s not natively handled\n", track, gf_4cc_to_str(m_subtype) ));
     321             : 
     322           3 :                                 codec_id = m_subtype;
     323             :                         }
     324           3 :                         udesc = gf_isom_get_generic_sample_description(read->mov, track, stsd_idx);
     325           3 :                         if (udesc) {
     326           0 :                                 dsi = udesc->extension_buf;
     327           0 :                                 dsi_size = udesc->extension_buf_size;
     328           0 :                                 udesc->extension_buf = NULL;
     329           0 :                                 udesc->extension_buf_size = 0;
     330             :                         }
     331             :                 }
     332             :         }
     333        1195 :         if (!streamtype || !codec_id) {
     334           0 :                 if (udesc) gf_free(udesc);
     335           0 :                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[IsoMedia] Failed to %s pid for track %d, could not extract codec/streamtype info\n", ch ? "update" : "create", track));
     336           0 :                 if (lang_desc) gf_odf_desc_del((GF_Descriptor *)lang_desc);
     337           0 :                 if (dsi) gf_free(dsi);
     338             :                 return;
     339             :         }
     340             : 
     341        1195 :         mime_cfg = gf_isom_subtitle_get_mime(read->mov, track, stsd_idx);
     342             : 
     343             :         //first setup, creation of PID and channel
     344        1195 :         if (!ch) {
     345             :                 Bool use_sidx_dur = GF_FALSE;
     346             :                 GF_FilterPid *pid;
     347             :                 first_config = GF_TRUE;
     348             : 
     349        1138 :                 gf_isom_get_reference(read->mov, track, GF_ISOM_REF_BASE, 1, &base_track);
     350             : 
     351        1138 :                 if (base_track) {
     352             :                         u32 base_subtype=0;
     353           6 :                         if (read->smode==MP4DMX_SINGLE)
     354             :                                 depends_on_id = 0;
     355             : 
     356           6 :                         switch (m_subtype) {
     357           0 :                         case GF_ISOM_SUBTYPE_LHV1:
     358             :                         case GF_ISOM_SUBTYPE_LHE1:
     359           0 :                                 base_subtype = gf_isom_get_media_subtype(read->mov, base_track, stsd_idx);
     360           0 :                                 switch (base_subtype) {
     361             :                                 case GF_ISOM_SUBTYPE_HVC1:
     362             :                                 case GF_ISOM_SUBTYPE_HEV1:
     363             :                                 case GF_ISOM_SUBTYPE_HVC2:
     364             :                                 case GF_ISOM_SUBTYPE_HEV2:
     365             :                                         break;
     366             :                                 default:
     367             :                                         external_base=GF_TRUE;
     368             :                                         break;
     369             :                                 }
     370             :                         }
     371             :                         if (external_base) {
     372           0 :                                 depends_on_id = gf_isom_get_track_id(read->mov, base_track);
     373             :                                 has_scalable_layers = GF_TRUE;
     374             :                         } else {
     375           6 :                                 switch (gf_isom_get_hevc_lhvc_type(read->mov, track, stsd_idx)) {
     376           2 :                                 case GF_ISOM_HEVCTYPE_HEVC_LHVC:
     377             :                                 case GF_ISOM_HEVCTYPE_LHVC_ONLY:
     378             :                                         has_scalable_layers = GF_TRUE;
     379           2 :                                         break;
     380             :                                 //this is likely temporal sublayer of base
     381           0 :                                 case GF_ISOM_HEVCTYPE_HEVC_ONLY:
     382             :                                         has_scalable_layers = GF_FALSE;
     383           0 :                                         if (gf_isom_get_reference_count(read->mov, track, GF_ISOM_REF_SCAL)<=0) {
     384           0 :                                                 depends_on_id = gf_isom_get_track_id(read->mov, base_track);
     385             :                                         }
     386             :                                         break;
     387             :                                 default:
     388             :                                         break;
     389             :                                 }
     390             :                         }
     391             :                 } else {
     392        1132 :                         switch (gf_isom_get_hevc_lhvc_type(read->mov, track, stsd_idx)) {
     393             :                         case GF_ISOM_HEVCTYPE_HEVC_LHVC:
     394             :                         case GF_ISOM_HEVCTYPE_LHVC_ONLY:
     395             :                                 has_scalable_layers = GF_TRUE;
     396             :                                 break;
     397             :                         default:
     398             :                                 break;
     399             :                         }
     400             : 
     401             :                         if (!has_scalable_layers) {
     402             :                                 u32 i;
     403        1129 :                                 GF_ISOTrackID track_id = gf_isom_get_track_id(read->mov, track);
     404        5041 :                                 for (i=0; i<gf_isom_get_track_count(read->mov); i++) {
     405        2787 :                                         if (gf_isom_get_reference_count(read->mov, i+1, GF_ISOM_REF_BASE)>=0) {
     406             :                                                 GF_ISOTrackID tkid;
     407        2787 :                                                 gf_isom_get_reference_ID(read->mov, i+1, GF_ISOM_REF_BASE, 1, &tkid);
     408        2787 :                                                 if (tkid==track_id) {
     409             :                                                         has_scalable_layers = GF_TRUE;
     410           4 :                                                         break;
     411             :                                                 }
     412             :                                         }
     413             :                                 }
     414             :                         }
     415             :                 }
     416             : 
     417        1138 :                 if (base_track && !ocr_es_id) {
     418           0 :                         ocr_es_id = gf_isom_get_track_id(read->mov, base_track);
     419             :                 }
     420        1138 :                 if (!ocr_es_id) ocr_es_id = esid;
     421             : 
     422             :                 //OK declare PID
     423        1138 :                 pid = gf_filter_pid_new(read->filter);
     424        1138 :                 if (read->pid)
     425         844 :                         gf_filter_pid_copy_properties(pid, read->pid);
     426             : 
     427        1138 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_ID, &PROP_UINT(esid));
     428        1138 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_CLOCK_ID, &PROP_UINT(ocr_es_id));
     429        1138 :                 if (depends_on_id && (depends_on_id != esid))
     430         114 :                         gf_filter_pid_set_property(pid, GF_PROP_PID_DEPENDENCY_ID, &PROP_UINT(depends_on_id));
     431             : 
     432        1138 :                 if (gf_isom_get_track_count(read->mov)>1) {
     433             :                         char szPName[1024];
     434         323 :                         const char *szST = gf_stream_type_name(streamtype);
     435         323 :                         sprintf(szPName, "%c%d", szST[0], esid);
     436         323 :                         gf_filter_pid_set_name(pid, szPName);
     437             :                 }
     438             : 
     439             :                 //MPEG-4 systems present
     440        1138 :                 if (use_iod)
     441          47 :                         gf_filter_pid_set_property(pid, GF_PROP_PID_ESID, &PROP_UINT(esid));
     442             : 
     443        1138 :                 if (gf_isom_is_track_in_root_od(read->mov, track)) {
     444          30 :                         switch (streamtype) {
     445          30 :                         case GF_STREAM_SCENE:
     446             :                         case GF_STREAM_OD:
     447          30 :                                 gf_filter_pid_set_property(pid, GF_PROP_PID_IN_IOD, &PROP_BOOL(GF_TRUE));
     448          30 :                                 break;
     449             :                         }
     450             :                 }
     451             : 
     452        1138 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(streamtype));
     453        1138 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_TIMESCALE, &PROP_UINT( gf_isom_get_media_timescale(read->mov, track) ) );
     454             : 
     455        1138 :                 if (!gf_sys_is_test_mode())
     456          23 :                         gf_filter_pid_set_property(pid, GF_PROP_PID_TRACK_NUM, &PROP_UINT(track) );
     457             : 
     458             :                 //Dolby Vision
     459        1138 :                 if (m_subtype == GF_ISOM_SUBTYPE_DVHE) {
     460           1 :                         GF_DOVIDecoderConfigurationRecord *dovi = gf_isom_dovi_config_get(read->mov, track, 1);
     461           1 :                         if (dovi) {
     462           1 :                                 u8 *data = NULL;
     463           1 :                                 u32 size = 0;
     464           1 :                                 GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
     465           1 :                                 gf_odf_dovi_cfg_write_bs(dovi, bs);
     466           1 :                                 gf_bs_get_content(bs, &data, &size);
     467           1 :                                 gf_filter_pid_set_property(pid, GF_PROP_PID_DOLBY_VISION, &PROP_DATA_NO_COPY(data, size));
     468           1 :                                 gf_bs_del(bs);
     469           1 :                                 gf_odf_dovi_cfg_del(dovi);
     470             :                         }
     471             :                 }
     472             : 
     473             :                 //create our channel
     474        1138 :                 ch = isor_create_channel(read, pid, track, 0, (codec_id==GF_CODECID_LHVC) ? GF_TRUE : GF_FALSE);
     475             : 
     476        1138 :                 if (lang_desc) {
     477         279 :                         char *lang=NULL;
     478         279 :                         gf_isom_get_media_language(read->mov, track, &lang);
     479             :                         //s32 idx = gf_lang_find(lang);
     480         279 :                         gf_filter_pid_set_property(pid, GF_PROP_PID_LANGUAGE, &PROP_STRING( lang ));
     481         279 :                         if (lang) gf_free(lang);
     482         279 :                         gf_odf_desc_del((GF_Descriptor *)lang_desc);
     483             :                         lang_desc = NULL;
     484             :                 }
     485             : 
     486             : 
     487        1138 :                 if (has_scalable_layers)
     488           9 :                         gf_filter_pid_set_property(pid, GF_PROP_PID_SCALABLE, &PROP_BOOL(GF_TRUE));
     489             : 
     490        1138 :                 if (gf_isom_get_reference_count(read->mov, track, GF_ISOM_REF_SABT)>0) {
     491          12 :                         gf_filter_pid_set_property(pid, GF_PROP_PID_TILE_BASE, &PROP_BOOL(GF_TRUE));
     492             :                 }
     493             : 
     494        1138 :                 if (srd_w && srd_h) {
     495          81 :                         gf_filter_pid_set_property(pid, GF_PROP_PID_CROP_POS, &PROP_VEC2I_INT(srd_x, srd_y) );
     496          81 :                         if (base_tile_track) {
     497          81 :                                 gf_isom_get_visual_info(read->mov, base_tile_track, stsd_idx, &w, &h);
     498          81 :                                 if (w && h) {
     499          81 :                                         gf_filter_pid_set_property(pid, GF_PROP_PID_ORIG_SIZE, &PROP_VEC2I_INT(w, h) );
     500             :                                 }
     501             :                         }
     502             :                 }
     503             : 
     504        3414 :                 for (exp_refs=0; exp_refs<3; exp_refs++) {
     505        3414 :                         u32 rtype = (exp_refs==2) ? GF_ISOM_REF_TBAS : exp_refs ? GF_ISOM_REF_SABT : GF_ISOM_REF_SCAL;
     506        3414 :                         const char *rname = (exp_refs==2) ? "isom:tbas" : exp_refs ? "isom:sabt" : "isom:scal";
     507        3414 :                         if (!exp_refs && (codec_id==GF_CODECID_LHVC))
     508           0 :                                 continue;
     509             : 
     510        3414 :                         nb_refs = gf_isom_get_reference_count(read->mov, track, rtype);
     511        3414 :                         if (nb_refs) {
     512             :                                 u32 j;
     513             :                                 GF_PropertyValue prop;
     514         126 :                                 prop.type = GF_PROP_4CC_LIST;
     515         126 :                                 prop.value.uint_list.nb_items = nb_refs;
     516         126 :                                 prop.value.uint_list.vals = gf_malloc(sizeof(u32)*nb_refs);
     517         474 :                                 for (j=0; j<nb_refs; j++) {
     518             :                                         u32 ref_tk;
     519         222 :                                         gf_isom_get_reference(read->mov, track, rtype, j+1, &ref_tk );
     520         222 :                                         prop.value.uint_list.vals[j] = gf_isom_get_track_id(read->mov, ref_tk);
     521             :                                 }
     522         126 :                                 gf_filter_pid_set_property_str(pid, rname, &prop);
     523         126 :                                 gf_free(prop.value.uint_list.vals);
     524             :                         }
     525             :                 }
     526             : 
     527        1138 :                 ch->duration = gf_isom_get_track_duration(read->mov, ch->track);
     528        1138 :                 if (!ch->duration) {
     529         272 :                         ch->duration = gf_isom_get_duration(read->mov);
     530             :                 }
     531        1138 :                 sample_count = gf_isom_get_sample_count(read->mov, ch->track);
     532             : 
     533        1138 :                 if (read->frag_type && !read->input_loaded) {
     534             :                         u32 ts;
     535             :                         u64 dur;
     536           1 :                         if (gf_isom_get_sidx_duration(read->mov, &dur, &ts)==GF_OK) {
     537           0 :                                 dur *= read->time_scale;
     538           0 :                                 dur /= ts;
     539           0 :                                 ch->duration = dur;
     540             :                                 use_sidx_dur = GF_TRUE;
     541             :                                 sample_count = 0;
     542             :                         }
     543             :                 }
     544             : 
     545        1138 :                 if (!read->mem_load_mode) {
     546             :                         //if no edit list (whether complex or simple TS offset) and no sidx, use media duration
     547        1134 :                         if (!ch->has_edit_list && !use_sidx_dur && !ch->ts_offset) {
     548             :                                 //no specific edit list type but edit present, use the duration in the edit
     549         918 :                                 if (gf_isom_get_edits_count(read->mov, ch->track)) {
     550          34 :                                         u64 dur = gf_isom_get_track_duration(read->mov, ch->track);
     551          34 :                                         gf_filter_pid_set_property(pid, GF_PROP_PID_DURATION, &PROP_FRAC64_INT(dur, read->time_scale));
     552             :                                 } else {
     553         884 :                                         u64 dur = gf_isom_get_media_duration(read->mov, ch->track);
     554         884 :                                         gf_filter_pid_set_property(pid, GF_PROP_PID_DURATION, &PROP_FRAC64_INT(dur, ch->time_scale));
     555             :                                 }
     556             :                         }
     557             :                         //otherwise trust track duration
     558             :                         else {
     559         216 :                                 gf_filter_pid_set_property(pid, GF_PROP_PID_DURATION, &PROP_FRAC64_INT(ch->duration, read->time_scale));
     560             :                         }
     561        1134 :                         gf_filter_pid_set_property(pid, GF_PROP_PID_NB_FRAMES, &PROP_UINT(sample_count));
     562             :                 }
     563             : 
     564        1138 :                 if (sample_count && (streamtype==GF_STREAM_VISUAL)) {
     565         564 :                         u64 mdur = gf_isom_get_media_duration(read->mov, track);
     566         564 :                         mdur /= sample_count;
     567         564 :                         gf_filter_pid_set_property(pid, GF_PROP_PID_FPS, &PROP_FRAC_INT(ch->time_scale, (u32) mdur));
     568             :                 }
     569             : 
     570        1138 :                 track_dur = (Double) (s64) ch->duration;
     571        1138 :                 track_dur /= read->time_scale;
     572             :                 //move channel duration in media timescale
     573        1138 :                 ch->duration = (u64) (track_dur * ch->time_scale);
     574             : 
     575             : 
     576             :                 //set stream subtype
     577        1138 :                 mtype = gf_isom_get_media_type(read->mov, track);
     578        1138 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_SUBTYPE, &PROP_4CC(mtype) );
     579             : 
     580        1138 :                 if (!read->mem_load_mode) {
     581        1134 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_MEDIA_DATA_SIZE, &PROP_LONGUINT(gf_isom_get_media_data_size(read->mov, track) ) );
     582             :                 }
     583             :                 //in no cache mode, depending on fetch speed we may have fetched a fragment or not, resulting in has_rap set
     584             :                 //always for HAS_SYNC to false
     585           4 :                 else if (gf_sys_is_test_mode() && !sample_count) {
     586           1 :                         gf_filter_pid_set_property(pid, GF_PROP_PID_HAS_SYNC, &PROP_BOOL(GF_FALSE) );
     587             :                 }
     588             : 
     589             : 
     590        1138 :                 w = gf_isom_get_constant_sample_size(read->mov, track);
     591        1138 :                 if (w)
     592         106 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_FRAME_SIZE, &PROP_UINT(w));
     593             : 
     594        1138 :                 if (read->mem_load_mode) {
     595           4 :                         gf_filter_pid_set_property(pid, GF_PROP_PID_PLAYBACK_MODE, &PROP_UINT(GF_PLAYBACK_MODE_NONE) );
     596             :                 } else {
     597        1134 :                         gf_filter_pid_set_property(pid, GF_PROP_PID_PLAYBACK_MODE, &PROP_UINT(GF_PLAYBACK_MODE_REWIND) );
     598             :                 }
     599             : 
     600             :                 GF_PropertyValue brands;
     601        1138 :                 brands.type = GF_PROP_4CC_LIST;
     602        1138 :                 u32 major_brand=0;
     603        1138 :                 gf_isom_get_brand_info(read->mov, &major_brand, NULL, &brands.value.uint_list.nb_items);
     604        1138 :                 brands.value.uint_list.vals = (u32 *) gf_isom_get_brands(read->mov);
     605        1138 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_ISOM_BRANDS, &brands);
     606        1138 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_ISOM_MBRAND, &PROP_4CC(major_brand) );
     607             : 
     608             :                 //we cannot expose average size/dur in mem mode with fragmented files (sample_count=0)
     609        1138 :                 if (sample_count) {
     610         883 :                         max_size = gf_isom_get_max_sample_size(read->mov, ch->track);
     611         883 :                         if (max_size) gf_filter_pid_set_property(pid, GF_PROP_PID_MAX_FRAME_SIZE, &PROP_UINT(max_size) );
     612             : 
     613         883 :                         max_size = gf_isom_get_avg_sample_size(read->mov, ch->track);
     614         883 :                         if (max_size) gf_filter_pid_set_property(pid, GF_PROP_PID_AVG_FRAME_SIZE, &PROP_UINT(max_size) );
     615             : 
     616         883 :                         max_size = gf_isom_get_max_sample_delta(read->mov, ch->track);
     617         883 :                         if (max_size) gf_filter_pid_set_property(pid, GF_PROP_PID_MAX_TS_DELTA, &PROP_UINT(max_size) );
     618             : 
     619         883 :                         max_size = gf_isom_get_max_sample_cts_offset(read->mov, ch->track);
     620         883 :                         if (max_size) gf_filter_pid_set_property(pid, GF_PROP_PID_MAX_CTS_OFFSET, &PROP_UINT(max_size) );
     621             : 
     622         883 :                         max_size = gf_isom_get_constant_sample_duration(read->mov, ch->track);
     623         883 :                         if (max_size) gf_filter_pid_set_property(pid, GF_PROP_PID_CONSTANT_DURATION, &PROP_UINT(max_size) );
     624             :                 }
     625             : 
     626             : 
     627             :                 u32 media_pl=0;
     628        1138 :                 if (streamtype==GF_STREAM_VISUAL) {
     629         751 :                         media_pl = gf_isom_get_pl_indication(read->mov, GF_ISOM_PL_VISUAL);
     630         387 :                 } else if (streamtype==GF_STREAM_AUDIO) {
     631         277 :                         media_pl = gf_isom_get_pl_indication(read->mov, GF_ISOM_PL_AUDIO);
     632             :                 }
     633        1138 :                 if (media_pl && (media_pl!=0xFF) ) gf_filter_pid_set_property(pid, GF_PROP_PID_PROFILE_LEVEL, &PROP_UINT(media_pl) );
     634             : 
     635             : #if !defined(GPAC_DISABLE_ISOM_WRITE)
     636        1138 :                 e = gf_isom_get_track_template(read->mov, ch->track, &tk_template, &tk_template_size);
     637        1138 :                 if (e == GF_OK) {
     638        1138 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_ISOM_TRACK_TEMPLATE, &PROP_DATA_NO_COPY(tk_template, tk_template_size) );
     639             :                 } else {
     640           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[IsoMedia] Failed to serialize track box: %s\n", gf_error_to_string(e) ));
     641             :                 }
     642             : 
     643        1138 :                 e = gf_isom_get_trex_template(read->mov, ch->track, &tk_template, &tk_template_size);
     644        1138 :                 if (e == GF_OK) {
     645         264 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_ISOM_TREX_TEMPLATE, &PROP_DATA_NO_COPY(tk_template, tk_template_size) );
     646             :                 }
     647             : 
     648        1138 :                 e = gf_isom_get_raw_user_data(read->mov, &tk_template, &tk_template_size);
     649        1138 :                 if (e==GF_OK) {
     650        1138 :                         if (tk_template_size)
     651         191 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_ISOM_UDTA, &PROP_DATA_NO_COPY(tk_template, tk_template_size) );
     652             :                 } else {
     653           0 :                         GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[IsoMedia] Failed to serialize moov UDTA box: %s\n", gf_error_to_string(e) ));
     654             :                 }
     655             : #endif
     656             : 
     657             :                 GF_Fraction64 moov_time;
     658        1138 :                 moov_time.num = gf_isom_get_duration(read->mov);
     659        1138 :                 moov_time.den = gf_isom_get_timescale(read->mov);
     660        1138 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_ISOM_MOVIE_TIME, &PROP_FRAC64(moov_time) );
     661             : 
     662             : 
     663             :                 u32 i;
     664             :                 s32 tx, ty;
     665             :                 s16 l;
     666        1138 :                 gf_isom_get_track_layout_info(read->mov, ch->track, &w, &h, &tx, &ty, &l);
     667        1138 :                 if (w && h) {
     668         809 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_WIDTH, &PROP_UINT(w) );
     669         809 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_HEIGHT, &PROP_UINT(h) );
     670         809 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_TRANS_X, &PROP_SINT(tx) );
     671         809 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_TRANS_Y, &PROP_SINT(ty) );
     672         809 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_ZORDER, &PROP_SINT(l) );
     673             :                 }
     674        1138 :                 if (codec_id==GF_CODECID_TX3G) {
     675          24 :                         u32 m_w = w;
     676          24 :                         u32 m_h = h;
     677          94 :                         for (i=0; i<gf_isom_get_track_count(read->mov); i++) {
     678          46 :                                 switch (gf_isom_get_media_type(read->mov, i+1)) {
     679          11 :                                 case GF_ISOM_MEDIA_SCENE:
     680             :                                 case GF_ISOM_MEDIA_VISUAL:
     681             :                                 case GF_ISOM_MEDIA_AUXV:
     682             :                                 case GF_ISOM_MEDIA_PICT:
     683          11 :                                         gf_isom_get_track_layout_info(read->mov, i+1, &w, &h, &tx, &ty, &l);
     684          11 :                                         if (w>m_w) m_w = w;
     685          11 :                                         if (h>m_h) m_h = h;
     686             :                                         break;
     687             :                                 default:
     688             :                                         break;
     689             :                                 }
     690             :                         }
     691          24 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_WIDTH_MAX, &PROP_UINT(m_w) );
     692          24 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_HEIGHT_MAX, &PROP_UINT(m_h) );
     693             :                         char *tx3g_config_sdp = NULL;
     694          72 :                         for (i=0; i<gf_isom_get_sample_description_count(read->mov, ch->track); i++) {
     695             :                                 u8 *tx3g;
     696             :                                 u32 l1;
     697             :                                 u32 tx3g_len, len;
     698          24 :                                 e = gf_isom_text_get_encoded_tx3g(read->mov, ch->track, i+1, GF_RTP_TX3G_SIDX_OFFSET, &tx3g, &tx3g_len);
     699          24 :                                 if (e==GF_OK) {
     700             :                                         char buffer[2000];
     701          24 :                                         len = gf_base64_encode(tx3g, tx3g_len, buffer, 2000);
     702          24 :                                         gf_free(tx3g);
     703          24 :                                         buffer[len] = 0;
     704             : 
     705          24 :                                         l1 = tx3g_config_sdp ? (u32) strlen(tx3g_config_sdp) : 0;
     706          24 :                                         tx3g_config_sdp = gf_realloc(tx3g_config_sdp, len+3+l1);
     707          24 :                                         tx3g_config_sdp[l1] = 0;
     708          24 :                                         if (i) strcat(tx3g_config_sdp, ", ");
     709             :                                         strcat(tx3g_config_sdp, buffer);
     710             :                                 }
     711             :                         }
     712          24 :                         if (tx3g_config_sdp) {
     713          24 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_DECODER_CONFIG_ENHANCEMENT, &PROP_STRING_NO_COPY(tx3g_config_sdp) );
     714             :                         }
     715             :                 }
     716             : 
     717             :                 u32 idx=0;
     718           6 :                 while (1) {
     719             :                         u32 data_len, int_val2, flags;
     720             :                         u64 int_val;
     721             :                         const char *name;
     722             :                         const u8 *data;
     723             :                         GF_ISOiTunesTag itag;
     724             :                         u32 itype = 0;
     725             :                         s32 tag_idx;
     726             : 
     727        1144 :                         e = gf_isom_apple_enum_tag(read->mov, idx, &itag, &data, &data_len, &int_val, &int_val2, &flags);
     728        1144 :                         if (e) break;
     729           6 :                         idx++;
     730             : 
     731           6 :                         tag_idx = gf_itags_find_by_itag(itag);
     732           6 :                         if (tag_idx>=0)
     733           6 :                                 itype = gf_itags_get_type(tag_idx);
     734             : 
     735           6 :                         name = gf_itags_get_name(tag_idx);
     736           6 :                         switch (itype) {
     737           0 :                         case GF_ITAG_BOOL:
     738           0 :                                 gf_filter_pid_set_property_str(ch->pid, name, &PROP_BOOL((Bool) int_val ) );
     739           0 :                                 break;
     740           0 :                         case GF_ITAG_INT8:
     741             :                         case GF_ITAG_INT16:
     742             :                         case GF_ITAG_INT32:
     743           0 :                                 gf_filter_pid_set_property_str(ch->pid, name, &PROP_UINT((u32) int_val ) );
     744           0 :                                 break;
     745           0 :                         case GF_ITAG_INT64:
     746           0 :                                 gf_filter_pid_set_property_str(ch->pid, name, &PROP_LONGUINT(int_val) );
     747           0 :                                 break;
     748           0 :                         case GF_ITAG_FRAC8:
     749             :                         case GF_ITAG_FRAC6:
     750           0 :                                 gf_filter_pid_set_property_str(ch->pid, name, &PROP_FRAC_INT((s32) int_val, int_val2)  );
     751           0 :                                 break;
     752           0 :                         case GF_ITAG_FILE:
     753           0 :                                 if (data && data_len)
     754           0 :                                         gf_filter_pid_set_property_str(ch->pid, name, &PROP_DATA((u8 *)data, data_len)  );
     755             :                                 break;
     756           6 :                         default:
     757           6 :                                 if (data && data_len) {
     758           6 :                                         if (gf_utf8_is_legal(data, data_len))
     759           6 :                                                 gf_filter_pid_set_property_str(ch->pid, name, &PROP_STRING(data) );
     760             :                                         else
     761           0 :                                                 gf_filter_pid_set_property_str(ch->pid, name, &PROP_DATA((u8 *)data, data_len)  );
     762             :                                 }
     763             :                                 break;
     764             :                         }
     765             :                 }
     766             : 
     767        1138 :                 if (codec_id==GF_CODECID_TMCD) {
     768           3 :                         u32 tmcd_flags=0, tmcd_fps_num=0, tmcd_fps_den=0, tmcd_fpt=0;
     769           3 :                         gf_isom_get_tmcd_config(read->mov, track, stsd_idx, &tmcd_flags, &tmcd_fps_num, &tmcd_fps_den, &tmcd_fpt);
     770           3 :                         gf_filter_pid_set_property_str(ch->pid, "tmcd:flags", &PROP_UINT(tmcd_flags) );
     771           3 :                         gf_filter_pid_set_property_str(ch->pid, "tmcd:framerate", &PROP_FRAC_INT(tmcd_fps_num, tmcd_fps_den) );
     772           3 :                         gf_filter_pid_set_property_str(ch->pid, "tmcd:frames_per_tick", &PROP_UINT(tmcd_fpt) );
     773             : 
     774             :                 }
     775             : 
     776        1138 :                 if (gf_sys_old_arch_compat()) {
     777             :                         Bool gf_isom_has_time_offset_table(GF_ISOFile *the_file, u32 trackNumber);
     778        1114 :                         if (gf_isom_has_time_offset_table(read->mov, ch->track))
     779         228 :                                 gf_filter_pid_set_property_str(ch->pid, "isom_force_ctts", &PROP_BOOL(GF_TRUE) );
     780             :                 }
     781             : 
     782        1138 :                 if (!gf_sys_is_test_mode()) {
     783             :                         u32 nb_udta;
     784          23 :                         const char *hdlr = NULL;
     785          23 :                         gf_isom_get_handler_name(read->mov, ch->track, &hdlr);
     786          23 :                         if (hdlr)
     787          23 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_ISOM_HANDLER, &PROP_STRING(hdlr));
     788             : 
     789          23 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_ISOM_TRACK_FLAGS, &PROP_UINT( gf_isom_get_track_flags(read->mov, ch->track) ));
     790             : 
     791          23 :                         if (streamtype==GF_STREAM_VISUAL) {
     792             :                                 GF_PropertyValue p;
     793             :                                 u32 vals[9];
     794             :                                 memset(vals, 0, sizeof(u32)*9);
     795             :                                 memset(&p, 0, sizeof(GF_PropertyValue));
     796          22 :                                 p.type = GF_PROP_UINT_LIST;
     797          22 :                                 p.value.uint_list.nb_items = 9;
     798          22 :                                 p.value.uint_list.vals = vals;
     799          22 :                                 gf_isom_get_track_matrix(read->mov, ch->track, vals);
     800          22 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_ISOM_TRACK_MATRIX, &p);
     801             :                         }
     802             : 
     803             : 
     804          23 :                         nb_udta =  gf_isom_get_udta_count(read->mov, ch->track);
     805          23 :                         if (nb_udta) {
     806           0 :                                 for (i=0; i<nb_udta; i++) {
     807             :                                         u32 j, type, nb_items;
     808             :                                         bin128 uuid;
     809           0 :                                         gf_isom_get_udta_type(read->mov, ch->track, i+1, &type, &uuid);
     810           0 :                                         nb_items = gf_isom_get_user_data_count(read->mov, ch->track, type, uuid);
     811             :                                         //we only export 4CC udta boxes
     812           0 :                                         if (!type) continue;
     813             : 
     814           0 :                                         for (j=0; j<nb_items; j++) {
     815             :                                                 char szName[31];
     816           0 :                                                 u8 *udta=NULL;
     817             :                                                 u32 udta_size;
     818           0 :                                                 gf_isom_get_user_data(read->mov, ch->track, type, uuid, j+1, &udta, &udta_size);
     819           0 :                                                 if (!udta) continue;
     820           0 :                                                 if (nb_items>1)
     821           0 :                                                         snprintf(szName, 30, "udta_%s_%d", gf_4cc_to_str(type), j+1);
     822             :                                                 else
     823           0 :                                                         snprintf(szName, 30, "udta_%s", gf_4cc_to_str(type));
     824           0 :                                                 szName[30]=0;
     825           0 :                                                 if (gf_utf8_is_legal(udta, udta_size)) {
     826           0 :                                                         gf_filter_pid_set_property_dyn(ch->pid, szName, &PROP_STRING_NO_COPY(udta));
     827             :                                                 } else {
     828           0 :                                                         gf_filter_pid_set_property_dyn(ch->pid, szName, &PROP_DATA_NO_COPY(udta, udta_size));
     829             :                                                 }
     830             :                                         }
     831             :                                 }
     832             :                         }
     833             :                 }
     834             :         }
     835             : 
     836             :         //update decoder configs
     837        1195 :         ch->check_avc_ps = ch->check_hevc_ps = ch->check_vvc_ps = GF_FALSE;
     838        1195 :         if (ch->avcc) gf_odf_avc_cfg_del(ch->avcc);
     839        1195 :         ch->avcc = NULL;
     840        1195 :         if (ch->hvcc) gf_odf_hevc_cfg_del(ch->hvcc);
     841        1195 :         ch->hvcc = NULL;
     842        1195 :         if (ch->vvcc) gf_odf_vvc_cfg_del(ch->vvcc);
     843        1195 :         ch->vvcc = NULL;
     844             : 
     845        1195 :         if (lang_desc) {
     846           0 :                 gf_odf_desc_del((GF_Descriptor *)lang_desc);
     847             :                 lang_desc = NULL;
     848             :         }
     849             :         
     850        1195 :         if (read->smode != MP4DMX_SINGLE) {
     851        1195 :                 if ((codec_id==GF_CODECID_LHVC) || (codec_id==GF_CODECID_HEVC)) {
     852          88 :                         Bool signal_lhv = (read->smode==MP4DMX_SPLIT) ? GF_TRUE : GF_FALSE;
     853          88 :                         GF_HEVCConfig *hvcc = gf_isom_hevc_config_get(read->mov, track, stsd_idx);
     854          88 :                         GF_HEVCConfig *lhcc = gf_isom_lhvc_config_get(read->mov, track, stsd_idx);
     855             : 
     856          88 :                         if (hvcc || lhcc) {
     857          86 :                                 if (dsi) gf_free(dsi);
     858          86 :                                 dsi = NULL;
     859             :                                 //no base layer config
     860          86 :                                 if (!hvcc) signal_lhv = GF_TRUE;
     861             : 
     862          86 :                                 if (signal_lhv && lhcc) {
     863           3 :                                         if (hvcc) {
     864           3 :                                                 hvcc->is_lhvc = GF_FALSE;
     865           3 :                                                 gf_odf_hevc_cfg_write(hvcc, &dsi, &dsi_size);
     866             :                                         }
     867           3 :                                         lhcc->is_lhvc = GF_TRUE;
     868           3 :                                         gf_odf_hevc_cfg_write(lhcc, &enh_dsi, &enh_dsi_size);
     869             :                                         codec_id = GF_CODECID_LHVC;
     870             :                                 } else {
     871          83 :                                         if (hvcc) {
     872          83 :                                                 hvcc->is_lhvc = GF_FALSE;
     873          83 :                                                 gf_odf_hevc_cfg_write(hvcc, &dsi, &dsi_size);
     874             :                                         }
     875          83 :                                         if (lhcc) {
     876           2 :                                                 lhcc->is_lhvc = GF_TRUE;
     877           2 :                                                 gf_odf_hevc_cfg_write(lhcc, &enh_dsi, &enh_dsi_size);
     878             :                                         }
     879             :                                         codec_id = GF_CODECID_HEVC;
     880             :                                 }
     881             :                         }
     882          88 :                         if (hvcc) gf_odf_hevc_cfg_del(hvcc);
     883          88 :                         if (lhcc) gf_odf_hevc_cfg_del(lhcc);
     884             :                 }
     885        1195 :                 if ((codec_id==GF_CODECID_AVC) || (codec_id==GF_CODECID_SVC) || (codec_id==GF_CODECID_MVC)) {
     886             :                         Bool is_mvc = GF_FALSE;
     887         422 :                         Bool signal_svc = (read->smode==MP4DMX_SPLIT) ? GF_TRUE : GF_FALSE;
     888         422 :                         GF_AVCConfig *avcc = gf_isom_avc_config_get(read->mov, track, stsd_idx);
     889         422 :                         GF_AVCConfig *svcc = gf_isom_svc_config_get(read->mov, track, stsd_idx);
     890         422 :                         if (!svcc) {
     891         415 :                                 svcc = gf_isom_mvc_config_get(read->mov, track, stsd_idx);
     892             :                                 is_mvc = GF_TRUE;
     893             :                         }
     894             : 
     895         422 :                         if (avcc || svcc) {
     896         420 :                                 if (dsi) gf_free(dsi);
     897         420 :                                 dsi = NULL;
     898             :                                 //no base layer config
     899         420 :                                 if (!avcc) signal_svc = GF_TRUE;
     900             : 
     901         420 :                                 if (signal_svc && svcc) {
     902           7 :                                         if (avcc) {
     903           1 :                                                 gf_odf_avc_cfg_write(avcc, &dsi, &dsi_size);
     904             :                                         }
     905           7 :                                         gf_odf_avc_cfg_write(svcc, &enh_dsi, &enh_dsi_size);
     906           7 :                                         codec_id = is_mvc ? GF_CODECID_MVC : GF_CODECID_SVC;
     907             :                                 } else {
     908         413 :                                         if (avcc) {
     909         413 :                                                 gf_odf_avc_cfg_write(avcc, &dsi, &dsi_size);
     910             :                                         }
     911         413 :                                         if (svcc) {
     912           0 :                                                 gf_odf_avc_cfg_write(svcc, &enh_dsi, &enh_dsi_size);
     913             :                                         }
     914             :                                         codec_id = GF_CODECID_AVC;
     915             :                                 }
     916             :                         }
     917         422 :                         if (avcc) gf_odf_avc_cfg_del(avcc);
     918         422 :                         if (svcc) gf_odf_avc_cfg_del(svcc);
     919             :                 }
     920             : 
     921        1195 :                 if (!gf_sys_is_test_mode()) {
     922             :                         u64 create_date, modif_date;
     923          23 :                         gf_isom_get_creation_time(read->mov, &create_date, &modif_date);
     924          23 :                         gf_filter_pid_set_property_str(ch->pid, "isom:creation_date", &PROP_LONGUINT(create_date));
     925          23 :                         gf_filter_pid_set_property_str(ch->pid, "isom:modification_date", &PROP_LONGUINT(modif_date));
     926             :                 }
     927             : 
     928             :         }
     929             : 
     930             :         //all stsd specific init/reconfig
     931        1195 :         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_CODECID, &PROP_UINT(codec_id));
     932        1195 :         if (dsi) {
     933         931 :                 ch->dsi_crc = gf_crc_32(dsi, dsi_size);
     934         931 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(dsi, dsi_size));
     935             :         }
     936        1195 :         if (enh_dsi) {
     937          12 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_DECODER_CONFIG_ENHANCEMENT, &PROP_DATA_NO_COPY(enh_dsi, enh_dsi_size));
     938             :         }
     939        1195 :         if (audio_fmt) {
     940          29 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(audio_fmt));
     941          29 :                 if (codec_id == GF_CODECID_RAW) {
     942          29 :                         gf_isom_enable_raw_pack(read->mov, track, read->frame_size);
     943             :                 }
     944             :         }
     945        1195 :         if (pix_fmt) {
     946           0 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_PIXFMT, &PROP_UINT(pix_fmt));
     947             :         }
     948             : 
     949        1195 :         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_CONFIG_IDX, &PROP_UINT(stsd_idx) );
     950             : 
     951        1195 :         w = h = 0;
     952        1195 :         gf_isom_get_visual_info(read->mov, track, stsd_idx, &w, &h);
     953        1195 :         if (w && h) {
     954             :                 GF_ISOM_Y3D_Info yt3d;
     955             :                 u32 hspace, vspace;
     956         826 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_WIDTH, &PROP_UINT(w));
     957         826 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_HEIGHT, &PROP_UINT(h));
     958             : 
     959         826 :                 gf_isom_get_pixel_aspect_ratio(read->mov, track, stsd_idx, &hspace, &vspace);
     960         826 :                 if (hspace != vspace)
     961           4 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_SAR, &PROP_FRAC_INT(hspace, vspace) );
     962             : 
     963             : 
     964         826 :                 e = gf_isom_get_y3d_info(ch->owner->mov, ch->track, stsd_idx, &yt3d);
     965         826 :                 if (e==GF_OK) {
     966           0 :                         if (yt3d.stereo_type) {
     967           0 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_STEREO_TYPE, &PROP_UINT(yt3d.stereo_type));
     968             :                         } else {
     969           0 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_STEREO_TYPE, NULL);
     970             :                         }
     971             : 
     972           0 :                         if (yt3d.projection_type) {
     973           0 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_PROJECTION_TYPE, &PROP_UINT(yt3d.projection_type));
     974           0 :                                 if (yt3d.projection_type==GF_PROJ360_CUBE_MAP) {
     975           0 :                                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_CUBE_MAP_PAD, yt3d.padding ? &PROP_UINT(yt3d.padding) : NULL);
     976             :                                 }
     977           0 :                                 else if (yt3d.projection_type==GF_PROJ360_EQR) {
     978           0 :                                         if (yt3d.top || yt3d.bottom || yt3d.left || yt3d.right)
     979           0 :                                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_EQR_CLAMP, &PROP_VEC4I_INT(yt3d.top, yt3d.bottom , yt3d.left , yt3d.right));
     980             :                                         else
     981           0 :                                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_EQR_CLAMP, NULL);
     982             :                                 }
     983             :                         } else {
     984           0 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_PROJECTION_TYPE, NULL);
     985             :                         }
     986           0 :                         if (yt3d.pose_present) {
     987           0 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_VR_POSE, &PROP_VEC3I_INT(yt3d.yaw, yt3d.pitch, yt3d.roll) );
     988             :                         } else {
     989           0 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_VR_POSE, NULL);
     990             :                         }
     991             :                 }
     992             :         }
     993        1195 :         sr = nb_ch = nb_bps = 0;
     994        1195 :         gf_isom_get_audio_info(read->mov,track, stsd_idx, &sr, &nb_ch, &nb_bps);
     995        1195 :         if (streamtype==GF_STREAM_AUDIO) {
     996         277 :                 if (!sr) sr = gf_isom_get_media_timescale(read->mov, track);
     997             :         }
     998             :         //nb_ch may be set to 0 for "not applicable" (3D / object coding audio)
     999        1195 :         if (sr) {
    1000             :                 u32 d1, d2;
    1001         277 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_SAMPLE_RATE, &PROP_UINT(sr));
    1002         277 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_NUM_CHANNELS, &PROP_UINT(nb_ch));
    1003             : 
    1004             :                 //to remove once we deprecate master
    1005         277 :                 if (!gf_sys_old_arch_compat()) {
    1006             :                         GF_AudioChannelLayout layout;
    1007           1 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_AUDIO_BPS, &PROP_UINT(nb_bps));
    1008             : 
    1009           1 :                         if (gf_isom_get_audio_layout(read->mov, track, stsd_idx, &layout)==GF_OK) {
    1010           0 :                                 if (layout.definedLayout) {
    1011           0 :                                         u64 lay = gf_audio_fmt_get_layout_from_cicp(layout.definedLayout);
    1012           0 :                                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_CHANNEL_LAYOUT, &PROP_LONGUINT(lay));
    1013             :                                 }
    1014             : 
    1015             :                         }
    1016             : 
    1017             :                 }
    1018             : 
    1019         277 :                 if (first_config ) {
    1020         277 :                         d1 = gf_isom_get_sample_duration(read->mov, ch->track, 1);
    1021         277 :                         d2 = gf_isom_get_sample_duration(read->mov, ch->track, 2);
    1022         277 :                         if (d1 && d2 && (d1==d2)) {
    1023         207 :                                 d1 *= sr;
    1024         207 :                                 d1 /= ch->time_scale;
    1025         207 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_SAMPLES_PER_FRAME, &PROP_UINT(d1));
    1026             :                         }
    1027             :                 }
    1028             : 
    1029         277 :                 if ((codec_id==GF_CODECID_MPHA) || (codec_id==GF_CODECID_MHAS)) {
    1030             :                         u32 nb_profiles;
    1031           1 :                         const u8 *prof_compat = gf_isom_get_mpegh_compatible_profiles(read->mov, ch->track, stsd_idx, &nb_profiles);
    1032           1 :                         if (prof_compat) {
    1033             :                                 u32 j;
    1034             :                                 GF_PropertyValue prop;
    1035           0 :                                 prop.type = GF_PROP_UINT_LIST;
    1036           0 :                                 prop.value.uint_list.nb_items = nb_profiles;
    1037           0 :                                 prop.value.uint_list.vals = gf_malloc(sizeof(u32)*nb_profiles);
    1038           0 :                                 for (j=0; j<nb_profiles; j++)
    1039           0 :                                         prop.value.uint_list.vals[j] = prof_compat[j];
    1040           0 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_MHA_COMPATIBLE_PROFILES, &prop);
    1041           0 :                                 gf_free(prop.value.uint_list.vals);
    1042             :                         }
    1043             :                 }
    1044             :         }
    1045             : 
    1046             : 
    1047        1195 :         gf_isom_get_bitrate(read->mov, ch->track, stsd_idx, &avg_rate, &max_rate, &buffer_size);
    1048             : 
    1049        1195 :         if (!avg_rate) {
    1050         184 :                 if (first_config && ch->duration) {
    1051          91 :                         u64 avgrate = 8 * gf_isom_get_media_data_size(read->mov, ch->track);
    1052          91 :                         avgrate = (u64) (avgrate / track_dur);
    1053          91 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_BITRATE, &PROP_UINT((u32) avgrate));
    1054             :                 }
    1055             :         } else {
    1056        1011 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_BITRATE, &PROP_UINT((u32) avg_rate));
    1057        1011 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_MAXRATE, &PROP_UINT((u32) max_rate));
    1058        1011 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_DBSIZE, &PROP_UINT((u32) buffer_size));
    1059             :         }
    1060             : 
    1061        1195 :         if (mime) gf_filter_pid_set_property_str(ch->pid, "meta:mime", &PROP_STRING(mime) );
    1062        1195 :         if (encoding) gf_filter_pid_set_property_str(ch->pid, "meta:encoding", &PROP_STRING(encoding) );
    1063        1195 :         if (namespace) gf_filter_pid_set_property_str(ch->pid, "meta:xmlns", &PROP_STRING(namespace) );
    1064        1195 :         if (schemaloc) gf_filter_pid_set_property_str(ch->pid, "meta:schemaloc", &PROP_STRING(schemaloc) );
    1065        1195 :         if (mime_cfg) gf_filter_pid_set_property_str(ch->pid, "meta:mime", &PROP_STRING(mime_cfg) );
    1066        1195 :         else if ((m_subtype==GF_ISOM_SUBTYPE_STPP) && namespace && strstr(namespace, "ns/ttml")) {
    1067             :                 mime_cfg = "application/ttml+xml;codecs=im1t";
    1068          10 :                 if (gf_isom_sample_has_subsamples(read->mov, track, 0, 0) )
    1069             :                         mime_cfg = "application/ttml+xml;codecs=im1i";
    1070          10 :                 gf_filter_pid_set_property_str(ch->pid, "meta:mime", &PROP_STRING(mime_cfg) );
    1071             :         }
    1072             : 
    1073        1195 :         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_ISOM_SUBTYPE, &PROP_4CC(m_subtype) );
    1074        1195 :         if (stxtcfg) gf_filter_pid_set_property(ch->pid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA((char *)stxtcfg, (u32) strlen(stxtcfg) ));
    1075             : 
    1076             : 
    1077             : #if !defined(GPAC_DISABLE_ISOM_WRITE)
    1078        1195 :         tk_template=NULL;
    1079        1195 :         tk_template_size=0;
    1080        1195 :         e = gf_isom_get_stsd_template(read->mov, ch->track, stsd_idx, &tk_template, &tk_template_size);
    1081        1195 :         if (e == GF_OK) {
    1082        1195 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_ISOM_STSD_TEMPLATE, &PROP_DATA_NO_COPY(tk_template, tk_template_size) );
    1083             :         } else {
    1084           0 :                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[IsoMedia] Failed to serialize stsd box: %s\n", gf_error_to_string(e) ));
    1085             :         }
    1086             : #endif
    1087             : 
    1088        1195 :         if (codec_id == GF_CODECID_DIMS) {
    1089             :                 GF_DIMSDescription dims;
    1090             :                 memset(&dims, 0, sizeof(GF_DIMSDescription));
    1091             : 
    1092           2 :                 gf_isom_get_dims_description(read->mov, ch->track, stsd_idx, &dims);
    1093           2 :                 gf_filter_pid_set_property_str(ch->pid, "dims:profile", &PROP_UINT(dims.profile));
    1094           2 :                 gf_filter_pid_set_property_str(ch->pid, "dims:level", &PROP_UINT(dims.level));
    1095           2 :                 gf_filter_pid_set_property_str(ch->pid, "dims:pathComponents", &PROP_UINT(dims.pathComponents));
    1096           2 :                 gf_filter_pid_set_property_str(ch->pid, "dims:fullRequestHost", &PROP_BOOL(dims.fullRequestHost));
    1097           2 :                 gf_filter_pid_set_property_str(ch->pid, "dims:streamType", &PROP_BOOL(dims.streamType));
    1098           2 :                 gf_filter_pid_set_property_str(ch->pid, "dims:redundant", &PROP_BOOL(dims.containsRedundant));
    1099           2 :                 if (dims.content_script_types)
    1100           0 :                         gf_filter_pid_set_property_str(ch->pid, "dims:scriptTypes", &PROP_STRING(dims.content_script_types));
    1101           2 :                 if (dims.textEncoding)
    1102           2 :                         gf_filter_pid_set_property_str(ch->pid, "meta:encoding", &PROP_STRING(dims.textEncoding));
    1103           2 :                 if (dims.contentEncoding)
    1104           2 :                         gf_filter_pid_set_property_str(ch->pid, "meta:content_encoding", &PROP_STRING(dims.contentEncoding));
    1105           2 :                 if (dims.xml_schema_loc)
    1106           0 :                         gf_filter_pid_set_property_str(ch->pid, "meta:schemaloc", &PROP_STRING(dims.xml_schema_loc));
    1107           2 :                 if (dims.mime_type)
    1108           0 :                         gf_filter_pid_set_property_str(ch->pid, "meta:mime", &PROP_STRING(dims.mime_type));
    1109             :         }
    1110        1193 :         else if (codec_id==GF_CODECID_AVC)
    1111         415 :                 ch->check_avc_ps = (ch->owner->xps_check==MP4DMX_XPS_REMOVE) ? GF_TRUE : GF_FALSE;
    1112         778 :         else if (codec_id==GF_CODECID_HEVC)
    1113          85 :                 ch->check_hevc_ps = (ch->owner->xps_check==MP4DMX_XPS_REMOVE) ? GF_TRUE : GF_FALSE;
    1114         693 :         else if (codec_id==GF_CODECID_VVC)
    1115           0 :                 ch->check_vvc_ps = (ch->owner->xps_check==MP4DMX_XPS_REMOVE) ? GF_TRUE : GF_FALSE;
    1116         693 :         else if (codec_id==GF_CODECID_MHAS) {
    1117           1 :                 if (!dsi) {
    1118           1 :                         ch->check_mhas_pl = GF_TRUE;
    1119           1 :                         GF_ISOSample *samp = gf_isom_get_sample(ch->owner->mov, ch->track, 1, NULL);
    1120           1 :                         if (samp) {
    1121           1 :                                 u64 ch_layout=0;
    1122           1 :                                 s32 PL = gf_mpegh_get_mhas_pl(samp->data, samp->dataLength, &ch_layout);
    1123           1 :                                 if (PL>0) {
    1124           1 :                                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_PROFILE_LEVEL, &PROP_UINT((u32) PL));
    1125           1 :                                         ch->check_mhas_pl = GF_FALSE;
    1126           1 :                                         if (ch_layout)
    1127           1 :                                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_CHANNEL_LAYOUT, &PROP_LONGUINT(ch_layout));
    1128             :                                 }
    1129           1 :                                 gf_isom_sample_del(&samp);
    1130             :                         }
    1131             :                 }
    1132             :         }
    1133             : 
    1134        1195 :         if (udesc) {
    1135           0 :                 gf_filter_pid_set_property_str(ch->pid, "codec_vendor", &PROP_UINT(udesc->vendor_code));
    1136           0 :                 gf_filter_pid_set_property_str(ch->pid, "codec_version", &PROP_UINT(udesc->version));
    1137           0 :                 gf_filter_pid_set_property_str(ch->pid, "codec_revision", &PROP_UINT(udesc->revision));
    1138           0 :                 gf_filter_pid_set_property_str(ch->pid, "compressor_name", &PROP_STRING(udesc->compressor_name));
    1139           0 :                 gf_filter_pid_set_property_str(ch->pid, "temporal_quality", &PROP_UINT(udesc->temporal_quality));
    1140           0 :                 gf_filter_pid_set_property_str(ch->pid, "spatial_quality", &PROP_UINT(udesc->spatial_quality));
    1141           0 :                 if (udesc->h_res) {
    1142           0 :                         gf_filter_pid_set_property_str(ch->pid, "hres", &PROP_UINT(udesc->h_res));
    1143           0 :                         gf_filter_pid_set_property_str(ch->pid, "vres", &PROP_UINT(udesc->v_res));
    1144           0 :                 } else if (udesc->nb_channels) {
    1145           0 :                         gf_filter_pid_set_property(ch->pid, GF_PROP_PID_NUM_CHANNELS, &PROP_UINT(udesc->nb_channels));
    1146           0 :                         switch (udesc->bits_per_sample) {
    1147           0 :                         case 8:
    1148           0 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(GF_AUDIO_FMT_U8));
    1149           0 :                                 break;
    1150           0 :                         case 16:
    1151           0 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(GF_AUDIO_FMT_S16));
    1152           0 :                                 break;
    1153           0 :                         case 24:
    1154           0 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(GF_AUDIO_FMT_S24));
    1155           0 :                                 break;
    1156           0 :                         case 32:
    1157           0 :                                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_AUDIO_FORMAT, &PROP_UINT(GF_AUDIO_FMT_S32));
    1158           0 :                                 break;
    1159           0 :                         default:
    1160           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[IsoMedia] Track %d unsupported audio bit depth %d\n", track, udesc->bits_per_sample ));
    1161             :                                 break;
    1162             :                         }
    1163           0 :                 }
    1164           0 :                 gf_filter_pid_set_property(ch->pid, GF_PROP_PID_BIT_DEPTH_Y, &PROP_UINT(udesc->depth));
    1165             : 
    1166           0 :                 gf_free(udesc);
    1167             :         }
    1168             : 
    1169             : 
    1170        1195 :         if (ch->check_avc_ps) {
    1171         331 :                 ch->avcc = gf_isom_avc_config_get(ch->owner->mov, ch->track, ch->last_sample_desc_index ? ch->last_sample_desc_index : 1);
    1172             :         }
    1173         864 :         else if (ch->check_hevc_ps) {
    1174          63 :                 ch->hvcc = gf_isom_hevc_config_get(ch->owner->mov, ch->track, ch->last_sample_desc_index ? ch->last_sample_desc_index : 1);
    1175             :         }
    1176         801 :         else if (ch->check_vvc_ps) {
    1177           0 :                 ch->vvcc = gf_isom_vvc_config_get(ch->owner->mov, ch->track, ch->last_sample_desc_index ? ch->last_sample_desc_index : 1);
    1178             :         }
    1179             : }
    1180             : 
    1181          57 : void isor_update_channel_config(ISOMChannel *ch)
    1182             : {
    1183          57 :         isor_declare_track(ch->owner, ch, ch->track, ch->last_sample_desc_index, GF_STREAM_UNKNOWN, GF_FALSE);
    1184             : 
    1185          57 : }
    1186             : 
    1187         947 : GF_Err isor_declare_objects(ISOMReader *read)
    1188             : {
    1189             :         const u8 *tag;
    1190             :         u32 tlen;
    1191             :         u32 i, count, j, track_id;
    1192             :         Bool highest_stream;
    1193             :         Bool single_media_found = GF_FALSE;
    1194             :         Bool use_iod = GF_FALSE;
    1195             :         GF_Err e;
    1196             :         Bool isom_contains_video = GF_FALSE;
    1197         947 :         GF_Descriptor *od = gf_isom_get_root_od(read->mov);
    1198         947 :         if (od && gf_list_count(((GF_ObjectDescriptor*)od)->ESDescriptors)) {
    1199             :                 use_iod = GF_TRUE;
    1200             :         }
    1201         947 :         if (od) gf_odf_desc_del(od);
    1202             : 
    1203             :         /*TODO
    1204             :          check for alternate tracks
    1205             :     */
    1206         947 :         count = gf_isom_get_track_count(read->mov);
    1207        3027 :         for (i=0; i<count; i++) {
    1208             :                 u32 mtype, m_subtype, streamtype, stsd_idx;
    1209             : 
    1210        1168 :                 mtype = gf_isom_get_media_type(read->mov, i+1);
    1211             : 
    1212        1168 :                 if (read->tkid) {
    1213          51 :                         u32 for_id=0;
    1214          51 :                         if (sscanf(read->tkid, "%d", &for_id)) {
    1215           0 :                                 u32 id = gf_isom_get_track_id(read->mov, i+1);
    1216          16 :                                 if (id != for_id) continue;
    1217          51 :                         } else if (!strcmp(read->tkid, "audio")) {
    1218          32 :                                 if (mtype!=GF_ISOM_MEDIA_AUDIO) continue;
    1219          19 :                         } else if (!strcmp(read->tkid, "video")) {
    1220          19 :                                 if (mtype!=GF_ISOM_MEDIA_VISUAL) continue;
    1221           0 :                         } else if (strlen(read->tkid)==4) {
    1222           0 :                                 u32 t = GF_4CC(read->tkid[0], read->tkid[1], read->tkid[2], read->tkid[3]);
    1223           0 :                                 if (mtype!=t) continue;
    1224             :                         } else {
    1225           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[IsoMedia] Bad format for tkid option %s, no match\n", read->tkid));
    1226           0 :                                 return GF_BAD_PARAM;
    1227             :                         }
    1228             :                 }
    1229             : 
    1230        1152 :                 switch (mtype) {
    1231             :                 case GF_ISOM_MEDIA_AUDIO:
    1232             :                         streamtype = GF_STREAM_AUDIO;
    1233             :                         break;
    1234         751 :                 case GF_ISOM_MEDIA_VISUAL:
    1235             :                 case GF_ISOM_MEDIA_AUXV:
    1236             :                 case GF_ISOM_MEDIA_PICT:
    1237             :                 case GF_ISOM_MEDIA_QTVR:
    1238             :                         streamtype = GF_STREAM_VISUAL;
    1239             :                         isom_contains_video = GF_TRUE;
    1240         751 :                         break;
    1241          61 :                 case GF_ISOM_MEDIA_TEXT:
    1242             :                 case GF_ISOM_MEDIA_SUBT:
    1243             :                 case GF_ISOM_MEDIA_SUBPIC:
    1244             :                 case GF_ISOM_MEDIA_MPEG_SUBT:
    1245             :                 case GF_ISOM_MEDIA_CLOSED_CAPTION:
    1246             :                         streamtype = GF_STREAM_TEXT;
    1247          61 :                         break;
    1248          24 :                 case GF_ISOM_MEDIA_FLASH:
    1249             :                 case GF_ISOM_MEDIA_DIMS:
    1250             :                 case GF_ISOM_MEDIA_SCENE:
    1251             :                         streamtype = GF_STREAM_SCENE;
    1252          24 :                         break;
    1253          12 :                 case GF_ISOM_MEDIA_OD:
    1254             :                         streamtype = GF_STREAM_OD;
    1255          12 :                         break;
    1256          19 :                 case GF_ISOM_MEDIA_META:
    1257             :                 case GF_ISOM_MEDIA_TIMECODE:
    1258             :                         streamtype = GF_STREAM_METADATA;
    1259          19 :                         break;
    1260             :                 /*hint tracks are never exported*/
    1261           0 :                 case GF_ISOM_MEDIA_HINT:
    1262           0 :                         continue;
    1263           0 :                 default:
    1264           0 :                         if (!read->allt) {
    1265           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[IsoMedia] Track %d type %s not supported, ignoring track - you may retry by specifying allt option\n", i+1, gf_4cc_to_str(mtype) ));
    1266           0 :                                 continue;
    1267             :                         }
    1268             :                         streamtype = GF_STREAM_UNKNOWN;
    1269             :                         break;
    1270             :                 }
    1271             : 
    1272        1152 :                 if (!read->alltk && !read->tkid && !gf_isom_is_track_enabled(read->mov, i+1)) {
    1273           0 :                         if (count>1) {
    1274           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[IsoMedia] Track %d is disabled, ignoring track - you may retry by specifying alltk option\n", i+1));
    1275           0 :                                 continue;
    1276             :                         } else {
    1277           0 :                                 GF_LOG(GF_LOG_WARNING, GF_LOG_CONTAINER, ("[IsoMedia] Track %d is disabled but single track in file, considering it enabled\n", i+1 ));
    1278             :                         }
    1279             :                 }
    1280             : 
    1281        1152 :                 stsd_idx = read->stsd ? read->stsd : 1;
    1282             :                 //some subtypes are not declared as readable objects
    1283        1152 :                 m_subtype = gf_isom_get_media_subtype(read->mov, i+1, stsd_idx);
    1284        1152 :                 switch (m_subtype) {
    1285         105 :                 case GF_ISOM_SUBTYPE_HVT1:
    1286         105 :                         if (read->smode == MP4DMX_SINGLE)
    1287           0 :                                 continue;
    1288             : 
    1289             :                         break;
    1290             :                 default:
    1291             :                         break;
    1292             :                 }
    1293             : 
    1294             :                 /*we declare only the highest video track (i.e the track we play)*/
    1295             :                 highest_stream = GF_TRUE;
    1296        1152 :                 track_id = gf_isom_get_track_id(read->mov, i+1);
    1297        1152 :                 if (read->play_only_track_id && (read->play_only_track_id != track_id)) continue;
    1298             : 
    1299        1152 :                 if (read->play_only_first_media) {
    1300          11 :                         if (read->play_only_first_media != mtype) continue;
    1301           1 :                         if (single_media_found) continue;
    1302             :                         single_media_found = GF_TRUE;
    1303             :                 }
    1304             : 
    1305        5103 :                 for (j = 0; j < count; j++) {
    1306        2828 :                         if (gf_isom_has_track_reference(read->mov, j+1, GF_ISOM_REF_SCAL, track_id) > 0) {
    1307             :                                 highest_stream = GF_FALSE;
    1308             :                                 break;
    1309             :                         }
    1310        2819 :                         if (gf_isom_has_track_reference(read->mov, j+1, GF_ISOM_REF_BASE, track_id) > 0) {
    1311             :                                 highest_stream = GF_FALSE;
    1312             :                                 break;
    1313             :                         }
    1314             :                 }
    1315             : 
    1316        1142 :                 if ((read->smode==MP4DMX_SINGLE) && (gf_isom_get_media_type(read->mov, i+1) == GF_ISOM_MEDIA_VISUAL) && !highest_stream)
    1317           0 :                         continue;
    1318             : 
    1319             : 
    1320        1142 :                 isor_declare_track(read, NULL, i+1, stsd_idx, streamtype, use_iod);
    1321             : 
    1322        1142 :                 if (read->tkid)
    1323             :                         break;
    1324             :         }
    1325             : 
    1326         947 :         if (!read->tkid) {
    1327             :                 /*declare image items*/
    1328         912 :                 count = gf_isom_get_meta_item_count(read->mov, GF_TRUE, 0);
    1329        1879 :                 for (i=0; i<count; i++) {
    1330          59 :                         if (! isor_declare_item_properties(read, NULL, i+1))
    1331          13 :                                 continue;
    1332             : 
    1333          46 :                         if (read->itt) break;
    1334             :                 }
    1335             :         }
    1336             :         
    1337             :         /*if cover art, declare a video pid*/
    1338         947 :         if (gf_isom_apple_get_tag(read->mov, GF_ISOM_ITUNE_COVER_ART, &tag, &tlen)==GF_OK) {
    1339             : 
    1340             :                 /*write cover data*/
    1341             :                 assert(!(tlen & 0x80000000));
    1342           0 :                 tlen &= 0x7FFFFFFF;
    1343             : 
    1344           0 :                 if (read->expart && !isom_contains_video) {
    1345           0 :                         GF_FilterPid *cover_pid=NULL;
    1346           0 :                         e = gf_filter_pid_raw_new(read->filter, NULL, NULL, NULL, NULL, (char *) tag, tlen, GF_FALSE, &cover_pid);
    1347           0 :                         if (e) {
    1348           0 :                                 GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("[MP3Dmx] error setting up video pid for cover art: %s\n", gf_error_to_string(e) ));
    1349             :                         }
    1350           0 :                         if (cover_pid) {
    1351             :                                 u8 *out_buffer;
    1352             :                                 GF_FilterPacket *dst_pck;
    1353           0 :                                 gf_filter_pid_set_property(cover_pid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_FILE) );
    1354           0 :                                 gf_filter_pid_set_name(cover_pid, "CoverArt");
    1355           0 :                                 dst_pck = gf_filter_pck_new_alloc(cover_pid, tlen, &out_buffer);
    1356           0 :                                 if (dst_pck) {
    1357           0 :                                         gf_filter_pck_set_framing(dst_pck, GF_TRUE, GF_TRUE);
    1358           0 :                                         memcpy(out_buffer, tag, tlen);
    1359           0 :                                         gf_filter_pck_send(dst_pck);
    1360             :                                 }
    1361           0 :                                 gf_filter_pid_set_eos(cover_pid);
    1362             :                         }
    1363             :                 }
    1364             :         }
    1365             :         return GF_OK;
    1366             : }
    1367             : 
    1368          89 : Bool isor_declare_item_properties(ISOMReader *read, ISOMChannel *ch, u32 item_idx)
    1369             : {
    1370             :         GF_ImageItemProperties props;
    1371             :         GF_FilterPid *pid;
    1372             :         GF_ESD *esd;
    1373          89 :         u32 item_id=0;
    1374          89 :         u32 scheme_type=0, scheme_version=0, item_type;
    1375             :         const char *item_name, *item_mime_type, *item_encoding;
    1376             : 
    1377          89 :         if (item_idx>gf_isom_get_meta_item_count(read->mov, GF_TRUE, 0))
    1378             :                 return GF_FALSE;
    1379             : 
    1380          85 :         item_name = item_mime_type = item_encoding = NULL;
    1381          85 :         gf_isom_get_meta_item_info(read->mov, GF_TRUE, 0, item_idx, &item_id, &item_type, &scheme_type, &scheme_version, NULL, NULL, NULL, &item_name, &item_mime_type, &item_encoding);
    1382             : 
    1383          85 :         if (!item_id) return GF_FALSE;
    1384          85 :         if (item_type==GF_ISOM_ITEM_TYPE_AUXI) return GF_FALSE;
    1385             : 
    1386          72 :         gf_isom_get_meta_image_props(read->mov, GF_TRUE, 0, item_id, &props);
    1387             : 
    1388             :         //check we support the protection scheme
    1389          72 :         switch (scheme_type) {
    1390             :         case GF_ISOM_CBC_SCHEME:
    1391             :         case GF_ISOM_CENS_SCHEME:
    1392             :         case GF_ISOM_CBCS_SCHEME:
    1393             :         case GF_ISOM_CENC_SCHEME:
    1394             :         case GF_ISOM_PIFF_SCHEME:
    1395             :         case 0:
    1396             :                 break;
    1397             :         default:
    1398             :                 return GF_FALSE;
    1399             :         }
    1400             : 
    1401             : 
    1402          72 :         esd = gf_media_map_item_esd(read->mov, item_id);
    1403          72 :         if (!esd) return GF_FALSE;
    1404             : 
    1405             : 
    1406             :         //OK declare PID
    1407          72 :         if (!ch)
    1408          46 :                 pid = gf_filter_pid_new(read->filter);
    1409             :         else {
    1410          26 :                 pid = ch->pid;
    1411          26 :                 ch->item_id = item_id;
    1412             :         }
    1413             : 
    1414             : 
    1415             :         //do not override PID ID if itt is set
    1416          72 :         if (!ch) {
    1417          46 :                 if (read->pid)
    1418          23 :                         gf_filter_pid_copy_properties(pid, read->pid);
    1419          46 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_ID, &PROP_UINT(esd->ESID));
    1420             :         }
    1421             : 
    1422          72 :         if (read->itemid)
    1423          72 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_ITEM_ID, &PROP_UINT(item_id));
    1424             :                 
    1425             :         //TODO: no support for LHEVC images
    1426             :         //gf_filter_pid_set_property(pid, GF_PROP_PID_DEPENDENCY_ID, &PROP_UINT(esd->dependsOnESID));
    1427             : 
    1428          72 :         gf_filter_pid_set_property(pid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(esd->decoderConfig->streamType));
    1429          72 :         gf_filter_pid_set_property(pid, GF_PROP_PID_CODECID, &PROP_UINT(esd->decoderConfig->objectTypeIndication));
    1430          72 :         gf_filter_pid_set_property(pid, GF_PROP_PID_TIMESCALE, &PROP_UINT(1000));
    1431          72 :         if (esd->decoderConfig->decoderSpecificInfo && esd->decoderConfig->decoderSpecificInfo->data) {
    1432          72 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_DECODER_CONFIG, &PROP_DATA_NO_COPY(esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength));
    1433             : 
    1434          72 :                 esd->decoderConfig->decoderSpecificInfo->data=NULL;
    1435          72 :                 esd->decoderConfig->decoderSpecificInfo->dataLength=0;
    1436             :         }
    1437             : 
    1438          72 :         if (props.width && props.height) {
    1439          72 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_WIDTH, &PROP_UINT(props.width));
    1440          72 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_HEIGHT, &PROP_UINT(props.height));
    1441             :         }
    1442          72 :         if (props.hidden) {
    1443           0 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_HIDDEN, &PROP_BOOL(props.hidden));
    1444             :         }
    1445             : 
    1446          72 :         if (gf_isom_get_meta_primary_item_id(read->mov, GF_TRUE, 0) == item_id) {
    1447          10 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_PRIMARY_ITEM, &PROP_BOOL(GF_TRUE));
    1448             :         } else {
    1449          62 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_PRIMARY_ITEM, &PROP_BOOL(GF_FALSE));
    1450             :         }
    1451             : 
    1452          72 :         if (!gf_sys_is_test_mode() && !read->itt)
    1453           0 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_ITEM_NUM, &PROP_UINT(item_idx) );
    1454             : 
    1455          72 :         gf_filter_pid_set_property_str(pid, "meta:mime", item_mime_type ? &PROP_STRING(item_mime_type) : NULL );
    1456          72 :         gf_filter_pid_set_property_str(pid, "meta:name", item_name ? &PROP_STRING(item_name) : NULL );
    1457          72 :         gf_filter_pid_set_property_str(pid, "meta:encoding", item_encoding ? &PROP_STRING(item_encoding) : NULL );
    1458             : 
    1459             : 
    1460             :         //setup cenc
    1461          72 :         if (scheme_type) {
    1462          13 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_PROTECTION_SCHEME_TYPE, &PROP_4CC(scheme_type) );
    1463          13 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_PROTECTION_SCHEME_VERSION, &PROP_UINT(scheme_version) );
    1464          13 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_ENCRYPTED, &PROP_BOOL(GF_TRUE) );
    1465             : 
    1466          13 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_ORIG_STREAM_TYPE, &PROP_UINT(esd->decoderConfig->streamType));
    1467          13 :                 gf_filter_pid_set_property(pid, GF_PROP_PID_STREAM_TYPE, &PROP_UINT(GF_STREAM_ENCRYPTED) );
    1468             :         }
    1469             : 
    1470          72 :         gf_odf_desc_del((GF_Descriptor *)esd);
    1471             : 
    1472          72 :         if (!ch) {
    1473          46 :                 ch = isor_create_channel(read, pid, 0, item_id, GF_FALSE);
    1474          46 :                 if (ch && scheme_type) {
    1475          13 :                         ch->is_cenc = GF_TRUE;
    1476          13 :                         ch->is_encrypted = GF_TRUE;
    1477             : 
    1478          13 :                         isor_declare_pssh(ch);
    1479             : 
    1480             :                 }
    1481             :         }
    1482             :         return GF_TRUE;
    1483             : }
    1484             : 
    1485             : #endif /*GPAC_DISABLE_ISOM*/
    1486             : 
    1487             : 
    1488             : 

Generated by: LCOV version 1.13