LCOV - code coverage report
Current view: top level - scene_manager - loader_isom.c (source / functions) Hit Total Coverage
Test: coverage.info Lines: 136 189 72.0 %
Date: 2021-04-29 23:48:07 Functions: 5 6 83.3 %

          Line data    Source code
       1             : /*
       2             :  *                      GPAC - Multimedia Framework C SDK
       3             :  *
       4             :  *                      Authors: Jean Le Feuvre
       5             :  *                      Copyright (c) Telecom ParisTech 2000-2012
       6             :  *                                      All rights reserved
       7             :  *
       8             :  *  This file is part of GPAC / Scene Management sub-project
       9             :  *
      10             :  *  GPAC is free software; you can redistribute it and/or modify
      11             :  *  it under the terms of the GNU Lesser General Public License as published by
      12             :  *  the Free Software Foundation; either version 2, or (at your option)
      13             :  *  any later version.
      14             :  *
      15             :  *  GPAC is distributed in the hope that it will be useful,
      16             :  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :  *  GNU Lesser General Public License for more details.
      19             :  *
      20             :  *  You should have received a copy of the GNU Lesser General Public
      21             :  *  License along with this library; see the file COPYING.  If not, write to
      22             :  *  the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
      23             :  *
      24             :  */
      25             : 
      26             : #include <gpac/scene_manager.h>
      27             : #include <gpac/constants.h>
      28             : #include <gpac/bifs.h>
      29             : #ifndef GPAC_DISABLE_LASER
      30             : #include <gpac/laser.h>
      31             : #endif
      32             : 
      33             : 
      34             : 
      35             : #if !defined(GPAC_DISABLE_ISOM) && !defined(GPAC_DISABLE_LOADER_ISOM)
      36             : 
      37          57 : static void UpdateODCommand(GF_ISOFile *mp4, GF_ODCom *com)
      38             : {
      39             :         u32 i, j;
      40             :         const char *szName;
      41             :         char szPath[2048];
      42             : 
      43          57 :         szName = gf_isom_get_filename(mp4);
      44          57 :         if (com->tag == GF_ODF_OD_UPDATE_TAG) {
      45             :                 GF_ObjectDescriptor *od;
      46             :                 GF_ODUpdate *odU = (GF_ODUpdate *)com;
      47          29 :                 i=0;
      48         112 :                 while ((od = (GF_ObjectDescriptor *)gf_list_enum(odU->objectDescriptors, &i))) {
      49             :                         GF_ESD *esd;
      50          54 :                         j=0;
      51         161 :                         while ((esd = (GF_ESD *)gf_list_enum(od->ESDescriptors, &j))) {
      52             :                                 //can happen when dumping with keep-ods
      53          53 :                                 if (esd->tag!=GF_ODF_ESD_TAG) {
      54           1 :                                         continue;
      55             :                                 }
      56          52 :                                 if (esd->URLString) continue;
      57             : 
      58          52 :                                 switch (esd->decoderConfig->streamType) {
      59           0 :                                 case GF_STREAM_OD:
      60           0 :                                         continue;
      61             : 
      62           0 :                                 case GF_STREAM_SCENE:
      63           0 :                                         if ((esd->decoderConfig->objectTypeIndication != GF_CODECID_AFX) &&
      64             :                                                 (esd->decoderConfig->objectTypeIndication != GF_CODECID_SYNTHESIZED_TEXTURE)
      65             :                                            ) {
      66           0 :                                                 continue;
      67             :                                         }
      68             :                                         break;
      69             :                                 /*dump the OCR track duration in case the OCR is used by media controls & co*/
      70           0 :                                 case GF_STREAM_OCR:
      71             :                                 {
      72             :                                         u32 track;
      73             :                                         Double dur;
      74           0 :                                         GF_MuxInfo *mi = (GF_MuxInfo *) gf_odf_desc_new(GF_ODF_MUXINFO_TAG);
      75           0 :                                         gf_list_add(esd->extensionDescriptors, mi);
      76           0 :                                         track = gf_isom_get_track_by_id(mp4, esd->ESID);
      77           0 :                                         dur = (Double) (s64) gf_isom_get_track_duration(mp4, track);
      78           0 :                                         dur /= gf_isom_get_timescale(mp4);
      79           0 :                                         mi->duration = (u32) (dur * 1000);
      80           0 :                                         continue;;
      81             :                                 }
      82             :                                 break;
      83             :                                 default:
      84             :                                         break;
      85             :                                 }
      86             : 
      87          52 :                                 GF_MuxInfo *mi = (GF_MuxInfo *) gf_odf_desc_new(GF_ODF_MUXINFO_TAG);
      88          52 :                                 gf_list_add(esd->extensionDescriptors, mi);
      89          52 :                                 sprintf(szPath, "%s#%d", szName, esd->ESID);
      90          52 :                                 mi->file_name = gf_strdup(szPath);
      91          52 :                                 mi->streamFormat = gf_strdup("MP4");
      92             :                         }
      93             :                 }
      94          33 :                 return;
      95             :         }
      96          28 :         if (com->tag == GF_ODF_ESD_UPDATE_TAG) {
      97             :                 GF_ESD *esd;
      98             :                 GF_ESDUpdate *esdU = (GF_ESDUpdate *)com;
      99           4 :                 i=0;
     100          12 :                 while ((esd = (GF_ESD *)gf_list_enum(esdU->ESDescriptors, &i))) {
     101             :                         Bool import = 1;
     102           4 :                         if (esd->URLString) continue;
     103           4 :                         switch (esd->decoderConfig->streamType) {
     104             :                         case GF_STREAM_OD:
     105             :                                 import = 0;
     106             :                                 break;
     107           0 :                         case GF_STREAM_SCENE:
     108           0 :                                 if ((esd->decoderConfig->objectTypeIndication != GF_CODECID_AFX) &&
     109             :                                         (esd->decoderConfig->objectTypeIndication != GF_CODECID_SYNTHESIZED_TEXTURE)
     110             :                                    ) {
     111             :                                         import = 0;
     112             :                                 }
     113             :                                 break;
     114             :                         /*dump the OCR track duration in case the OCR is used by media controls & co*/
     115           0 :                         case GF_STREAM_OCR:
     116             :                         {
     117             :                                 u32 track;
     118             :                                 Double dur;
     119           0 :                                 GF_MuxInfo *mi = (GF_MuxInfo *) gf_odf_desc_new(GF_ODF_MUXINFO_TAG);
     120           0 :                                 gf_list_add(esd->extensionDescriptors, mi);
     121           0 :                                 track = gf_isom_get_track_by_id(mp4, esd->ESID);
     122           0 :                                 dur = (Double) (s64) gf_isom_get_track_duration(mp4, track);
     123           0 :                                 dur /= gf_isom_get_timescale(mp4);
     124           0 :                                 mi->duration = (u32) (dur * 1000);
     125             :                                 import = 0;
     126             :                         }
     127             :                         break;
     128             :                         default:
     129             :                                 break;
     130             :                         }
     131             :                         if (import) {
     132           4 :                                 GF_MuxInfo *mi = (GF_MuxInfo *) gf_odf_desc_new(GF_ODF_MUXINFO_TAG);
     133           4 :                                 gf_list_add(esd->extensionDescriptors, mi);
     134           4 :                                 sprintf(szPath, "%s#%d", szName, esd->ESID);
     135           4 :                                 mi->file_name = gf_strdup(szPath);
     136           4 :                                 mi->streamFormat = gf_strdup("MP4");
     137             :                         }
     138             :                 }
     139             :                 return;
     140             :         }
     141             : }
     142             : 
     143          18 : static void mp4_report(GF_SceneLoader *load, GF_Err e, char *format, ...)
     144             : {
     145             : #ifndef GPAC_DISABLE_LOG
     146          18 :         if (format && gf_log_tool_level_on(GF_LOG_PARSER, e ? GF_LOG_ERROR : GF_LOG_WARNING)) {
     147             :                 char szMsg[1024];
     148             :                 va_list args;
     149           0 :                 va_start(args, format);
     150             :                 vsnprintf(szMsg, 1024, format, args);
     151           0 :                 va_end(args);
     152           0 :                 GF_LOG((u32) (e ? GF_LOG_ERROR : GF_LOG_WARNING), GF_LOG_PARSER, ("[MP4 Loading] %s\n", szMsg) );
     153             :         }
     154             : #endif
     155          18 : }
     156             : 
     157          18 : static GF_Err gf_sm_load_run_isom(GF_SceneLoader *load)
     158             : {
     159             :         GF_Err e;
     160             :         FILE *logs;
     161             :         u32 i, j, di, nbBifs, nbLaser, nb_samp, samp_done, init_offset;
     162             :         GF_StreamContext *sc;
     163             :         GF_ESD *esd;
     164             :         GF_ODCodec *od_dec;
     165             : #ifndef GPAC_DISABLE_BIFS
     166             :         GF_BifsDecoder *bifs_dec;
     167             : #endif
     168             : #ifndef GPAC_DISABLE_LASER
     169             :         GF_LASeRCodec *lsr_dec;
     170             : #endif
     171             : 
     172          18 :         if (!load || !load->isom) return GF_BAD_PARAM;
     173             : 
     174             :         nbBifs = nbLaser = 0;
     175             :         e = GF_OK;
     176             : #ifndef GPAC_DISABLE_BIFS
     177          18 :         bifs_dec = gf_bifs_decoder_new(load->scene_graph, 1);
     178             : #endif
     179          18 :         od_dec = gf_odf_codec_new();
     180             :         logs = NULL;
     181             : #ifndef GPAC_DISABLE_LASER
     182          18 :         lsr_dec = gf_laser_decoder_new(load->scene_graph);
     183             : #endif
     184             :         esd = NULL;
     185             :         /*load each stream*/
     186             :         nb_samp = 0;
     187         120 :         for (i=0; i<gf_isom_get_track_count(load->isom); i++) {
     188          84 :                 u32 type = gf_isom_get_media_type(load->isom, i+1);
     189          84 :                 u32 subtype = gf_isom_get_mpeg4_subtype(load->isom, i+1, 1);
     190          84 :                 switch (type) {
     191          51 :                 case GF_ISOM_MEDIA_SCENE:
     192             :                 case GF_ISOM_MEDIA_OD:
     193          51 :                         nb_samp += gf_isom_get_sample_count(load->isom, i+1);
     194          51 :                         break;
     195          33 :                 default:
     196          33 :                         if (subtype==GF_ISOM_SUBTYPE_MP4S) {
     197           0 :                                 nb_samp += gf_isom_get_sample_count(load->isom, i+1);
     198             :                         }
     199             :                         break;
     200             :                 }
     201             :         }
     202             :         samp_done = 1;
     203          18 :         gf_isom_text_set_streaming_mode(load->isom, 1);
     204             : 
     205         120 :         for (i=0; i<gf_isom_get_track_count(load->isom); i++) {
     206          84 :                 u32 type = gf_isom_get_media_type(load->isom, i+1);
     207          84 :                 u32 subtype = gf_isom_get_mpeg4_subtype(load->isom, i+1, 1);
     208          84 :                 switch (type) {
     209             :                 case GF_ISOM_MEDIA_SCENE:
     210             :                 case GF_ISOM_MEDIA_OD:
     211             :                         break;
     212          33 :                 default:
     213          33 :                         if (subtype!=GF_ISOM_SUBTYPE_MP4S)
     214          33 :                                 continue;
     215             :                         break;
     216             :                 }
     217          51 :                 esd = gf_isom_get_esd(load->isom, i+1, 1);
     218          51 :                 if (!esd || !esd->decoderConfig) continue;
     219          51 :                 if (esd->decoderConfig->objectTypeIndication==GF_CODECID_TEXT_MPEG4)
     220           0 :                         continue;
     221             : 
     222          51 :                 if ((esd->decoderConfig->objectTypeIndication == GF_CODECID_AFX) ||
     223             :                         (esd->decoderConfig->objectTypeIndication == GF_CODECID_SYNTHESIZED_TEXTURE)
     224             :                    ) {
     225           0 :                         nb_samp += gf_isom_get_sample_count(load->isom, i+1);
     226           0 :                         continue;
     227             :                 }
     228          51 :                 sc = gf_sm_stream_new(load->ctx, esd->ESID, esd->decoderConfig->streamType, esd->decoderConfig->objectTypeIndication);
     229          51 :                 sc->streamType = esd->decoderConfig->streamType;
     230          51 :                 sc->ESID = esd->ESID;
     231          51 :                 sc->codec_id = esd->decoderConfig->objectTypeIndication;
     232          51 :                 sc->timeScale = gf_isom_get_media_timescale(load->isom, i+1);
     233             : 
     234             :                 /*we still need to reconfig the BIFS*/
     235          51 :                 if (esd->decoderConfig->streamType==GF_STREAM_SCENE) {
     236             : #ifndef GPAC_DISABLE_BIFS
     237             :                         /*BIFS*/
     238          18 :                         if (esd->decoderConfig->objectTypeIndication<=2) {
     239          16 :                                 if (!esd->dependsOnESID && nbBifs && !i)
     240           0 :                                         mp4_report(load, GF_OK, "several scene namespaces used or improper scene dependencies in file - import may be incorrect");
     241          16 :                                 if (!esd->decoderConfig->decoderSpecificInfo) {
     242             :                                         /* Hack for T-DMB non compliant streams */
     243           0 :                                         e = gf_bifs_decoder_configure_stream(bifs_dec, esd->ESID, NULL, 0, esd->decoderConfig->objectTypeIndication);
     244             :                                 } else {
     245          16 :                                         e = gf_bifs_decoder_configure_stream(bifs_dec, esd->ESID, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, esd->decoderConfig->objectTypeIndication);
     246             :                                 }
     247          16 :                                 if (e) goto exit;
     248          16 :                                 nbBifs++;
     249             :                         }
     250             : #endif
     251             : 
     252             : #ifndef GPAC_DISABLE_LASER
     253             :                         /*LASER*/
     254          18 :                         if (esd->decoderConfig->objectTypeIndication==0x09) {
     255           2 :                                 if (!esd->dependsOnESID && nbBifs && !i)
     256           0 :                                         mp4_report(load, GF_OK, "several scene namespaces used or improper scene dependencies in file - import may be incorrect");
     257           2 :                                 e = gf_laser_decoder_configure_stream(lsr_dec, esd->ESID, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength);
     258           2 :                                 if (e) goto exit;
     259             :                                 nbLaser++;
     260             :                         }
     261             : #endif
     262             :                 }
     263             : 
     264             :                 init_offset = 0;
     265             :                 /*dump all AUs*/
     266         349 :                 for (j=0; j<gf_isom_get_sample_count(load->isom, i+1); j++) {
     267             :                         GF_AUContext *au;
     268         247 :                         GF_ISOSample *samp = gf_isom_get_sample(load->isom, i+1, j+1, &di);
     269         247 :                         if (!samp) {
     270           0 :                                 mp4_report(load, gf_isom_last_error(load->isom), "Unable to fetch sample %d from track ID %d - aborting track import", j+1, gf_isom_get_track_id(load->isom, i+1));
     271           0 :                                 break;
     272             :                         }
     273             :                         /*check if track has initial offset*/
     274         247 :                         if (!j && gf_isom_get_edits_count(load->isom, i+1)) {
     275             :                                 u64 EditTime, dur, mtime;
     276             :                                 GF_ISOEditType mode;
     277           0 :                                 gf_isom_get_edit(load->isom, i+1, 1, &EditTime, &dur, &mtime, &mode);
     278           0 :                                 if (mode==GF_ISOM_EDIT_EMPTY) {
     279           0 :                                         init_offset = (u32) (dur * sc->timeScale / gf_isom_get_timescale(load->isom) );
     280             :                                 }
     281             :                         }
     282         247 :                         samp->DTS += init_offset;
     283             : 
     284         247 :                         au = gf_sm_stream_au_new(sc, samp->DTS, ((Double)(s64) samp->DTS) / sc->timeScale, (samp->IsRAP==RAP) ? 1 : 0);
     285             : 
     286         247 :                         if (esd->decoderConfig->streamType==GF_STREAM_SCENE) {
     287             : #ifndef GPAC_DISABLE_BIFS
     288         190 :                                 if (esd->decoderConfig->objectTypeIndication<=2)
     289         184 :                                         e = gf_bifs_decode_command_list(bifs_dec, esd->ESID, samp->data, samp->dataLength, au->commands);
     290             : #endif
     291             : #ifndef GPAC_DISABLE_LASER
     292         190 :                                 if (esd->decoderConfig->objectTypeIndication==0x09)
     293           6 :                                         e = gf_laser_decode_command_list(lsr_dec, esd->ESID, samp->data, samp->dataLength, au->commands);
     294             : #endif
     295             :                         } else {
     296          57 :                                 e = gf_odf_codec_set_au(od_dec, samp->data, samp->dataLength);
     297          57 :                                 if (!e) e = gf_odf_codec_decode(od_dec);
     298          57 :                                 if (!e) {
     299          57 :                                         while (1) {
     300         114 :                                                 GF_ODCom *odc = gf_odf_codec_get_com(od_dec);
     301         114 :                                                 if (!odc) break;
     302             :                                                 /*update ESDs if any*/
     303          57 :                                                 UpdateODCommand(load->isom, odc);
     304          57 :                                                 gf_list_add(au->commands, odc);
     305             :                                         }
     306             :                                 }
     307             :                         }
     308         247 :                         gf_isom_sample_del(&samp);
     309         247 :                         if (e) {
     310           0 :                                 mp4_report(load, gf_isom_last_error(load->isom), "decoding sample %d from track ID %d failed", j+1, gf_isom_get_track_id(load->isom, i+1));
     311           0 :                                 goto exit;
     312             :                         }
     313             : 
     314         247 :                         samp_done++;
     315         247 :                         gf_set_progress("MP4 Loading", samp_done, nb_samp);
     316             :                 }
     317          51 :                 gf_odf_desc_del((GF_Descriptor *) esd);
     318             :                 esd = NULL;
     319             :         }
     320          18 :         gf_isom_text_set_streaming_mode(load->isom, 0);
     321             : 
     322          18 : exit:
     323             : #ifndef GPAC_DISABLE_BIFS
     324          18 :         gf_bifs_decoder_del(bifs_dec);
     325             : #endif
     326          18 :         gf_odf_codec_del(od_dec);
     327             : #ifndef GPAC_DISABLE_LASER
     328          18 :         gf_laser_decoder_del(lsr_dec);
     329             : #endif
     330          18 :         if (esd) gf_odf_desc_del((GF_Descriptor *) esd);
     331             :         if (logs) gf_fclose(logs);
     332             :         return e;
     333             : }
     334             : 
     335          18 : static void gf_sm_load_done_isom(GF_SceneLoader *load)
     336             : {
     337             :         /*nothing to do the file is not ours*/
     338          18 : }
     339             : 
     340           0 : static GF_Err gf_sm_isom_suspend(GF_SceneLoader *loader, Bool suspend)
     341             : {
     342           0 :         return GF_OK;
     343             : }
     344             : 
     345          18 : GF_Err gf_sm_load_init_isom(GF_SceneLoader *load)
     346             : {
     347             :         u32 i;
     348             :         GF_BIFSConfig *bc;
     349             :         GF_ESD *esd;
     350             :         GF_Err e;
     351             :         char *scene_msg = "MPEG-4 BIFS Scene Parsing";
     352          18 :         if (!load->isom) return GF_BAD_PARAM;
     353             : 
     354             :         /*load IOD*/
     355          18 :         load->ctx->root_od = (GF_ObjectDescriptor *) gf_isom_get_root_od(load->isom);
     356          18 :         if (!load->ctx->root_od) {
     357           0 :                 e = gf_isom_last_error(load->isom);
     358           0 :                 if (e) return e;
     359             :         }
     360             :         else {
     361          18 :                 switch (load->ctx->root_od->tag) {
     362             :                 case GF_ODF_OD_TAG:
     363             :                 case GF_ODF_IOD_TAG:
     364             :                 case GF_ODF_ISOM_OD_TAG:
     365             :                 case GF_ODF_ISOM_IOD_TAG:
     366             :                         break;
     367           0 :                 default:
     368           0 :                         gf_odf_desc_del((GF_Descriptor *) load->ctx->root_od);
     369           0 :                         load->ctx->root_od = NULL;
     370           0 :                         break;
     371             :                 }
     372             :         }
     373             : 
     374             :         esd = NULL;
     375             : 
     376             :         /*get root scene stream*/
     377          20 :         for (i=0; i<gf_isom_get_track_count(load->isom); i++) {
     378          20 :                 u32 type = gf_isom_get_media_type(load->isom, i+1);
     379          20 :                 if (type != GF_ISOM_MEDIA_SCENE) continue;
     380          18 :                 if (! gf_isom_is_track_in_root_od(load->isom, i+1) ) continue;
     381          18 :                 esd = gf_isom_get_esd(load->isom, i+1, 1);
     382             : 
     383          18 :                 if (esd && esd->URLString) {
     384           0 :                         gf_odf_desc_del((GF_Descriptor *)esd);
     385             :                         esd = NULL;
     386           0 :                         continue;
     387             :                 }
     388             : 
     389             :                 /*make sure we load the root BIFS stream first*/
     390          18 :                 if (esd && esd->dependsOnESID && (esd->dependsOnESID!=esd->ESID) ) {
     391           0 :                         u32 track = gf_isom_get_track_by_id(load->isom, esd->dependsOnESID);
     392           0 :                         if (gf_isom_get_media_type(load->isom, track) != GF_ISOM_MEDIA_OD) {
     393           0 :                                 gf_odf_desc_del((GF_Descriptor *)esd);
     394             :                                 esd = NULL;
     395           0 :                                 continue;
     396             :                         }
     397             :                 }
     398          18 :                 if (esd && esd->decoderConfig && esd->decoderConfig->objectTypeIndication==0x09) scene_msg = "MPEG-4 LASeR Scene Parsing";
     399             :                 break;
     400             :         }
     401          18 :         if (!esd) return GF_OK;
     402             : 
     403          18 :         GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("%s\n", scene_msg));
     404             : 
     405             :         /*BIFS: update size & pixel metrics info*/
     406          18 :         if (esd->decoderConfig) {
     407          18 :                 if (esd->decoderConfig->objectTypeIndication<=2) {
     408          16 :                         bc = gf_odf_get_bifs_config(esd->decoderConfig->decoderSpecificInfo, esd->decoderConfig->objectTypeIndication);
     409          16 :                         if (!bc->elementaryMasks && bc->pixelWidth && bc->pixelHeight) {
     410          16 :                                 load->ctx->scene_width = bc->pixelWidth;
     411          16 :                                 load->ctx->scene_height = bc->pixelHeight;
     412          16 :                                 load->ctx->is_pixel_metrics = bc->pixelMetrics;
     413             :                         }
     414          16 :                         gf_odf_desc_del((GF_Descriptor *) bc);
     415             :                         /*note we don't load the first BIFS AU to avoid storing the BIFS decoder, needed to properly handle quantization*/
     416             :                 }
     417             :                 /*LASeR*/
     418           2 :                 else if (esd->decoderConfig->objectTypeIndication==0x09) {
     419           2 :                         load->ctx->is_pixel_metrics = 1;
     420             :                 }
     421             :         }
     422          18 :         gf_odf_desc_del((GF_Descriptor *) esd);
     423             :         esd = NULL;
     424             : 
     425             : #ifdef GPAC_ENABLE_COVERAGE
     426          18 :         if (gf_sys_is_cov_mode()) {
     427          18 :                 mp4_report(load, GF_OK, NULL);
     428             :                 gf_sm_isom_suspend(load, GF_TRUE);
     429             :                 gf_sm_isom_suspend(load, GF_FALSE);
     430             :         }
     431             : #endif
     432             : 
     433          18 :         load->process = gf_sm_load_run_isom;
     434          18 :         load->done = gf_sm_load_done_isom;
     435          18 :         load->suspend = gf_sm_isom_suspend;
     436          18 :         return GF_OK;
     437             : }
     438             : 
     439             : #endif /*GPAC_DISABLE_ISOM && GPAC_DISABLE_LOADER_ISOM*/

Generated by: LCOV version 1.13