📄 encode_isom.c
字号:
gf_isom_change_mpeg4_description(mp4, track, 1, esd); /*sync shadow generation*/ if (rap_mode==2) { GF_AUContext *au; u32 au_count = gf_list_count(sc->AUs); last_rap = 0; for (j=0; j<au_count; j++) { au = (GF_AUContext *)gf_list_get(sc->AUs, j); e = gf_sg_command_apply_list(ctx->scene_graph, au->commands, 0); if (!j) continue; /*force a RAP shadow on last sample*/ if ((au->timing - last_rap < rap_delay) && (j+1<au_count) ) continue; samp = gf_isom_sample_new(); last_rap = samp->DTS = au->timing - init_offset; samp->IsRAP = 1; /*RAP generation*/ if (bifs_enc) e = gf_bifs_encoder_get_rap(bifs_enc, &samp->data, &samp->dataLength); if (!e) e = gf_isom_add_sample_shadow(mp4, track, samp); gf_isom_sample_del(&samp); if (e) goto exit; } } /*if offset add edit list*/ gf_sm_finalize_mux(mp4, esd, (u32) init_offset); gf_isom_set_last_sample_duration(mp4, track, 0); if (delete_desc) { gf_odf_desc_del((GF_Descriptor *) esd); esd = NULL; } } /*to do - proper PL setup according to node used...*/ gf_isom_set_pl_indication(mp4, GF_ISOM_PL_SCENE, 1); gf_isom_set_pl_indication(mp4, GF_ISOM_PL_GRAPHICS, 1);exit: if (bifs_enc) gf_bifs_encoder_del(bifs_enc);#ifndef GPAC_DISABLE_SVG if (lsr_enc) gf_laser_encoder_del(lsr_enc);#endif if (esd && delete_desc) gf_odf_desc_del((GF_Descriptor *) esd); return e;}static GF_Err gf_sm_encode_od(GF_SceneManager *ctx, GF_ISOFile *mp4, char *mediaSource, GF_SMEncodeOptions *opts){ u32 i, j, n, m, rap_delay; GF_ESD *esd; GF_StreamContext *sc; GF_AUContext *au; u32 count, track, rate, di; u64 dur, time_slice, init_offset, avg_rate, last_rap, last_not_shadow; Bool is_in_iod, delete_desc, rap_inband, rap_shadow; GF_ISOSample *samp; GF_Err e; GF_ODCodec *codec, *rap_codec; GF_InitialObjectDescriptor *iod; gf_isom_set_pl_indication(mp4, GF_ISOM_PL_OD, 0xFE); iod = (GF_InitialObjectDescriptor *) ctx->root_od; count = 0; i=0; while ((sc = (GF_StreamContext*)gf_list_enum(ctx->streams, &i))) { if (sc->streamType == GF_STREAM_OD) count++; } /*no OD stream, nothing to do*/ if (!count) return GF_OK; if (!iod && count>1) return GF_NOT_SUPPORTED; rap_inband = rap_shadow = 0; rap_delay = 0; if (opts && opts->rap_freq) { if (opts->flags & GF_SM_ENCODE_RAP_INBAND) { rap_inband = 1; } else { rap_shadow = 1; } } esd = NULL; codec = rap_codec = NULL; delete_desc = 0; i=0; while ((sc = (GF_StreamContext*)gf_list_enum(ctx->streams, &i))){ if (sc->streamType != GF_STREAM_OD) continue; delete_desc = 0; esd = NULL; is_in_iod = 1; if (iod) { is_in_iod = 0; j=0; while ((esd = (GF_ESD*)gf_list_enum(iod->ESDescriptors, &j))) { if (esd->decoderConfig->streamType != GF_STREAM_OD){ esd = NULL; continue; } if (!sc->ESID) sc->ESID = esd->ESID; if (sc->ESID == esd->ESID) { is_in_iod = 1; break; } } } if (!esd) esd = gf_sm_locate_esd(ctx, sc->ESID); if (!esd) { delete_desc = 1; esd = gf_odf_desc_esd_new(2); esd->ESID = sc->ESID; esd->decoderConfig->objectTypeIndication = 1; esd->decoderConfig->streamType = GF_STREAM_OD; } /*create OD track*/ if (!esd->slConfig) esd->slConfig = (GF_SLConfig *) gf_odf_desc_new(GF_ODF_SLC_TAG); if (sc->timeScale) esd->slConfig->timestampResolution = sc->timeScale; if (!esd->slConfig->timestampResolution) esd->slConfig->timestampResolution = 1000; track = gf_isom_new_track(mp4, sc->ESID, GF_ISOM_MEDIA_OD, esd->slConfig->timestampResolution); if (!sc->ESID) sc->ESID = gf_isom_get_track_id(mp4, track); gf_isom_set_track_enabled(mp4, track, 1); /*no DSI required*/ /*create stream description*/ gf_isom_new_mpeg4_description(mp4, track, esd, NULL, NULL, &di); /*add to root OD*/ if (is_in_iod) gf_isom_add_track_to_root_od(mp4, track); codec = gf_odf_codec_new(); if (rap_inband || rap_shadow) { rap_codec = gf_odf_codec_new(); rap_delay = opts->rap_freq * esd->slConfig->timestampResolution / 1000; } dur = avg_rate = 0; esd->decoderConfig->bufferSizeDB = 0; esd->decoderConfig->maxBitrate = 0; rate = 0; time_slice = 0; init_offset = 0; last_rap = 0; rap_delay = 0; last_not_shadow = 0; if (opts) rap_delay = opts->rap_freq * esd->slConfig->timestampResolution / 1000; /*encode all samples and perform import - FIXME this is destructive...*/ j=0; while ((au = (GF_AUContext *)gf_list_enum(sc->AUs, &j))) { while (gf_list_count(au->commands) ) { GF_ODCom *com = (GF_ODCom *) gf_list_get(au->commands, 0); gf_list_rem(au->commands, 0); /*only updates commandes need to be parsed for import*/ switch (com->tag) { case GF_ODF_OD_UPDATE_TAG: { GF_ObjectDescriptor *od; GF_ODUpdate *odU = (GF_ODUpdate *)com; n=0; while ((od = (GF_ObjectDescriptor *) gf_list_enum(odU->objectDescriptors, &n))) { GF_ESD *imp_esd; m=0; while ((imp_esd = (GF_ESD*)gf_list_enum(od->ESDescriptors, &m))) { switch (imp_esd->tag) { case GF_ODF_ESD_TAG: e = gf_sm_import_stream(ctx, mp4, imp_esd, mediaSource); if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[ISO File Encode] cannot import stream %d (error %s)\n", imp_esd->ESID, gf_error_to_string(e))); gf_odf_com_del(&com); goto err_exit; } gf_sm_finalize_mux(mp4, imp_esd, 0); break; case GF_ODF_ESD_REF_TAG: case GF_ODF_ESD_INC_TAG: break; default: GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[ISO File Encode] Invalid descriptor in OD%d.ESDescr\n", od->objectDescriptorID)); e = GF_BAD_PARAM; goto err_exit; break; } } } } break; case GF_ODF_ESD_UPDATE_TAG: { GF_ESD *imp_esd; GF_ESDUpdate *esdU = (GF_ESDUpdate *)com; m=0; while ((imp_esd = (GF_ESD*)gf_list_enum(esdU->ESDescriptors, &m))) { switch (imp_esd->tag) { case GF_ODF_ESD_TAG: e = gf_sm_import_stream(ctx, mp4, imp_esd, mediaSource); if (e) { GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[ISO File Encode] cannot import stream %d (error %s)\n", imp_esd->ESID, gf_error_to_string(e))); gf_odf_com_del(&com); goto err_exit; } gf_sm_finalize_mux(mp4, imp_esd, 0); break; case GF_ODF_ESD_REF_TAG: case GF_ODF_ESD_INC_TAG: break; default: GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("[ISO File Encode] Invalid descriptor in ESDUpdate (OD %d)\n", esdU->ODID)); e = GF_BAD_PARAM; goto err_exit; break; } } } break; } /*add to codec*/ gf_odf_codec_add_com(codec, com); if (rap_codec) { e = gf_odf_codec_apply_com(rap_codec, com); if (e) goto err_exit; } } e = gf_odf_codec_encode(codec, 1); if (e) goto err_exit; /*time in sec conversion*/ if (au->timing_sec) au->timing = (u64) (au->timing_sec * esd->slConfig->timestampResolution); if (j==1) init_offset = au->timing; samp = gf_isom_sample_new(); samp->DTS = au->timing - init_offset; samp->IsRAP = au->is_rap; last_not_shadow = samp->DTS; if (rap_inband && (samp->DTS - last_rap >= rap_delay)) { last_rap = samp->DTS; e = gf_odf_codec_encode(rap_codec, 0); if (e) goto err_exit; e = gf_odf_codec_get_au(rap_codec, &samp->data, &samp->dataLength); samp->IsRAP = 1; } else { e = gf_odf_codec_get_au(codec, &samp->data, &samp->dataLength); } if (!e) e = gf_isom_add_sample(mp4, track, di, samp); dur = au->timing - init_offset; avg_rate += samp->dataLength; rate += samp->dataLength; if (esd->decoderConfig->bufferSizeDB<samp->dataLength) esd->decoderConfig->bufferSizeDB = samp->dataLength; if (samp->DTS - time_slice > esd->slConfig->timestampResolution) { if (esd->decoderConfig->maxBitrate < rate) esd->decoderConfig->maxBitrate = rate; rate = 0; time_slice = samp->DTS; } if (rap_shadow && (samp->DTS - last_rap >= rap_delay)) { last_rap = samp->DTS; e = gf_odf_codec_encode(rap_codec, 0); if (e) goto err_exit; if (samp->data) free(samp->data); samp->data = NULL; samp->dataLength = 0; e = gf_odf_codec_get_au(rap_codec, &samp->data, &samp->dataLength); if (e) goto err_exit; samp->IsRAP = 1; e = gf_isom_add_sample_shadow(mp4, track, samp); if (e) goto err_exit; last_not_shadow = 0; } gf_isom_sample_del(&samp); if (e) goto err_exit; } if (dur) { esd->decoderConfig->avgBitrate = (u32) (avg_rate * esd->slConfig->timestampResolution * 8 / dur); esd->decoderConfig->maxBitrate *= 8; } else { esd->decoderConfig->avgBitrate = 0; esd->decoderConfig->maxBitrate = 0; } gf_isom_change_mpeg4_description(mp4, track, 1, esd); gf_sm_finalize_mux(mp4, esd, (u32) init_offset); if (delete_desc) { gf_odf_desc_del((GF_Descriptor *) esd); esd = NULL; } esd = NULL; gf_isom_set_last_sample_duration(mp4, track, 0); if (rap_codec) { if (last_not_shadow) { samp = gf_isom_sample_new(); samp->DTS = last_not_shadow; samp->IsRAP = 1; e = gf_odf_codec_encode(rap_codec, 0); if (!e) e = gf_odf_codec_get_au(rap_codec, &samp->data, &samp->dataLength); if (!e) e = gf_isom_add_sample_shadow(mp4, track, samp); if (e) goto err_exit; gf_isom_sample_del(&samp); } gf_odf_codec_del(rap_codec); rap_codec = NULL; } } e = gf_isom_set_pl_indication(mp4, GF_ISOM_PL_OD, 1); err_exit: if (codec) gf_odf_codec_del(codec); if (rap_codec) gf_odf_codec_del(rap_codec); if (esd && delete_desc) gf_odf_desc_del((GF_Descriptor *) esd); return e;}GF_EXPORTGF_Err gf_sm_encode_to_file(GF_SceneManager *ctx, GF_ISOFile *mp4, GF_SMEncodeOptions *opts){ u32 i, count; GF_Descriptor *desc; GF_Err e; if (!ctx->scene_graph) return GF_BAD_PARAM; if (ctx->root_od && (ctx->root_od->tag != GF_ODF_IOD_TAG) && (ctx->root_od->tag != GF_ODF_OD_TAG)) return GF_BAD_PARAM; /*import specials, that is input remapping to BIFS*/ e = gf_sm_import_specials(ctx); if (e) return e; /*encode BIFS*/ e = gf_sm_encode_scene(ctx, mp4, opts, 0); if (e) return e; /*encode LASeR*/ e = gf_sm_encode_scene(ctx, mp4, opts, 1); if (e) return e; /*then encode OD to setup all streams*/ e = gf_sm_encode_od(ctx, mp4, opts ? opts->mediaSource : NULL, opts); if (e) return e; /*store iod*/ if (ctx->root_od) { gf_isom_set_root_od_id(mp4, ctx->root_od->objectDescriptorID); if (ctx->root_od->URLString) gf_isom_set_root_od_url(mp4, ctx->root_od->URLString); count = gf_list_count(ctx->root_od->extensionDescriptors); for (i=0; i<count; i++) { desc = (GF_Descriptor *) gf_list_get(ctx->root_od->extensionDescriptors, i); gf_isom_add_desc_to_root_od(mp4, desc); } count = gf_list_count(ctx->root_od->IPMP_Descriptors); for (i=0; i<count; i++) { desc = (GF_Descriptor *) gf_list_get(ctx->root_od->IPMP_Descriptors, i); gf_isom_add_desc_to_root_od(mp4, desc); } count = gf_list_count(ctx->root_od->OCIDescriptors); for (i=0; i<count; i++) { desc = (GF_Descriptor *) gf_list_get(ctx->root_od->OCIDescriptors, i); gf_isom_add_desc_to_root_od(mp4, desc); } if (ctx->root_od->tag==GF_ODF_IOD_TAG) { GF_InitialObjectDescriptor *iod = (GF_InitialObjectDescriptor*)ctx->root_od; if (iod->IPMPToolList) gf_isom_add_desc_to_root_od(mp4, (GF_Descriptor *) iod->IPMPToolList); } /*we assume all ESs described in bt/xmt input are used*/ } /*set PLs*/ if (ctx->root_od && ctx->root_od->tag==GF_ODF_IOD_TAG) { GF_InitialObjectDescriptor *iod = (GF_InitialObjectDescriptor *)ctx->root_od; gf_isom_set_pl_indication(mp4, GF_ISOM_PL_SCENE, iod->scene_profileAndLevel); gf_isom_set_pl_indication(mp4, GF_ISOM_PL_GRAPHICS, iod->graphics_profileAndLevel); } else { gf_isom_set_pl_indication(mp4, GF_ISOM_PL_SCENE, 0xFE); gf_isom_set_pl_indication(mp4, GF_ISOM_PL_GRAPHICS, 0xFE); } return GF_OK;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -