Commit message: fixed #2165
CVE: CVE-2022-29339
CWE: CWE-703
Vulnerability description: In GPAC 2.1-DEV-rev87-g053aae8-master, function BS_ReadByte() in utils/bitstream.c has a failed assertion, which causes a Denial of Service. This vulnerability was fixed in commit 9ea93a2.

Project: gpac
File: bitstream.c

void gf_bs_write_u32(GF_BitStream *bs, u32 value)
{
	assert(!bs->nbBits);
	if (bs->cache_write && (bs->buffer_written+4 < bs->cache_write_size) ) {
		bs->cache_write[bs->buffer_written] = (u8) ((value>>24)&0xff);
		bs->cache_write[bs->buffer_written+1] = (u8) ((value>>16)&0xff);
		bs->cache_write[bs->buffer_written+2] = (u8) ((value>>8)&0xff);
		bs->cache_write[bs->buffer_written+3] = (u8) ((value)&0xff);
		bs->buffer_written += 4;
	} else {
		BS_WriteByte(bs, (u8) ((value>>24)&0xff));
		BS_WriteByte(bs, (u8) ((value>>16)&0xff));
		BS_WriteByte(bs, (u8) ((value>>8)&0xff));
		BS_WriteByte(bs, (u8) ((value)&0xff));
	}
}

Project: gpac
File: avc_ext.c

GF_DOVIDecoderConfigurationRecord *gf_isom_dovi_config_get(GF_ISOFile* the_file, u32 trackNumber, u32 DescriptionIndex)
{
	GF_TrackBox* trak;
	GF_MPEGVisualSampleEntryBox *entry;
	trak = gf_isom_get_track_from_file(the_file, trackNumber);
	if (!trak || !trak->Media || !DescriptionIndex) return NULL;
	entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex - 1);
	if (!entry) return NULL;
	if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO) return NULL;
	if (!entry->size || !entry->dovi_config) return NULL;
	return DOVI_DuplicateConfig(&entry->dovi_config->DOVIConfig);
}

Project: gpac
File: bitstream.c

static s32 bs_handle_nbits_overflow(GF_BitStream* bs, s32 nBits, s32 max_shift)
{
	if (nBits > max_shift) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to write %d bits, when max is %d\n", nBits, max_shift));
	}
	while (nBits > max_shift) {
		gf_bs_write_long_int(bs, 0, max_shift);
		nBits -= max_shift;
	}

	return nBits;
}

Project: gpac
File: bitstream.c

u32 gf_bs_read_u32_le(GF_BitStream *bs)
{
	u32 ret, v;
	ret = gf_bs_read_int(bs, 8);
	v = gf_bs_read_int(bs, 8);
	v<<=8;
	ret |= v;
	v = gf_bs_read_int(bs, 8);
	v<<=16;
	ret |= v;
	v = gf_bs_read_int(bs, 8);
	v<<=24;
	ret |= v;
	return ret;
}

Project: gpac
File: bitstream.c

u32 gf_bs_read_u8_until_delimiter(GF_BitStream *bs, u8 delimiter, u8* out, u32 max_length) {
	u32 i = 0;
	char token=0;
	u64 cur_pos = gf_bs_get_position(bs);

	if (!max_length) out = NULL;

	while(gf_bs_available(bs) && (!max_length || i < max_length)) {
		gf_bs_read_data(bs, &token, 1);
		if (token == delimiter) goto found;
		if (out) out[i] = token;
		i++;
	}

	/* Delimiter not found */
	gf_bs_seek(bs, cur_pos);
	return 0;

found:
	return i;
}

Project: gpac
File: avc_ext.c

void gf_vvc_parse_ps(GF_VVCConfig* vvccfg, VVCState* vvc, u32 nal_type)
{
	u32 i, j;
	if (!vvccfg) return;

	for (i = 0; i < gf_list_count(vvccfg->param_array); i++) {
		GF_NALUFFParamArray* ar = gf_list_get(vvccfg->param_array, i);
		if (ar->type != nal_type) continue;
		for (j = 0; j < gf_list_count(ar->nalus); j++) {
			u8 ntype, tid, lid;
			GF_NALUFFParam* sl = gf_list_get(ar->nalus, j);
			gf_vvc_parse_nalu(sl->data, sl->size, vvc, &ntype, &tid, &lid);
		}
	}
}

Project: gpac
File: avc_ext.c

GF_VVCConfig *gf_isom_vvc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
{
	GF_TrackBox *trak;
	u32 type;
	GF_MPEGVisualSampleEntryBox *entry;
	/*todo, add support for subpic track and nvcl tracks*/
	trak = gf_isom_get_track_from_file(the_file, trackNumber);
	if (!trak || !trak->Media || !DescriptionIndex) return NULL;
	type = gf_isom_get_vvc_type(the_file, trackNumber, DescriptionIndex);
	if (type==GF_ISOM_VVCTYPE_NONE)
		return NULL;
	entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
	if (!entry) return NULL;
	if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO) return NULL;

	if ((type==GF_ISOM_VVCTYPE_SUBPIC) || (type==GF_ISOM_VVCTYPE_NVCL)) {
		GF_VVCNaluConfigurationBox *vvnc = (GF_VVCNaluConfigurationBox *) gf_isom_box_find_child(entry->child_boxes, GF_ISOM_BOX_TYPE_VVNC);
		if (!vvnc) return NULL;
		GF_VVCConfig *vvcc = gf_odf_vvc_cfg_new();
		vvcc->nal_unit_size = vvnc->nal_unit_size;
		return vvcc;
	}
	if (!entry->vvc_config) return NULL;
	return VVC_DuplicateConfig(entry->vvc_config->config);
}

Project: gpac
File: bitstream.c

static void BS_WriteBit(GF_BitStream *bs, u32 bit)
{
	bs->current <<= 1;
	bs->current |= bit;
	if (++ bs->nbBits == 8) {
		bs->nbBits = 0;
		BS_WriteByte(bs, (u8) bs->current);
		bs->current = 0;
	}
}

Project: gpac
File: avc_ext.c

GF_AV1Config *gf_isom_av1_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
{
	GF_TrackBox *trak;
	GF_MPEGVisualSampleEntryBox *entry;
	if (gf_isom_get_reference_count(the_file, trackNumber, GF_ISOM_REF_TBAS)) {
		u32 ref_track;
		GF_Err e = gf_isom_get_reference(the_file, trackNumber, GF_ISOM_REF_TBAS, 1, &ref_track);
		if (e == GF_OK) {
			trackNumber = ref_track;
		}
	}
	trak = gf_isom_get_track_from_file(the_file, trackNumber);
	if (!trak || !trak->Media || !DescriptionIndex) return NULL;
	entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex - 1);
	if (!entry) return NULL;
	if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO) return NULL;
	if (!entry->av1_config|| !entry->av1_config->config) return NULL;
	return AV1_DuplicateConfig(entry->av1_config->config);
}

Project: gpac
File: bitstream.c

void gf_bs_write_u24(GF_BitStream *bs, u32 value)
{
	assert(!bs->nbBits);
	if (bs->cache_write && (bs->buffer_written+3 < bs->cache_write_size) ) {
		bs->cache_write[bs->buffer_written] = (u8) ((value>>16)&0xff);
		bs->cache_write[bs->buffer_written+1] = (u8) ((value>>8)&0xff);
		bs->cache_write[bs->buffer_written+2] = (u8) ((value)&0xff);
		bs->buffer_written += 3;
	} else {
		BS_WriteByte(bs, (u8) ((value>>16)&0xff));
		BS_WriteByte(bs, (u8) ((value>>8)&0xff));
		BS_WriteByte(bs, (u8) ((value)&0xff));
	}
}

Project: gpac
File: avc_ext.c

GF_ISOMAVCType gf_isom_get_avc_svc_type(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
{
	u32 type;
	GF_TrackBox *trak;
	GF_MPEGVisualSampleEntryBox *entry;
	trak = gf_isom_get_track_from_file(the_file, trackNumber);
	if (!trak || !trak->Media || !trak->Media->handler || !DescriptionIndex) return GF_ISOM_AVCTYPE_NONE;
	if (!gf_isom_is_video_handler_type(trak->Media->handler->handlerType))
		return GF_ISOM_AVCTYPE_NONE;

	entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
	if (!entry) return GF_ISOM_AVCTYPE_NONE;
	if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO) return GF_ISOM_AVCTYPE_NONE;

	type = entry->type;

	if (type == GF_ISOM_BOX_TYPE_ENCV) {
		GF_ProtectionSchemeInfoBox *sinf = (GF_ProtectionSchemeInfoBox *) gf_isom_box_find_child(entry->child_boxes, GF_ISOM_BOX_TYPE_SINF);
		if (sinf && sinf->original_format) type = sinf->original_format->data_format;
	}
	else if (type == GF_ISOM_BOX_TYPE_RESV) {
		if (entry->rinf && entry->rinf->original_format) type = entry->rinf->original_format->data_format;
	}

	switch (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_MVC1:
	case GF_ISOM_BOX_TYPE_DVA1:
	case GF_ISOM_BOX_TYPE_DVAV:
		break;
	default:
		return GF_ISOM_AVCTYPE_NONE;
	}
	if (entry->avc_config && !entry->svc_config && !entry->mvc_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->mvc_config) return GF_ISOM_AVCTYPE_AVC_MVC;
	if (!entry->avc_config && entry->svc_config) return GF_ISOM_AVCTYPE_SVC_ONLY;
	if (!entry->avc_config && entry->mvc_config) return GF_ISOM_AVCTYPE_MVC_ONLY;
	return GF_ISOM_AVCTYPE_NONE;
}

Project: gpac
File: bitstream.c

void gf_bs_enable_emulation_byte_removal(GF_BitStream *bs, Bool do_remove)
{
	if (bs) {
		bs->remove_emul_prevention_byte = do_remove;
		bs->nb_zeros = 0;
	}
}

Project: gpac
File: bitstream.c

u32 gf_bs_write_byte(GF_BitStream *bs, u8 byte, u32 repeat_count)
{
	if (!gf_bs_is_align(bs) || bs->cache_write) {
		u32 count = 0;
		while (count<repeat_count) {
			gf_bs_write_int(bs, byte, 8);
			count++;
		}
		return count;
	}

	switch (bs->bsmode) {
	case GF_BITSTREAM_WRITE:
		if (bs->position + repeat_count > bs->size)
			return 0;
		memset(bs->original + bs->position, byte, repeat_count);
		bs->position += repeat_count;
		return repeat_count;
	case GF_BITSTREAM_WRITE_DYN:
		/*need to gf_realloc ...*/
		if (bs->position+repeat_count> bs->size) {
			u32 new_size = (u32) (bs->size*2);
			if (!new_size) new_size = BS_MEM_BLOCK_ALLOC_SIZE;

			if (bs->size + repeat_count > 0xFFFFFFFF)
				return 0;
			while (new_size < (u32) ( bs->size + repeat_count))
				new_size *= 2;
			bs->original = (char*)gf_realloc(bs->original, sizeof(u32)*new_size);
			if (!bs->original)
				return 0;
			bs->size = new_size;
		}
		memset(bs->original + bs->position, byte, repeat_count);
		bs->position += repeat_count;
		return repeat_count;
	case GF_BITSTREAM_FILE_READ:
	case GF_BITSTREAM_FILE_WRITE:
		if (gf_fwrite(&byte, repeat_count, bs->stream) != repeat_count)
			return 0;
		if (bs->size == bs->position) bs->size += repeat_count;
		bs->position += repeat_count;
		return repeat_count;
	default:
		return 0;
	}
}

Project: gpac
File: bitstream.c

void gf_bs_write_int(GF_BitStream *bs, s32 _value, s32 nBits)
{
	u32 value, nb_shift;
	s32 max_shift = sizeof(s32) * 8;
	if (!nBits) return;
	nBits = bs_handle_nbits_overflow(bs, nBits, max_shift);
	//move to unsigned to avoid sanitizer warnings when we pass a value not codable on the given number of bits
	//we do this when setting bit fields to all 1's
	value = (u32) _value;
	nb_shift = max_shift - nBits;
	if (nb_shift)
		value <<= nb_shift;

	while (--nBits >= 0) {
		//but check value as signed
		BS_WriteBit (bs, ((s32)value) < 0);
		value <<= 1;
	}
}

Project: gpac
File: bitstream.c

u64 gf_bs_set_cookie(GF_BitStream *bs, u64 cookie)
{
	u64 res = 0;
	if (bs) {
		res = bs->cookie;
		bs->cookie = cookie;
	}
	return res;
}

Project: gpac
File: avc_ext.c

GF_AVCConfig *gf_isom_svc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
{
	GF_TrackBox *trak;
	GF_MPEGVisualSampleEntryBox *entry;
	trak = gf_isom_get_track_from_file(the_file, trackNumber);
	if (!trak || !trak->Media || !DescriptionIndex) return NULL;
	if (gf_isom_get_avc_svc_type(the_file, trackNumber, DescriptionIndex)==GF_ISOM_AVCTYPE_NONE)
		return NULL;
	entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
	if (!entry) return NULL;
	if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO) return NULL;
	if (!entry->svc_config) return NULL;
	return AVC_DuplicateConfig(entry->svc_config->config);
}

Project: gpac
File: bitstream.c

u32 gf_bs_read_u32(GF_BitStream *bs)
{
	u32 ret;
	assert(bs->nbBits==8);

	if (bs->cache_read && (bs->cache_read_pos+4<bs->cache_read_size) ) {
		ret = bs->cache_read[bs->cache_read_pos];
		ret<<=8;
		ret |= bs->cache_read[bs->cache_read_pos+1];
		ret<<=8;
		ret |= bs->cache_read[bs->cache_read_pos+2];
		ret<<=8;
		ret |= bs->cache_read[bs->cache_read_pos+3];
		bs->cache_read_pos+=4;
		bs->position+=4;
		return ret;
	}
	ret = BS_ReadByte(bs);
	ret<<=8;
	ret |= BS_ReadByte(bs);
	ret<<=8;
	ret |= BS_ReadByte(bs);
	ret<<=8;
	ret |= BS_ReadByte(bs);
	return ret;
}

Project: gpac
File: bitstream.c

static u8 BS_ReadByte(GF_BitStream *bs)
{
	Bool is_eos;
	if (bs->bsmode == GF_BITSTREAM_READ) {
		u8 res;
		if (bs->position >= bs->size) {
			if (bs->EndOfStream) bs->EndOfStream(bs->par);
			if (!bs->overflow_state) bs->overflow_state = 1;
			return 0;
		}
		res = bs->original[bs->position++];

		if (bs->remove_emul_prevention_byte) {
			if ((bs->nb_zeros==2) && (res==0x03) && (bs->position<bs->size) && (bs->original[bs->position]<0x04)) {
				bs->nb_zeros = 0;
				res = bs->original[bs->position++];
			}
			if (!res) bs->nb_zeros++;
			else bs->nb_zeros = 0;
		}
		return res;
	}
	if (bs->cache_write)
		bs_flush_write_cache(bs);

	is_eos = gf_feof(bs->stream);
	//cache not fully read, reset EOS
	if (bs->cache_read && (bs->cache_read_pos<bs->cache_read_size))
		is_eos = GF_FALSE;

	/*we are in FILE mode, test for end of file*/
	if (!is_eos) {
		u8 res;
		Bool loc_eos=GF_FALSE;
		assert(bs->position<=bs->size);
		bs->position++;

		res = gf_bs_load_byte(bs, &loc_eos);
		if (loc_eos) goto bs_eof;

		if (bs->remove_emul_prevention_byte) {
			if ((bs->nb_zeros==2) && (res==0x03) && (bs->position<bs->size)) {
				u8 next = gf_bs_load_byte(bs, &loc_eos);
				if (next < 0x04) {
					bs->nb_zeros = 0;
					res = next;
					bs->position++;
				} else {
					gf_bs_seek(bs, bs->position);
				}
			}
			if (!res) bs->nb_zeros++;
			else bs->nb_zeros = 0;
		}
		return res;
	}

bs_eof:
	if (bs->EndOfStream) {
		bs->EndOfStream(bs->par);
		if (!bs->overflow_state) bs->overflow_state = 1;
	} else {
		if (!bs->overflow_state) {
			bs->overflow_state = 1;
			GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to overread bitstream\n"));
		}
	}
	assert(bs->position <= 1+bs->size);
	return 0;
}

