GF_EXPORT GF_Err gf_isom_change_ismacryp_protection(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex, char *scheme_uri, char *kms_uri) { GF_TrackBox *trak; GF_Err e; GF_SampleEntryBox *sea; GF_ProtectionInfoBox *sinf; 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 || !sampleDescriptionIndex) return GF_BAD_PARAM; sea = NULL; sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, GF_ISOM_ISMACRYP_SCHEME, &sea); if (!sinf) return GF_OK; if (scheme_uri) { gf_free(sinf->scheme_type->URI); sinf->scheme_type->URI = gf_strdup(scheme_uri); } if (kms_uri) { gf_free(sinf->info->ikms->URI); sinf->info->ikms->URI = gf_strdup(kms_uri); } return GF_OK; }
GF_WebVTTSampleEntryBox *gf_webvtt_isom_get_description(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex) { GF_WebVTTSampleEntryBox *wvtt; GF_TrackBox *trak; GF_Err e; if (!descriptionIndex) return NULL; e = CanAccessMovie(movie, GF_ISOM_OPEN_READ); if (e) return NULL; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !trak->Media) return NULL; switch (trak->Media->handler->handlerType) { case GF_ISOM_MEDIA_TEXT: break; default: return NULL; } wvtt = (GF_WebVTTSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, descriptionIndex - 1); if (!wvtt) return NULL; switch (wvtt->type) { case GF_ISOM_BOX_TYPE_WVTT: break; default: return NULL; } return wvtt; }
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_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_remove_track_protection(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex) { GF_TrackBox *trak; GF_Err e; GF_SampleEntryBox *sea; GF_ProtectionInfoBox *sinf; 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 || !sampleDescriptionIndex) return GF_BAD_PARAM; sea = NULL; sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, GF_ISOM_CENC_SCHEME, &sea); if (!sinf) sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, GF_ISOM_CBC_SCHEME, &sea); if (!sinf) sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, GF_ISOM_ISMACRYP_SCHEME, &sea); if (!sinf) sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, GF_ISOM_OMADRM_SCHEME, &sea); if (!sinf) sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, GF_ISOM_ADOBE_SCHEME, &sea); if (!sinf) return GF_OK; sea->type = sinf->original_format->data_format; gf_isom_box_array_del(sea->protections); sea->protections = gf_list_new(); if (sea->type == GF_4CC('2','6','4','b')) sea->type = GF_ISOM_BOX_TYPE_AVC1; if (sea->type == GF_4CC('2','6','5','b')) sea->type = GF_ISOM_BOX_TYPE_HVC1; return GF_OK; }
GF_Err gf_isom_3gp_config_update(GF_ISOFile *the_file, u32 trackNumber, GF_3GPConfig *param, u32 DescriptionIndex) { GF_TrackBox *trak; GF_Err e; GF_3GPConfig *cfg; GF_3GPPAudioSampleEntryBox *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 || !param || !DescriptionIndex) return GF_BAD_PARAM; cfg = NULL; entry = (GF_3GPPAudioSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex-1); if (!entry) return GF_BAD_PARAM; switch (entry->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: cfg = &entry->info->cfg; break; case GF_ISOM_SUBTYPE_3GP_H263: cfg = & ((GF_3GPPVisualSampleEntryBox *)entry)->info->cfg; break; default: break; } if (!cfg || (cfg->type != param->type)) return GF_BAD_PARAM; memcpy(cfg, param, sizeof(GF_3GPConfig)); return GF_OK; }
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_set_meta_xml_memory(GF_ISOFile *file, Bool root_meta, u32 track_num, unsigned char *data, u32 data_size, Bool IsBinaryXML) { GF_Err e; GF_XMLBox *xml; GF_MetaBox *meta; e = CanAccessMovie(file, GF_ISOM_OPEN_WRITE); if (e) return e; meta = gf_isom_get_meta(file, root_meta, track_num); if (!meta) return GF_BAD_PARAM; e = gf_isom_remove_meta_xml(file, root_meta, track_num); if (e) return e; xml = (GF_XMLBox *)xml_New(); if (!xml) return GF_OUT_OF_MEM; gf_list_add(meta->other_boxes, xml); if (IsBinaryXML) xml->type = GF_ISOM_BOX_TYPE_BXML; /*assume 32bit max size = 4Go should be sufficient for a DID!!*/ xml->xml_length = data_size; xml->xml = (char*)gf_malloc(sizeof(unsigned char)*xml->xml_length); memcpy(xml->xml, data, sizeof(unsigned char)*xml->xml_length); return GF_OK; }
GF_EXPORT GF_Err gf_isom_set_ipod_compatible(GF_ISOFile *the_file, u32 trackNumber) { static const u8 ipod_ext[][16] = { { 0x6B, 0x68, 0x40, 0xF2, 0x5F, 0x24, 0x4F, 0xC5, 0xBA, 0x39, 0xA5, 0x1B, 0xCF, 0x03, 0x23, 0xF3} }; static const u8 ipod_ext_data[][4] = { { 0x00, 0x00, 0x00, 0x00 } }; 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) return GF_BAD_PARAM; entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, 0); if (!entry) return GF_OK; 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: case GF_ISOM_BOX_TYPE_HVC1: case GF_ISOM_BOX_TYPE_HEV1: break; default: return GF_OK; } if (!entry->ipod_ext) entry->ipod_ext = (GF_UnknownUUIDBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_UUID); memcpy(entry->ipod_ext->uuid, ipod_ext, sizeof(u8)*16); entry->ipod_ext->dataSize = 4; entry->ipod_ext->data = gf_malloc(sizeof(u8)*4); memcpy(entry->ipod_ext->data, ipod_ext_data, sizeof(u8)*4); return GF_OK; }
GF_Err gf_isom_svc_config_del(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex) { 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; } if (entry->svc_config) { gf_isom_box_del((GF_Box*)entry->svc_config); entry->svc_config = NULL; } AVC_RewriteESDescriptor(entry); return GF_OK; }
M4Err M4_AMR_UpdateStreamConfig(M4File *the_file, u32 trackNumber, LPAMRCONFIGURATION param, u32 DescriptionIndex) { TrackAtom *trak; M4Err e; AMRSampleEntryAtom *entry; e = CanAccessMovie((M4Movie *)the_file, M4_OPEN_WRITE); if (e) return e; trak = GetTrackFromFile(the_file, trackNumber); if (!trak || !trak->Media || !param || !DescriptionIndex) return M4BadParam; entry = ChainGetEntry(trak->Media->information->sampleTable->SampleDescription->atomList, DescriptionIndex-1); if (!entry) return M4BadParam; switch (entry->type) { case AMRSampleEntryAtomType: case WB_AMRSampleEntryAtomType: break; default: return M4BadParam; } entry->amr_info->decoder_version = param->decoder_version; entry->amr_info->frames_per_sample = param->frames_per_sample; entry->amr_info->mode_change_period = param->mode_change_period; entry->amr_info->mode_set = param->mode_set; entry->amr_info->vendor = param->vendor; //change atom type entry->type = param->WideBandAMR ? WB_AMRSampleEntryAtomType : AMRSampleEntryAtomType; return M4OK; }
GF_Err gf_isom_change_ismacryp_protection(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex, char *scheme_uri, char *kms_uri) { GF_TrackBox *trak; GF_Err e; GF_SampleEntryBox *sea; 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 || !StreamDescriptionIndex) return GF_BAD_PARAM; Media_GetSampleDesc(trak->Media, StreamDescriptionIndex, &sea, NULL); /*non-encrypted or non-ISMA*/ if (!sea || !sea->protection_info) return GF_BAD_PARAM; if (!sea->protection_info->scheme_type || !sea->protection_info->original_format) return GF_NON_COMPLIANT_BITSTREAM; if (scheme_uri) { free(sea->protection_info->scheme_type->URI); sea->protection_info->scheme_type->URI = strdup(scheme_uri); } if (kms_uri) { free(sea->protection_info->info->ikms->URI); sea->protection_info->info->ikms->URI = strdup(kms_uri); } return GF_OK; }
GF_EXPORT GF_Err gf_isom_set_meta_type(GF_ISOFile *file, Bool root_meta, u32 track_num, u32 metaType) { char szName[20]; GF_MetaBox *meta; GF_Err e = CanAccessMovie(file, GF_ISOM_OPEN_WRITE); if (e) return e; meta = gf_isom_get_meta(file, root_meta, track_num); if (!meta) { if (!metaType) return GF_OK; meta = (GF_MetaBox *) meta_New(); if (root_meta) { file->meta = meta; gf_list_add(file->TopBoxes, meta); } else { gf_isom_insert_moov(file); if (!track_num) { file->moov->meta = meta; } else { GF_TrackBox *tk = (GF_TrackBox *)gf_list_get(file->moov->trackList, track_num-1); if (!tk) { gf_isom_box_del((GF_Box *)meta); return GF_BAD_PARAM; } tk->meta = meta; } } } else if (!metaType) { if (root_meta) { gf_list_del_item(file->TopBoxes, meta); gf_isom_box_del((GF_Box *)file->meta); file->meta = NULL; } else if (file->moov) { if (!track_num) { gf_isom_box_del((GF_Box *)file->moov->meta); file->moov->meta = NULL; } else { GF_TrackBox *tk = (GF_TrackBox *)gf_list_get(file->moov->trackList, track_num-1); if (!tk) return GF_BAD_PARAM; gf_isom_box_del((GF_Box *)tk->meta); tk->meta = NULL; } } return GF_OK; } if (!meta->handler) meta->handler = (GF_HandlerBox *)hdlr_New(); if (meta->handler->nameUTF8) gf_free(meta->handler->nameUTF8); meta->handler->handlerType = metaType; sprintf(szName, "GPAC %s Handler", gf_4cc_to_str(metaType)); meta->handler->nameUTF8 = gf_strdup(szName); return GF_OK; }
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_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_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; }
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_text_has_similar_description(GF_ISOFile *movie, u32 trackNumber, GF_TextSampleDescriptor *desc, u32 *outDescIdx, Bool *same_box, Bool *same_styles) { GF_TrackBox *trak; GF_Err e; u32 i, j, count; GF_Tx3gSampleEntryBox *txt; *same_box = *same_styles = 0; *outDescIdx = 0; if (!desc) return GF_BAD_PARAM; 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 || !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; } count = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); for (i=0; i<count; i++) { Bool same_fonts; txt = (GF_Tx3gSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, i); if (!txt) continue; if ((txt->type != GF_ISOM_BOX_TYPE_TX3G) && (txt->type != GF_ISOM_BOX_TYPE_TEXT)) continue; if (txt->back_color != desc->back_color) continue; if (txt->displayFlags != desc->displayFlags) continue; if (txt->vertical_justification != desc->vert_justif) continue; if (txt->horizontal_justification != desc->horiz_justif) continue; if (txt->font_table->entry_count != desc->font_count) continue; same_fonts = 1; for (j=0; j<desc->font_count; j++) { if (txt->font_table->fonts[j].fontID != desc->fonts[j].fontID) same_fonts = 0; else if (strcmp(desc->fonts[j].fontName, txt->font_table->fonts[j].fontName)) same_fonts = 0; } if (same_fonts) { *outDescIdx = i+1; if (!memcmp(&txt->default_box, &desc->default_pos, sizeof(GF_BoxRecord))) *same_box = 1; if (!memcmp(&txt->default_style, &desc->default_style, sizeof(GF_StyleRecord))) *same_styles = 1; return GF_OK; } } return GF_OK; }
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; }
//to use with internally supported protocols GF_Err gf_isom_new_hint_description(GF_ISOFile *the_file, u32 trackNumber, s32 HintTrackVersion, s32 LastCompatibleVersion, u8 Rely, u32 *HintDescriptionIndex) { GF_Err e; u32 drefIndex; GF_TrackBox *trak; GF_HintSampleEntryBox *hdesc; GF_RelyHintBox *relyA; e = CanAccessMovie(the_file, GF_ISOM_OPEN_WRITE); if (e) return e; trak = gf_isom_get_track_from_file(the_file, trackNumber); *HintDescriptionIndex = 0; if (!trak || !IsHintTrack(trak)) return GF_BAD_PARAM; //OK, create a new HintSampleDesc hdesc = (GF_HintSampleEntryBox *) gf_isom_box_new(GetHintFormat(trak)); if (HintTrackVersion > 0) hdesc->HintTrackVersion = HintTrackVersion; if (LastCompatibleVersion > 0) hdesc->LastCompatibleVersion = LastCompatibleVersion; //create a data reference - WE ONLY DEAL WITH SELF-CONTAINED HINT TRACKS e = Media_CreateDataRef(trak->Media->information->dataInformation->dref, NULL, NULL, &drefIndex); if (e) return e; hdesc->dataReferenceIndex = drefIndex; //add the entry to our table... e = stsd_AddBox(trak->Media->information->sampleTable->SampleDescription, (GF_Box *) hdesc); if (e) return e; *HintDescriptionIndex = gf_list_count(trak->Media->information->sampleTable->SampleDescription->boxList); //RTP needs a default timeScale... use the media one. if (CheckHintFormat(trak, GF_ISOM_HINT_RTP)) { e = gf_isom_rtp_set_timescale(the_file, trackNumber, *HintDescriptionIndex, trak->Media->mediaHeader->timeScale); if (e) return e; } if (!Rely) return GF_OK; //we need a rely box (common to all protocols) relyA = (GF_RelyHintBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_RELY); if (Rely == 1) { relyA->prefered = 1; } else { relyA->required = 1; } return gf_list_add(hdesc->HintDataTable, relyA); }
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; }
M4Err M4_AMR_NewStreamConfig(M4File *the_file, u32 trackNumber, LPAMRCONFIGURATION param, char *URLname, char *URNname, u32 *outDescriptionIndex) { TrackAtom *trak; M4Err e; u32 dataRefIndex; TrackReferenceTypeAtom *dpnd; TrackReferenceAtom *tref; AMRSampleEntryAtom *entry; e = CanAccessMovie((M4Movie *)the_file, M4_OPEN_WRITE); if (e) return e; trak = GetTrackFromFile(the_file, trackNumber); if (!trak || !trak->Media || !param) return M4BadParam; dpnd = NULL; tref = NULL; //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 = GetMP4Time(); //create a new entry entry = (AMRSampleEntryAtom *) CreateAtom(param->WideBandAMR ? WB_AMRSampleEntryAtomType : AMRSampleEntryAtomType); if (!entry) return M4OutOfMem; entry->amr_info = (AMRConfigAtom *) CreateAtom(AMRConfigAtomType); if (!entry->amr_info) { DelAtom((Atom *) entry); return M4OutOfMem; } entry->samplerate_hi = trak->Media->mediaHeader->timeScale; entry->dataReferenceIndex = dataRefIndex; entry->amr_info->decoder_version = param->decoder_version; entry->amr_info->vendor = param->vendor; entry->amr_info->frames_per_sample = param->frames_per_sample; entry->amr_info->mode_change_period = param->mode_change_period; entry->amr_info->mode_set = param->mode_set; e = ChainAddEntry(trak->Media->information->sampleTable->SampleDescription->atomList, entry); *outDescriptionIndex = ChainGetCount(trak->Media->information->sampleTable->SampleDescription->atomList); 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; }
M4Err M4_H263_NewStreamConfig(M4File *the_file, u32 trackNumber, LPH263CONFIGURATION param, char *URLname, char *URNname, u32 *outDescriptionIndex) { TrackAtom *trak; M4Err e; u32 dataRefIndex; TrackReferenceTypeAtom *dpnd; TrackReferenceAtom *tref; H263SampleEntryAtom *entry; e = CanAccessMovie((M4Movie *)the_file, M4_OPEN_WRITE); if (e) return e; trak = GetTrackFromFile(the_file, trackNumber); if (!trak || !trak->Media || !param) return M4BadParam; dpnd = NULL; tref = NULL; //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 = GetMP4Time(); //create a new entry entry = (H263SampleEntryAtom *) CreateAtom(H263SampleEntryAtomType); if (!entry) return M4OutOfMem; entry->h263_config = (H263ConfigAtom *) CreateAtom(H263ConfigAtomType); if (!entry->h263_config) { DelAtom((Atom *) entry); return M4OutOfMem; } entry->dataReferenceIndex = dataRefIndex; entry->h263_config->decoder_version = param->decoder_version; entry->h263_config->vendor = param->vendor; entry->h263_config->Level = param->Level; entry->h263_config->Profile = param->Profile; e = ChainAddEntry(trak->Media->information->sampleTable->SampleDescription->atomList, entry); *outDescriptionIndex = ChainGetCount(trak->Media->information->sampleTable->SampleDescription->atomList); return e; }
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; }
GF_Err gf_isom_set_ipod_compatible(GF_ISOFile *the_file, u32 trackNumber) { static u8 ipod_ext[][16] = { { 0x6B, 0x68, 0x40, 0xF2, 0x5F, 0x24, 0x4F, 0xC5, 0xBA, 0x39, 0xA5, 0x1B, 0xCF, 0x03, 0x23, 0xF3} }; 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) return GF_BAD_PARAM; entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, 0); if (!entry) return GF_OK; if (entry->type != GF_ISOM_BOX_TYPE_AVC1) return GF_OK; if (!entry->ipod_ext) entry->ipod_ext = (GF_UnknownUUIDBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_UUID); memcpy(entry->ipod_ext->uuid, ipod_ext, sizeof(u8)*16); entry->ipod_ext->dataSize = 0; return GF_OK; }
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; }
M4Err M4_H263_UpdateStreamConfig(M4File *the_file, u32 trackNumber, LPH263CONFIGURATION param, u32 DescriptionIndex) { TrackAtom *trak; M4Err e; H263SampleEntryAtom *entry; e = CanAccessMovie((M4Movie *)the_file, M4_OPEN_WRITE); if (e) return e; trak = GetTrackFromFile(the_file, trackNumber); if (!trak || !trak->Media || !param || !DescriptionIndex) return M4BadParam; entry = ChainGetEntry(trak->Media->information->sampleTable->SampleDescription->atomList, DescriptionIndex-1); if (!entry || (entry->type!=H263SampleEntryAtomType) ) return M4BadParam; entry->h263_config->decoder_version = param->decoder_version; entry->h263_config->vendor = param->vendor; entry->h263_config->Profile = param->Profile; entry->h263_config->Level = param->Level; return M4OK; }