GF_Err gf_isom_update_xml_subtitle_description(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex, GF_GenericSubtitleSampleDescriptor *desc) { GF_TrackBox *trak; GF_Err e; if (!descriptionIndex || !desc) return GF_BAD_PARAM; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media) return GF_BAD_PARAM; switch (trak->Media->handler->handlerType) { case GF_ISOM_MEDIA_MPEG_SUBT: break; default: return GF_BAD_PARAM; } if (!movie->keep_utc) trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); return e; }
GF_Err gf_isom_hevc_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_HEVCConfig *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_HVC1); if (!entry) return GF_OUT_OF_MEM; entry->hevc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_HVCC); entry->hevc_config->config = HEVC_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); HEVC_RewriteESDescriptor(entry); return e; }
GF_Err gf_isom_new_webvtt_description(GF_ISOFile *movie, u32 trackNumber, GF_TextSampleDescriptor *desc, char *URLname, char *URNname, u32 *outDescriptionIndex) { GF_TrackBox *trak; GF_Err e; u32 dataRefIndex; GF_WebVTTSampleEntryBox *wvtt; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media) return GF_BAD_PARAM; switch (trak->Media->handler->handlerType) { case GF_ISOM_MEDIA_TEXT: break; default: 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(); wvtt = (GF_WebVTTSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_WVTT); wvtt->dataReferenceIndex = dataRefIndex; gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, wvtt); if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); return e; }
GF_Err gf_isom_update_text_description(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex, GF_TextSampleDescriptor *desc) { GF_TrackBox *trak; GF_Err e; u32 i; GF_Tx3gSampleEntryBox *txt; if (!descriptionIndex || !desc) return GF_BAD_PARAM; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media || !desc->font_count) return GF_BAD_PARAM; switch (trak->Media->handler->handlerType) { case GF_ISOM_MEDIA_TEXT: case GF_ISOM_MEDIA_SUBT: break; default: return GF_BAD_PARAM; } txt = (GF_Tx3gSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, descriptionIndex - 1); if (!txt) return GF_BAD_PARAM; switch (txt->type) { case GF_ISOM_BOX_TYPE_TX3G: case GF_ISOM_BOX_TYPE_TEXT: break; default: return GF_BAD_PARAM; } if (!movie->keep_utc) trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); txt->back_color = desc->back_color; txt->default_box = desc->default_pos; txt->default_style = desc->default_style; txt->displayFlags = desc->displayFlags; txt->vertical_justification = desc->vert_justif; txt->horizontal_justification = desc->horiz_justif; if (txt->font_table) gf_isom_box_del((GF_Box*)txt->font_table); txt->font_table = (GF_FontTableBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_FTAB); txt->font_table->entry_count = desc->font_count; txt->font_table->fonts = (GF_FontRecord *) gf_malloc(sizeof(GF_FontRecord) * desc->font_count); for (i=0; i<desc->font_count; i++) { txt->font_table->fonts[i].fontID = desc->fonts[i].fontID; if (desc->fonts[i].fontName) txt->font_table->fonts[i].fontName = gf_strdup(desc->fonts[i].fontName); } return e; }
GF_Err gf_isom_new_text_description(GF_ISOFile *movie, u32 trackNumber, GF_TextSampleDescriptor *desc, char *URLname, char *URNname, u32 *outDescriptionIndex) { GF_TrackBox *trak; GF_Err e; u32 dataRefIndex, i; GF_Tx3gSampleEntryBox *txt; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media || !desc->font_count) return GF_BAD_PARAM; switch (trak->Media->handler->handlerType) { case GF_ISOM_MEDIA_TEXT: case GF_ISOM_MEDIA_SUBT: break; default: 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; } if (!movie->keep_utc) trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); txt = (GF_Tx3gSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_TX3G); txt->dataReferenceIndex = dataRefIndex; gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, txt); if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); txt->back_color = desc->back_color; txt->default_box = desc->default_pos; txt->default_style = desc->default_style; txt->displayFlags = desc->displayFlags; txt->vertical_justification = desc->vert_justif; txt->horizontal_justification = desc->horiz_justif; txt->font_table = (GF_FontTableBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_FTAB); txt->font_table->entry_count = desc->font_count; txt->font_table->fonts = (GF_FontRecord *) gf_malloc(sizeof(GF_FontRecord) * desc->font_count); for (i=0; i<desc->font_count; i++) { txt->font_table->fonts[i].fontID = desc->fonts[i].fontID; if (desc->fonts[i].fontName) txt->font_table->fonts[i].fontName = gf_strdup(desc->fonts[i].fontName); } return e; }
GF_Err gf_isom_new_xml_subtitle_description(GF_ISOFile *movie, u32 trackNumber, const char *xmlnamespace, const char *xml_schema_loc, const char *mimes, u32 *outDescriptionIndex) { GF_TrackBox *trak; GF_Err e; u32 dataRefIndex; GF_MetaDataSampleEntryBox *stpp; char *URLname = NULL; char *URNname = NULL; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media) return GF_BAD_PARAM; switch (trak->Media->handler->handlerType) { case GF_ISOM_MEDIA_MPEG_SUBT: case GF_ISOM_MEDIA_META: case GF_ISOM_MEDIA_TEXT: break; default: return GF_BAD_PARAM; } if (!xmlnamespace) { GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("XML (Subtitle, Metadata or Text) SampleEntry: namespace is mandatory. Abort.\n")); 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; } if (!movie->keep_utc) trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); stpp = (GF_MetaDataSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_STPP); stpp->dataReferenceIndex = dataRefIndex; gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, stpp); if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); stpp->xml_namespace = gf_strdup(xmlnamespace); if (xml_schema_loc) stpp->xml_schema_loc = gf_strdup(xml_schema_loc); //optional if (mimes) stpp->mime_type = gf_strdup(mimes); //optional return e; }
GF_Err gf_isom_new_xml_metadata_description(GF_ISOFile *movie, u32 trackNumber, const char *_namespace, const char *schema_loc, const char *content_encoding, u32 *outDescriptionIndex) { GF_TrackBox *trak; GF_Err e; u32 dataRefIndex; GF_MetaDataSampleEntryBox *metad; char *URLname = NULL; char *URNname = NULL; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media || !_namespace) return GF_BAD_PARAM; switch (trak->Media->handler->handlerType) { case GF_ISOM_MEDIA_MPEG_SUBT: case GF_ISOM_MEDIA_META: case GF_ISOM_MEDIA_TEXT: break; default: 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; } if (!movie->keep_utc) trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); metad = (GF_MetaDataSampleEntryBox*) gf_isom_box_new(GF_ISOM_BOX_TYPE_METX); if (!metad) return GF_OUT_OF_MEM; metad->dataReferenceIndex = dataRefIndex; metad->xml_namespace = gf_strdup(_namespace); if (content_encoding) metad->content_encoding = gf_strdup(content_encoding); if (schema_loc) metad->xml_schema_loc = gf_strdup(schema_loc); e = gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, metad); if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); return e; }
GF_Err gf_isom_new_dims_description(GF_ISOFile *movie, u32 trackNumber, GF_DIMSDescription *desc, char *URLname, char *URNname, u32 *outDescriptionIndex) { GF_TrackBox *trak; GF_Err e; u32 dataRefIndex; GF_DIMSSampleEntryBox *dims; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media) return GF_BAD_PARAM; if (trak->Media->handler->handlerType != GF_ISOM_MEDIA_SCENE) 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; } if (!movie->keep_utc) trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); dims = (GF_DIMSSampleEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_DIMS); dims->dataReferenceIndex = dataRefIndex; gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, dims); if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); dims->config = (GF_DIMSSceneConfigBox*) gf_isom_box_new(GF_ISOM_BOX_TYPE_DIMC); dims->config->profile = desc->profile; dims->config->level = desc->level; dims->config->pathComponents = desc->pathComponents; dims->config->fullRequestHost = desc->fullRequestHost; dims->config->containsRedundant = desc->containsRedundant; if (!dims->config->containsRedundant) dims->config->containsRedundant = 1; dims->config->streamType = desc->streamType; dims->config->textEncoding = gf_strdup(desc->textEncoding ? desc->textEncoding : ""); dims->config->contentEncoding = gf_strdup(desc->contentEncoding ? desc->contentEncoding : ""); if (desc->content_script_types) { dims->scripts = (GF_DIMSScriptTypesBox*) gf_isom_box_new(GF_ISOM_BOX_TYPE_DIST); dims->scripts->content_script_types = gf_strdup(desc->content_script_types); } return e; }
GF_Err gf_isom_new_generic_subtitle_description(GF_ISOFile *movie, u32 trackNumber, char *content_encoding, char *xml_schema_loc, char *mime_type_or_namespace, Bool is_xml, char *URLname, char *URNname, u32 *outDescriptionIndex) { GF_TrackBox *trak; GF_Err e; u32 dataRefIndex; GF_MetaDataSampleEntryBox *metasd; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media) return GF_BAD_PARAM; switch (trak->Media->handler->handlerType) { case GF_ISOM_MEDIA_SUBM: break; default: 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(); metasd = (GF_MetaDataSampleEntryBox *) gf_isom_box_new((is_xml ? GF_ISOM_BOX_TYPE_METX : GF_ISOM_BOX_TYPE_METT)); metasd->dataReferenceIndex = dataRefIndex; gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, metasd); if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); metasd->content_encoding = gf_strdup(content_encoding); metasd->xml_schema_loc = gf_strdup(xml_schema_loc); metasd->mime_type_or_namespace = gf_strdup(mime_type_or_namespace); return e; }
GF_Err gf_isom_update_dims_description(GF_ISOFile *movie, u32 trackNumber, GF_DIMSDescription *desc, char *URLname, char *URNname, u32 DescriptionIndex) { GF_TrackBox *trak; GF_Err e; GF_DIMSSampleEntryBox *dims; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media || !desc || !DescriptionIndex) return GF_BAD_PARAM; dims = (GF_DIMSSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex - 1); if (!dims) return GF_BAD_PARAM; if (dims->type != GF_ISOM_BOX_TYPE_DIMS) return GF_BAD_PARAM; if (!dims->config) dims->config = (GF_DIMSSceneConfigBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_DIMC); if (!movie->keep_utc) trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); dims->config->profile = desc->profile; dims->config->level = desc->level; dims->config->pathComponents = desc->pathComponents; dims->config->fullRequestHost = desc->fullRequestHost; dims->config->containsRedundant = desc->containsRedundant; dims->config->streamType = desc->streamType; if (dims->config->textEncoding) gf_free(dims->config->textEncoding); dims->config->textEncoding = gf_strdup(desc->textEncoding ? desc->textEncoding : ""); if (dims->config->contentEncoding) gf_free(dims->config->contentEncoding); dims->config->contentEncoding = gf_strdup(desc->contentEncoding ? desc->contentEncoding : ""); if (desc->content_script_types) { if (!dims->scripts) dims->scripts = (GF_DIMSScriptTypesBox*)gf_isom_box_new(GF_ISOM_BOX_TYPE_DIST); if (dims->scripts->content_script_types) gf_free(dims->scripts->content_script_types); dims->scripts->content_script_types = gf_strdup(desc->content_script_types ? desc->content_script_types : ""); } else if (dims->scripts) { gf_isom_box_del((GF_Box *)dims->scripts); dims->scripts = NULL; } return e; }
GF_EXPORT GF_Err gf_isom_ac3_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_AC3Config *cfg, char *URLname, char *URNname, u32 *outDescriptionIndex) { GF_TrackBox *trak; GF_Err e; u32 dataRefIndex; GF_AC3SampleEntryBox *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; } if (!the_file->keep_utc) trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); if (cfg->is_ec3) { entry = (GF_AC3SampleEntryBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_EC3); if (!entry) return GF_OUT_OF_MEM; entry->info = (GF_AC3ConfigBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_DEC3); } else { entry = (GF_AC3SampleEntryBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_AC3); if (!entry) return GF_OUT_OF_MEM; entry->info = (GF_AC3ConfigBox *)gf_isom_box_new(GF_ISOM_BOX_TYPE_DAC3); } if (!entry->info) { gf_isom_box_del((GF_Box *)entry); return GF_OUT_OF_MEM; } memcpy(&entry->info->cfg, cfg, sizeof(GF_AC3Config)); entry->samplerate_hi = trak->Media->mediaHeader->timeScale; 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); return e; }
GF_Err gf_isom_update_stxt_description(GF_ISOFile *movie, u32 trackNumber, const char *encoding, const char *config, u32 DescriptionIndex) { GF_TrackBox *trak; GF_Err e; GF_MetaDataSampleEntryBox *sample_entry; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media || !DescriptionIndex) return GF_BAD_PARAM; sample_entry = (GF_MetaDataSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex-1); if (!sample_entry) return GF_BAD_PARAM; if (sample_entry->type != GF_ISOM_BOX_TYPE_METT && sample_entry->type != GF_ISOM_BOX_TYPE_SBTT && sample_entry->type != GF_ISOM_BOX_TYPE_STXT) { return GF_BAD_PARAM; } if (!sample_entry->config) sample_entry->config = (GF_TextConfigBox*) gf_isom_box_new(GF_ISOM_BOX_TYPE_TXTC); if (!movie->keep_utc) trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); if (sample_entry->config->config) { gf_free(sample_entry->config->config); } sample_entry->config->config = gf_strdup(config); if (sample_entry->content_encoding) { gf_free(sample_entry->content_encoding); } if (encoding) { sample_entry->content_encoding = gf_strdup(encoding); } return e; }
void gf_isom_insert_moov(GF_ISOFile *file) { u64 now; GF_MovieHeaderBox *mvhd; if (file->moov) return; //OK, create our boxes (mvhd, iods, ...) file->moov = (GF_MovieBox *) moov_New(); file->moov->mov = file; //Header SetUp now = gf_isom_get_mp4time(); mvhd = (GF_MovieHeaderBox *) mvhd_New(); mvhd->creationTime = now; mvhd->modificationTime = now; mvhd->nextTrackID = 1; //600 is our default movie TimeScale mvhd->timeScale = 600; file->interleavingTime = mvhd->timeScale; moov_AddBox((GF_Box*)file->moov, (GF_Box *)mvhd); gf_list_add(file->TopBoxes, file->moov); }
GF_Err gf_isom_update_webvtt_description(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex, const char *config) { GF_Err e; GF_WebVTTSampleEntryBox *wvtt; GF_TrackBox *trak; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return GF_BAD_PARAM; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media) return GF_BAD_PARAM; switch (trak->Media->handler->handlerType) { case GF_ISOM_MEDIA_TEXT: case GF_ISOM_MEDIA_SUBT: case GF_ISOM_MEDIA_MPEG_SUBT: break; default: return GF_BAD_PARAM; } wvtt = (GF_WebVTTSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, descriptionIndex - 1); if (!wvtt) return GF_BAD_PARAM; switch (wvtt->type) { case GF_ISOM_BOX_TYPE_WVTT: break; default: return GF_BAD_PARAM; } if (wvtt) { if (!movie->keep_utc) trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); wvtt->config = (GF_StringBox *)boxstring_new_with_data(GF_ISOM_BOX_TYPE_VTTC, config); } else { e = GF_BAD_PARAM; } return e; }
GF_Err SetTrackDuration(GF_TrackBox *trak) { u64 trackDuration; u32 i; GF_EdtsEntry *ent; GF_EditListBox *elst; GF_Err e; //the total duration is the media duration: adjust it in case... e = Media_SetDuration(trak); if (e) return e; //assert the timeScales are non-NULL if (!trak->moov->mvhd->timeScale || !trak->Media->mediaHeader->timeScale) return GF_ISOM_INVALID_FILE; trackDuration = (trak->Media->mediaHeader->duration * trak->moov->mvhd->timeScale) / trak->Media->mediaHeader->timeScale; //if we have an edit list, the duration is the sum of all the editList //entries' duration (always expressed in MovieTimeScale) if (trak->editBox && !trak->editBox->last_is_empty && trak->editBox->editList) { trackDuration = 0; elst = trak->editBox->editList; i=0; while ((ent = (GF_EdtsEntry*)gf_list_enum(elst->entryList, &i))) { trackDuration += ent->segmentDuration; if (ent->mediaRate && !ent->segmentDuration) { trak->editBox->last_is_empty = 1; } } if (trak->editBox->last_is_empty) { ent = (GF_EdtsEntry*) gf_list_last(elst->entryList); ent->segmentDuration = trackDuration; } } trak->Header->duration = trackDuration; trak->Header->modificationTime = gf_isom_get_mp4time(); return GF_OK; }
GF_Err gf_isom_update_generic_subtitle_description( GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex, GF_GenericSubtitleSampleDescriptor *desc) { GF_TrackBox *trak; GF_Err e; if (!descriptionIndex || !desc) return GF_BAD_PARAM; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media) return GF_BAD_PARAM; switch (trak->Media->handler->handlerType) { case GF_ISOM_MEDIA_SUBM: break; default: return GF_BAD_PARAM; } //GF_GenericSubtitleSampleEntryBox *gsub; //gsub = (GF_GenericSubtitleSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, descriptionIndex - 1); //if (!gsub) return GF_BAD_PARAM; //switch (txt->type) { //case GF_ISOM_BOX_TYPE_METX: //case GF_ISOM_BOX_TYPE_METT: // break; //default: // return GF_BAD_PARAM; //} trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); return e; }
GF_EXPORT GF_Err gf_isom_3gp_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_3GPConfig *cfg, char *URLname, char *URNname, u32 *outDescriptionIndex) { GF_TrackBox *trak; GF_Err e; u32 dataRefIndex; u32 cfg_type; 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; switch (cfg->type) { case GF_ISOM_SUBTYPE_3GP_AMR: case GF_ISOM_SUBTYPE_3GP_AMR_WB: if (trak->Media->handler->handlerType!=GF_ISOM_MEDIA_AUDIO) return GF_BAD_PARAM; cfg_type = GF_ISOM_BOX_TYPE_DAMR; break; case GF_ISOM_SUBTYPE_3GP_EVRC: if (trak->Media->handler->handlerType!=GF_ISOM_MEDIA_AUDIO) return GF_BAD_PARAM; cfg_type = GF_ISOM_BOX_TYPE_DEVC; break; case GF_ISOM_SUBTYPE_3GP_QCELP: if (trak->Media->handler->handlerType!=GF_ISOM_MEDIA_AUDIO) return GF_BAD_PARAM; cfg_type = GF_ISOM_BOX_TYPE_DQCP; break; case GF_ISOM_SUBTYPE_3GP_SMV: if (trak->Media->handler->handlerType!=GF_ISOM_MEDIA_AUDIO) return GF_BAD_PARAM; cfg_type = GF_ISOM_BOX_TYPE_DSMV; break; case GF_ISOM_SUBTYPE_3GP_H263: if (trak->Media->handler->handlerType!=GF_ISOM_MEDIA_VISUAL) return GF_BAD_PARAM; cfg_type = GF_ISOM_BOX_TYPE_D263; break; case 0: return GF_BAD_PARAM; default: return GF_NOT_SUPPORTED; } //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(); switch (cfg->type) { case GF_ISOM_SUBTYPE_3GP_AMR: case GF_ISOM_SUBTYPE_3GP_AMR_WB: case GF_ISOM_SUBTYPE_3GP_EVRC: case GF_ISOM_SUBTYPE_3GP_QCELP: case GF_ISOM_SUBTYPE_3GP_SMV: { GF_3GPPAudioSampleEntryBox *entry = (GF_3GPPAudioSampleEntryBox *) gf_isom_box_new(cfg->type); if (!entry) return GF_OUT_OF_MEM; entry->info = (GF_3GPPConfigBox *) gf_isom_box_new(cfg_type); if (!entry->info) { gf_isom_box_del((GF_Box *) entry); return GF_OUT_OF_MEM; } memcpy(&entry->info->cfg, cfg, sizeof(GF_3GPConfig)); entry->samplerate_hi = trak->Media->mediaHeader->timeScale; 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); } break; case GF_ISOM_SUBTYPE_3GP_H263: { GF_3GPPVisualSampleEntryBox *entry = (GF_3GPPVisualSampleEntryBox *) gf_isom_box_new(cfg->type); if (!entry) return GF_OUT_OF_MEM; entry->info = (GF_3GPPConfigBox *) gf_isom_box_new(cfg_type); if (!entry->info) { gf_isom_box_del((GF_Box *) entry); return GF_OUT_OF_MEM; } memcpy(&entry->info->cfg, cfg, sizeof(GF_3GPConfig)); 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); } break; } return e; }
GF_Err gf_isom_new_stxt_description(GF_ISOFile *movie, u32 trackNumber, u32 type, const char *mime, const char *encoding, const char * config, u32 *outDescriptionIndex) { GF_TrackBox *trak; GF_Err e; u32 dataRefIndex; GF_MetaDataSampleEntryBox *sample_entry; char *URLname = NULL; char *URNname = NULL; e = CanAccessMovie(movie, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media) return GF_BAD_PARAM; switch (trak->Media->handler->handlerType) { case GF_ISOM_MEDIA_MPEG_SUBT: case GF_ISOM_MEDIA_META: case GF_ISOM_MEDIA_SCENE: case GF_ISOM_MEDIA_TEXT: case GF_ISOM_MEDIA_SUBT: break; default: return GF_BAD_PARAM; } switch (type) { case GF_ISOM_SUBTYPE_SBTT: case GF_ISOM_SUBTYPE_STXT: case GF_ISOM_SUBTYPE_METT: break; default: GF_LOG(GF_LOG_ERROR, GF_LOG_PARSER, ("SampleEntry shall be either Metadata, Subtitle or SimpleText. Abort.\n")); return GF_BAD_PARAM; } if (!mime) { GF_LOG(GF_LOG_WARNING, GF_LOG_PARSER, ("Text (Metadata, Subtitle or SimpleText) SampleEntry: mime is mandatory. Using text/plain.\n")); mime = "text/plain"; } //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; } if (!movie->keep_utc) trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time(); sample_entry = (GF_MetaDataSampleEntryBox *) gf_isom_box_new(type); sample_entry->dataReferenceIndex = dataRefIndex; gf_list_add(trak->Media->information->sampleTable->SampleDescription->other_boxes, sample_entry); if (outDescriptionIndex) *outDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->other_boxes); sample_entry->mime_type = gf_strdup(mime); if (encoding) sample_entry->content_encoding = gf_strdup(encoding); if (config) { sample_entry->config = (GF_TextConfigBox*) gf_isom_box_new(GF_ISOM_BOX_TYPE_TXTC); sample_entry->config->config = gf_strdup(config); } return e; }