Project: gpac
File: avc_ext.c

GF_Err avcc_box_size(GF_Box *s)
{
	u32 i, count;
	GF_AVCConfigurationBox *ptr = (GF_AVCConfigurationBox *)s;

	if (!ptr->config) {
		ptr->size = 0;
		return GF_OK;
	}
	ptr->size += 7;
	count = gf_list_count(ptr->config->sequenceParameterSets);
	for (i=0; i<count; i++)
		ptr->size += 2 + ((GF_NALUFFParam *)gf_list_get(ptr->config->sequenceParameterSets, i))->size;

	count = gf_list_count(ptr->config->pictureParameterSets);
	for (i=0; i<count; i++)
		ptr->size += 2 + ((GF_NALUFFParam *)gf_list_get(ptr->config->pictureParameterSets, i))->size;


	if ((ptr->type==GF_ISOM_BOX_TYPE_AVCC) || (ptr->type==GF_ISOM_BOX_TYPE_AVCE)) {
		if (gf_avcc_use_extensions(ptr->config->AVCProfileIndication)) {
			ptr->size += 4;
			count = ptr->config->sequenceParameterSetExtensions ?gf_list_count(ptr->config->sequenceParameterSetExtensions) : 0;
			for (i=0; i<count; i++)
				ptr->size += 2 + ((GF_NALUFFParam *)gf_list_get(ptr->config->sequenceParameterSetExtensions, i))->size;
		}
	}
	return GF_OK;
}

Project: gpac
File: bitstream.c

GF_BitStream *gf_bs_new(const u8 *buffer, u64 BufferSize, u32 mode)
{
	GF_BitStream *tmp = (GF_BitStream *)gf_malloc(sizeof(GF_BitStream));
	if (!tmp) return NULL;
	memset(tmp, 0, sizeof(GF_BitStream));

	tmp->original = (char*)buffer;
	tmp->size = BufferSize;

	tmp->bsmode = mode;

	switch (tmp->bsmode) {
	case GF_BITSTREAM_READ:
		tmp->nbBits = 8;
		tmp->current = 0;
		break;
	case GF_BITSTREAM_WRITE:
	case GF_BITSTREAM_WRITE_DYN:
		tmp->nbBits = 0;
		if (! buffer) {
			/*if BufferSize is specified, use it. This is typically used when AvgSize of
			some buffers is known, but some exceed it.*/
			if (BufferSize) {
				tmp->size = BufferSize;
			} else {
				tmp->size = BS_MEM_BLOCK_ALLOC_SIZE;
			}
			tmp->original = (char *) gf_malloc(sizeof(char) * ((u32) tmp->size));
			if (! tmp->original) {
				gf_free(tmp);
				return NULL;
			}
			tmp->bsmode = GF_BITSTREAM_WRITE_DYN;
		} else {
			tmp->original = (char*)buffer;
			tmp->size = BufferSize;
		}
		break;
	default:
		/*the stream constructor is not the same...*/
		gf_free(tmp);
		return NULL;
	}
	return tmp;
}

Project: gpac
File: avc_ext.c

GF_Err hvcc_box_read(GF_Box *s, GF_BitStream *bs)
{
	u64 consumed;
	GF_HEVCConfigurationBox *ptr = (GF_HEVCConfigurationBox *)s;

	if (ptr->config) gf_odf_hevc_cfg_del(ptr->config);

	consumed = gf_bs_get_position(bs);
	switch (s->type) {
	case GF_ISOM_BOX_TYPE_HVCC:
	case GF_ISOM_BOX_TYPE_HVCE:
		ptr->config = gf_odf_hevc_cfg_read_bs(bs, GF_FALSE);
		break;
	default:
		ptr->config = gf_odf_hevc_cfg_read_bs(bs, GF_TRUE);
		break;
	}
	consumed = gf_bs_get_position(bs) - consumed ;
	ISOM_DECREASE_SIZE(ptr, (u32)consumed)

	return ptr->config ? GF_OK : GF_ISOM_INVALID_FILE;
}

Project: gpac
File: bitstream.c

u64 gf_bs_get_position(GF_BitStream *bs)
{
	if (bs->cache_write)
		return bs->position + bs->buffer_written;
	return bs->position;
}

Project: gpac
File: bitstream.c

u16 gf_bs_read_u16_le(GF_BitStream *bs)
{
	u32 ret, v;
	ret = gf_bs_read_int(bs, 8);
	v = gf_bs_read_int(bs, 8);
	v<<=8;
	ret |= v;
	return ret;
}

Project: gpac
File: bitstream.c

GF_BitStream *gf_bs_new_cbk_buffer(GF_Err (*on_block_out)(void *cbk, u8 *data, u32 block_size), void *usr_data, u8 *buffer, u32 buffer_size)
{
	GF_BitStream *tmp;

	if (!on_block_out) return NULL;

	tmp = (GF_BitStream *)gf_malloc(sizeof(GF_BitStream));
	if (!tmp) return NULL;
	memset(tmp, 0, sizeof(GF_BitStream));

	if (buffer && buffer_size) {
		tmp->size = buffer_size;
		tmp->original = buffer;
	} else {
		tmp->size = buffer_size ? buffer_size : 10*BS_MEM_BLOCK_ALLOC_SIZE;
		tmp->original = (char *) gf_malloc(sizeof(char) * ((u32) tmp->size));
		if (! tmp->original) {
			gf_free(tmp);
			return NULL;
		}
	}
	tmp->bsmode = GF_BITSTREAM_WRITE_DYN;
	tmp->on_block_out = on_block_out;
	tmp->usr_data = usr_data;

	return tmp;
}

Project: gpac
File: bitstream.c

u64 gf_bs_read_u64_le(GF_BitStream *bs)
{
	u64 ret, v;
	ret = gf_bs_read_int(bs, 8);
	v = gf_bs_read_int(bs, 8);
	v<<=8;
	ret |= v;
	v = gf_bs_read_int(bs, 8);
	v<<=16;
	ret |= v;
	v = gf_bs_read_int(bs, 8);
	v<<=24;
	ret |= v;
	v = gf_bs_read_int(bs, 8);
	v<<=32;
	ret |= v;
	v = gf_bs_read_int(bs, 8);
	v<<=40;
	ret |= v;
	v = gf_bs_read_int(bs, 8);
	v<<=48;
	ret |= v;
	v = gf_bs_read_int(bs, 8);
	v<<=56;
	ret |= v;
	return ret;
}

Project: gpac
File: bitstream.c

u32 gf_bs_read_u8(GF_BitStream *bs)
{
	assert(bs->nbBits==8);
	if (bs->cache_read && (bs->cache_read_pos+1<bs->cache_read_size) ) {
		u32 ret = bs->cache_read[bs->cache_read_pos];
		bs->cache_read_pos+=1;
		bs->position+=1;
		return ret;
	}

	return (u32) BS_ReadByte(bs);
}

Project: gpac
File: bitstream.c

GF_Err gf_bs_seek(GF_BitStream *bs, u64 offset)
{
	bs->overflow_state = 0;
	if (bs->on_block_out) {
		GF_Err e;
		if (offset < bs->bytes_out) {
			GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to seek on byte range already forwarded\n"));
			return GF_BAD_PARAM;
		}
		/*warning: we allow offset = bs->size for WRITE buffers*/
		if (offset - bs->bytes_out > bs->size)
			return GF_BAD_PARAM;
		gf_bs_align(bs);
		e = BS_SeekIntern(bs, offset - bs->bytes_out);
		bs->position += bs->bytes_out;
		return e;
	}
	if (bs->cache_write)
		bs_flush_write_cache(bs);

	/*warning: we allow offset = bs->size for WRITE buffers*/
	if (offset > bs->size) return GF_BAD_PARAM;

	gf_bs_align(bs);
	return BS_SeekIntern(bs, offset);
}

Project: gpac
File: bitstream.c

u32 gf_bs_peek_bits(GF_BitStream *bs, u32 numBits, u64 byte_offset)
{
	u64 curPos;
	u32 curBits, ret, current, nb_zeros;

	if ( (bs->bsmode != GF_BITSTREAM_READ) && (bs->bsmode != GF_BITSTREAM_FILE_READ)) return 0;
	if (!numBits || (bs->size < bs->position + byte_offset)) return 0;

	/*store our state*/
	curPos = bs->position;
	curBits = bs->nbBits;
	current = bs->current;
	nb_zeros = bs->nb_zeros;

	if (byte_offset) {
		if (bs->remove_emul_prevention_byte) {
			while (byte_offset) {
				gf_bs_read_int(bs, 8);
				byte_offset--;
			}
		} else {
			gf_bs_seek(bs, bs->position + byte_offset);
		}
	}
	ret = gf_bs_read_int(bs, numBits);

	/*restore our cache - position*/
	gf_bs_seek(bs, curPos);
	/*to avoid re-reading our bits ...*/
	bs->nbBits = curBits;
	bs->current = current;
	bs->nb_zeros = nb_zeros;
	return ret;
}

Project: gpac
File: bitstream.c

void gf_bs_write_u64(GF_BitStream *bs, u64 value)
{
	assert(!bs->nbBits);
	gf_bs_write_u32(bs, (u32) ((value>>32)&0xffffffff));
	gf_bs_write_u32(bs, (u32) (value&0xffffffff));
}

Project: gpac
File: bitstream.c

u8 gf_bs_bits_available(GF_BitStream *bs)
{
	if (bs->size > bs->position) return 8;
	if (bs->nbBits < 8) return (8-bs->nbBits);
	return 0;
}

Project: gpac
File: avc_ext.c

static void merge_avc_config(GF_AVCConfig *dst_cfg, GF_AVCConfig *src_cfg)
{
	GF_AVCConfig *cfg;
	if (!src_cfg || !dst_cfg) return;
	cfg = AVC_DuplicateConfig(src_cfg);
	if (!cfg) return;

	while (gf_list_count(cfg->sequenceParameterSets)) {
		GF_NALUFFParam *p = (GF_NALUFFParam*)gf_list_get(cfg->sequenceParameterSets, 0);
		gf_list_rem(cfg->sequenceParameterSets, 0);
		gf_list_insert(dst_cfg->sequenceParameterSets, p, 0);
	}
	while (gf_list_count(cfg->pictureParameterSets)) {
		GF_NALUFFParam *p = (GF_NALUFFParam*)gf_list_get(cfg->pictureParameterSets, 0);
		gf_list_rem(cfg->pictureParameterSets, 0);
		gf_list_insert(dst_cfg->pictureParameterSets, p, 0);
	}
	gf_odf_avc_cfg_del(cfg);
}

Project: gpac
File: avc_ext.c

void VP9_RewriteESDescriptorEx(GF_MPEGVisualSampleEntryBox *vp9, GF_MediaBox *mdia)
{
	GF_BitRateBox *btrt = gf_isom_sample_entry_get_bitrate((GF_SampleEntryBox *)vp9, GF_FALSE);

	if (vp9->emul_esd) gf_odf_desc_del((GF_Descriptor *)vp9->emul_esd);
	vp9->emul_esd = gf_odf_desc_esd_new(2);
	vp9->emul_esd->decoderConfig->streamType = GF_STREAM_VISUAL;
	if (vp9->type == GF_ISOM_BOX_TYPE_VP08)
		vp9->emul_esd->decoderConfig->objectTypeIndication = GF_CODECID_VP8;
	else
		vp9->emul_esd->decoderConfig->objectTypeIndication = GF_CODECID_VP9;

	if (btrt) {
		vp9->emul_esd->decoderConfig->bufferSizeDB = btrt->bufferSizeDB;
		vp9->emul_esd->decoderConfig->avgBitrate = btrt->avgBitrate;
		vp9->emul_esd->decoderConfig->maxBitrate = btrt->maxBitrate;
	}

	if (vp9->vp_config && vp9->vp_config->config) {
		GF_VPConfig *vp9_cfg = VP_DuplicateConfig(vp9->vp_config->config);
		if (vp9_cfg) {
			gf_odf_vp_cfg_write(vp9_cfg, &vp9->emul_esd->decoderConfig->decoderSpecificInfo->data, &vp9->emul_esd->decoderConfig->decoderSpecificInfo->dataLength, GF_FALSE);
			gf_odf_vp_cfg_del(vp9_cfg);
		}
	}
}

Project: gpac
File: bitstream.c

void gf_bs_del(GF_BitStream *bs)
{
	if (!bs) return;
	if (bs->on_block_out && bs->position>bs->bytes_out) {
		bs->on_block_out(bs->usr_data, bs->original, (u32) (bs->position - bs->bytes_out) );
	}
	/*if we are in dynamic mode (alloc done by the bitstream), free the buffer if still present*/
	if ((bs->bsmode == GF_BITSTREAM_WRITE_DYN) && bs->original) gf_free(bs->original);
	if (bs->cache_write) {
		bs_flush_write_cache(bs);
		gf_free(bs->cache_write);
	}
	if (bs->cache_read)
		gf_free(bs->cache_read);
	gf_free(bs);
}

Project: gpac
File: bitstream.c

u32 gf_bs_read_u16(GF_BitStream *bs)
{
	u32 ret;
	assert(bs->nbBits==8);
	if (bs->cache_read && (bs->cache_read_pos+2<bs->cache_read_size) ) {
		ret = bs->cache_read[bs->cache_read_pos];
		ret<<=8;
		ret |= bs->cache_read[bs->cache_read_pos+1];
		bs->cache_read_pos+=2;
		bs->position+=2;
		return ret;
	}

	ret = BS_ReadByte(bs);
	ret<<=8;
	ret |= BS_ReadByte(bs);
	return ret;
}

Project: gpac
File: bitstream.c

u64 gf_bs_get_size(GF_BitStream *bs)
{
	if (bs->cache_write) {
		if (bs->size == bs->position)
			return bs->size + bs->buffer_written;
		else
			return bs->size;
	}
	if (bs->on_block_out)
		return bs->position;
	return bs->size;
}

Project: gpac
File: avc_ext.c

GF_Err vvnc_box_read(GF_Box *s, GF_BitStream *bs)
{
	GF_VVCNaluConfigurationBox *ptr = (GF_VVCNaluConfigurationBox *)s;

	ISOM_DECREASE_SIZE(ptr, 1)
	gf_bs_read_int(bs, 6);
	ptr->nal_unit_size = 1 + gf_bs_read_int(bs, 2);
	return GF_OK;
}

Project: gpac
File: bitstream.c

u32 gf_bs_read_data(GF_BitStream *bs, u8 *data, u32 nbBytes)
{
	u64 orig = bs->position;

	if (bs->position+nbBytes > bs->size) return 0;

	if (gf_bs_is_align(bs) ) {
		s32 bytes_read, bytes_read_cache;
		switch (bs->bsmode) {
		case GF_BITSTREAM_READ:
		case GF_BITSTREAM_WRITE:
		case GF_BITSTREAM_WRITE_DYN:
			memcpy(data, bs->original + bs->position, nbBytes);
			bs->position += nbBytes;
			return nbBytes;
		case GF_BITSTREAM_FILE_READ:
		case GF_BITSTREAM_FILE_WRITE:
			if (bs->cache_write)
				bs_flush_write_cache(bs);

			bytes_read = bytes_read_cache = 0;
			if (bs->cache_read) {
				u32 csize = bs->cache_read_size-bs->cache_read_pos;
				if (csize>nbBytes) csize = nbBytes;
				memcpy(data, bs->cache_read + bs->cache_read_pos, csize);
				bs->cache_read_pos += csize;
				nbBytes -= csize;
				bytes_read_cache = csize;
			}
			if (nbBytes) {
				bytes_read = (s32) gf_fread(data + bytes_read_cache, nbBytes, bs->stream);
				if (bytes_read<0) return bytes_read_cache;
			}
			bs->position += bytes_read + bytes_read_cache;
			return bytes_read + bytes_read_cache;
		default:
			return 0;
		}
	}

	while (nbBytes-- > 0) {
		*data++ = gf_bs_read_int(bs, 8);
	}
	return (u32) (bs->position - orig);

}

