M4Err M4SM_LoaderRun_MP4(M4ContextLoader *load) { u32 i, j, di, nbBifs, nb_samp, samp_done; M4StreamContext *sc, *base_bifs; ESDescriptor *esd; LPODCODEC oddec; LPBIFSDEC bdec; M4Err e; if (!load || !load->isom) return M4BadParam; base_bifs = ChainGetEntry(load->ctx->streams, 0); /*no scene info*/ if (!base_bifs) return M4OK; nbBifs = 1; e = M4OK; bdec = BIFS_NewDecoder(load->scene_graph, 1); oddec = OD_NewCodec(OD_READ); esd = NULL; /*load each stream*/ nb_samp = 0; for (i=0; i<M4_GetTrackCount(load->isom); i++) { u32 type = M4_GetMediaType(load->isom, i+1); switch (type) { case M4_BIFSMediaType: case M4_ODMediaType: nb_samp += M4_GetSampleCount(load->isom, i+1); break; default: break; } } samp_done = 1; for (i=0; i<M4_GetTrackCount(load->isom); i++) { u32 type = M4_GetMediaType(load->isom, i+1); switch (type) { case M4_BIFSMediaType: break; case M4_ODMediaType: break; default: continue; } esd = M4_GetStreamDescriptor(load->isom, i+1, 1); if (!esd) continue; if (base_bifs->ESID!=esd->ESID) { sc = M4SM_NewStream(load->ctx, esd->ESID, esd->decoderConfig->streamType, esd->decoderConfig->objectTypeIndication); sc->streamType = esd->decoderConfig->streamType; sc->ESID = esd->ESID; sc->objectType = esd->decoderConfig->objectTypeIndication; sc->timeScale = M4_GetMediaTimeScale(load->isom, i+1); j=0; } else { j=1; sc = base_bifs; } /*we still need to reconfig the BIFS*/ if (esd->decoderConfig->streamType==M4ST_SCENE) { if (!esd->dependsOnESID && nbBifs && !j) mp4_report(load, M4OK, "Warning: several BIFS namespaces used or improper BIFS dependencies in file - import may be incorrect"); e = BIFS_ConfigureStream(bdec, esd->ESID, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, esd->decoderConfig->objectTypeIndication); if (e) goto exit; nbBifs++; } /*dump all AUs*/ for (; j<M4_GetSampleCount(load->isom, i+1); j++) { M4AUContext *au; M4Sample *samp = M4_GetSample(load->isom, i+1, j+1, &di); if (!samp) { mp4_report(load, M4_GetLastError(load->isom), "Unable to fetch sample %d from track ID %d - aborting track import", j+1, M4_GetTrackID(load->isom, i+1)); break; // e = M4_GetLastError(load->isom); // goto exit; } au = M4SM_NewAU(sc, samp->DTS, ((Double)samp->DTS) / sc->timeScale, samp->IsRAP); if (esd->decoderConfig->streamType==M4ST_SCENE) { e = BIFS_DecodeAUMemory(bdec, esd->ESID, samp->data, samp->dataLength, au->commands); } else { e = OD_SetBuffer(oddec, samp->data, samp->dataLength); if (!e) e = OD_DecodeAU(oddec); if (!e) { while (1) { ODCommand *odc = OD_GetCommand(oddec); if (!odc) break; /*update ESDs if any*/ UpdateODCommand(load->isom, odc); ChainAddEntry(au->commands, odc); } } } M4_DeleteSample(&samp); if (e) goto exit; samp_done++; if (load->OnProgress) load->OnProgress(load->cbk, samp_done, nb_samp); } OD_DeleteDescriptor((Descriptor **) &esd); } exit: BIFS_DeleteDecoder(bdec); OD_DeleteCodec(oddec); if (esd) OD_DeleteDescriptor((Descriptor **) &esd); return e; }
static GF_Err gf_sm_load_run_isom(GF_SceneLoader *load) { GF_Err e; FILE *logs; u32 i, j, di, nbBifs, nbLaser, nb_samp, samp_done, init_offset; GF_StreamContext *sc; GF_ESD *esd; GF_ODCodec *od_dec; #ifndef GPAC_DISABLE_BIFS GF_BifsDecoder *bifs_dec; #endif #ifndef GPAC_DISABLE_LASER GF_LASeRCodec *lsr_dec; #endif if (!load || !load->isom) return GF_BAD_PARAM; nbBifs = nbLaser = 0; e = GF_OK; #ifndef GPAC_DISABLE_BIFS bifs_dec = gf_bifs_decoder_new(load->scene_graph, 1); gf_bifs_decoder_set_extraction_path(bifs_dec, load->localPath, load->fileName); #endif od_dec = gf_odf_codec_new(); logs = NULL; #ifndef GPAC_DISABLE_LASER lsr_dec = gf_laser_decoder_new(load->scene_graph); #endif esd = NULL; /*load each stream*/ nb_samp = 0; for (i=0; i<gf_isom_get_track_count(load->isom); i++) { u32 type = gf_isom_get_media_type(load->isom, i+1); switch (type) { case GF_ISOM_MEDIA_SCENE: case GF_ISOM_MEDIA_OD: nb_samp += gf_isom_get_sample_count(load->isom, i+1); break; default: break; } } samp_done = 1; gf_isom_text_set_streaming_mode(load->isom, 1); for (i=0; i<gf_isom_get_track_count(load->isom); i++) { u32 type = gf_isom_get_media_type(load->isom, i+1); switch (type) { case GF_ISOM_MEDIA_SCENE: case GF_ISOM_MEDIA_OD: break; default: continue; } esd = gf_isom_get_esd(load->isom, i+1, 1); if (!esd) continue; if ((esd->decoderConfig->objectTypeIndication == GPAC_OTI_SCENE_AFX) || (esd->decoderConfig->objectTypeIndication == GPAC_OTI_SCENE_SYNTHESIZED_TEXTURE) ) { nb_samp += gf_isom_get_sample_count(load->isom, i+1); continue; } sc = gf_sm_stream_new(load->ctx, esd->ESID, esd->decoderConfig->streamType, esd->decoderConfig->objectTypeIndication); sc->streamType = esd->decoderConfig->streamType; sc->ESID = esd->ESID; sc->objectType = esd->decoderConfig->objectTypeIndication; sc->timeScale = gf_isom_get_media_timescale(load->isom, i+1); /*we still need to reconfig the BIFS*/ if (esd->decoderConfig->streamType==GF_STREAM_SCENE) { #ifndef GPAC_DISABLE_BIFS /*BIFS*/ if (esd->decoderConfig->objectTypeIndication<=2) { if (!esd->dependsOnESID && nbBifs && !i) mp4_report(load, GF_OK, "several scene namespaces used or improper scene dependencies in file - import may be incorrect"); if (!esd->decoderConfig->decoderSpecificInfo) { /* Hack for T-DMB non compliant streams */ e = gf_bifs_decoder_configure_stream(bifs_dec, esd->ESID, NULL, 0, esd->decoderConfig->objectTypeIndication); } else { e = gf_bifs_decoder_configure_stream(bifs_dec, esd->ESID, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength, esd->decoderConfig->objectTypeIndication); } if (e) goto exit; nbBifs++; } #endif #ifndef GPAC_DISABLE_LASER /*LASER*/ if (esd->decoderConfig->objectTypeIndication==0x09) { if (!esd->dependsOnESID && nbBifs && !i) mp4_report(load, GF_OK, "several scene namespaces used or improper scene dependencies in file - import may be incorrect"); e = gf_laser_decoder_configure_stream(lsr_dec, esd->ESID, esd->decoderConfig->decoderSpecificInfo->data, esd->decoderConfig->decoderSpecificInfo->dataLength); if (e) goto exit; nbLaser++; } #endif } init_offset = 0; /*dump all AUs*/ for (j=0; j<gf_isom_get_sample_count(load->isom, i+1); j++) { GF_AUContext *au; GF_ISOSample *samp = gf_isom_get_sample(load->isom, i+1, j+1, &di); if (!samp) { 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)); break; } /*check if track has initial offset*/ if (!j && gf_isom_get_edit_segment_count(load->isom, i+1)) { u64 EditTime, dur, mtime; u8 mode; gf_isom_get_edit_segment(load->isom, i+1, 1, &EditTime, &dur, &mtime, &mode); if (mode==GF_ISOM_EDIT_EMPTY) { init_offset = (u32) (dur * sc->timeScale / gf_isom_get_timescale(load->isom) ); } } samp->DTS += init_offset; au = gf_sm_stream_au_new(sc, samp->DTS, ((Double)(s64) samp->DTS) / sc->timeScale, (samp->IsRAP==RAP) ? 1 : 0); if (esd->decoderConfig->streamType==GF_STREAM_SCENE) { #ifndef GPAC_DISABLE_BIFS if (esd->decoderConfig->objectTypeIndication<=2) e = gf_bifs_decode_command_list(bifs_dec, esd->ESID, samp->data, samp->dataLength, au->commands); #endif #ifndef GPAC_DISABLE_LASER if (esd->decoderConfig->objectTypeIndication==0x09) e = gf_laser_decode_command_list(lsr_dec, esd->ESID, samp->data, samp->dataLength, au->commands); #endif } else { e = gf_odf_codec_set_au(od_dec, samp->data, samp->dataLength); if (!e) e = gf_odf_codec_decode(od_dec); if (!e) { while (1) { GF_ODCom *odc = gf_odf_codec_get_com(od_dec); if (!odc) break; /*update ESDs if any*/ UpdateODCommand(load->isom, odc); gf_list_add(au->commands, odc); } } } gf_isom_sample_del(&samp); if (e) { 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)); goto exit; } samp_done++; gf_set_progress("MP4 Loading", samp_done, nb_samp); } gf_odf_desc_del((GF_Descriptor *) esd); esd = NULL; } gf_isom_text_set_streaming_mode(load->isom, 0); exit: #ifndef GPAC_DISABLE_BIFS gf_bifs_decoder_del(bifs_dec); #endif gf_odf_codec_del(od_dec); #ifndef GPAC_DISABLE_LASER gf_laser_decoder_del(lsr_dec); #endif if (esd) gf_odf_desc_del((GF_Descriptor *) esd); if (logs) gf_fclose(logs); return e; }