GF_Err iloc_Write(GF_Box *s, GF_BitStream *bs) { GF_Err e; u32 i, j, item_count, extent_count; GF_ItemLocationBox *ptr = (GF_ItemLocationBox *)s; if (!s) return GF_BAD_PARAM; e = gf_isom_full_box_write(s, bs); if (e) return e; gf_bs_write_int(bs, ptr->offset_size, 4); gf_bs_write_int(bs, ptr->length_size, 4); gf_bs_write_int(bs, ptr->base_offset_size, 4); gf_bs_write_int(bs, 0, 4); item_count = gf_list_count(ptr->location_entries); gf_bs_write_u16(bs, item_count); for (i = 0; i < item_count; i++) { GF_ItemLocationEntry *location = (GF_ItemLocationEntry *)gf_list_get(ptr->location_entries, i); gf_bs_write_u16(bs, location->item_ID); gf_bs_write_u16(bs, location->data_reference_index); gf_bs_write_long_int(bs, location->base_offset, 8*ptr->base_offset_size); extent_count = gf_list_count(location->extent_entries); gf_bs_write_u16(bs, extent_count); for (j=0; j<extent_count; j++) { GF_ItemExtentEntry *extent = (GF_ItemExtentEntry *)gf_list_get(location->extent_entries, j); gf_bs_write_long_int(bs, extent->extent_offset, 8*ptr->offset_size); gf_bs_write_long_int(bs, extent->extent_length, 8*ptr->length_size); } } return GF_OK; }
/*allocates and writes the SL-PDU (Header + PDU) given the SLConfig and the GF_SLHeader for this PDU. AUs must be split in PDUs by another process if needed (packetizer).*/ GF_EXPORT void gf_sl_packetize(GF_SLConfig* slConfig, GF_SLHeader *Header, char *PDU, u32 size, char **outPacket, u32 *OutSize) { GF_BitStream *bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); *OutSize = 0; if (!bs) return; if (slConfig->useAccessUnitStartFlag) gf_bs_write_int(bs, Header->accessUnitStartFlag, 1); if (slConfig->useAccessUnitEndFlag) gf_bs_write_int(bs, Header->accessUnitEndFlag, 1); if (slConfig->OCRLength > 0) gf_bs_write_int(bs, Header->OCRflag, 1); if (slConfig->useIdleFlag) gf_bs_write_int(bs, Header->idleFlag, 1); if (slConfig->usePaddingFlag) { gf_bs_write_int(bs, Header->paddingFlag, 1); if (Header->paddingFlag) gf_bs_write_int(bs, Header->paddingBits, 3); } if (! Header->idleFlag && (! Header->paddingFlag || Header->paddingBits != 0)) { if (slConfig->packetSeqNumLength > 0) gf_bs_write_int(bs, Header->packetSequenceNumber, slConfig->packetSeqNumLength); if (slConfig->degradationPriorityLength > 0) { gf_bs_write_int(bs, Header->degradationPriorityFlag, 1); if (Header->degradationPriorityFlag) gf_bs_write_int(bs, Header->degradationPriority, slConfig->degradationPriorityLength); } if (Header->OCRflag) gf_bs_write_long_int(bs, Header->objectClockReference, slConfig->OCRLength); if (Header->accessUnitStartFlag) { if (slConfig->useRandomAccessPointFlag) gf_bs_write_int(bs, Header->randomAccessPointFlag, 1); if (slConfig->AUSeqNumLength > 0) gf_bs_write_int(bs, Header->AU_sequenceNumber, slConfig->AUSeqNumLength); if (slConfig->useTimestampsFlag) { gf_bs_write_int(bs, Header->decodingTimeStampFlag, 1); gf_bs_write_int(bs, Header->compositionTimeStampFlag, 1); } if (slConfig->instantBitrateLength > 0) gf_bs_write_int(bs, Header->instantBitrateFlag, 1); if (Header->decodingTimeStampFlag) gf_bs_write_long_int(bs, Header->decodingTimeStamp, slConfig->timestampLength); if (Header->compositionTimeStampFlag) gf_bs_write_long_int(bs, Header->compositionTimeStamp, slConfig->timestampLength); if (slConfig->AULength > 0) gf_bs_write_int(bs, Header->accessUnitLength, slConfig->AULength); if (Header->instantBitrateFlag) gf_bs_write_int(bs, Header->instantBitrate, slConfig->instantBitrateLength); } } //done with the Header, Alin gf_bs_align(bs); //write the PDU - already byte aligned with stuffing (paddingBits in SL Header) gf_bs_write_data(bs, PDU, size); gf_bs_align(bs); gf_bs_get_content(bs, outPacket, OutSize); gf_bs_del(bs); }
// // Writer // GF_Err gf_odf_write_slc(GF_BitStream *bs, GF_SLConfig *sl) { GF_Err e; u32 size; if (! sl) return GF_BAD_PARAM; e = gf_odf_size_descriptor((GF_Descriptor *)sl, &size); e = gf_odf_write_base_descriptor(bs, sl->tag, size); gf_bs_write_int(bs, sl->predefined, 8); if (! sl->predefined) { gf_bs_write_int(bs, sl->useAccessUnitStartFlag, 1); gf_bs_write_int(bs, sl->useAccessUnitEndFlag, 1); gf_bs_write_int(bs, sl->useRandomAccessPointFlag, 1); gf_bs_write_int(bs, sl->hasRandomAccessUnitsOnlyFlag, 1); gf_bs_write_int(bs, sl->usePaddingFlag, 1); gf_bs_write_int(bs, sl->useTimestampsFlag, 1); gf_bs_write_int(bs, sl->useIdleFlag, 1); gf_bs_write_int(bs, sl->durationFlag, 1); gf_bs_write_int(bs, sl->timestampResolution, 32); gf_bs_write_int(bs, sl->OCRResolution, 32); gf_bs_write_int(bs, sl->timestampLength, 8); gf_bs_write_int(bs, sl->OCRLength, 8); gf_bs_write_int(bs, sl->AULength, 8); gf_bs_write_int(bs, sl->instantBitrateLength, 8); gf_bs_write_int(bs, sl->degradationPriorityLength, 4); gf_bs_write_int(bs, sl->AUSeqNumLength, 5); gf_bs_write_int(bs, sl->packetSeqNumLength, 5); gf_bs_write_int(bs, 3, 2); //reserved: 0b11 == 3 } if (sl->durationFlag) { gf_bs_write_int(bs, sl->timeScale, 32); gf_bs_write_int(bs, sl->AUDuration, 16); gf_bs_write_int(bs, sl->CUDuration, 16); } if (! sl->useTimestampsFlag) { gf_bs_write_long_int(bs, sl->startDTS, sl->timestampLength); gf_bs_write_long_int(bs, sl->startCTS, sl->timestampLength); } return GF_OK; }
GF_Err gf_isom_ismacryp_sample_to_sample(GF_ISMASample *s, GF_ISOSample *dest) { GF_BitStream *bs; if (!s || !dest) return GF_BAD_PARAM; bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE); if (s->flags & GF_ISOM_ISMA_USE_SEL_ENC) { gf_bs_write_int(bs, (s->flags & GF_ISOM_ISMA_IS_ENCRYPTED) ? 1 : 0, 1); gf_bs_write_int(bs, 0, 7); } if (s->flags & GF_ISOM_ISMA_IS_ENCRYPTED) { if (s->IV_length) gf_bs_write_long_int(bs, s->IV, 8*s->IV_length); if (s->KI_length) gf_bs_write_data(bs, (char*)s->key_indicator, s->KI_length); } gf_bs_write_data(bs, s->data, s->dataLength); if (dest->data) free(dest->data); dest->data = NULL; dest->dataLength = 0; gf_bs_get_content(bs, &dest->data, &dest->dataLength); gf_bs_del(bs); return GF_OK; }
/*write the AU header section - return the nb of BITS written for AU header*/ u32 gf_rtp_build_au_hdr_write(GP_RTPPacketizer *builder, u32 PayloadSize, u32 RTP_TS) { u32 nbBits = 0; s32 delta; /*selective encryption*/ if (builder->flags & GP_RTP_PCK_SELECTIVE_ENCRYPTION) { gf_bs_write_int(builder->pck_hdr, builder->is_encrypted, 1); gf_bs_write_int(builder->pck_hdr, 0, 7); nbBits = 8; } /*IV*/ if (builder->first_sl_in_rtp) { if (builder->slMap.IV_length) { gf_bs_write_long_int(builder->pck_hdr, builder->IV, 8*builder->slMap.IV_length); nbBits += 8*builder->slMap.IV_length; } } else if (builder->slMap.IV_delta_length) { /*NOT SUPPORTED!!! this only applies to interleaving*/ } /*key*/ if (builder->slMap.KI_length) { if (builder->first_sl_in_rtp || (builder->flags & GP_RTP_PCK_KEY_IDX_PER_AU)) { if (builder->key_indicator) gf_bs_write_data(builder->pck_hdr, builder->key_indicator, builder->slMap.KI_length); else gf_bs_write_int(builder->pck_hdr, 0, 8*builder->slMap.KI_length); nbBits += 8*builder->slMap.KI_length; } } /*size length*/ if (builder->slMap.ConstantSize) { if (PayloadSize != builder->slMap.ConstantSize) return nbBits; } else if (builder->slMap.SizeLength) { /*write the AU size - if not enough bytes (real-time cases) set size to 0*/ if (builder->sl_header.accessUnitLength >= (1<<builder->slMap.SizeLength)) { gf_bs_write_int(builder->pck_hdr, 0, builder->slMap.SizeLength); } else { gf_bs_write_int(builder->pck_hdr, builder->sl_header.accessUnitLength, builder->slMap.SizeLength); } nbBits += builder->slMap.SizeLength; } /*AU index*/ if (builder->first_sl_in_rtp) { if (builder->slMap.IndexLength) { gf_bs_write_int(builder->pck_hdr, builder->sl_header.AU_sequenceNumber, builder->slMap.IndexLength); nbBits += builder->slMap.IndexLength; } } else { if (builder->slMap.IndexDeltaLength) { //check interleaving, otherwise force default (which is currently always the case) delta = builder->sl_header.AU_sequenceNumber - builder->last_au_sn; delta -= 1; gf_bs_write_int(builder->pck_hdr, delta, builder->slMap.IndexDeltaLength); nbBits += builder->slMap.IndexDeltaLength; } } /*CTS Flag*/ if (builder->slMap.CTSDeltaLength) { if (builder->first_sl_in_rtp) { builder->sl_header.compositionTimeStampFlag = 0; builder->sl_header.compositionTimeStamp = RTP_TS; } gf_bs_write_int(builder->pck_hdr, builder->sl_header.compositionTimeStampFlag, 1); nbBits += 1; } /*CTS*/ if (builder->sl_header.compositionTimeStampFlag) { delta = (u32) builder->sl_header.compositionTimeStamp - RTP_TS; gf_bs_write_int(builder->pck_hdr, delta, builder->slMap.CTSDeltaLength); nbBits += builder->slMap.CTSDeltaLength; } /*DTS Flag*/ if (builder->slMap.DTSDeltaLength) { gf_bs_write_int(builder->pck_hdr, builder->sl_header.decodingTimeStampFlag, 1); nbBits += 1; } /*DTS*/ if (builder->sl_header.decodingTimeStampFlag) { delta = (u32) (builder->sl_header.compositionTimeStamp - builder->sl_header.decodingTimeStamp); gf_bs_write_int(builder->pck_hdr, delta, builder->slMap.DTSDeltaLength); nbBits += builder->slMap.DTSDeltaLength; } /*RAP indication*/ if (builder->slMap.RandomAccessIndication) { gf_bs_write_int(builder->pck_hdr, builder->sl_header.randomAccessPointFlag, 1); nbBits ++; } /*stream state - write AUSeqNum*/ if (builder->slMap.StreamStateIndication) { gf_bs_write_int(builder->pck_hdr, builder->sl_header.AU_sequenceNumber, builder->slMap.StreamStateIndication); nbBits += builder->slMap.StreamStateIndication; } return nbBits; }
GF_EXPORT GF_Err gf_odf_hevc_cfg_write_bs(GF_HEVCConfig *cfg, GF_BitStream *bs) { u32 i, count; gf_bs_write_int(bs, cfg->configurationVersion, 8); gf_bs_write_int(bs, cfg->profile_space, 2); gf_bs_write_int(bs, cfg->tier_flag, 1); gf_bs_write_int(bs, cfg->profile_idc, 5); gf_bs_write_int(bs, cfg->general_profile_compatibility_flags, 32); gf_bs_write_int(bs, cfg->progressive_source_flag, 1); gf_bs_write_int(bs, cfg->interlaced_source_flag, 1); gf_bs_write_int(bs, cfg->non_packed_constraint_flag, 1); gf_bs_write_int(bs, cfg->frame_only_constraint_flag, 1); /*only lowest 44 bits used*/ gf_bs_write_long_int(bs, cfg->constraint_indicator_flags, 44); gf_bs_write_int(bs, cfg->level_idc, 8); gf_bs_write_int(bs, 0xFF, 4); gf_bs_write_int(bs, cfg->min_spatial_segmentation_idc, 12); gf_bs_write_int(bs, 0xFF, 6); gf_bs_write_int(bs, cfg->parallelismType, 2); gf_bs_write_int(bs, 0xFF, 6); gf_bs_write_int(bs, cfg->chromaFormat, 2); gf_bs_write_int(bs, 0xFF, 5); gf_bs_write_int(bs, cfg->luma_bit_depth-8, 3); gf_bs_write_int(bs, 0xFF, 5); gf_bs_write_int(bs, cfg->chroma_bit_depth-8, 3); gf_bs_write_int(bs, cfg->avgFrameRate, 16); gf_bs_write_int(bs, cfg->constantFrameRate, 2); gf_bs_write_int(bs, cfg->numTemporalLayers, 3); gf_bs_write_int(bs, cfg->temporalIdNested, 1); gf_bs_write_int(bs, cfg->nal_unit_size - 1, 2); if (cfg->is_shvc) { gf_bs_write_int(bs, cfg->complete_representation, 1); gf_bs_write_int(bs, cfg->non_hevc_base_layer, 1); gf_bs_write_int(bs, cfg->num_layers ? cfg->num_layers - 1 : 0, 6); gf_bs_write_int(bs, cfg->scalability_mask, 16); } count = gf_list_count(cfg->param_array); gf_bs_write_int(bs, count, 8); for (i=0; i<count; i++) { u32 nalucount, j; GF_HEVCParamArray *ar = gf_list_get(cfg->param_array, i); gf_bs_write_int(bs, ar->array_completeness, 1); gf_bs_write_int(bs, 0, 1); gf_bs_write_int(bs, ar->type, 6); nalucount = gf_list_count(ar->nalus); gf_bs_write_int(bs, nalucount, 16); for (j=0; j<nalucount; j++) { GF_AVCConfigSlot *sl = (GF_AVCConfigSlot *)gf_list_get(ar->nalus, j); gf_bs_write_int(bs, sl->size, 16); gf_bs_write_data(bs, sl->data, sl->size); } } return GF_OK; }