Project: gpac
File: bitstream.c

static void bs_flush_write_cache(GF_BitStream *bs)
{
	if (bs->buffer_written) {
		u32 nb_write;
		nb_write = (u32) gf_fwrite(bs->cache_write, bs->buffer_written, bs->stream);

		//check we didn't rewind the bitstream
		if (bs->size == bs->position)
			bs->size += nb_write;
		bs->position += nb_write;
		bs->buffer_written = 0;
	}
}

Project: gpac
File: bitstream.c

GF_BitStream *gf_bs_from_file(FILE *f, u32 mode)
{
	GF_BitStream *tmp;
	if (!f) return NULL;

	tmp = (GF_BitStream *)gf_malloc(sizeof(GF_BitStream));
	if (!tmp) return NULL;
	memset(tmp, 0, sizeof(GF_BitStream));
	/*switch to internal mode*/
	mode = (mode==GF_BITSTREAM_READ) ? GF_BITSTREAM_FILE_READ : GF_BITSTREAM_FILE_WRITE;
	tmp->bsmode = mode;
	tmp->current = 0;
	tmp->nbBits = (mode == GF_BITSTREAM_FILE_READ) ? 8 : 0;
	tmp->original = NULL;
	tmp->position = 0;
	tmp->stream = f;

	/*get the size of this file (for read streams)*/
	tmp->position = gf_ftell(f);
	tmp->size = gf_fsize(f);
	gf_fseek(f, tmp->position, SEEK_SET);


	if (mode==GF_BITSTREAM_FILE_READ) {
		tmp->cache_read_alloc = gf_opts_get_int("core", "bs-cache-size");
		if (tmp->cache_read_alloc) {
			tmp->cache_read_pos = tmp->cache_read_size = tmp->cache_read_alloc;
			tmp->cache_read = gf_malloc(tmp->cache_read_alloc);
			if (!tmp->cache_read) {
				gf_free(tmp);
				return NULL;
			}
		}
	}
	if (mode == GF_BITSTREAM_FILE_WRITE) {
		tmp->cache_write_size = gf_opts_get_int("core", "bs-cache-size");
		if (tmp->cache_write_size) {
			tmp->cache_write = (char*)gf_malloc(tmp->cache_write_size);
			if (!tmp->cache_write) {
				gf_free(tmp);
				return NULL;
			}
			tmp->buffer_written = 0;
		}
	}

	return tmp;
}

Project: gpac
File: bitstream.c

u8 gf_bs_read_bit(GF_BitStream *bs)
{
	if (bs->nbBits == 8) {
		bs->current = BS_ReadByte(bs);
		bs->nbBits = 0;
	}
#ifdef NO_OPTS
	{
		s32 ret;
		bs->current <<= 1;
		bs->nbBits++;
		ret = (bs->current & 0x100) >> 8;
		return (u8) ret;
	}
#else
	return (u8) (bs->current & bit_mask[bs->nbBits++]) ? 1 : 0;
#endif

}

Project: gpac
File: avc_ext.c

GF_Err vvnc_box_size(GF_Box *s)
{
	s->size += 1;
	return GF_OK;
}

Project: gpac
File: bitstream.c

u64 gf_bs_get_refreshed_size(GF_BitStream *bs)
{
	s64 offset;

	switch (bs->bsmode) {
	case GF_BITSTREAM_READ:
	case GF_BITSTREAM_WRITE:
		return bs->size;

	default:
		if (bs->cache_write)
			bs_flush_write_cache(bs);

		if (bs->stream) {
			offset = gf_ftell(bs->stream);
			bs->size = gf_fsize(bs->stream);
			gf_fseek(bs->stream, offset, SEEK_SET);
		}
		return bs->size;
	}
}

Project: gpac
File: bitstream.c

void gf_bs_flush(GF_BitStream *bs)
{
	if (!bs->stream) return;
	if (bs->bsmode != GF_BITSTREAM_FILE_WRITE) return;

	if (bs->cache_write)
		bs_flush_write_cache(bs);

	gf_fflush(bs->stream);
}

Project: gpac
File: bitstream.c

u32 gf_bs_write_data(GF_BitStream *bs, const u8 *data, u32 nbBytes)
{
	/*we need some feedback for this guy...*/
	u64 begin = bs->position;
	if (!nbBytes) return 0;

	if (gf_bs_is_align(bs)) {
		switch (bs->bsmode) {
		case GF_BITSTREAM_WRITE:
			if (bs->position+nbBytes > bs->size) {
				GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to overwrite bitstream by %d bytes\n", bs->position + nbBytes - bs->size));
				return 0;
			}
			memcpy(bs->original + bs->position, data, nbBytes);
			bs->position += nbBytes;
			return nbBytes;
		case GF_BITSTREAM_WRITE_DYN:
			//if callback mode and dispatch not disabled, dispatch bytes
			if (bs->on_block_out && !bs->prevent_dispatch) {
				assert(bs->position >= bs->bytes_out);

				if (bs->position - bs->bytes_out + nbBytes <= bs->size) {
					memcpy(bs->original + bs->position - bs->bytes_out, data, nbBytes);
					bs->position += nbBytes;
				} else {
					if (bs->position > bs->bytes_out)
						bs->on_block_out(bs->usr_data, bs->original, (u32) (bs->position - bs->bytes_out) );
					if (nbBytes)
						bs->on_block_out(bs->usr_data, (char *) data, nbBytes);

					bs->position += nbBytes;
					bs->bytes_out = bs->position;
				}
				assert(bs->position >= bs->bytes_out);
				return nbBytes;
			}
			//otherwise store
			/*need to gf_realloc ...*/
			if (bs->position + nbBytes - bs->bytes_out > bs->size) {
				u32 new_size = (u32) (bs->size*2);
				if (!new_size) new_size = BS_MEM_BLOCK_ALLOC_SIZE;

				if (bs->size + nbBytes > 0xFFFFFFFF)
					return 0;

				while (new_size < (u32) ( bs->size + nbBytes))
					new_size *= 2;
				bs->original = (char*)gf_realloc(bs->original, sizeof(u32)*new_size);
				if (!bs->original)
					return 0;
				bs->size = new_size;
			}
			memcpy(bs->original + bs->position - bs->bytes_out, data, nbBytes);
			bs->position += nbBytes;
			return nbBytes;
		case GF_BITSTREAM_FILE_READ:
		case GF_BITSTREAM_FILE_WRITE:
			if (bs->cache_write) {
				//if block fits in our write cache, write it
				if (bs->buffer_written + nbBytes < bs->cache_write_size) {
					memcpy(bs->cache_write+bs->buffer_written, data, nbBytes);
					bs->buffer_written+=nbBytes;
					return nbBytes;
				}
				//otherwise flush cache and use file write
				bs_flush_write_cache(bs);
			}

			if (gf_fwrite(data, nbBytes, bs->stream) != nbBytes) return 0;

			if (bs->size == bs->position) bs->size += nbBytes;
			bs->position += nbBytes;
			return nbBytes;
		default:
			return 0;
		}
	}

	while (nbBytes) {
		gf_bs_write_int(bs, (s32) *data, 8);
		data++;
		nbBytes--;
	}
	return (u32) (bs->position - begin);
}

Project: gpac
File: avc_ext.c

GF_Err vvcc_box_size(GF_Box *s)
{
	u32 i, count, j, subcount;
	GF_VVCConfigurationBox *ptr = (GF_VVCConfigurationBox *)s;

	if (!ptr->config) {
		ptr->size = 0;
		return GF_OK;
	}

	ptr->size += 1;
	if (ptr->config->ptl_present) {
		ptr->size += 3;
		//size PTL
		if (!ptr->config->general_constraint_info)
			ptr->config->num_constraint_info = 0;
		if (!ptr->config->sub_profiles_idc)
			ptr->config->num_sub_profiles = 0;

		ptr->size += 3 + ptr->config->num_constraint_info;
		if (ptr->config->numTemporalLayers>1)
			ptr->size += 1;
		for (i=0; i<ptr->config->numTemporalLayers; i++) {
			if (ptr->config->ptl_sublayer_present_mask & (1<<i))
				ptr->size+=1;
		}
		ptr->size += 1 + ptr->config->num_sub_profiles*4;
		//end size PTL
		ptr->size += 6;
	}

	ptr->size += 1;
	count = gf_list_count(ptr->config->param_array);
	for (i=0; i<count; i++) {
		GF_NALUFFParamArray *ar = (GF_NALUFFParamArray*)gf_list_get(ptr->config->param_array, i);
		if ((ar->type != GF_VVC_NALU_DEC_PARAM) && (ar->type != GF_VVC_NALU_OPI))
			ptr->size += 3;
		else
			ptr->size += 1;

		subcount = gf_list_count(ar->nalus);
		for (j=0; j<subcount; j++) {
			ptr->size += 2 + ((GF_NALUFFParam *)gf_list_get(ar->nalus, j))->size;
		}
	}
	return GF_OK;
}

Project: gpac
File: bitstream.c

GF_Err gf_bs_reassign_buffer(GF_BitStream *bs, const u8 *buffer, u64 BufferSize)
{
	if (!bs) return GF_BAD_PARAM;
	bs->total_bits_read = 0;
	if (bs->bsmode == GF_BITSTREAM_READ) {
		bs->original = (char*)buffer;
		bs->size = BufferSize;
		bs->position = 0;
		bs->current = 0;
		bs->nbBits = 8;
		bs->current = 0;
		bs->nb_zeros = 0;
		return GF_OK;
	}
	if (bs->bsmode==GF_BITSTREAM_WRITE) {
		if (!buffer || !BufferSize) return GF_BAD_PARAM;
		bs->original = (char*)buffer;
		bs->size = BufferSize;
		bs->position = 0;
		bs->current = 0;
		bs->nbBits = 0;
		bs->current = 0;
		return GF_OK;
	}
	if (bs->bsmode!=GF_BITSTREAM_WRITE_DYN) return GF_BAD_PARAM;
	if (bs->original) return GF_BAD_PARAM;

	bs->position = 0;
	bs->current = 0;
	bs->nbBits = 0;
	bs->current = 0;
	bs->size = BufferSize ? BufferSize : BS_MEM_BLOCK_ALLOC_SIZE;
	if (buffer) {
		bs->original = (char *) buffer;
	} else {
		bs->original = (char *) gf_malloc(sizeof(char) * ((u32) bs->size));
		if (! bs->original) {
			return GF_OUT_OF_MEM;
		}
	}
	return GF_OK;
}

Project: gpac
File: bitstream.c

void gf_bs_write_u64_le(GF_BitStream *bs, u64 val)
{
	gf_bs_write_int(bs, val & 0xFF, 8);
	gf_bs_write_int(bs, (val>>8) & 0xFF, 8);
	gf_bs_write_int(bs, (val>>16) & 0xFF, 8);
	gf_bs_write_int(bs, (val>>24) & 0xFF, 8);
	gf_bs_write_int(bs, (val>>32) & 0xFF, 8);
	gf_bs_write_int(bs, (val>>40) & 0xFF, 8);
	gf_bs_write_int(bs, (val>>48) & 0xFF, 8);
	gf_bs_write_int(bs, (val>>56) & 0xFF, 8);
}

Project: gpac
File: bitstream.c

void gf_bs_write_u16(GF_BitStream *bs, u32 value)
{
	assert(!bs->nbBits);
	if (bs->cache_write && (bs->buffer_written+2 < bs->cache_write_size) ) {
		bs->cache_write[bs->buffer_written] = (u8) ((value>>8)&0xff);
		bs->cache_write[bs->buffer_written+1] = (u8) ((value)&0xff);
		bs->buffer_written += 2;
	} else {
		BS_WriteByte(bs, (u8) ((value>>8)&0xff));
		BS_WriteByte(bs, (u8) ((value)&0xff));
	}
}

Project: gpac
File: bitstream.c

void gf_bs_log_idx(GF_BitStream *bs, u32 nBits, const char *fname, s64 val, s32 idx1, s32 idx2, s32 idx3)
{
	assert(bs);
	if (bs->on_log) bs->on_log(bs->log_udta, fname, nBits, val, idx1, idx2, idx3);
}

Project: gpac
File: bitstream.c

void gf_bs_rewind_bits(GF_BitStream *bs, u64 nbBits)
{
	u64 nbBytes;
	if (bs->bsmode != GF_BITSTREAM_READ) return;

	nbBits -= (bs->nbBits);
	nbBytes = (nbBits+8)>>3;
	nbBits = nbBytes*8 - nbBits;
	gf_bs_align(bs);
	assert(bs->position >= nbBytes);
	bs->position -= nbBytes + 1;
	gf_bs_read_int(bs, (u32)nbBits);
	return;
}

Project: gpac
File: avc_ext.c

