📄 loader_isom.c
字号:
/* * GPAC - Multimedia Framework C SDK * * Copyright (c) Jean Le Feuvre 2000-2005 * All rights reserved * * This file is part of GPAC / Scene Management sub-project * * GPAC is free software; you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2, or (at your option) * any later version. * * GPAC is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * */#include <gpac/scene_manager.h>#include <gpac/constants.h>#include <gpac/bifs.h>#ifndef GPAC_DISABLE_SVG#include <gpac/laser.h>#endif#ifndef GPAC_READ_ONLYstatic void UpdateODCommand(GF_ISOFile *mp4, GF_ODCom *com){ u32 i, j; const char *szName; char szPath[2048]; szName = gf_isom_get_filename(mp4); if (com->tag == GF_ODF_OD_UPDATE_TAG) { GF_ObjectDescriptor *od; GF_ODUpdate *odU = (GF_ODUpdate *)com; i=0; while ((od = (GF_ObjectDescriptor *)gf_list_enum(odU->objectDescriptors, &i))) { GF_ESD *esd; j=0; while ((esd = (GF_ESD *)gf_list_enum(od->ESDescriptors, &j))) { if (esd->URLString) continue; switch (esd->decoderConfig->streamType) { case GF_STREAM_OD: case GF_STREAM_SCENE: break; /*dump the OCR track duration in case the OCR is used by media controls & co*/ case GF_STREAM_OCR: { u32 track; Double dur; GF_MuxInfo *mi = (GF_MuxInfo *) gf_odf_desc_new(GF_ODF_MUXINFO_TAG); gf_list_add(esd->extensionDescriptors, mi); track = gf_isom_get_track_by_id(mp4, esd->ESID); dur = (Double) (s64) gf_isom_get_track_duration(mp4, track); dur /= gf_isom_get_timescale(mp4); mi->duration = (u32) (dur * 1000); } break; default: { GF_MuxInfo *mi = (GF_MuxInfo *) gf_odf_desc_new(GF_ODF_MUXINFO_TAG); gf_list_add(esd->extensionDescriptors, mi); sprintf(szPath, "%s#%d", szName, esd->ESID); mi->file_name = strdup(szPath); mi->streamFormat = strdup("MP4"); } break; } } } return; } if (com->tag == GF_ODF_ESD_UPDATE_TAG) { GF_ESD *esd; GF_ESDUpdate *esdU = (GF_ESDUpdate *)com; i=0; while ((esd = (GF_ESD *)gf_list_enum(esdU->ESDescriptors, &i))) { if (esd->URLString) continue; switch (esd->decoderConfig->streamType) { case GF_STREAM_OD: case GF_STREAM_SCENE: break; /*dump the OCR track duration in case the OCR is used by media controls & co*/ case GF_STREAM_OCR: { u32 track; Double dur; GF_MuxInfo *mi = (GF_MuxInfo *) gf_odf_desc_new(GF_ODF_MUXINFO_TAG); gf_list_add(esd->extensionDescriptors, mi); track = gf_isom_get_track_by_id(mp4, esd->ESID); dur = (Double) (s64) gf_isom_get_track_duration(mp4, track); dur /= gf_isom_get_timescale(mp4); mi->duration = (u32) (dur * 1000); } break; default: { GF_MuxInfo *mi = (GF_MuxInfo *) gf_odf_desc_new(GF_ODF_MUXINFO_TAG); gf_list_add(esd->extensionDescriptors, mi); sprintf(szPath, "%s#%d", szName, esd->ESID); mi->file_name = strdup(szPath); mi->streamFormat = strdup("MP4"); } break; } } return; }}static void mp4_report(GF_SceneLoader *load, GF_Err e, char *format, ...){#ifndef GPAC_DISABLE_LOG if (gf_log_get_level() && (gf_log_get_tools() & GF_LOG_PARSER)) { char szMsg[1024]; va_list args; va_start(args, format); vsprintf(szMsg, format, args); va_end(args); GF_LOG((u32) (e ? GF_LOG_ERROR : GF_LOG_WARNING), GF_LOG_PARSER, ("[MP4 Loading] %s\n", szMsg) ); }#endif}GF_Err gf_sm_load_run_MP4(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; GF_BifsDecoder *bifs_dec;#ifndef GPAC_DISABLE_SVG GF_LASeRCodec *lsr_dec;#endif if (!load || !load->isom) return GF_BAD_PARAM; nbBifs = nbLaser = 0; e = GF_OK; bifs_dec = gf_bifs_decoder_new(load->scene_graph, 1); od_dec = gf_odf_codec_new(); logs = NULL;#ifndef GPAC_DISABLE_SVG 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: break; case GF_ISOM_MEDIA_OD: break; default: continue; } esd = gf_isom_get_esd(load->isom, i+1, 1); if (!esd) 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) { /*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"); 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++; }#ifndef GPAC_DISABLE_SVG /*LASER*/ else 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); if (esd->decoderConfig->streamType==GF_STREAM_SCENE) { if (esd->decoderConfig->objectTypeIndication<=2) e = gf_bifs_decode_command_list(bifs_dec, esd->ESID, samp->data, samp->dataLength, au->commands);#ifndef GPAC_DISABLE_SVG else 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: gf_bifs_decoder_del(bifs_dec); gf_odf_codec_del(od_dec);#ifndef GPAC_DISABLE_SVG gf_laser_decoder_del(lsr_dec);#endif if (esd) gf_odf_desc_del((GF_Descriptor *) esd); if (logs) fclose(logs); return e;}GF_Err gf_sm_load_init_MP4(GF_SceneLoader *load){ u32 i, track; GF_BIFSConfig *bc; GF_ESD *esd; GF_Err e; char *scene_msg = "MPEG-4 BIFS Scene Parsing"; if (!load->isom) return GF_BAD_PARAM; /*load IOD*/ load->ctx->root_od = (GF_ObjectDescriptor *) gf_isom_get_root_od(load->isom); if (!load->ctx->root_od) { e = gf_isom_last_error(load->isom); if (e) return e; } else if ((load->ctx->root_od->tag != GF_ODF_OD_TAG) && (load->ctx->root_od->tag != GF_ODF_IOD_TAG)) { gf_odf_desc_del((GF_Descriptor *) load->ctx->root_od); load->ctx->root_od = NULL; } esd = NULL; /*get root scene stream*/ for (i=0; i<gf_isom_get_track_count(load->isom); i++) { u32 type = gf_isom_get_media_type(load->isom, i+1); if (type != GF_ISOM_MEDIA_SCENE) continue; if (! gf_isom_is_track_in_root_od(load->isom, i+1) ) continue; esd = gf_isom_get_esd(load->isom, i+1, 1); if (esd && esd->URLString) { gf_odf_desc_del((GF_Descriptor *)esd); esd = NULL; continue; } /*make sure we load the root BIFS stream first*/ if (esd && esd->dependsOnESID && (esd->dependsOnESID!=esd->ESID) ) { u32 track = gf_isom_get_track_by_id(load->isom, esd->dependsOnESID); if (gf_isom_get_media_type(load->isom, track) != GF_ISOM_MEDIA_OD) { gf_odf_desc_del((GF_Descriptor *)esd); esd = NULL; continue; } } if (esd->decoderConfig->objectTypeIndication==0x09) scene_msg = "MPEG-4 LASeR Scene Parsing"; break; } if (!esd) return GF_OK; e = GF_OK; GF_LOG(GF_LOG_INFO, GF_LOG_PARSER, ("%s\n", scene_msg)); track = i+1; /*BIFS: update size & pixel metrics info*/ if (esd->decoderConfig->objectTypeIndication<=2) { bc = gf_odf_get_bifs_config(esd->decoderConfig->decoderSpecificInfo, esd->decoderConfig->objectTypeIndication); if (!bc->elementaryMasks && bc->pixelWidth && bc->pixelHeight) { load->ctx->scene_width = bc->pixelWidth; load->ctx->scene_height = bc->pixelHeight; load->ctx->is_pixel_metrics = bc->pixelMetrics; } gf_odf_desc_del((GF_Descriptor *) bc); /*note we don't load the first BIFS AU to avoid storing the BIFS decoder, needed to properly handle quantization*/ } /*LASeR*/ else if (esd->decoderConfig->objectTypeIndication==0x09) { load->ctx->is_pixel_metrics = 1; } gf_odf_desc_del((GF_Descriptor *) esd); esd = NULL; return GF_OK;}void gf_sm_load_done_MP4(GF_SceneLoader *load){ /*nothing to do the file is not ours*/}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -