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; }
//remove all SDP info at the track level GF_Err gf_isom_sdp_clean_track(GF_ISOFile *the_file, u32 trackNumber) { GF_TrackBox *trak; GF_UserDataMap *map; GF_HintTrackInfoBox *hnti; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return GF_BAD_PARAM; //currently, only RTP hinting supports SDP if (!CheckHintFormat(trak, GF_ISOM_HINT_RTP)) return GF_BAD_PARAM; map = udta_getEntry(trak->udta, GF_ISOM_BOX_TYPE_HNTI, NULL); if (!map) return GF_ISOM_INVALID_FILE; //we should have only one HNTI in the UDTA if (gf_list_count(map->boxList) != 1) return GF_ISOM_INVALID_FILE; hnti = (GF_HintTrackInfoBox *)gf_list_get(map->boxList, 0); if (!hnti->SDP) return GF_OK; //and free the SDP gf_free(((GF_SDPBox *)hnti->SDP)->sdpText); ((GF_SDPBox *)hnti->SDP)->sdpText = NULL; return GF_OK; }
GF_EXPORT u32 gf_isom_get_payt_count(GF_ISOFile *the_file, u32 trackNumber) { u32 i, count; GF_TrackBox *trak; GF_UserDataMap *map; GF_HintInfoBox *hinf; GF_PAYTBox *payt; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return 0; if (!CheckHintFormat(trak, GF_4CC('r', 't', 'p', ' '))) return 0; map = udta_getEntry(trak->udta, GF_ISOM_BOX_TYPE_HINF, NULL); if (!map) return 0; if (gf_list_count(map->boxList) != 1) return 0; hinf = (GF_HintInfoBox *)gf_list_get(map->boxList, 0); count = 0; i = 0; while ((payt = gf_list_enum(hinf->boxList, &i))) { if (payt->type == GF_ISOM_BOX_TYPE_PAYT) count++; } return count; }
//adds a chunk of data (max 14 bytes) in the packet that is directly copied //while streaming GF_Err gf_isom_hint_direct_data(GF_ISOFile *the_file, u32 trackNumber, char *data, u32 dataLength, u8 AtBegin) { GF_TrackBox *trak; GF_HintSampleEntryBox *entry; u32 count; GF_HintPacket *pck; GF_ImmediateDTE *dte; GF_Err e; u32 offset = 0; if (!dataLength) return GF_OK; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !IsHintTrack(trak) || (dataLength > 14)) return GF_BAD_PARAM; e = Media_GetSampleDesc(trak->Media, trak->Media->information->sampleTable->currentEntryIndex, (GF_SampleEntryBox **) &entry, &count); if (e) return e; if (!entry->hint_sample) return GF_BAD_PARAM; count = gf_list_count(entry->hint_sample->packetTable); if (!count) return GF_BAD_PARAM; pck = (GF_HintPacket *)gf_list_get(entry->hint_sample->packetTable, count - 1); dte = (GF_ImmediateDTE *) NewDTE(1); memcpy(dte->data, data + offset, dataLength); dte->dataLength = dataLength; return gf_isom_hint_pck_add_dte(entry->hint_sample->HintType, pck, (GF_GenericDTE *)dte, AtBegin); }
GF_Err gf_isom_rtp_packet_begin(GF_ISOFile *the_file, u32 trackNumber, s32 relativeTime, u8 PackingBit, u8 eXtensionBit, u8 MarkerBit, u8 PayloadType, u8 B_frame, u8 IsRepeatedPacket, u16 SequenceNumber) { GF_TrackBox *trak; GF_HintSampleEntryBox *entry; GF_RTPPacket *pck; u32 dataRefIndex; GF_Err e; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !CheckHintFormat(trak, GF_ISOM_HINT_RTP)) return GF_BAD_PARAM; e = Media_GetSampleDesc(trak->Media, trak->Media->information->sampleTable->currentEntryIndex, (GF_SampleEntryBox **) &entry, &dataRefIndex); if (e) return e; if (!entry->hint_sample) return GF_BAD_PARAM; pck = (GF_RTPPacket *) gf_isom_hint_pck_new(entry->hint_sample->HintType); pck->P_bit = PackingBit ? 1 : 0; pck->X_bit = eXtensionBit ? 1 : 0; pck->M_bit = MarkerBit ? 1 : 0; pck->payloadType = PayloadType; pck->SequenceNumber = SequenceNumber; pck->B_bit = B_frame ? 1 : 0; pck->R_bit = IsRepeatedPacket ? 1 : 0; pck->relativeTransTime = relativeTime; return gf_list_add(entry->hint_sample->packetTable, pck); }
GF_EXPORT GF_3GPConfig *gf_isom_3gp_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex) { GF_3GPConfig *config, *res; GF_TrackBox *trak; GF_SampleEntryBox *entry; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !StreamDescriptionIndex) return NULL; config = NULL; entry = (GF_SampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, StreamDescriptionIndex-1); if (!entry) return NULL; 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: if (! ((GF_3GPPAudioSampleEntryBox*)entry)->info) return NULL; config = & ((GF_3GPPAudioSampleEntryBox*)entry)->info->cfg; break; case GF_ISOM_SUBTYPE_3GP_H263: if (! ((GF_3GPPVisualSampleEntryBox*)entry)->info) return NULL; config = & ((GF_3GPPVisualSampleEntryBox*)entry)->info->cfg; break; default: return NULL; } if (!config) return NULL; res = (GF_3GPConfig*)gf_malloc(sizeof(GF_3GPConfig)); memcpy(res, config, sizeof(GF_3GPConfig)); return res; }
GF_EXPORT GF_Err gf_isom_get_dims_description(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex, GF_DIMSDescription *desc) { GF_DIMSSampleEntryBox *dims; GF_TrackBox *trak; trak = gf_isom_get_track_from_file(movie, trackNumber); if (!trak || !descriptionIndex || !desc) 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; memset(desc, 0, sizeof(GF_DIMSDescription)); if (dims->config) { desc->profile = dims->config->profile; desc->level = dims->config->level; desc->pathComponents = dims->config->pathComponents; desc->fullRequestHost = dims->config->fullRequestHost; desc->containsRedundant = dims->config->containsRedundant; desc->streamType = dims->config->streamType; desc->textEncoding = dims->config->textEncoding; desc->contentEncoding = dims->config->contentEncoding; } if (dims->scripts) { desc->content_script_types = dims->scripts->content_script_types; } return GF_OK; }
/* SimpleTextSampleEntry: also used for MetadataTextSampleEntry and SubtitleTextSampleEntry */ GF_EXPORT GF_Err gf_isom_stxt_get_description(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex, const char **mime, const char **encoding, const char **config) { GF_TrackBox *trak; GF_MetaDataSampleEntryBox *entry; *mime = NULL; *config = NULL; *encoding = NULL; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !StreamDescriptionIndex) return GF_BAD_PARAM; entry = (GF_MetaDataSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, StreamDescriptionIndex-1); if (!entry || ((entry->type!=GF_ISOM_BOX_TYPE_STXT) && (entry->type!=GF_ISOM_BOX_TYPE_METT) && (entry->type!=GF_ISOM_BOX_TYPE_SBTT))) { return GF_BAD_PARAM; } if (entry->config) { *config = entry->config->config; } if (entry->mime_type) { *mime = entry->mime_type; } if (entry->content_encoding) { *encoding = entry->content_encoding; } return GF_OK; }
GF_WebVTTSampleEntryBox *gf_webvtt_isom_get_description(GF_ISOFile *movie, u32 trackNumber, u32 descriptionIndex) { GF_WebVTTSampleEntryBox *wvtt; GF_TrackBox *trak; if (!descriptionIndex) 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; }
/* XMLSubtitleSampleEntry */ GF_EXPORT GF_Err gf_isom_xml_subtitle_get_description(GF_ISOFile *the_file, u32 trackNumber, u32 StreamDescriptionIndex, const char **xmlnamespace, const char **xml_schema_loc, const char **mimes) { GF_TrackBox *trak; GF_MetaDataSampleEntryBox *entry; *xmlnamespace = NULL; *xml_schema_loc = NULL; *mimes = NULL; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !StreamDescriptionIndex) return GF_BAD_PARAM; entry = (GF_MetaDataSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, StreamDescriptionIndex-1); if (!entry || (entry->type!=GF_ISOM_BOX_TYPE_STPP)) { return GF_BAD_PARAM; } if (entry->mime_type) { *mimes = entry->mime_type; } if (entry->xml_schema_loc) { *xml_schema_loc = entry->xml_schema_loc; } *xmlnamespace = entry->xml_namespace; return GF_OK; }
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_EXPORT u32 gf_isom_get_avc_svc_type(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 GF_ISOM_AVCTYPE_NONE; if (trak->Media->handler->handlerType != GF_ISOM_MEDIA_VISUAL) return GF_ISOM_AVCTYPE_NONE; entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->other_boxes, DescriptionIndex-1); if (!entry) return GF_ISOM_AVCTYPE_NONE; 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_ISOM_AVCTYPE_NONE; } if (entry->avc_config && !entry->svc_config) return GF_ISOM_AVCTYPE_AVC_ONLY; if (entry->avc_config && entry->svc_config) return GF_ISOM_AVCTYPE_AVC_SVC; if (!entry->avc_config && entry->svc_config) return GF_ISOM_AVCTYPE_SVC_ONLY; return GF_ISOM_AVCTYPE_NONE; }
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_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_remove_samp_enc_box(GF_ISOFile *the_file, u32 trackNumber) { u32 i; GF_SampleTableBox *stbl; GF_TrackBox *trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return GF_BAD_PARAM; stbl = trak->Media->information->sampleTable; if (!stbl) return GF_BAD_PARAM; for (i = 0; i < gf_list_count(stbl->other_boxes); i++) { GF_Box *a = (GF_Box *)gf_list_get(stbl->other_boxes, i); if ((a->type ==GF_ISOM_BOX_TYPE_UUID) && (((GF_UUIDBox *)a)->internal_4cc == GF_ISOM_BOX_UUID_PSEC)) { piff_psec_del(a); gf_list_rem(stbl->other_boxes, i); i--; } else if (a->type == GF_ISOM_BOX_TYPE_SENC) { senc_del(a); gf_list_rem(stbl->other_boxes, i); i--; } } if (!gf_list_count(stbl->other_boxes)) { gf_list_del(stbl->other_boxes); stbl->other_boxes = NULL; } return GF_OK; }
GF_EXPORT GF_Err gf_isom_reset_hint_reader(GF_ISOFile *the_file, u32 trackNumber, u32 sample_start, u32 ts_offset, u32 sn_offset, u32 ssrc) { GF_Err e; GF_TrackBox *trak; GF_HintSampleEntryBox *entry; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return GF_BAD_PARAM; if (!sample_start) return GF_BAD_PARAM; if (sample_start>=trak->Media->information->sampleTable->SampleSize->sampleCount) return GF_BAD_PARAM; e = Media_GetSampleDesc(trak->Media, 1, (GF_SampleEntryBox **) &entry, NULL); if (e) return e; switch (entry->type) { case GF_ISOM_BOX_TYPE_RTP_STSD: break; default: return GF_NOT_SUPPORTED; } entry->hint_ref = NULL; e = Track_FindRef(trak, GF_ISOM_REF_HINT, &entry->hint_ref); if (e) return e; entry->cur_sample = sample_start; entry->pck_sn = 1 + sn_offset; entry->ssrc = ssrc; entry->ts_offset = ts_offset; if (entry->hint_sample) gf_isom_hint_sample_del(entry->hint_sample); entry->hint_sample = NULL; return GF_OK; }
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 void gf_isom_cenc_get_default_info(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex, u32 *default_IsEncrypted, u8 *default_IV_size, bin128 *default_KID) { GF_TrackBox *trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return; gf_isom_cenc_get_default_info_ex(trak, sampleDescriptionIndex, default_IsEncrypted, default_IV_size, default_KID); }
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_EXPORT GF_ISMASample *gf_isom_get_ismacryp_sample(GF_ISOFile *the_file, u32 trackNumber, GF_ISOSample *samp, u32 sampleDescriptionIndex) { GF_TrackBox *trak; GF_ISMASampleFormatBox *fmt; GF_ProtectionInfoBox *sinf; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return NULL; sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, 0, NULL); if (!sinf) return NULL; /*ISMA*/ if (sinf->scheme_type->scheme_type == GF_ISOM_ISMACRYP_SCHEME) { fmt = sinf->info->isfm; if (!fmt) return NULL; return gf_isom_ismacryp_sample_from_data(samp->data, samp->dataLength, sinf->info->isfm->selective_encryption, sinf->info->isfm->key_indicator_length, sinf->info->isfm->IV_length); } /*OMA*/ else if (sinf->scheme_type->scheme_type == GF_4CC('o','d','k','m') ) { if (!sinf->info->okms) return NULL; fmt = sinf->info->okms->fmt; if (fmt) { return gf_isom_ismacryp_sample_from_data(samp->data, samp->dataLength, fmt->selective_encryption, fmt->key_indicator_length, fmt->IV_length); } /*OMA default: no selective encryption, one key, 128 bit IV*/ return gf_isom_ismacryp_sample_from_data(samp->data, samp->dataLength, GF_FALSE, 0, 128); } return NULL; }
//sets the RTP SequenceNumber Offset that the server will add to the packets //if not set, the server adds a random offset GF_Err gf_isom_rtp_set_time_sequence_offset(GF_ISOFile *the_file, u32 trackNumber, u32 HintDescriptionIndex, u32 SequenceNumberOffset) { GF_TrackBox *trak; GF_HintSampleEntryBox *hdesc; u32 i, count; GF_SeqOffHintEntryBox *ent; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !CheckHintFormat(trak, GF_ISOM_HINT_RTP)) return GF_BAD_PARAM; //OK, create a new HintSampleDesc hdesc = (GF_HintSampleEntryBox *)gf_list_get(trak->Media->information->sampleTable->SampleDescription->boxList, HintDescriptionIndex - 1); count = gf_list_count(hdesc->HintDataTable); for (i=0; i< count; i++) { ent = (GF_SeqOffHintEntryBox *)gf_list_get(hdesc->HintDataTable, i); if (ent->type == GF_ISOM_BOX_TYPE_SNRO) { ent->SeqOffset = SequenceNumberOffset; return GF_OK; } } //we have to create a new entry... ent = (GF_SeqOffHintEntryBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_SNRO); ent->SeqOffset = SequenceNumberOffset; return gf_list_add(hdesc->HintDataTable, ent); }
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_rtp_packet_set_flags(GF_ISOFile *the_file, u32 trackNumber, u8 PackingBit, u8 eXtensionBit, u8 MarkerBit, u8 disposable_packet, u8 IsRepeatedPacket) { GF_TrackBox *trak; GF_HintSampleEntryBox *entry; GF_RTPPacket *pck; u32 dataRefIndex, ind; GF_Err e; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !CheckHintFormat(trak, GF_ISOM_HINT_RTP)) return GF_BAD_PARAM; e = Media_GetSampleDesc(trak->Media, trak->Media->information->sampleTable->currentEntryIndex, (GF_SampleEntryBox **) &entry, &dataRefIndex); if (e) return e; if (!entry->hint_sample) return GF_BAD_PARAM; ind = gf_list_count(entry->hint_sample->packetTable); if (!ind) return GF_BAD_PARAM; pck = (GF_RTPPacket *)gf_list_get(entry->hint_sample->packetTable, ind-1); pck->P_bit = PackingBit ? 1 : 0; pck->X_bit = eXtensionBit ? 1 : 0; pck->M_bit = MarkerBit ? 1 : 0; pck->B_bit = disposable_packet ? 1 : 0; pck->R_bit = IsRepeatedPacket ? 1 : 0; return GF_OK; }
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; }
//set the time offset of this packet. This enables packets to be placed in the hint track //in decoding order, but have their presentation time-stamp in the transmitted //packet be in a different order. Typically used for MPEG video with B-frames GF_Err gf_isom_rtp_packet_set_offset(GF_ISOFile *the_file, u32 trackNumber, s32 timeOffset) { GF_RTPOBox *rtpo; GF_TrackBox *trak; GF_HintSampleEntryBox *entry; GF_RTPPacket *pck; u32 dataRefIndex, i; GF_Err e; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !CheckHintFormat(trak, GF_ISOM_HINT_RTP)) return GF_BAD_PARAM; e = Media_GetSampleDesc(trak->Media, trak->Media->information->sampleTable->currentEntryIndex, (GF_SampleEntryBox **) &entry, &dataRefIndex); if (e) return e; if (!entry->hint_sample) return GF_BAD_PARAM; pck = (GF_RTPPacket *)gf_list_get(entry->hint_sample->packetTable, gf_list_count(entry->hint_sample->packetTable) - 1); if (!pck) return GF_BAD_PARAM; //look in the TLV i=0; while ((rtpo = (GF_RTPOBox *)gf_list_enum(pck->TLV, &i))) { if (rtpo->type == GF_ISOM_BOX_TYPE_RTPO) { rtpo->timeOffset = timeOffset; return GF_OK; } } //not found, add it rtpo = (GF_RTPOBox *) gf_isom_box_new(GF_ISOM_BOX_TYPE_RTPO); rtpo->timeOffset = timeOffset; return gf_list_add(pck->TLV, rtpo); }
GF_EXPORT GF_Err gf_isom_get_cenc_info(GF_ISOFile *the_file, u32 trackNumber, u32 sampleDescriptionIndex, u32 *outOriginalFormat, u32 *outSchemeType, u32 *outSchemeVersion, u32 *outIVLength) { GF_TrackBox *trak; GF_ProtectionInfoBox *sinf; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return GF_BAD_PARAM; sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, GF_ISOM_CENC_SCHEME, NULL); if (!sinf) sinf = gf_isom_get_sinf_entry(trak, sampleDescriptionIndex, GF_ISOM_CBC_SCHEME, NULL); if (!sinf) return GF_BAD_PARAM; if (outOriginalFormat) { *outOriginalFormat = sinf->original_format->data_format; if (IsMP4Description(sinf->original_format->data_format)) *outOriginalFormat = GF_ISOM_SUBTYPE_MPEG4; } if (outSchemeType) *outSchemeType = sinf->scheme_type->scheme_type; if (outSchemeVersion) *outSchemeVersion = sinf->scheme_type->scheme_version; if (outIVLength) { if (sinf->info && sinf->info->tenc) *outIVLength = sinf->info->tenc->IV_size; else *outIVLength = 0; } return GF_OK; }
GF_EXPORT GF_Err gf_isom_sdp_track_get(GF_ISOFile *the_file, u32 trackNumber, const char **sdp, u32 *length) { GF_TrackBox *trak; GF_UserDataMap *map; GF_HintTrackInfoBox *hnti; GF_SDPBox *sdpa; *sdp = NULL; *length = 0; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return GF_BAD_PARAM; if (!trak->udta) return GF_OK; map = udta_getEntry(trak->udta, GF_ISOM_BOX_TYPE_HNTI, NULL); if (!map) return GF_ISOM_INVALID_FILE; //we should have only one HNTI in the UDTA if (gf_list_count(map->boxList) != 1) return GF_ISOM_INVALID_FILE; hnti = (GF_HintTrackInfoBox *)gf_list_get(map->boxList, 0); if (!hnti->SDP) return GF_OK; sdpa = (GF_SDPBox *) hnti->SDP; *length = strlen(sdpa->sdpText); *sdp = sdpa->sdpText; return GF_OK; }
GF_Err gf_isom_remove_cenc_saio(GF_ISOFile *the_file, u32 trackNumber) { u32 i; GF_SampleTableBox *stbl; GF_TrackBox *trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak) return GF_BAD_PARAM; stbl = trak->Media->information->sampleTable; if (!stbl) return GF_BAD_PARAM; for (i = 0; i < gf_list_count(stbl->sai_offsets); i++) { GF_SampleAuxiliaryInfoOffsetBox *saio = (GF_SampleAuxiliaryInfoOffsetBox *)gf_list_get(stbl->sai_offsets, i); if (saio->aux_info_type != GF_4CC('c', 'e', 'n', 'c')) continue; saio_del((GF_Box *)saio); gf_list_rem(stbl->sai_offsets, i); i--; } if (!gf_list_count(stbl->sai_offsets)) { gf_list_del(stbl->sai_offsets); stbl->sai_offsets = NULL; } return GF_OK; }
GF_EXPORT const char *gf_isom_get_payt_info(GF_ISOFile *the_file, u32 trackNumber, u32 index, u32 *payID) { u32 i, count; GF_TrackBox *trak; GF_UserDataMap *map; GF_HintInfoBox *hinf; GF_PAYTBox *payt; trak = gf_isom_get_track_from_file(the_file, trackNumber); if (!trak || !index) return NULL; if (!CheckHintFormat(trak, GF_4CC('r', 't', 'p', ' '))) return NULL; map = udta_getEntry(trak->udta, GF_ISOM_BOX_TYPE_HINF, NULL); if (!map) return NULL; if (gf_list_count(map->boxList) != 1) return NULL; hinf = (GF_HintInfoBox *)gf_list_get(map->boxList, 0); count = 0; i = 0; while ((payt = gf_list_enum(hinf->boxList, &i))) { if (payt->type == GF_ISOM_BOX_TYPE_PAYT) { count++; if (count == index) { if (payID) *payID=payt->payloadCode; return payt->payloadString; } } } return NULL; }
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; }