GF_Err gf_isom_nalu_sample_rewrite(GF_MediaBox *mdia, GF_ISOSample *sample, u32 sampleNumber, GF_MPEGVisualSampleEntryBox *entry)
{
	Bool is_hevc = GF_FALSE;
	//if only one sync given in the sample sync table, insert sps/pps/vps before cra/bla in hevc
//	Bool check_cra_bla = (mdia->information->sampleTable->SyncSample && mdia->information->sampleTable->SyncSample->nb_entries>1) ? 0 : 1;
	Bool check_cra_bla = GF_TRUE;
	Bool insert_nalu_delim = GF_TRUE;
	Bool force_sei_inspect = GF_FALSE;
	GF_Err e = GF_OK;
	GF_BitStream *sei_suffix_bs = NULL;
	Bool ps_transfered = GF_FALSE;
	u32 nal_size, nal_unit_size_field, extractor_mode;
	Bool rewrite_ps, rewrite_start_codes, insert_vdrd_code;
	u8 nal_type;
	u32 nal_hdr, sabt_ref, i, track_num;
	u32 temporal_id = 0;
	GF_ISOFile *file = mdia->mediaTrack->moov->mov;
	GF_TrackReferenceTypeBox *scal = NULL;

	Track_FindRef(mdia->mediaTrack, GF_ISOM_REF_SCAL, &scal);

	rewrite_ps = (mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_INBAND_PS_FLAG) ? GF_TRUE : GF_FALSE;
	rewrite_start_codes = (mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_ANNEXB_FLAG) ? GF_TRUE : GF_FALSE;
	insert_vdrd_code = (mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_VDRD_FLAG) ? GF_TRUE : GF_FALSE;
	if (!entry->svc_config && !entry->mvc_config && !entry->lhvc_config) insert_vdrd_code = GF_FALSE;
	extractor_mode = mdia->mediaTrack->extractor_mode&0x0000FFFF;

	if (mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_TILE_ONLY) {
		insert_nalu_delim = GF_FALSE;
	}

	track_num = 1 + gf_list_find(mdia->mediaTrack->moov->trackList, mdia->mediaTrack);

	if ( (extractor_mode != GF_ISOM_NALU_EXTRACT_INSPECT) && !(mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_TILE_ONLY) ) {
		u32 ref_track, di;
		//aggregate all sabt samples with the same DTS
		if (entry->lhvc_config && !entry->hevc_config && !(mdia->mediaTrack->extractor_mode & GF_ISOM_NALU_EXTRACT_LAYER_ONLY)) {
			if (gf_isom_get_reference_count(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_SCAL) <= 0) {
				//FIXME - for now we only support two layers (base + enh) in implicit
				if ( gf_isom_get_reference_count(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_BASE) >= 1) {
					GF_ISOSample *base_samp;
					gf_isom_get_reference(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_BASE, 1, &ref_track);
					switch (gf_isom_get_media_subtype(mdia->mediaTrack->moov->mov , ref_track, 1)) {
					case GF_ISOM_SUBTYPE_HVC1:
					case GF_ISOM_SUBTYPE_HVC2:
					case GF_ISOM_SUBTYPE_HEV1:
					case GF_ISOM_SUBTYPE_HEV2:

						if (!mdia->extracted_samp) {
							mdia->extracted_samp = gf_isom_sample_new();
							if (!mdia->extracted_samp) return GF_OUT_OF_MEM;
						}

						base_samp = gf_isom_get_sample_ex(mdia->mediaTrack->moov->mov, ref_track, sampleNumber + mdia->mediaTrack->sample_count_at_seg_start, &di, mdia->extracted_samp, NULL);
						if (base_samp && base_samp->data) {
							if (!sample->alloc_size || (sample->alloc_size<sample->dataLength+base_samp->dataLength) ) {
								sample->data = gf_realloc(sample->data, sample->dataLength+base_samp->dataLength);
								if (sample->alloc_size) sample->alloc_size = sample->dataLength+base_samp->dataLength;
							}
							memmove(sample->data + base_samp->dataLength, sample->data , sample->dataLength);
							memcpy(sample->data, base_samp->data, base_samp->dataLength);
							sample->dataLength += base_samp->dataLength;
						}
						Track_FindRef(mdia->mediaTrack, GF_ISOM_REF_BASE, &scal);
						break;
					}
				}
			}
		}

		sabt_ref = gf_isom_get_reference_count(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_SABT);
		if ((s32) sabt_ref > 0) {
			force_sei_inspect = GF_TRUE;
			for (i=0; i<sabt_ref; i++) {
				GF_ISOSample *tile_samp;
				gf_isom_get_reference(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_SABT, i+1, &ref_track);

				if (!mdia->extracted_samp) {
					mdia->extracted_samp = gf_isom_sample_new();
					if (!mdia->extracted_samp) return GF_OUT_OF_MEM;
				}

				tile_samp = gf_isom_get_sample_ex(mdia->mediaTrack->moov->mov, ref_track, sampleNumber + mdia->mediaTrack->sample_count_at_seg_start, &di, mdia->extracted_samp, NULL);
				if (tile_samp  && tile_samp ->data) {
					if (!sample->alloc_size || (sample->alloc_size<sample->dataLength+tile_samp->dataLength) ) {
						sample->data = gf_realloc(sample->data, sample->dataLength+tile_samp->dataLength);
						if (sample->alloc_size) sample->alloc_size = sample->dataLength+tile_samp->dataLength;
					}
					memcpy(sample->data + sample->dataLength, tile_samp->data, tile_samp->dataLength);
					sample->dataLength += tile_samp->dataLength;
				}
			}
		}
	}

	if ( gf_isom_get_reference_count(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_TBAS) >= 1) {
		u32 ref_track;
		u32 idx = gf_list_find(mdia->information->sampleTable->SampleDescription->child_boxes, entry);
		GF_TrackBox *tbas;
		gf_isom_get_reference(mdia->mediaTrack->moov->mov, track_num, GF_ISOM_REF_TBAS, 1, &ref_track);
		tbas = (GF_TrackBox *)gf_list_get(mdia->mediaTrack->moov->trackList, ref_track-1);
		entry = gf_list_get(tbas->Media->information->sampleTable->SampleDescription->child_boxes, idx);
	}


	if (sample->IsRAP < SAP_TYPE_2) {
		if (mdia->information->sampleTable->no_sync_found || (!sample->IsRAP && check_cra_bla) ) {
			sample->IsRAP = is_sample_idr(mdia, sample, entry);
		}
	}
	if (!sample->IsRAP)
		rewrite_ps = GF_FALSE;

	if (extractor_mode != GF_ISOM_NALU_EXTRACT_LAYER_ONLY)
		insert_vdrd_code = GF_FALSE;

	if (!entry) return GF_BAD_PARAM;

	//this is a compatible HEVC, don't insert VDRD, insert NALU delim
	if (entry->lhvc_config && entry->hevc_config)
		insert_vdrd_code = GF_FALSE;

	if (extractor_mode == GF_ISOM_NALU_EXTRACT_INSPECT) {
		if (!rewrite_ps && !rewrite_start_codes)
			return GF_OK;
	}

	nal_unit_size_field = 0;
	/*if svc rewrite*/
	if (entry->svc_config && entry->svc_config->config)
		nal_unit_size_field = entry->svc_config->config->nal_unit_size;
	/*if mvc rewrite*/
	if (entry->mvc_config && entry->mvc_config->config)
		nal_unit_size_field = entry->mvc_config->config->nal_unit_size;

	/*if lhvc rewrite*/
	else if (entry->lhvc_config && entry->lhvc_config->config)  {
		is_hevc = GF_TRUE;
		nal_unit_size_field = entry->lhvc_config->config->nal_unit_size;
	}

	/*otherwise do nothing*/
	else if (!rewrite_ps && !rewrite_start_codes && !scal && !force_sei_inspect) {
		return GF_OK;
	}

	if (!nal_unit_size_field) {
		if (entry->avc_config && entry->avc_config->config)
			nal_unit_size_field = entry->avc_config->config->nal_unit_size;
		else if (entry->lhvc_config && entry->lhvc_config->config) {
			nal_unit_size_field = entry->lhvc_config->config->nal_unit_size;
			is_hevc = GF_TRUE;
		}
		else if (entry->hevc_config && entry->hevc_config->config) {
			nal_unit_size_field = entry->hevc_config->config->nal_unit_size;
			is_hevc = GF_TRUE;
		}
	}

	if (!nal_unit_size_field) return GF_ISOM_INVALID_FILE;

	//setup PS rewriter
	if (!mdia->nalu_ps_bs)
		mdia->nalu_ps_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
	gf_bs_seek(mdia->nalu_ps_bs, 0);

	//setup sample reader
	if (mdia->in_sample_buffer_alloc<sample->dataLength) {
		mdia->in_sample_buffer_alloc = sample->dataLength;
		mdia->in_sample_buffer = gf_realloc(mdia->in_sample_buffer, sample->dataLength);
	}
	memcpy(mdia->in_sample_buffer, sample->data, sample->dataLength);

	if (!mdia->nalu_parser) {
		mdia->nalu_parser = gf_bs_new(mdia->in_sample_buffer, sample->dataLength, GF_BITSTREAM_READ);
		if (!mdia->nalu_parser && sample->data) return GF_ISOM_INVALID_FILE;
	} else {
		e = gf_bs_reassign_buffer(mdia->nalu_parser, mdia->in_sample_buffer, sample->dataLength);
		if (e) return e;
	}
	//setup output
	if (!mdia->nalu_out_bs) {
		u8 *output;
		u32 outSize;
		mdia->nalu_out_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
		gf_bs_get_content(mdia->nalu_out_bs, &output, &outSize);
	}

	gf_bs_reassign_buffer(mdia->nalu_out_bs, sample->data, sample->alloc_size ? sample->alloc_size : sample->dataLength);

	/*rewrite start code with NALU delim*/
	if (rewrite_start_codes) {

		//we are SVC, don't write NALU delim, only insert VDRD NALU
		if (insert_vdrd_code) {
			if (is_hevc) {
				//spec is not clear here, we don't insert an NALU AU delimiter before the layer starts since it breaks openHEVC
//				insert_nalu_delim=0;
			} else {
				gf_bs_write_int(mdia->nalu_out_bs, 1, 32);
				gf_bs_write_int(mdia->nalu_out_bs, GF_AVC_NALU_VDRD , 8);
				insert_nalu_delim=0;
			}
		}

		//AVC/HEVC base, insert NALU delim
		if (insert_nalu_delim) {
			gf_bs_write_int(mdia->nalu_out_bs, 1, 32);
			if (is_hevc) {
#ifndef GPAC_DISABLE_HEVC
				gf_bs_write_int(mdia->nalu_out_bs, 0, 1);
				gf_bs_write_int(mdia->nalu_out_bs, GF_HEVC_NALU_ACCESS_UNIT, 6);
				gf_bs_write_int(mdia->nalu_out_bs, insert_vdrd_code ? 1 : 0, 6); //we should pick the layerID of the following nalus ...
				gf_bs_write_int(mdia->nalu_out_bs, 1, 3); //nuh_temporal_id_plus1 - cannot be 0, we use 1 by default, and overwrite it if needed at the end

				/*pic-type - by default we signal all slice types possible*/
				gf_bs_write_int(mdia->nalu_out_bs, 2, 3);
				gf_bs_write_int(mdia->nalu_out_bs, 0, 5);
#endif
			} else {
				gf_bs_write_int(mdia->nalu_out_bs, (sample->data[0] & 0x60) | GF_AVC_NALU_ACCESS_UNIT, 8);
				gf_bs_write_int(mdia->nalu_out_bs, 0xF0 , 8); /*7 "all supported NALUs" (=111) + rbsp trailing (10000)*/;
			}
		}
	}

	if (rewrite_ps) {
		Bool has_vps = GF_FALSE;
		//in inspect mode or single-layer mode just use the xPS from this layer
		if (extractor_mode == GF_ISOM_NALU_EXTRACT_DEFAULT) {
			if (scal) {
				for (i=0; i<scal->trackIDCount; i++) {
					GF_TrackBox *a_track = GetTrackbyID(mdia->mediaTrack->moov, scal->trackIDs[i]);
					GF_MPEGVisualSampleEntryBox *an_entry = NULL;
					if (a_track && a_track->Media && a_track->Media->information && a_track->Media->information->sampleTable && a_track->Media->information->sampleTable->SampleDescription)
						an_entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(a_track->Media->information->sampleTable->SampleDescription->child_boxes, 0);

					if (an_entry)
						nalu_merge_ps(mdia->nalu_ps_bs, rewrite_start_codes, nal_unit_size_field, an_entry, is_hevc, &has_vps);
				}
			}
		}
		nalu_merge_ps(mdia->nalu_ps_bs, rewrite_start_codes, nal_unit_size_field, entry, is_hevc, &has_vps);


		if (is_hevc) {
			/*little optimization if we are not asked to start codes: copy over the sample*/
			if (!rewrite_start_codes && !entry->lhvc_config && !scal) {
				if (! ps_transfered) {
					nal_type = (sample->data[nal_unit_size_field] & 0x7E) >> 1;
					//temp fix - if we detect xPS in the beginning of the sample do NOT copy the ps bitstream
					//this is not correct since we are not sure whether they are the same xPS or not, but it crashes openHEVC ...
					switch (nal_type) {
#ifndef GPAC_DISABLE_HEVC
					case GF_HEVC_NALU_VID_PARAM:
					case GF_HEVC_NALU_SEQ_PARAM:
					case GF_HEVC_NALU_PIC_PARAM:
						break;
#endif
					default:
						gf_bs_transfer(mdia->nalu_out_bs, mdia->nalu_ps_bs, GF_TRUE);
						break;
					}
				}
				gf_bs_write_data(mdia->nalu_out_bs, mdia->in_sample_buffer, sample->dataLength);
				gf_bs_get_content_no_truncate(mdia->nalu_out_bs, &sample->data, &sample->dataLength, &sample->alloc_size);

				return GF_OK;
			}
		}
	} else {
		ps_transfered = GF_TRUE;
	}

	/*little optimization if we are not asked to rewrite extractors or start codes: copy over the sample*/
	if (!scal && !rewrite_start_codes && !rewrite_ps && !force_sei_inspect) {
		if (! ps_transfered)
		{
			gf_bs_transfer(mdia->nalu_out_bs, mdia->nalu_ps_bs, GF_TRUE);
		}
		gf_bs_write_data(mdia->nalu_out_bs, mdia->in_sample_buffer, sample->dataLength);
		gf_bs_get_content_no_truncate(mdia->nalu_out_bs, &sample->data, &sample->dataLength, &sample->alloc_size);
		return GF_OK;
	}

	if (!mdia->tmp_nal_copy_buffer) {
		mdia->tmp_nal_copy_buffer = gf_malloc(sizeof(char) * 4096);
		mdia->tmp_nal_copy_buffer_alloc = 4096;
	}


	while (gf_bs_available(mdia->nalu_parser)) {
		nal_size = gf_bs_read_int(mdia->nalu_parser, 8*nal_unit_size_field);
		if (gf_bs_get_position(mdia->nalu_parser) + nal_size > sample->dataLength) {
			GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("Sample %u (size %u) rewrite: corrupted NAL Unit (size %u)\n", sampleNumber, sample->dataLength, nal_size));
			goto exit;
		}
		if (nal_size > mdia->tmp_nal_copy_buffer_alloc) {
			mdia->tmp_nal_copy_buffer_alloc = nal_size;
			mdia->tmp_nal_copy_buffer = (char*) gf_realloc(mdia->tmp_nal_copy_buffer, sizeof(char)*nal_size);
		}
		if (is_hevc) {
			nal_hdr = gf_bs_read_u16(mdia->nalu_parser);
			nal_type = (nal_hdr&0x7E00) >> 9;
		} else {
			nal_hdr = gf_bs_read_u8(mdia->nalu_parser);
			nal_type = nal_hdr & 0x1F;
		}

		if (is_hevc) {
#ifndef GPAC_DISABLE_HEVC
			GF_BitStream *write_to_bs = mdia->nalu_out_bs;
#endif

			if (!ps_transfered) {
				gf_bs_transfer(mdia->nalu_out_bs, mdia->nalu_ps_bs, GF_TRUE);
				ps_transfered = GF_TRUE;
			}

#ifndef GPAC_DISABLE_HEVC
			switch (nal_type) {
			/*we already wrote AU delim, and we trash aggregators*/
			case GF_HEVC_NALU_ACCESS_UNIT:
			case GF_HEVC_NALU_FF_AGGREGATOR:
				gf_bs_skip_bytes(mdia->nalu_parser, nal_size-2);
				continue;

			//extractor
			case GF_HEVC_NALU_FF_EXTRACTOR:
				e = process_extractor(file, mdia, sampleNumber, sample->DTS, nal_size, nal_hdr, nal_unit_size_field, GF_TRUE, rewrite_ps, rewrite_start_codes, extractor_mode);
				if (e) goto exit;
				break;

			case GF_HEVC_NALU_SLICE_TSA_N:
			case GF_HEVC_NALU_SLICE_STSA_N:
			case GF_HEVC_NALU_SLICE_TSA_R:
			case GF_HEVC_NALU_SLICE_STSA_R:
				if (temporal_id < (nal_hdr & 0x7))
					temporal_id = (nal_hdr & 0x7);
				/*rewrite nal*/
				gf_bs_read_data(mdia->nalu_parser, mdia->tmp_nal_copy_buffer, nal_size-2);
				if (rewrite_start_codes)
					gf_bs_write_u32(mdia->nalu_out_bs, 1);
				else
					gf_bs_write_int(mdia->nalu_out_bs, nal_size, 8*nal_unit_size_field);

				gf_bs_write_u16(mdia->nalu_out_bs, nal_hdr);
				gf_bs_write_data(mdia->nalu_out_bs, mdia->tmp_nal_copy_buffer, nal_size-2);
				break;

			case GF_HEVC_NALU_SLICE_BLA_W_LP:
			case GF_HEVC_NALU_SLICE_BLA_W_DLP:
			case GF_HEVC_NALU_SLICE_BLA_N_LP:
			case GF_HEVC_NALU_SLICE_IDR_W_DLP:
			case GF_HEVC_NALU_SLICE_IDR_N_LP:
			case GF_HEVC_NALU_SLICE_CRA:
				//insert xPS before CRA/BLA
				if (check_cra_bla && !sample->IsRAP) {
					sample->IsRAP = sap_type_from_nal_type(nal_type);
					if (sei_suffix_bs) gf_bs_del(sei_suffix_bs);
					return gf_isom_nalu_sample_rewrite(mdia, sample, sampleNumber, entry);
				}
			default:
				/*rewrite nal*/
				if (nal_size<2) {
					GF_LOG(GF_LOG_ERROR, GF_LOG_CONTAINER, ("[iso file] Invalid nal size %d in sample %d\n", nal_type, sampleNumber));
					e = GF_NON_COMPLIANT_BITSTREAM;
					goto exit;
				}

				gf_bs_read_data(mdia->nalu_parser, mdia->tmp_nal_copy_buffer, nal_size-2);

				if (nal_type==GF_HEVC_NALU_SEI_SUFFIX) {
					if (!sei_suffix_bs) sei_suffix_bs = gf_bs_new(NULL, 0, GF_BITSTREAM_WRITE);
					write_to_bs = sei_suffix_bs;
				}

				if (rewrite_start_codes)
					gf_bs_write_u32(write_to_bs, 1);
				else
					gf_bs_write_int(write_to_bs, nal_size, 8*nal_unit_size_field);

				gf_bs_write_u16(write_to_bs, nal_hdr);
				gf_bs_write_data(write_to_bs, mdia->tmp_nal_copy_buffer, nal_size-2);
			}
#endif

			//done with HEVC
			continue;
		}

		switch(nal_type) {
		case GF_AVC_NALU_ACCESS_UNIT:
		case GF_AVC_NALU_FF_AGGREGATOR:
			/*we already wrote this stuff, and we trash aggregators*/
			gf_bs_skip_bytes(mdia->nalu_parser, nal_size-1);
			continue;
		//extractor
		case GF_AVC_NALU_FF_EXTRACTOR:
			e = process_extractor(file, mdia, sampleNumber, sample->DTS, nal_size, nal_hdr, nal_unit_size_field, GF_FALSE, rewrite_ps, rewrite_start_codes, extractor_mode);
			if (e) goto exit;
			break;
//			case GF_AVC_NALU_SEI:
		case GF_AVC_NALU_SEQ_PARAM:
		case GF_AVC_NALU_PIC_PARAM:
		case GF_AVC_NALU_SEQ_PARAM_EXT:
		case GF_AVC_NALU_SVC_SUBSEQ_PARAM:
			// we will rewrite the sps/pps if and only if there is no sps/pps in bistream
			if (!ps_transfered) {
				ps_transfered = GF_TRUE;
			}
		default:
			if (!ps_transfered) {
				gf_bs_transfer(mdia->nalu_out_bs, mdia->nalu_ps_bs, GF_TRUE);
				ps_transfered = GF_TRUE;
			}
			gf_bs_read_data(mdia->nalu_parser, mdia->tmp_nal_copy_buffer, nal_size-1);
			if (rewrite_start_codes)
				gf_bs_write_u32(mdia->nalu_out_bs, 1);
			else
				gf_bs_write_int(mdia->nalu_out_bs, nal_size, 8*nal_unit_size_field);

			gf_bs_write_u8(mdia->nalu_out_bs, nal_hdr);
			gf_bs_write_data(mdia->nalu_out_bs, mdia->tmp_nal_copy_buffer, nal_size-1);
		}
	}

	if (sei_suffix_bs) {
		gf_bs_transfer(mdia->nalu_out_bs, sei_suffix_bs, GF_FALSE);
	}
	/*done*/
	gf_bs_get_content_no_truncate(mdia->nalu_out_bs, &sample->data, &sample->dataLength, &sample->alloc_size);

	/*rewrite temporal ID of AU Ddelim NALU (first one)*/
	if (rewrite_start_codes && is_hevc && temporal_id) {
		sample->data[6] = (sample->data[6] & 0xF8) | (temporal_id+1);
	}


