void AVC_RewriteESDescriptor(GF_MPEGVisualSampleEntryBox *avc) { GF_AVCConfig *avcc, *svcc; if (avc->emul_esd) gf_odf_desc_del((GF_Descriptor *)avc->emul_esd); avc->emul_esd = gf_odf_desc_esd_new(2); avc->emul_esd->decoderConfig->streamType = GF_STREAM_VISUAL; /*AVC OTI is 0x21, AVC parameter set stream OTI (not supported in gpac) is 0x22*/ avc->emul_esd->decoderConfig->objectTypeIndication = GPAC_OTI_VIDEO_AVC; if (avc->bitrate) { avc->emul_esd->decoderConfig->bufferSizeDB = avc->bitrate->bufferSizeDB; avc->emul_esd->decoderConfig->avgBitrate = avc->bitrate->avgBitrate; avc->emul_esd->decoderConfig->maxBitrate = avc->bitrate->maxBitrate; } if (avc->descr) { u32 i=0; GF_Descriptor *desc,*clone; i=0; while ((desc = (GF_Descriptor *)gf_list_enum(avc->descr->descriptors, &i))) { clone = NULL; gf_odf_desc_copy(desc, &clone); if (gf_odf_desc_add_desc((GF_Descriptor *)avc->emul_esd, clone) != GF_OK) gf_odf_desc_del(clone); } } if (avc->avc_config) { avcc = avc->avc_config->config ? AVC_DuplicateConfig(avc->avc_config->config) : NULL; /*merge SVC config*/ if (avc->svc_config) { svcc = AVC_DuplicateConfig(avc->svc_config->config); while (gf_list_count(svcc->sequenceParameterSets)) { GF_AVCConfigSlot *p = (GF_AVCConfigSlot*)gf_list_get(svcc->sequenceParameterSets, 0); gf_list_rem(svcc->sequenceParameterSets, 0); gf_list_add(avcc->sequenceParameterSets, p); } while (gf_list_count(svcc->pictureParameterSets)) { GF_AVCConfigSlot *p = (GF_AVCConfigSlot*)gf_list_get(svcc->pictureParameterSets, 0); gf_list_rem(svcc->pictureParameterSets, 0); gf_list_add(avcc->pictureParameterSets, p); } gf_odf_avc_cfg_del(svcc); } if (avcc) { gf_odf_avc_cfg_write(avcc, &avc->emul_esd->decoderConfig->decoderSpecificInfo->data, &avc->emul_esd->decoderConfig->decoderSpecificInfo->dataLength); gf_odf_avc_cfg_del(avcc); } } else if (avc->svc_config) { svcc = AVC_DuplicateConfig(avc->svc_config->config); gf_odf_avc_cfg_write(svcc, &avc->emul_esd->decoderConfig->decoderSpecificInfo->data, &avc->emul_esd->decoderConfig->decoderSpecificInfo->dataLength); gf_odf_avc_cfg_del(svcc); } }
static GF_Err gf_isom_avc_config_update_ex(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_AVCConfig *cfg, u32 op_type) { GF_TrackBox *trak; GF_Err e; GF_MPEGVisualSampleEntryBox *entry; e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !trak->Media || !cfg || !DescriptionIndex) return GF_BAD_PARAM; entry = (GF_MPEGVisualSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, DescriptionIndex-1); if (!entry) return GF_BAD_PARAM; switch (entry->type) { case GF_ISOM_BOX_TYPE_AVC1: case GF_ISOM_BOX_TYPE_AVC2: case GF_ISOM_BOX_TYPE_SVC1: break; default: return GF_BAD_PARAM; } switch (op_type) { /*AVCC replacement*/ case 0: if (!entry->avc_config) entry->avc_config = (GF_AVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_AVCC); if (entry->avc_config->config) gf_odf_avc_cfg_del(entry->avc_config->config); entry->avc_config->config = AVC_DuplicateConfig(cfg); entry->type = GF_ISOM_BOX_TYPE_AVC1; break; /*SVCC replacement*/ case 1: if (!entry->svc_config) entry->svc_config = (GF_AVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_SVCC); if (entry->svc_config->config) gf_odf_avc_cfg_del(entry->svc_config->config); entry->svc_config->config = AVC_DuplicateConfig(cfg); entry->type = GF_ISOM_BOX_TYPE_AVC1; break; /*SVCC replacement and AVC removal*/ case 2: if (entry->avc_config) { gf_isom_box_del((GF_Box*)entry->avc_config); entry->avc_config = NULL; } if (!entry->svc_config) entry->svc_config = (GF_AVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_SVCC); if (entry->svc_config->config) gf_odf_avc_cfg_del(entry->svc_config->config); entry->svc_config->config = AVC_DuplicateConfig(cfg); entry->type = GF_ISOM_BOX_TYPE_SVC1; break; } AVC_RewriteESDescriptor(entry); return GF_OK; }
GF_Err gf_isom_svc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_AVCConfig *cfg, char *URLname, char *URNname, u32 *outDescriptionIndex) { GF_TrackBox *trak; GF_Err e; u32 dataRefIndex; GF_MPEGVisualSampleEntryBox *entry; e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !trak->Media || !cfg) return GF_BAD_PARAM; //get or create the data ref e = Media_FindDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex); if (e) return e; if (!dataRefIndex) { e = Media_CreateDataRef(trak->Media->information->dataInformation->dref, URLname, URNname, &dataRefIndex); if (e) return e; } trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); //create a new entry entry = (GF_MPEGVisualSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_SVC1); if (!entry) return GF_OUT_OF_MEM; entry->svc_config = (GF_AVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_SVCC); entry->svc_config->config = AVC_DuplicateConfig(cfg); entry->dataReferenceIndex = dataRefIndex; e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, entry); *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); AVC_RewriteESDescriptor(entry); return e; }
GF_EXPORT GF_AVCConfig *gf_isom_svc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex) { GF_TrackBox *trak; GF_MPEGVisualSampleEntryBox *entry; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !trak->Media || !DescriptionIndex) return NULL; entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, DescriptionIndex-1); if (!entry) return NULL; if (!entry->svc_config) return NULL; return AVC_DuplicateConfig(entry->svc_config->config); }
GF_Err gf_isom_avc_config_update(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_AVCConfig *cfg) { GF_TrackBox *trak; GF_Err e; GF_MPEGVisualSampleEntryBox *entry; e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !trak->Media || !cfg || !DescriptionIndex) return GF_BAD_PARAM; entry = (GF_MPEGVisualSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, DescriptionIndex-1); if (!entry) return GF_BAD_PARAM; if (entry->type != GF_ISOM_BOX_TYPE_AVC1) return GF_BAD_PARAM; if (entry->avc_config->config) gf_odf_avc_cfg_del(entry->avc_config->config); entry->avc_config->config = AVC_DuplicateConfig(cfg); AVC_RewriteESDescriptor(entry); return GF_OK; }
static GF_Err gf_isom_avc_config_update_ex(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_AVCConfig *cfg, u32 op_type) { GF_TrackBox *trak; GF_Err e; GF_MPEGVisualSampleEntryBox *entry; e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !trak->Media || !DescriptionIndex) return GF_BAD_PARAM; entry = (GF_MPEGVisualSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex-1); if (!entry) return GF_BAD_PARAM; switch (entry->type) { case GF_ISOM_BOX_TYPE_AVC1: case GF_ISOM_BOX_TYPE_AVC2: case GF_ISOM_BOX_TYPE_AVC3: case GF_ISOM_BOX_TYPE_AVC4: case GF_ISOM_BOX_TYPE_SVC1: break; default: return GF_BAD_PARAM; } switch (op_type) { /*AVCC replacement*/ case 0: if (!cfg) return GF_BAD_PARAM; if (!entry->avc_config) entry->avc_config = (GF_AVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_AVCC); if (entry->avc_config->config) gf_odf_avc_cfg_del(entry->avc_config->config); entry->avc_config->config = AVC_DuplicateConfig(cfg); entry->type = GF_ISOM_BOX_TYPE_AVC1; break; /*SVCC replacement*/ case 1: if (!cfg) return GF_BAD_PARAM; if (!entry->svc_config) entry->svc_config = (GF_AVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_SVCC); if (entry->svc_config->config) gf_odf_avc_cfg_del(entry->svc_config->config); entry->svc_config->config = AVC_DuplicateConfig(cfg); entry->type = GF_ISOM_BOX_TYPE_AVC1; break; /*SVCC replacement and AVC removal*/ case 2: if (!cfg) return GF_BAD_PARAM; if (entry->avc_config) { gf_isom_box_del((GF_Box*)entry->avc_config); entry->avc_config = NULL; } if (!entry->svc_config) entry->svc_config = (GF_AVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_SVCC); if (entry->svc_config->config) gf_odf_avc_cfg_del(entry->svc_config->config); entry->svc_config->config = AVC_DuplicateConfig(cfg); entry->type = GF_ISOM_BOX_TYPE_SVC1; break; /*AVCC removal and switch to avc3*/ case 3: if (!entry->avc_config || !entry->avc_config->config) return GF_BAD_PARAM; if (entry->svc_config) { gf_isom_box_del((GF_Box*)entry->svc_config); entry->svc_config = NULL; } while (gf_list_count(entry->avc_config->config->sequenceParameterSets)) { GF_AVCConfigSlot *sl = gf_list_get(entry->avc_config->config->sequenceParameterSets, 0); gf_list_rem(entry->avc_config->config->sequenceParameterSets, 0); if (sl->data) gf_free(sl->data); gf_free(sl); } while (gf_list_count(entry->avc_config->config->pictureParameterSets)) { GF_AVCConfigSlot *sl = gf_list_get(entry->avc_config->config->pictureParameterSets, 0); gf_list_rem(entry->avc_config->config->pictureParameterSets, 0); if (sl->data) gf_free(sl->data); gf_free(sl); } if (entry->type == GF_ISOM_BOX_TYPE_AVC1) entry->type = GF_ISOM_BOX_TYPE_AVC3; else if (entry->type == GF_ISOM_BOX_TYPE_AVC2) entry->type = GF_ISOM_BOX_TYPE_AVC4; break; } AVC_RewriteESDescriptor(entry); return GF_OK; }