exit:
	if (sei_suffix_bs)
		gf_bs_del(sei_suffix_bs);

	return e;
}

Project: gpac
File: bitstream.c

static GFINLINE u8 gf_bs_load_byte(GF_BitStream *bs, Bool *is_eos)
{
	u8 res;
	if (bs->cache_read) {
		if (bs->cache_read_pos == bs->cache_read_size) {
			bs->cache_read_size = (u32) gf_fread(bs->cache_read, bs->cache_read_alloc, bs->stream);
			bs->cache_read_pos = 0;
			if (!bs->cache_read_size) {
				*is_eos = GF_TRUE;
				return 0;
			}
		}
		res = bs->cache_read[bs->cache_read_pos];
		bs->cache_read_pos++;
	} else {
		res = gf_fgetc(bs->stream);
	}
	return res;
}

Project: gpac
File: bitstream.c

void gf_bs_write_u8(GF_BitStream *bs, u32 value)
{
	assert(!bs->nbBits);

	if (bs->cache_write && (bs->buffer_written+1 < bs->cache_write_size) ) {
		bs->cache_write[bs->buffer_written] = (u8) value;
		bs->buffer_written += 1;
	} else {
		BS_WriteByte(bs, (u8) value);
	}
}

Project: gpac
File: bitstream.c

u32 gf_bs_read_u24(GF_BitStream *bs)
{
	u32 ret;
	assert(bs->nbBits==8);

	if (bs->cache_read && (bs->cache_read_pos+3<bs->cache_read_size) ) {
		ret = bs->cache_read[bs->cache_read_pos];
		ret<<=8;
		ret |= bs->cache_read[bs->cache_read_pos+1];
		ret<<=8;
		ret |= bs->cache_read[bs->cache_read_pos+2];
		bs->cache_read_pos+=3;
		bs->position+=3;
		return ret;
	}

	ret = BS_ReadByte(bs);
	ret<<=8;
	ret |= BS_ReadByte(bs);
	ret<<=8;
	ret |= BS_ReadByte(bs);
	return ret;
}

Project: gpac
File: bitstream.c

u32 gf_bs_get_bit_position(GF_BitStream *bs)
{
	return bs->nbBits;
}

Project: gpac
File: bitstream.c

static s32 BS_CutBuffer(GF_BitStream *bs)
{
	s32 nbBytes;
	if ( (bs->bsmode != GF_BITSTREAM_WRITE_DYN) && (bs->bsmode != GF_BITSTREAM_WRITE)) return (u32) -1;
	/*Align our buffer or we're dead!*/
	gf_bs_align(bs);

	nbBytes = (u32) (bs->size - bs->position);
	if (!nbBytes || (nbBytes == 0xFFFFFFFF) || (bs->position >= 0xFFFFFFFF)) return 0;
	/*
		bs->original = (char*)gf_realloc(bs->original, (u32) bs->position);
		if (! bs->original) return (u32) -1;
	*/
	/*just in case, re-adjust..*/
	bs->size = bs->position;
	return nbBytes;
}

Project: gpac
File: avc_ext.c

void vvnc_box_del(GF_Box *s)
{
	GF_VVCNaluConfigurationBox *ptr = (GF_VVCNaluConfigurationBox*)s;
	gf_free(ptr);
}

Project: gpac
File: bitstream.c

static GF_Err BS_SeekIntern(GF_BitStream *bs, u64 offset)
{
	u32 i;
	/*if mem, do it */
	if ((bs->bsmode == GF_BITSTREAM_READ) || (bs->bsmode == GF_BITSTREAM_WRITE) || (bs->bsmode == GF_BITSTREAM_WRITE_DYN)) {
		if (offset > 0xFFFFFFFF) return GF_IO_ERR;
		if (!bs->original) return GF_BAD_PARAM;
		/*0 for write, read will be done automatically*/
		if (offset >= bs->size) {
			if ( (bs->bsmode == GF_BITSTREAM_READ) || (bs->bsmode == GF_BITSTREAM_WRITE) ) {
				if (offset > bs->size) {
					GF_LOG(GF_LOG_WARNING, GF_LOG_CORE, ("[BS] Attempt to seek to %d after end of bitstream %d, assuming seek to end\n", offset, bs->size));
				}
				bs->position = bs->size;
				bs->nbBits = (bs->bsmode == GF_BITSTREAM_READ) ? 8 : 0;
				return GF_OK;
			}
			/*in DYN, gf_realloc ...*/
			bs->original = (char*)gf_realloc(bs->original, (u32) (offset + 1));
			if (!bs->original)
				return GF_OUT_OF_MEM;
			for (i = 0; i < (u32) (offset + 1 - bs->size); i++) {
				bs->original[bs->size + i] = 0;
			}
			bs->size = offset + 1;
		}
		bs->current = bs->original[offset];
		bs->position = offset;
		bs->nbBits = (bs->bsmode == GF_BITSTREAM_READ) ? 8 : 0;
		return GF_OK;
	}

	if (bs->cache_write)
		bs_flush_write_cache(bs);

	if (bs->cache_read) {
		bs->cache_read_pos = bs->cache_read_size;
	}

	gf_fseek(bs->stream, offset, SEEK_SET);

	bs->position = offset;
	bs->current = 0;
	/*setup NbBits so that next acccess to the buffer will trigger read/write*/
	bs->nbBits = (bs->bsmode == GF_BITSTREAM_FILE_READ) ? 8 : 0;
	return GF_OK;
}

Project: gpac
File: bitstream.c

Double gf_bs_read_double(GF_BitStream *bs)
{
	char buf [8] = "\0\0\0\0\0\0\0";
	s32 i;
	for (i = 0; i < 64; i++)
		buf[7-i/8] |= gf_bs_read_bit(bs) << (7 - i%8);
	return (* (Double *) buf);
}

Project: gpac
File: avc_ext.c

GF_Err gf_isom_vp_config_new(GF_ISOFile *the_file, u32 trackNumber, GF_VPConfig *cfg, const char *URLname, const char *URNname, u32 *outDescriptionIndex, u32 vpx_type)
{
	GF_TrackBox *trak;
	GF_Err e;
	u32 dataRefIndex;
	GF_SampleDescriptionBox *stsd;
	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, (char *)URLname, (char *)URNname, &dataRefIndex);
	if (e) return e;
	if (!dataRefIndex) {
		e = Media_CreateDataRef(the_file, trak->Media->information->dataInformation->dref, (char *)URLname, (char *)URNname, &dataRefIndex);
		if (e) return e;
	}
	if (!the_file->keep_utc)
		trak->Media->mediaHeader->modificationTime = gf_isom_get_mp4time();

	stsd = trak->Media->information->sampleTable->SampleDescription;
	//create a new entry
	entry = (GF_MPEGVisualSampleEntryBox *)gf_isom_box_new_parent(&stsd->child_boxes, vpx_type);
	if (!entry) return GF_OUT_OF_MEM;

	entry->vp_config = (GF_VPConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_VPCC);
	if (!entry->vp_config) return GF_OUT_OF_MEM;
	entry->vp_config->config = VP_DuplicateConfig(cfg);
	if (!entry->vp_config->config) return GF_OUT_OF_MEM;
	strncpy(entry->compressor_name, "\012VPC Coding", sizeof(entry->compressor_name)-1);
	entry->dataReferenceIndex = dataRefIndex;
	*outDescriptionIndex = gf_list_count(stsd->child_boxes);
	return e;
}

Project: gpac
File: bitstream.c

void gf_bs_truncate(GF_BitStream *bs)
{
	bs->size = bs->position;
}

Project: gpac
File: avc_ext.c

GF_Err gf_isom_vvc_config_update_ex(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_VVCConfig *cfg, u32 operand_type, Bool keep_xps)
{
	u32 array_incomplete;
	GF_TrackBox *trak;
	GF_Err e;
	GF_MPEGVisualSampleEntryBox *entry;
	GF_SampleDescriptionBox *stsd;

	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;
	stsd = trak->Media->information->sampleTable->SampleDescription;
	entry = (GF_MPEGVisualSampleEntryBox *)gf_list_get(stsd->child_boxes, DescriptionIndex-1);
	if (!entry) return GF_BAD_PARAM;
	switch (entry->type) {
	case GF_ISOM_BOX_TYPE_VVC1:
	case GF_ISOM_BOX_TYPE_VVI1:
		break;
	default:
		return GF_BAD_PARAM;
	}


	if (operand_type <= GF_ISOM_VVCC_SET_INBAND) {
		if ((operand_type != GF_ISOM_VVCC_SET_INBAND) && !entry->vvc_config) {
			entry->vvc_config = (GF_VVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_VVCC);
			if (!entry->vvc_config) return GF_OUT_OF_MEM;
		}

		if (cfg) {
			if (entry->vvc_config->config) gf_odf_vvc_cfg_del(entry->vvc_config->config);
			entry->vvc_config->config = VVC_DuplicateConfig(cfg);
		} else {
			operand_type = GF_ISOM_VVCC_SET_INBAND;
		}
		if (operand_type == GF_ISOM_VVCC_UPDATE) {
			return GF_OK;
		}

		array_incomplete = (operand_type==GF_ISOM_VVCC_SET_INBAND) ? 1 : 0;
		if (entry->vvc_config && nalu_cleanup_config(entry->vvc_config->config ? entry->vvc_config->config->param_array : NULL,
			(operand_type==GF_ISOM_VVCC_SET_INBAND),
			keep_xps)
		) {
			array_incomplete=1;
		}
		switch (entry->type) {
		case GF_ISOM_BOX_TYPE_VVC1:
		case GF_ISOM_BOX_TYPE_VVI1:
			entry->type = array_incomplete ? GF_ISOM_BOX_TYPE_VVI1 : GF_ISOM_BOX_TYPE_VVC1;
			break;
		}
	}
	return GF_OK;
}

Project: gpac
File: avc_ext.c

GF_AVCConfig *gf_isom_avc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
{
	GF_TrackBox *trak;
	GF_MPEGVisualSampleEntryBox *entry;
	trak = gf_isom_get_track_from_file(the_file, trackNumber);
	if (!trak || !trak->Media || !DescriptionIndex) return NULL;
	if (gf_isom_get_avc_svc_type(the_file, trackNumber, DescriptionIndex)==GF_ISOM_AVCTYPE_NONE)
		return NULL;

	entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
	if (!entry) return NULL;
	if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO) return NULL;
	if (!entry->avc_config) return NULL;
	return AVC_DuplicateConfig(entry->avc_config->config);
}

Project: gpac
File: avc_ext.c

GF_HEVCConfig *gf_isom_lhvc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
{
	GF_HEVCConfig *lhvc;
	GF_OperatingPointsInformation *oinf=NULL;
	GF_TrackBox *trak;
	GF_MPEGVisualSampleEntryBox *entry;
	trak = gf_isom_get_track_from_file(the_file, trackNumber);
	if (!trak || !trak->Media || !DescriptionIndex) return NULL;
	if (gf_isom_get_hevc_lhvc_type(the_file, trackNumber, DescriptionIndex)==GF_ISOM_HEVCTYPE_NONE)
		return NULL;
	entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
	if (!entry) return NULL;
	if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO) return NULL;
	if (!entry->lhvc_config) return NULL;
	lhvc = HEVC_DuplicateConfig(entry->lhvc_config->config);
	if (!lhvc) return NULL;

	gf_isom_get_oinf_info(the_file, trackNumber, &oinf);
	if (oinf) {
		LHEVC_ProfileTierLevel *ptl = (LHEVC_ProfileTierLevel *)gf_list_last(oinf->profile_tier_levels);
		if (ptl) {
			lhvc->profile_space  = ptl->general_profile_space;
			lhvc->tier_flag = ptl->general_tier_flag;
			lhvc->profile_idc = ptl->general_profile_idc;
			lhvc->general_profile_compatibility_flags = ptl->general_profile_compatibility_flags;
			lhvc->constraint_indicator_flags = ptl->general_constraint_indicator_flags;
		}
	}
	return lhvc;
}

Project: gpac
File: avc_ext.c

GF_Err gf_isom_oinf_read_entry(void *entry, GF_BitStream *bs)
{
	GF_OperatingPointsInformation* ptr = (GF_OperatingPointsInformation *)entry;
	u32 i, j, count;

	if (!ptr) return GF_BAD_PARAM;
	ptr->scalability_mask = gf_bs_read_u16(bs);
	gf_bs_read_int(bs, 2);//reserved
	count = gf_bs_read_int(bs, 6);
	for (i = 0; i < count; i++) {
		LHEVC_ProfileTierLevel *ptl;
		GF_SAFEALLOC(ptl, LHEVC_ProfileTierLevel);
		if (!ptl) return GF_OUT_OF_MEM;
		ptl->general_profile_space = gf_bs_read_int(bs, 2);
		ptl->general_tier_flag= gf_bs_read_int(bs, 1);
		ptl->general_profile_idc = gf_bs_read_int(bs, 5);
		ptl->general_profile_compatibility_flags = gf_bs_read_u32(bs);
		ptl->general_constraint_indicator_flags = gf_bs_read_long_int(bs, 48);
		ptl->general_level_idc = gf_bs_read_u8(bs);
		gf_list_add(ptr->profile_tier_levels, ptl);
	}
	count = gf_bs_read_u16(bs);
	for (i = 0; i < count; i++) {
		LHEVC_OperatingPoint *op;
		GF_SAFEALLOC(op, LHEVC_OperatingPoint);
		if (!op) return GF_OUT_OF_MEM;
		op->output_layer_set_idx = gf_bs_read_u16(bs);
		op->max_temporal_id = gf_bs_read_u8(bs);
		op->layer_count = gf_bs_read_u8(bs);
		if (op->layer_count > GF_ARRAY_LENGTH(op->layers_info)) {
			gf_free(op);
			return GF_NON_COMPLIANT_BITSTREAM;
		}
		for (j = 0; j < op->layer_count; j++) {
			op->layers_info[j].ptl_idx = gf_bs_read_u8(bs);
			op->layers_info[j].layer_id = gf_bs_read_int(bs, 6);
			op->layers_info[j].is_outputlayer = gf_bs_read_int(bs, 1) ? GF_TRUE : GF_FALSE;
			op->layers_info[j].is_alternate_outputlayer = gf_bs_read_int(bs, 1) ? GF_TRUE : GF_FALSE;

			if (gf_bs_is_overflow(bs)) {
				gf_free(op);
				return GF_NON_COMPLIANT_BITSTREAM;
			}
		}
		op->minPicWidth = gf_bs_read_u16(bs);
		op->minPicHeight = gf_bs_read_u16(bs);
		op->maxPicWidth = gf_bs_read_u16(bs);
		op->maxPicHeight = gf_bs_read_u16(bs);
		op->maxChromaFormat = gf_bs_read_int(bs, 2);
		op->maxBitDepth = gf_bs_read_int(bs, 3) + 8;
		gf_bs_read_int(bs, 1);//reserved
		op->frame_rate_info_flag = gf_bs_read_int(bs, 1) ? GF_TRUE : GF_FALSE;
		op->bit_rate_info_flag = gf_bs_read_int(bs, 1) ? GF_TRUE : GF_FALSE;
		if (op->frame_rate_info_flag) {
			op->avgFrameRate = gf_bs_read_u16(bs);
			gf_bs_read_int(bs, 6); //reserved
			op->constantFrameRate = gf_bs_read_int(bs, 2);
		}
		if (op->bit_rate_info_flag) {
			op->maxBitRate = gf_bs_read_u32(bs);
			op->avgBitRate = gf_bs_read_u32(bs);
		}
		if (gf_bs_is_overflow(bs)) {
			gf_free(op);
			return GF_NON_COMPLIANT_BITSTREAM;
		}
		gf_list_add(ptr->operating_points, op);
	}
	count = gf_bs_read_u8(bs);
	for (i = 0; i < count; i++) {
		LHEVC_DependentLayer *dep;
		GF_SAFEALLOC(dep, LHEVC_DependentLayer);
		if (!dep) return GF_OUT_OF_MEM;
		dep->dependent_layerID = gf_bs_read_u8(bs);
		dep->num_layers_dependent_on = gf_bs_read_u8(bs);
		if (dep->num_layers_dependent_on > GF_ARRAY_LENGTH(dep->dependent_on_layerID)) {
			gf_free(dep);
			return GF_NON_COMPLIANT_BITSTREAM;
		}
		for (j = 0; j < dep->num_layers_dependent_on; j++)
			dep->dependent_on_layerID[j] = gf_bs_read_u8(bs);
		for (j = 0; j < 16; j++) {
			if (ptr->scalability_mask & (1 << j))
				dep->dimension_identifier[j] = gf_bs_read_u8(bs);
		}
		if (gf_bs_is_overflow(bs)) {
			gf_free(dep);
			return GF_NON_COMPLIANT_BITSTREAM;
		}
		gf_list_add(ptr->dependency_layers, dep);
	}

	return GF_OK;
}

Project: gpac
File: bitstream.c

u8 gf_bs_align(GF_BitStream *bs)
{
	u8 res = 8 - bs->nbBits;
	if ( (bs->bsmode == GF_BITSTREAM_READ) || (bs->bsmode == GF_BITSTREAM_FILE_READ)) {
		if (res > 0) {
			gf_bs_read_int(bs, res);
		}
		return res;
	}
	if (bs->nbBits > 0) {
		gf_bs_write_int (bs, 0, res);
		return res;
	}
	return 0;
}

Project: gpac
File: bitstream.c

u32 gf_bs_is_overflow(GF_BitStream *bs)
{
	return bs->overflow_state;
}

Project: gpac
File: bitstream.c

void gf_bs_set_eos_callback(GF_BitStream *bs, void (*EndOfStream)(void *par), void *par)
{
	bs->EndOfStream = EndOfStream;
	bs->par = par;
}

Project: gpac
File: bitstream.c

void gf_bs_prevent_dispatch(GF_BitStream *bs, Bool prevent_dispatch)
{
	if (!bs) return;
	if (prevent_dispatch) {
		bs->prevent_dispatch ++;
		return;
	}
	if (!bs->prevent_dispatch) return;
	bs->prevent_dispatch --;

	if (bs->on_block_out && !bs->prevent_dispatch) {
		assert(bs->position >= bs->bytes_out);
		if (bs->position > bs->bytes_out) {
			bs->on_block_out(bs->usr_data, bs->original, (u32) (bs->position - bs->bytes_out));
			bs->bytes_out = bs->position;
		}
	}
}

Project: gpac
File: bitstream.c

void gf_bs_write_double (GF_BitStream *bs, Double value)
{
	u32 i;
	union
	{	Double d;
		char sz [8];
	} double_value;
	double_value.d = value;
	for (i = 0; i < 64; i++) {
		BS_WriteBit(bs, (double_value.sz [7 - i / 8] & 1 << (7 - i % 8)) != 0);
	}
}

Project: gpac
File: avc_ext.c

GF_HEVCConfig *gf_isom_hevc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
{
	GF_TrackBox *trak;
	GF_MPEGVisualSampleEntryBox *entry;
	if (gf_isom_get_reference_count(the_file, trackNumber, GF_ISOM_REF_TBAS)) {
		u32 ref_track;
		GF_Err e = gf_isom_get_reference(the_file, trackNumber, GF_ISOM_REF_TBAS, 1, &ref_track);
		if (e == GF_OK) {
			trackNumber = ref_track;
		}
	}
	trak = gf_isom_get_track_from_file(the_file, trackNumber);
	if (!trak || !trak->Media || !DescriptionIndex) return NULL;
	if (gf_isom_get_hevc_lhvc_type(the_file, trackNumber, DescriptionIndex)==GF_ISOM_HEVCTYPE_NONE)
		return NULL;
	entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
	if (!entry) return NULL;
	if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO) return NULL;
	if (!entry->hevc_config) return NULL;
	return HEVC_DuplicateConfig(entry->hevc_config->config);
}

Project: gpac
File: avc_ext.c

GF_Box *vvnc_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_VVCNaluConfigurationBox, GF_ISOM_BOX_TYPE_VVNC);
	return (GF_Box *)tmp;
}

Project: gpac
File: bitstream.c

u64 gf_bs_read_long_int(GF_BitStream *bs, u32 nBits)
{
	u64 ret = 0;
	if (nBits>64) {
		u32 skip = nBits-64;
		if (gf_bs_available(bs) * 8 < nBits-8) {
			if (bs->EndOfStream) bs->EndOfStream(bs->par);
			bs->position = bs->size;
			if (!bs->overflow_state) bs->overflow_state = 1;
			return 0;
		}
		GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("Reading %d bits but max should be 64, skipping %d most significants bits\n", nBits, nBits-64));
		//avoid recursion
		while (skip) {
			if (skip>32) {
				gf_bs_read_int(bs, 32);
				skip-=32;
			} else {
				gf_bs_read_int(bs, skip);
				skip=0;
			}
		}
		ret = gf_bs_read_long_int(bs, 64);
	} else {
		while (nBits-- > 0) {
			ret <<= 1;
			ret |= gf_bs_read_bit(bs);
		}
	}
	return ret;
}

Project: gpac
File: bitstream.c

static void BS_WriteByte(GF_BitStream *bs, u8 val)
{
	/*we don't allow write on READ buffers*/
	if ( (bs->bsmode == GF_BITSTREAM_READ) || (bs->bsmode == GF_BITSTREAM_FILE_READ) ) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to write on read bitstream\n"));
		return;
	}
	if (!bs->original && !bs->stream) {
		GF_LOG(GF_LOG_ERROR, GF_LOG_CORE, ("[BS] Attempt to write on unassigned bitstream\n"));
		return;
	}
	/*we are in MEM mode*/
	if ( (bs->bsmode == GF_BITSTREAM_WRITE) || (bs->bsmode == GF_BITSTREAM_WRITE_DYN) ) {
		//if callback mode and dispatch is not blocked, dispatch
		if (bs->on_block_out && !bs->prevent_dispatch) {
			assert(bs->position >= bs->bytes_out);
			if (bs->position - bs->bytes_out == bs->size) {
				bs->on_block_out(bs->usr_data, bs->original, (u32) (bs->position - bs->bytes_out));
				bs->bytes_out = bs->position;
			}
			if (bs->original)
				bs->original[bs->position - bs->bytes_out] = val;
			bs->position++;
			assert(bs->position >= bs->bytes_out);
			return;
		}
		//otherwise store
		if (bs->position - bs->bytes_out == bs->size) {
			/*no more space...*/
			if (bs->bsmode != GF_BITSTREAM_WRITE_DYN) return;
			/*gf_realloc if enough space...*/
			if (bs->size > 0xFFFFFFFF) return;
			bs->size = bs->size ? (bs->size * 2) : BS_MEM_BLOCK_ALLOC_SIZE;
			bs->original = (char*)gf_realloc(bs->original, (u32)bs->size);
			if (!bs->original) return;
		}
		if (bs->original)
			bs->original[bs->position - bs->bytes_out] = val;
		bs->position++;
		return;
	}
	if (bs->cache_write) {
		if (bs->buffer_written == bs->cache_write_size) {
			bs_flush_write_cache(bs);
		}
		bs->cache_write[bs->buffer_written] = val;
		bs->buffer_written++;
		if (bs->buffer_written == bs->cache_write_size) {
			bs_flush_write_cache(bs);
		}
		return;
	}
	/*we are in FILE mode, no pb for any gf_realloc...*/
	gf_fputc(val, bs->stream);

	/*check we didn't rewind the stream*/
	if (bs->size == bs->position) bs->size++;
	bs->position += 1;
}

Project: gpac
File: bitstream.c

u64 gf_bs_available(GF_BitStream *bs)
{
	s64 cur, end;

	/*in WRITE mode only, this should not be called, but return something big in case ...*/
	if ( (bs->bsmode == GF_BITSTREAM_WRITE)
	        || (bs->bsmode == GF_BITSTREAM_WRITE_DYN)
	   )
		return (u64) -1;

	/*we are in MEM mode*/
	if (bs->bsmode == GF_BITSTREAM_READ) {
		if (bs->size < bs->position)
			return 0;
		else
			return (bs->size - bs->position);
	}
	/*FILE READ: assume size hasn't changed, otherwise the user shall call gf_bs_get_refreshed_size*/
	if (bs->bsmode==GF_BITSTREAM_FILE_READ) {
		if (bs->position>bs->size) return 0;
		return (bs->size - bs->position);
	}
	if (bs->cache_write)
		bs_flush_write_cache(bs);

	cur = gf_ftell(bs->stream);
	end = gf_fsize(bs->stream);
	gf_fseek(bs->stream, cur, SEEK_SET);

	return (u64) (end - cur);
}

Project: gpac
File: bitstream.c

u32 gf_bs_get_bit_offset(GF_BitStream *bs)
{
	if (bs->bsmode==GF_BITSTREAM_READ) return (u32) ( (bs->position - 1) * 8 + bs->nbBits);
	return (u32) ( (bs->position ) * 8 + bs->nbBits);
}

Project: gpac
File: bitstream.c

GF_BitStream *gf_bs_new_cbk(GF_Err (*on_block_out)(void *cbk, u8 *data, u32 block_size), void *usr_data, u32 block_size)
{
	return gf_bs_new_cbk_buffer(on_block_out, usr_data, NULL, block_size);

}

Project: gpac
File: bitstream.c

u32 gf_bs_read_vluimsbf5(GF_BitStream *bs)
{
	u32 nb_words = 0;
	while (gf_bs_read_int(bs, 1)) nb_words++;
	nb_words++;
	return gf_bs_read_int(bs, 4*nb_words);
}

Project: gpac
File: bitstream.c

void gf_bs_reassign(GF_BitStream *bs, FILE *stream)
{
	if (!bs) return;
	switch (bs->bsmode) {
	case GF_BITSTREAM_FILE_WRITE:
	case GF_BITSTREAM_FILE_READ:
		bs->stream = stream;
		if (gf_ftell(stream) != bs->position)
			gf_bs_seek(bs, bs->position);
		break;
	}
}

Project: gpac
File: bitstream.c

u32 gf_bs_read_int(GF_BitStream *bs, u32 nBits)
{
	u32 ret;
	bs->total_bits_read+= nBits;

#ifndef NO_OPTS
	if (nBits + bs->nbBits <= 8) {
		bs->nbBits += nBits;
		ret = (bs->current >> (8 - bs->nbBits) ) & bits_mask[nBits];
		return ret;
	}
#endif
	ret = 0;
	while (nBits-- > 0) {
		ret <<= 1;
		ret |= gf_bs_read_bit(bs);
	}
	return ret;
}

Project: gpac
File: avc_ext.c

GF_Err vvnc_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_VVCNaluConfigurationBox *ptr = (GF_VVCNaluConfigurationBox *) s;
	if (!s) return GF_BAD_PARAM;

	e = gf_isom_full_box_write(s, bs);
	if (e) return e;
	gf_bs_write_int(bs, 0, 6);
	gf_bs_write_int(bs, ptr->nal_unit_size-1, 2);
	return GF_OK;
}

Project: gpac
File: avc_ext.c

GF_Err vvcc_box_write(GF_Box *s, GF_BitStream *bs)
{
	GF_Err e;
	GF_VVCConfigurationBox *ptr = (GF_VVCConfigurationBox *) s;
	if (!s) return GF_BAD_PARAM;
	if (!ptr->config) return GF_OK;

	e = gf_isom_full_box_write(s, bs);
	if (e) return e;

	return gf_odf_vvc_cfg_write_bs(ptr->config, bs);
}

Project: gpac
File: bitstream.c

GF_Err gf_bs_transfer(GF_BitStream *dst, GF_BitStream *src, Bool keep_src)
{
	u8 *data;
	u32 data_len, written;

	data = NULL;
	data_len = 0;
	gf_bs_get_content(src, &data, &data_len);
	if (!data || !data_len)
	{
		if (data) {
			if (keep_src) {
				src->original = data;
				src->size = data_len;
			} else {
				gf_free(data);
			}
			return GF_IO_ERR;
		}
		return GF_OK;
	}
	written = gf_bs_write_data(dst, data, data_len);
	if (keep_src) {
		src->original = data;
		src->size = data_len;
	} else {
		gf_free(data);
	}
	if (written<data_len) return GF_IO_ERR;
	return GF_OK;
}

Project: gpac
File: bitstream.c

void gf_bs_skip_bytes(GF_BitStream *bs, u64 nbBytes)
{
	if (!bs || !nbBytes) return;

	gf_bs_align(bs);

	/*special case for file skipping...*/
	if ((bs->bsmode == GF_BITSTREAM_FILE_WRITE) || (bs->bsmode == GF_BITSTREAM_FILE_READ)) {
		if (bs->cache_write)
			bs_flush_write_cache(bs);

		if (bs->cache_read) {
			u32 csize = bs->cache_read_size - bs->cache_read_pos;
			if (csize>=nbBytes) {
				bs->cache_read_pos += (u32) nbBytes;
				bs->position += nbBytes;
				return;
			}
			nbBytes -= csize;
			bs->position += csize;
			bs->cache_read_pos = bs->cache_read_size;
		}
		//weird msys2 bug resulting in broken seek on some files ?!?  -the bug is not happening when doing absolute seek
//		gf_fseek(bs->stream, nbBytes, SEEK_CUR);
		bs->position += nbBytes;
		if (bs->bsmode == GF_BITSTREAM_FILE_READ) {
			if (bs->position > bs->size) bs->position = bs->size;
		}
		gf_fseek(bs->stream, bs->position, SEEK_SET);
		return;
	}

	/*special case for reading*/
	if (bs->bsmode == GF_BITSTREAM_READ) {
		if (bs->remove_emul_prevention_byte) {
			while (nbBytes) {
				gf_bs_read_u8(bs);
				nbBytes--;
			}
		} else {
			bs->position += nbBytes;
		}
		return;
	}
	/*for writing we must do it this way, otherwise pb in dynamic buffers*/
	while (nbBytes) {
		gf_bs_write_int(bs, 0, 8);
		nbBytes--;
	}
}

Project: gpac
File: bitstream.c

Float gf_bs_read_float(GF_BitStream *bs)
{
	char buf [4] = "\0\0\0";
#ifdef NO_OPTS
	s32 i;
	for (i = 0; i < 32; i++)
		buf[3-i/8] |= gf_bs_read_bit(bs) << (7 - i%8);
#else
	buf[3] = gf_bs_read_int(bs, 8);
	buf[2] = gf_bs_read_int(bs, 8);
	buf[1] = gf_bs_read_int(bs, 8);
	buf[0] = gf_bs_read_int(bs, 8);
#endif
	return (* (Float *) buf);
}

Project: gpac
File: bitstream.c

void gf_bs_write_long_int(GF_BitStream *bs, s64 _value, s32 nBits)
{
	s32 max_shift = sizeof(s64) * 8;
	if (!nBits) return;
	nBits = bs_handle_nbits_overflow(bs, nBits, max_shift);

	//cf note in gf_bs_write_int
	u64 value = (u64) _value;
	value <<= max_shift - nBits;
	while (--nBits >= 0) {
		BS_WriteBit (bs, ((s64)value) < 0);
		value <<= 1;
	}
}

Project: gpac
File: bitstream.c

void gf_bs_mark_overflow(GF_BitStream *bs, Bool reset)
{
	bs->overflow_state = reset ? 0 : 2;
}

Project: gpac
File: avc_ext.c

GF_Err gf_isom_vvc_config_update(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_VVCConfig *cfg)
{
	return gf_isom_vvc_config_update_ex(the_file, trackNumber, DescriptionIndex, cfg, GF_ISOM_VVCC_UPDATE, GF_FALSE);
}

Project: gpac
File: bitstream.c

GF_Err gf_bs_set_logger(GF_BitStream *bs, void (*on_bs_log)(void *udta, const char *field_name, u32 nb_bits, u64 field_val, s32 idx1, s32 idx2, s32 idx3), void *udta)
{
	if (!bs) return GF_BAD_PARAM;
	bs->on_log = on_bs_log;
	bs->log_udta = udta;
	return GF_OK;
}

Project: gpac
File: bitstream.c

void gf_bs_write_float(GF_BitStream *bs, Float value)
{
	u32 i;
	union
	{	float f;
		char sz [4];
	} float_value;
	float_value.f = value;

	for (i = 0; i < 32; i++)
		BS_WriteBit(bs, (float_value.sz [3 - i / 8] & 1 << (7 - i % 8)) != 0);

}

Project: gpac
File: avc_ext.c

GF_ISOMHEVCType gf_isom_get_hevc_lhvc_type(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
{
	u32 type;
	GF_TrackBox *trak;
	GF_MPEGVisualSampleEntryBox *entry;
	trak = gf_isom_get_track_from_file(the_file, trackNumber);
	if (!trak || !trak->Media || !DescriptionIndex) return GF_ISOM_HEVCTYPE_NONE;
	if (!gf_isom_is_video_handler_type(trak->Media->handler->handlerType))
		return GF_ISOM_HEVCTYPE_NONE;
	entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
	if (!entry) return GF_ISOM_HEVCTYPE_NONE;
	if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO) return GF_ISOM_HEVCTYPE_NONE;
	type = entry->type;

	if (type == GF_ISOM_BOX_TYPE_ENCV) {
		GF_ProtectionSchemeInfoBox *sinf = (GF_ProtectionSchemeInfoBox *) gf_isom_box_find_child(entry->child_boxes, GF_ISOM_BOX_TYPE_SINF);
		if (sinf && sinf->original_format) type = sinf->original_format->data_format;
	}
	else if (type == GF_ISOM_BOX_TYPE_RESV) {
		if (entry->rinf && entry->rinf->original_format) type = entry->rinf->original_format->data_format;
	}

	switch (type) {
	case GF_ISOM_BOX_TYPE_HVC1:
	case GF_ISOM_BOX_TYPE_HEV1:
	case GF_ISOM_BOX_TYPE_HVC2:
	case GF_ISOM_BOX_TYPE_HEV2:
	case GF_ISOM_BOX_TYPE_LHV1:
	case GF_ISOM_BOX_TYPE_LHE1:
	case GF_ISOM_BOX_TYPE_HVT1:
	case GF_ISOM_BOX_TYPE_DVHE:
	case GF_ISOM_BOX_TYPE_DVH1:
		break;
	default:
		return GF_ISOM_HEVCTYPE_NONE;
	}
	if (entry->hevc_config && !entry->lhvc_config) return GF_ISOM_HEVCTYPE_HEVC_ONLY;
	if (entry->hevc_config && entry->lhvc_config) return GF_ISOM_HEVCTYPE_HEVC_LHVC;
	if (!entry->hevc_config && entry->lhvc_config) return GF_ISOM_HEVCTYPE_LHVC_ONLY;
	return GF_ISOM_HEVCTYPE_NONE;
}

Project: gpac
File: avc_ext.c

void gf_hevc_parse_ps(GF_HEVCConfig* hevccfg, HEVCState* hevc, u32 nal_type)
{
	u32 i, j;
	if (!hevccfg) return;

	for (i = 0; i < gf_list_count(hevccfg->param_array); i++) {
		GF_NALUFFParamArray* ar = gf_list_get(hevccfg->param_array, i);
		if (ar->type != nal_type) continue;
		for (j = 0; j < gf_list_count(ar->nalus); j++) {
			u8 ntype, tid, lid;
			GF_NALUFFParam* sl = gf_list_get(ar->nalus, j);
			gf_hevc_parse_nalu(sl->data, sl->size, hevc, &ntype, &tid, &lid);
		}
	}
}

Project: gpac
File: avc_ext.c

GF_Err gf_isom_hevc_config_update_ex(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex, GF_HEVCConfig *cfg, u32 operand_type, Bool keep_xps)
{
	u32 array_incomplete;
	GF_TrackBox *trak;
	GF_Err e;
	GF_MPEGVisualSampleEntryBox *entry;
	GF_SampleDescriptionBox *stsd;

	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;
	stsd = trak->Media->information->sampleTable->SampleDescription;
	entry = (GF_MPEGVisualSampleEntryBox *)gf_list_get(stsd->child_boxes, DescriptionIndex-1);
	if (!entry) return GF_BAD_PARAM;
	switch (entry->type) {
	case GF_ISOM_BOX_TYPE_HVC1:
	case GF_ISOM_BOX_TYPE_HEV1:
	case GF_ISOM_BOX_TYPE_HVC2:
	case GF_ISOM_BOX_TYPE_HEV2:
	case GF_ISOM_BOX_TYPE_LHV1:
	case GF_ISOM_BOX_TYPE_LHE1:
	case GF_ISOM_BOX_TYPE_HVT1:
		break;
	default:
		return GF_BAD_PARAM;
	}


	if (operand_type == GF_ISOM_HVCC_SET_TILE_BASE_TRACK) {
		if (entry->type==GF_ISOM_BOX_TYPE_HVC1)
			entry->type = GF_ISOM_BOX_TYPE_HVC2;
		else if (entry->type==GF_ISOM_BOX_TYPE_HEV1)
			entry->type = GF_ISOM_BOX_TYPE_HEV2;
	} else if (operand_type == GF_ISOM_HVCC_SET_TILE) {
		if (!entry->hevc_config) entry->hevc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_HVCC);
		if (!entry->hevc_config) return GF_OUT_OF_MEM;
		if (entry->hevc_config->config) gf_odf_hevc_cfg_del(entry->hevc_config->config);
		entry->hevc_config->config = NULL;
		entry->type = GF_ISOM_BOX_TYPE_HVT1;
	} else if (operand_type < GF_ISOM_HVCC_SET_LHVC) {
		if ((operand_type != GF_ISOM_HVCC_SET_INBAND) && !entry->hevc_config) {
			entry->hevc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_HVCC);
			if (!entry->hevc_config) return GF_OUT_OF_MEM;
		}

		if (cfg) {
			if (entry->hevc_config->config) gf_odf_hevc_cfg_del(entry->hevc_config->config);
			entry->hevc_config->config = HEVC_DuplicateConfig(cfg);
		} else {
			operand_type=GF_ISOM_HVCC_SET_INBAND;
		}
		array_incomplete = (operand_type==GF_ISOM_HVCC_SET_INBAND) ? 1 : 0;
		if (entry->hevc_config && nalu_cleanup_config(entry->hevc_config->config ? entry->hevc_config->config->param_array : NULL,
			(operand_type==GF_ISOM_HVCC_SET_INBAND) ? GF_TRUE:GF_FALSE,
			keep_xps)
		) {
			array_incomplete=1;
		}

		if (entry->lhvc_config && nalu_cleanup_config(entry->lhvc_config->config ? entry->lhvc_config->config->param_array : NULL,
			(operand_type==GF_ISOM_HVCC_SET_INBAND),
			keep_xps)
		)
			array_incomplete=1;

		switch (entry->type) {
		case GF_ISOM_BOX_TYPE_HEV1:
		case GF_ISOM_BOX_TYPE_HVC1:
			entry->type = array_incomplete ? GF_ISOM_BOX_TYPE_HEV1 : GF_ISOM_BOX_TYPE_HVC1;
			break;
		case GF_ISOM_BOX_TYPE_HEV2:
		case GF_ISOM_BOX_TYPE_HVC2:
			entry->type = array_incomplete ? GF_ISOM_BOX_TYPE_HEV2 : GF_ISOM_BOX_TYPE_HVC2;
			break;
		case GF_ISOM_BOX_TYPE_LHE1:
		case GF_ISOM_BOX_TYPE_LHV1:
			entry->type = array_incomplete ? GF_ISOM_BOX_TYPE_LHE1 : GF_ISOM_BOX_TYPE_LHV1;
			break;
		}
	} else {

		/*SVCC replacement/removal with HEVC base, backward compatible signaling*/
		if ((operand_type==GF_ISOM_HVCC_SET_LHVC_WITH_BASE_BACKWARD) || (operand_type==GF_ISOM_HVCC_SET_LHVC_WITH_BASE) || (operand_type==GF_ISOM_HVCC_SET_HEVC_TILE_BASE) ) {
			if (!entry->hevc_config) return GF_BAD_PARAM;
			if (!cfg) {
				if (entry->lhvc_config) {
					gf_isom_box_del_parent(&entry->child_boxes, (GF_Box*)entry->lhvc_config);
					entry->lhvc_config = NULL;
				}
				if (entry->type==GF_ISOM_BOX_TYPE_LHE1) entry->type = (operand_type==GF_ISOM_HVCC_SET_LHVC_WITH_BASE) ? GF_ISOM_BOX_TYPE_HEV2 : GF_ISOM_BOX_TYPE_HEV1;
				else if (entry->type==GF_ISOM_BOX_TYPE_HEV1) entry->type = (operand_type==GF_ISOM_HVCC_SET_LHVC_WITH_BASE) ? GF_ISOM_BOX_TYPE_HEV2 : GF_ISOM_BOX_TYPE_HEV1;
				else entry->type =  (operand_type==GF_ISOM_HVCC_SET_LHVC_WITH_BASE) ? GF_ISOM_BOX_TYPE_HVC2 : GF_ISOM_BOX_TYPE_HVC1;
			} else {
				if (operand_type != GF_ISOM_HVCC_SET_HEVC_TILE_BASE) {
					if (!entry->lhvc_config) {
						entry->lhvc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_LHVC);
						if (!entry->lhvc_config) return GF_OUT_OF_MEM;
					}
					if (entry->lhvc_config->config) gf_odf_hevc_cfg_del(entry->lhvc_config->config);
					entry->lhvc_config->config = HEVC_DuplicateConfig(cfg);
					if (!entry->lhvc_config->config) return GF_OUT_OF_MEM;
				}

				if (operand_type==GF_ISOM_HVCC_SET_LHVC_WITH_BASE_BACKWARD) {
					if (entry->type==GF_ISOM_BOX_TYPE_HEV2) entry->type = GF_ISOM_BOX_TYPE_HEV1;
					else entry->type = GF_ISOM_BOX_TYPE_HVC1;
				} else {
					if (entry->type==GF_ISOM_BOX_TYPE_HEV1) entry->type = GF_ISOM_BOX_TYPE_HEV2;
					else entry->type = GF_ISOM_BOX_TYPE_HVC2;
				}
			}
		}
		/*LHEVC track without base*/
		else if (operand_type==GF_ISOM_HVCC_SET_LHVC) {
			if (entry->hevc_config) {
				gf_isom_box_del_parent(&entry->child_boxes, (GF_Box*)entry->hevc_config);
				entry->hevc_config=NULL;
			}
			if (!cfg) return GF_BAD_PARAM;

			if (!entry->lhvc_config) {
				entry->lhvc_config = (GF_HEVCConfigurationBox*)gf_isom_box_new_parent(&entry->child_boxes, GF_ISOM_BOX_TYPE_LHVC);
				if (!entry->lhvc_config) return GF_OUT_OF_MEM;
			}
			if (entry->lhvc_config->config) gf_odf_hevc_cfg_del(entry->lhvc_config->config);
			entry->lhvc_config->config = HEVC_DuplicateConfig(cfg);
			if (!entry->lhvc_config->config) return GF_OUT_OF_MEM;

			if ((entry->type==GF_ISOM_BOX_TYPE_HEV1) || (entry->type==GF_ISOM_BOX_TYPE_HEV2)) entry->type = GF_ISOM_BOX_TYPE_LHE1;
			else entry->type = GF_ISOM_BOX_TYPE_LHV1;
		}
		/*LHEVC inband, no config change*/
		else if (operand_type==GF_ISOM_LHCC_SET_INBAND) {
			entry->type = GF_ISOM_BOX_TYPE_LHE1;
		}
	}

	HEVC_RewriteESDescriptor(entry);
	return GF_OK;
}

Project: gpac
File: avc_ext.c

GF_AVCConfig *gf_isom_mvc_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
{
	GF_TrackBox *trak;
	GF_MPEGVisualSampleEntryBox *entry;
	trak = gf_isom_get_track_from_file(the_file, trackNumber);
	if (!trak || !trak->Media || !DescriptionIndex) return NULL;
	if (gf_isom_get_avc_svc_type(the_file, trackNumber, DescriptionIndex)==GF_ISOM_AVCTYPE_NONE)
		return NULL;
	entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
	if (!entry) return NULL;
	if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO) return NULL;
	if (!entry->mvc_config) return NULL;
	return AVC_DuplicateConfig(entry->mvc_config->config);
}

Project: gpac
File: bitstream.c

GF_Err gf_bs_insert_data(GF_BitStream *bs, u8 *data, u32 size, u64 offset)
{
	u64 cur_r, cur_w, pos;
	u32 nb_io;

	if (bs->on_block_out) return GF_BAD_PARAM;

	pos = bs->position;
	nb_io = gf_bs_write_data(bs, data, size);
	if (nb_io != size) goto exit;

	cur_w = bs->position;
	gf_bs_seek(bs, pos);
	cur_r = pos;
	pos = cur_w;
	while (cur_r > offset) {
		u8 block[8196];
		u32 move_bytes = 8196;
		if (cur_r - offset < move_bytes)
			move_bytes = (u32) (cur_r - offset);

		gf_bs_seek(bs, cur_r - move_bytes);
		nb_io = gf_bs_read_data(bs, block, move_bytes);
		if (nb_io != move_bytes) goto exit;
		gf_bs_seek(bs, cur_w - move_bytes);
		nb_io = gf_bs_write_data(bs, block, move_bytes);
		if (nb_io != move_bytes) goto exit;
		cur_r -= move_bytes;
		cur_w -= move_bytes;
	}

	gf_bs_seek(bs, offset);
	nb_io = gf_bs_write_data(bs, data, size);
	if (nb_io != size) goto exit;

	gf_bs_seek(bs, pos);
	return GF_OK;

exit:
	gf_bs_seek(bs, pos);
	return GF_IO_ERR;
}

Project: gpac
File: avc_ext.c

GF_Err avcc_box_read(GF_Box *s, GF_BitStream *bs)
{
	u32 i, count;
	GF_AVCConfigurationBox *ptr = (GF_AVCConfigurationBox *)s;

	if (ptr->config) gf_odf_avc_cfg_del(ptr->config);
	ptr->config = gf_odf_avc_cfg_new();

	ISOM_DECREASE_SIZE(ptr, 7) //7 includes the 2 counts of sps and pps

	Bool is_avcc;
	if ((ptr->type==GF_ISOM_BOX_TYPE_AVCC) || (ptr->type==GF_ISOM_BOX_TYPE_AVCE))
		is_avcc = GF_TRUE;
	else
		is_avcc = GF_FALSE;

	//we don't use gf_odf_avc_cfg_read to deal with missing rext profile signaling on many files
	ptr->config->configurationVersion = gf_bs_read_u8(bs);
	ptr->config->AVCProfileIndication = gf_bs_read_u8(bs);
	ptr->config->profile_compatibility = gf_bs_read_u8(bs);
	ptr->config->AVCLevelIndication = gf_bs_read_u8(bs);
	if (is_avcc) {
		gf_bs_read_int(bs, 6);
	} else {
		ptr->config->complete_representation = gf_bs_read_int(bs, 1);
		gf_bs_read_int(bs, 5);
	}
	ptr->config->nal_unit_size = 1 + gf_bs_read_int(bs, 2);
	gf_bs_read_int(bs, 3);
	count = gf_bs_read_int(bs, 5);

	for (i=0; i<count; i++) {
		ISOM_DECREASE_SIZE(ptr, 2)
		GF_NALUFFParam *sl = (GF_NALUFFParam *) gf_malloc(sizeof(GF_NALUFFParam));
		sl->size = gf_bs_read_u16(bs);
		if (!sl->size || (gf_bs_available(bs) < sl->size) || (ptr->size < sl->size) ) {
			gf_free(sl);
			GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("AVCC: Not enough bits to parse. Aborting.\n"));
			return GF_ISOM_INVALID_FILE;
		}
		sl->data = (char *)gf_malloc(sizeof(char) * sl->size);
		gf_bs_read_data(bs, sl->data, sl->size);
		gf_list_add(ptr->config->sequenceParameterSets, sl);
		ptr->size -= sl->size;
	}

	count = gf_bs_read_u8(bs);
	for (i=0; i<count; i++) {
		ISOM_DECREASE_SIZE(ptr, 2)
		GF_NALUFFParam *sl = (GF_NALUFFParam *)gf_malloc(sizeof(GF_NALUFFParam));
		sl->size = gf_bs_read_u16(bs);
		if (!sl->size || (gf_bs_available(bs) < sl->size) || (ptr->size<sl->size)) {
			gf_free(sl);
			GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("AVCC: Not enough bits to parse. Aborting.\n"));
			return GF_ISOM_INVALID_FILE;
		}
		sl->data = (char *)gf_malloc(sizeof(char) * sl->size);
		gf_bs_read_data(bs, sl->data, sl->size);
		gf_list_add(ptr->config->pictureParameterSets, sl);
		ptr->size -= sl->size;
	}

	//not avcC (svcC; mvcC), no check for rext signaling
	if (!is_avcc)
		return GF_OK;

	//not REXT profile, no check for rext signaling
	if (!gf_avcc_use_extensions(ptr->config->AVCProfileIndication))
		return GF_OK;

	//non-compliant file (rext signaling missing), try to fill in values from SPS
	if (!ptr->size) {
		/*set default values ...*/
		ptr->config->chroma_format = 1;
		ptr->config->luma_bit_depth = 8;
		ptr->config->chroma_bit_depth = 8;

#ifndef GPAC_DISABLE_AV_PARSERS
		GF_NALUFFParam *sl = (GF_NALUFFParam*)gf_list_get(ptr->config->sequenceParameterSets, 0);
		if (sl) {
			AVCState avc;
			s32 idx;
			memset(&avc, 0, sizeof(AVCState));
			idx = gf_avc_read_sps(sl->data, sl->size, &avc, 0, NULL);
			if (idx>=0) {
				ptr->config->chroma_format = avc.sps[idx].chroma_format;
				ptr->config->luma_bit_depth = 8 + avc.sps[idx].luma_bit_depth_m8;
				ptr->config->chroma_bit_depth = 8 + avc.sps[idx].chroma_bit_depth_m8;
			}
		}
#endif
		GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("[isom/avcc] Missing REXT profile signaling, patching.\n"));
		return GF_OK;
	}
	ISOM_DECREASE_SIZE(ptr, 4)
	gf_bs_read_int(bs, 6);
	ptr->config->chroma_format = gf_bs_read_int(bs, 2);
	gf_bs_read_int(bs, 5);
	ptr->config->luma_bit_depth = 8 + gf_bs_read_int(bs, 3);
	gf_bs_read_int(bs, 5);
	ptr->config->chroma_bit_depth = 8 + gf_bs_read_int(bs, 3);

	count = gf_bs_read_int(bs, 8);
	if (count*2 > ptr->size) {
		//ffmpeg just ignores this part while allocating bytes (filled with garbage?)
		GF_LOG(GF_LOG_WARNING, GF_LOG_CODING, ("AVCC: invalid numOfSequenceParameterSetExt value. Skipping.\n"));
		return GF_OK;
	}
	if (count) {
		ptr->config->sequenceParameterSetExtensions = gf_list_new();
		for (i=0; i<count; i++) {
			ISOM_DECREASE_SIZE(ptr, 2)
			GF_NALUFFParam *sl = (GF_NALUFFParam *)gf_malloc(sizeof(GF_NALUFFParam));
			sl->size = gf_bs_read_u16(bs);
			if ((gf_bs_available(bs) < sl->size) || (ptr->size<sl->size)) {
				gf_free(sl);
				GF_LOG(GF_LOG_ERROR, GF_LOG_CODING, ("AVCC: Not enough bits to parse. Aborting.\n"));
				return GF_ISOM_INVALID_FILE;
			}
			sl->data = (char *)gf_malloc(sizeof(char) * sl->size);
			gf_bs_read_data(bs, sl->data, sl->size);
			gf_list_add(ptr->config->sequenceParameterSetExtensions, sl);
			ptr->size -= sl->size;
		}
	}
	return GF_OK;
}

Project: gpac
File: bitstream.c

u64 gf_bs_get_cookie(GF_BitStream *bs)
{
	if (!bs) return 0;
	return bs->cookie;
}

Project: gpac
File: avc_ext.c

GF_Box *vvcc_box_new()
{
	ISOM_DECL_BOX_ALLOC(GF_VVCConfigurationBox, GF_ISOM_BOX_TYPE_VVCC);
	return (GF_Box *)tmp;
}

Project: gpac
File: bitstream.c

Bool gf_bs_is_align(GF_BitStream *bs)
{
	switch (bs->bsmode) {
	case GF_BITSTREAM_READ:
	case GF_BITSTREAM_FILE_READ:
		return ( (8 == bs->nbBits) ? GF_TRUE : GF_FALSE);
	default:
		return !bs->nbBits;
	}
}

Project: gpac
File: bitstream.c

void gf_bs_get_content_no_truncate(GF_BitStream *bs, u8 **output, u32 *outSize, u32 *alloc_size)
{
	/*only in WRITE MEM mode*/
	if (!bs || bs->bsmode != GF_BITSTREAM_WRITE_DYN) return;

	if (bs->on_block_out && bs->position>bs->bytes_out) {
		bs->on_block_out(bs->usr_data, bs->original, (u32) (bs->position - bs->bytes_out) );
	}

	if (!bs->position && !bs->nbBits) {
		if (!alloc_size) {
			*output = NULL;
			gf_free(bs->original);
		} else {
			*alloc_size = (u32) bs->size;
			*output = bs->original;
		}
		*outSize = 0;
	} else {
		if (alloc_size) {
			/*Align our buffer or we're dead!*/
			gf_bs_align(bs);
			*alloc_size = (u32) bs->size;
			*outSize = (u32) bs->position;
			*output = bs->original;
		} else {
			s32 copy = BS_CutBuffer(bs);
			if (copy < 0) {
				*output = NULL;
			} else
				*output = bs->original;
			*outSize = (u32) bs->size;
		}
	}
	bs->original = NULL;
	bs->size = 0;
	bs->position = 0;
}

Project: gpac
File: bitstream.c

void gf_bs_get_content(GF_BitStream *bs, u8 **output, u32 *outSize)
{
	gf_bs_get_content_no_truncate(bs, output, outSize, NULL);
}

Project: gpac
File: avc_ext.c

GF_VPConfig *gf_isom_vp_config_get(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
{
	GF_TrackBox *trak;
	GF_MPEGVisualSampleEntryBox *entry;
	trak = gf_isom_get_track_from_file(the_file, trackNumber);
	if (!trak || !trak->Media || !DescriptionIndex) return NULL;
	entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex - 1);
	if (!entry) return NULL;
	if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO) return NULL;
	if (!entry->vp_config || !entry->vp_config->config) return NULL;
	return VP_DuplicateConfig(entry->vp_config->config);
}

Project: gpac
File: bitstream.c

u64 gf_bs_read_u64(GF_BitStream *bs)
{
	u64 ret;

	if (bs->cache_read && (bs->cache_read_pos+8<bs->cache_read_size) ) {
		ret = bs->cache_read[bs->cache_read_pos];
		ret<<=8;
		ret |= bs->cache_read[bs->cache_read_pos+1];
		ret<<=8;
		ret |= bs->cache_read[bs->cache_read_pos+2];
		ret<<=8;
		ret |= bs->cache_read[bs->cache_read_pos+3];
		ret<<=8;
		ret |= bs->cache_read[bs->cache_read_pos+4];
		ret<<=8;
		ret |= bs->cache_read[bs->cache_read_pos+5];
		ret<<=8;
		ret |= bs->cache_read[bs->cache_read_pos+6];
		ret<<=8;
		ret |= bs->cache_read[bs->cache_read_pos+7];
		bs->cache_read_pos+=8;
		bs->position+=8;
		return ret;
	}
	ret = gf_bs_read_u32(bs);
	ret<<=32;
	ret |= gf_bs_read_u32(bs);
	return ret;
}

Project: gpac
File: avc_ext.c

GF_Err avcc_box_write(GF_Box *s, GF_BitStream *bs)
{
	u32 i, count;
	GF_Err e;
	GF_AVCConfigurationBox *ptr = (GF_AVCConfigurationBox *) s;
	if (!s) return GF_BAD_PARAM;
	if (!ptr->config) return GF_OK;
	e = gf_isom_box_write_header(s, bs);
	if (e) return e;

	Bool is_avcc;
	if ((ptr->type==GF_ISOM_BOX_TYPE_AVCC) || (ptr->type==GF_ISOM_BOX_TYPE_AVCE))
		is_avcc = GF_TRUE;
	else
		is_avcc = GF_FALSE;

	gf_bs_write_u8(bs, ptr->config->configurationVersion);
	gf_bs_write_u8(bs, ptr->config->AVCProfileIndication);
	gf_bs_write_u8(bs, ptr->config->profile_compatibility);
	gf_bs_write_u8(bs, ptr->config->AVCLevelIndication);
	if (is_avcc) {
		gf_bs_write_int(bs, 0x3F, 6);
	} else {
		gf_bs_write_int(bs, ptr->config->complete_representation, 1);
		gf_bs_write_int(bs, 0x1F, 5);
	}
	gf_bs_write_int(bs, ptr->config->nal_unit_size - 1, 2);
	gf_bs_write_int(bs, 0x7, 3);
	count = gf_list_count(ptr->config->sequenceParameterSets);
	gf_bs_write_int(bs, count, 5);
	for (i=0; i<count; i++) {
		GF_NALUFFParam *sl = (GF_NALUFFParam *) gf_list_get(ptr->config->sequenceParameterSets, i);
		gf_bs_write_u16(bs, sl->size);
		gf_bs_write_data(bs, sl->data, sl->size);
	}

	count = gf_list_count(ptr->config->pictureParameterSets);
	gf_bs_write_u8(bs, count);
	for (i=0; i<count; i++) {
		GF_NALUFFParam *sl = (GF_NALUFFParam *) gf_list_get(ptr->config->pictureParameterSets, i);
		gf_bs_write_u16(bs, sl->size);
		gf_bs_write_data(bs, sl->data, sl->size);
	}


	if (is_avcc) {
		if (gf_avcc_use_extensions(ptr->config->AVCProfileIndication)) {
			gf_bs_write_int(bs, 0xFF, 6);
			gf_bs_write_int(bs, ptr->config->chroma_format, 2);
			gf_bs_write_int(bs, 0xFF, 5);
			gf_bs_write_int(bs, ptr->config->luma_bit_depth - 8, 3);
			gf_bs_write_int(bs, 0xFF, 5);
			gf_bs_write_int(bs, ptr->config->chroma_bit_depth - 8, 3);

			count = ptr->config->sequenceParameterSetExtensions ? gf_list_count(ptr->config->sequenceParameterSetExtensions) : 0;
			gf_bs_write_u8(bs, count);
			for (i=0; i<count; i++) {
				GF_NALUFFParam *sl = (GF_NALUFFParam *) gf_list_get(ptr->config->sequenceParameterSetExtensions, i);
				gf_bs_write_u16(bs, sl->size);
				gf_bs_write_data(bs, sl->data, sl->size);
			}
		}
	}
	return GF_OK;
}

Project: gpac
File: avc_ext.c

GF_ISOMVVCType gf_isom_get_vvc_type(GF_ISOFile *the_file, u32 trackNumber, u32 DescriptionIndex)
{
	u32 type;
	GF_TrackBox *trak;
	GF_MPEGVisualSampleEntryBox *entry;
	trak = gf_isom_get_track_from_file(the_file, trackNumber);
	if (!trak || !trak->Media || !DescriptionIndex) return GF_ISOM_VVCTYPE_NONE;
	if (!gf_isom_is_video_handler_type(trak->Media->handler->handlerType))
		return GF_ISOM_VVCTYPE_NONE;
	entry = (GF_MPEGVisualSampleEntryBox*)gf_list_get(trak->Media->information->sampleTable->SampleDescription->child_boxes, DescriptionIndex-1);
	if (!entry) return GF_ISOM_VVCTYPE_NONE;
	if (entry->internal_type != GF_ISOM_SAMPLE_ENTRY_VIDEO) return GF_ISOM_VVCTYPE_NONE;
	type = entry->type;

	if (type == GF_ISOM_BOX_TYPE_ENCV) {
		GF_ProtectionSchemeInfoBox *sinf = (GF_ProtectionSchemeInfoBox *) gf_isom_box_find_child(entry->child_boxes, GF_ISOM_BOX_TYPE_SINF);
		if (sinf && sinf->original_format) type = sinf->original_format->data_format;
	}
	else if (type == GF_ISOM_BOX_TYPE_RESV) {
		if (entry->rinf && entry->rinf->original_format) type = entry->rinf->original_format->data_format;
	}

	switch (type) {
	case GF_ISOM_BOX_TYPE_VVC1:
	case GF_ISOM_BOX_TYPE_VVI1:
		return GF_ISOM_VVCTYPE_ONLY;
	case GF_ISOM_SUBTYPE_VVS1:
		return GF_ISOM_VVCTYPE_SUBPIC;
	case GF_ISOM_SUBTYPE_VVCN:
		return GF_ISOM_VVCTYPE_NVCL;
	default:
		return GF_ISOM_VVCTYPE_NONE;
	}
	return GF_ISOM_VVCTYPE_NONE;
}

Project: gpac
File: bitstream.c

void gf_bs_write_u32_le(GF_BitStream *bs, u32 val)
{
	gf_bs_write_int(bs, val & 0xFF, 8);
	gf_bs_write_int(bs, val>>8, 8);
	gf_bs_write_int(bs, val>>16, 8);
	gf_bs_write_int(bs, val>>24, 8);
}

Project: gpac
File: bitstream.c

void gf_bs_write_u16_le(GF_BitStream *bs, u32 val)
{
	gf_bs_write_int(bs, val & 0xFF, 8);
	gf_bs_write_int(bs, val>>8, 8);
}