Example #1
0
static u_char*
mss_write_uuid_tfrf_atom(u_char* p, segment_timing_info_t* timing_info)
{
	size_t atom_size = TFRF_ATOM_SIZE;
	uint64_t timestamp;
	uint64_t duration;
	int i;

	timestamp = timing_info->timestamp;
	duration = timing_info->duration;

	write_atom_header(p, atom_size, 'u', 'u', 'i', 'd');
	p = vod_copy(p, tfrf_uuid, sizeof(tfrf_uuid));
	write_be32(p, 0x01000000);		// version / flags
	*p++ = MSS_LOOK_AHEAD_COUNT;

	for (i = 0; i < MSS_LOOK_AHEAD_COUNT; i++)
	{
		timestamp += duration;
		write_be64(p, timestamp);
		write_be64(p, duration);
	}

	return p;
}
static u_char*
edash_packager_passthrough_write_encryption_atoms(void* ctx, u_char* p, size_t mdat_atom_start)
{
	mp4_encrypt_passthrough_context_t* context = ctx;
	media_clip_filtered_t* cur_clip;
	media_sequence_t* sequence = context->sequence;
	media_track_t* cur_track;
	size_t senc_atom_size;
	uint32_t flags;

	// saiz / saio
	p = mp4_encrypt_passthrough_write_saiz_saio(ctx, p, mdat_atom_start - context->auxiliary_info_size);

	// senc
	senc_atom_size = ATOM_HEADER_SIZE + sizeof(senc_atom_t) + context->auxiliary_info_size;
	write_atom_header(p, senc_atom_size, 's', 'e', 'n', 'c');
	flags = context->use_subsamples ? 0x2 : 0x0;
	write_be32(p, flags);		// flags
	write_be32(p, sequence->total_frame_count);
	for (cur_clip = sequence->filtered_clips; cur_clip < sequence->filtered_clips_end; cur_clip++)
	{
		cur_track = cur_clip->first_track;
		p = vod_copy(p, 
			cur_track->encryption_info.auxiliary_info, 
			cur_track->encryption_info.auxiliary_info_end - cur_track->encryption_info.auxiliary_info);
	}

	return p;
}
static u_char* 
mp4_builder_write_audio_trun_atom(u_char* p, media_sequence_t* sequence, uint32_t first_frame_offset)
{
	media_clip_filtered_t* cur_clip;
	input_frame_t* cur_frame;
	input_frame_t* last_frame;
	size_t atom_size;

	atom_size = ATOM_HEADER_SIZE + sizeof(trun_atom_t) + sequence->total_frame_count * 2 * sizeof(uint32_t);

	write_atom_header(p, atom_size, 't', 'r', 'u', 'n');
	write_be32(p, 0x301);								// flags = data offset, duration, size
	write_be32(p, sequence->total_frame_count);
	write_be32(p, first_frame_offset);	// first frame offset relative to moof start offset

	for (cur_clip = sequence->filtered_clips; cur_clip < sequence->filtered_clips_end; cur_clip++)
	{
		cur_frame = cur_clip->first_track->first_frame;
		last_frame = cur_clip->first_track->last_frame;
		for (; cur_frame < last_frame; cur_frame++)
		{
			write_be32(p, cur_frame->duration);
			write_be32(p, cur_frame->size);
		}
	}
	return p;
}
static u_char*
hds_write_afra_atom_header(u_char* p, size_t atom_size, uint32_t video_key_frame_count)
{
	write_atom_header(p, atom_size, 'a', 'f', 'r', 'a');
	write_be32(p, 0);
	*p++ = 0xC0;								// LongIDs | LongOffsets
	write_be32(p, HDS_TIMESCALE);				// timescale
	write_be32(p, video_key_frame_count);		// entries
	return p;
}
Example #5
0
u_char*
mp4_builder_write_mfhd_atom(u_char* p, uint32_t segment_index)
{
	size_t atom_size = ATOM_HEADER_SIZE + sizeof(mfhd_atom_t);

	write_atom_header(p, atom_size, 'm', 'f', 'h', 'd');
	write_be32(p, 0);
	write_be32(p, segment_index);
	return p;
}
Example #6
0
static u_char*
dash_packager_write_tfdt64_atom(u_char* p, uint64_t earliest_pres_time)
{
	size_t atom_size = ATOM_HEADER_SIZE + sizeof(tfdt64_atom_t);

	write_atom_header(p, atom_size, 't', 'f', 'd', 't');
	write_dword(p, 0x01000000);			// version = 1
	write_qword(p, earliest_pres_time);
	return p;
}
Example #7
0
static u_char*
mss_playready_audio_write_uuid_piff_atom(u_char* p, mp4_encrypt_state_t* state, media_sequence_t* sequence, size_t atom_size)
{
	write_atom_header(p, atom_size, 'u', 'u', 'i', 'd');
	p = vod_copy(p, piff_uuid, sizeof(piff_uuid));
	write_dword(p, 0);
	write_dword(p, sequence->total_frame_count);
	p = mp4_encrypt_audio_write_auxiliary_data(state, p);

	return p;
}
Example #8
0
static u_char*
mss_write_tfhd_atom(u_char* p, uint32_t track_id, uint32_t flags)
{
	size_t atom_size = ATOM_HEADER_SIZE + sizeof(tfhd_atom_t);

	write_atom_header(p, atom_size, 't', 'f', 'h', 'd');
	write_dword(p, 0x20);		// default sample flags
	write_dword(p, track_id);
	write_dword(p, flags);
	return p;
}
static u_char*
mss_playready_video_write_uuid_piff_atom(u_char* p, mp4_encrypt_video_state_t* state, media_sequence_t* sequence, size_t atom_size)
{
	write_atom_header(p, atom_size, 'u', 'u', 'i', 'd');
	p = vod_copy(p, piff_uuid, sizeof(piff_uuid));
	write_be32(p, 2);
	write_be32(p, sequence->total_frame_count);
	p = vod_copy(p, state->auxiliary_data.start, state->auxiliary_data.pos - state->auxiliary_data.start);

	return p;
}
Example #10
0
u_char*
mp4_encrypt_audio_write_saiz_saio(mp4_encrypt_state_t* state, u_char* p, size_t auxiliary_data_offset)
{
	size_t saiz_atom_size = ATOM_HEADER_SIZE + sizeof(saiz_atom_t);
	size_t saio_atom_size = ATOM_HEADER_SIZE + sizeof(saio_atom_t);

	// moof.traf.saiz
	write_atom_header(p, saiz_atom_size, 's', 'a', 'i', 'z');
	write_be32(p, 0);			// version, flags
	*p++ = MP4_AES_CTR_IV_SIZE;				// default auxiliary sample size
	write_be32(p, state->sequence->total_frame_count);

	// moof.traf.saio
	write_atom_header(p, saio_atom_size, 's', 'a', 'i', 'o');
	write_be32(p, 0);			// version, flags
	write_be32(p, 1);			// entry count
	write_be32(p, auxiliary_data_offset);

	return p;
}
Example #11
0
static u_char*
mss_write_uuid_tfxd_atom(u_char* p, segment_timing_info_t* timing_info)
{
	size_t atom_size = ATOM_HEADER_SIZE + sizeof(uuid_tfxd_atom_t);

	write_atom_header(p, atom_size, 'u', 'u', 'i', 'd');
	p = vod_copy(p, tfxd_uuid, sizeof(tfxd_uuid));
	write_be32(p, 0x01000000);		// version / flags
	write_be64(p, timing_info->timestamp);
	write_be64(p, timing_info->duration);
	return p;
}
static u_char*
hds_write_tfhd_atom(u_char* p, uint32_t track_id, uint64_t base_data_offset)
{
	size_t atom_size = ATOM_HEADER_SIZE + sizeof(tfhd_atom_t);

	write_atom_header(p, atom_size, 't', 'f', 'h', 'd');
	write_be32(p, 3);							// flags - base data offset | sample description
	write_be32(p, track_id);
	write_be64(p, base_data_offset);
	write_be32(p, 1);							// sample_desc_index
	return p;
}
Example #13
0
u_char*
mp4_encrypt_video_write_saiz_saio(mp4_encrypt_video_state_t* state, u_char* p, size_t auxiliary_data_offset)
{
	// moof.traf.saiz
	write_atom_header(p, state->base.saiz_atom_size, 's', 'a', 'i', 'z');
	write_be32(p, 0);			// version, flags
	*p++ = state->default_auxiliary_sample_size;
	write_be32(p, state->saiz_sample_count);
	if (state->default_auxiliary_sample_size == 0)
	{
		p = vod_copy(p, state->auxiliary_sample_sizes, state->saiz_sample_count);
	}

	// moof.traf.saio
	write_atom_header(p, state->base.saio_atom_size, 's', 'a', 'i', 'o');
	write_be32(p, 0);			// version, flags
	write_be32(p, 1);			// entry count
	write_be32(p, auxiliary_data_offset);

	return p;
}
static u_char*
edash_packager_write_pssh(u_char* p, drm_system_info_t* cur_info)
{
	size_t pssh_atom_size;

	pssh_atom_size = ATOM_HEADER_SIZE + sizeof(pssh_atom_t) + cur_info->data.len;

	write_atom_header(p, pssh_atom_size, 'p', 's', 's', 'h');
	write_be32(p, 0);						// version + flags
	p = vod_copy(p, cur_info->system_id, DRM_SYSTEM_ID_SIZE);	// system id
	write_be32(p, cur_info->data.len);		// data size
	p = vod_copy(p, cur_info->data.data, cur_info->data.len);
	return p;
}
Example #15
0
static u_char*
mss_write_uuid_tfxd_atom(u_char* p, mpeg_stream_metadata_t* stream_metadata)
{
	size_t atom_size = ATOM_HEADER_SIZE + sizeof(uuid_tfxd_atom_t);
	uint64_t timestamp = rescale_time(stream_metadata->first_frame_time_offset, stream_metadata->media_info.timescale, MSS_TIMESCALE);
	uint64_t duration = rescale_time(stream_metadata->total_frames_duration, stream_metadata->media_info.timescale, MSS_TIMESCALE);

	write_atom_header(p, atom_size, 'u', 'u', 'i', 'd');
	p = vod_copy(p, tfxd_uuid, sizeof(tfxd_uuid));
	write_dword(p, 0x01000000);		// version / flags
	write_qword(p, timestamp);
	write_qword(p, duration);
	return p;
}
Example #16
0
static u_char*
dash_packager_write_trex_atom(u_char* p, uint32_t track_id)
{
	size_t atom_size = ATOM_HEADER_SIZE + sizeof(trex_atom_t);

	write_atom_header(p, atom_size, 't', 'r', 'e', 'x');
	write_dword(p, 0);			// version + flags
	write_dword(p, track_id);	// track id
	write_dword(p, 1);			// default sample description index
	write_dword(p, 0);			// default sample duration
	write_dword(p, 0);			// default sample size
	write_dword(p, 0);			// default sample size
	return p;
}
static u_char*
hds_write_single_audio_frame_trun_atom(u_char* p, input_frame_t* frame, uint32_t offset)
{
	size_t atom_size;

	atom_size = TRUN_SIZE_SINGLE_AUDIO_FRAME;

	write_atom_header(p, atom_size, 't', 'r', 'u', 'n');
	write_be32(p, 0x301);				// flags = data offset, duration, size
	write_be32(p, 1);					// frame count
	write_be32(p, offset);				// offset from mdat start to frame raw data (excluding the tag)
	write_be32(p, frame->duration);
	write_be32(p, frame->size);
	return p;
}
Example #18
0
static u_char*
dash_packager_write_mvhd64_atom(u_char* p, uint32_t timescale, uint64_t duration)
{
	size_t atom_size = ATOM_HEADER_SIZE + sizeof(mvhd64_atom_t);

	write_atom_header(p, atom_size, 'm', 'v', 'h', 'd');
	write_dword(p, 0x01000000);	// version + flags
	write_qword(p, 0LL);		// creation time
	write_qword(p, 0LL);		// modification time
	write_dword(p, timescale);	// timescale
	write_qword(p, duration);	// duration
	p = dash_packager_write_mvhd_constants(p);
	write_dword(p, 0xffffffff); // next track id
	return p;
}
Example #19
0
static u_char* 
mp4_builder_write_video_trun_atom(u_char* p, media_sequence_t* sequence, uint32_t first_frame_offset)
{
	media_clip_filtered_t* cur_clip;
	frame_list_part_t* part;
	input_frame_t* cur_frame;
	input_frame_t* last_frame;
	size_t atom_size;

	atom_size = ATOM_HEADER_SIZE + sizeof(trun_atom_t) + sequence->total_frame_count * 4 * sizeof(uint32_t);

	write_atom_header(p, atom_size, 't', 'r', 'u', 'n');
	write_be32(p, 0xF01);								// flags = data offset, duration, size, key, delay
	write_be32(p, sequence->total_frame_count);
	write_be32(p, first_frame_offset);	// first frame offset relative to moof start offset

	for (cur_clip = sequence->filtered_clips; cur_clip < sequence->filtered_clips_end; cur_clip++)
	{
		part = &cur_clip->first_track->frames;
		last_frame = part->last_frame;
		for (cur_frame = part->first_frame;; cur_frame++)
		{
			if (cur_frame >= last_frame)
			{
				if (part->next == NULL)
				{
					break;
				}
				part = part->next;
				cur_frame = part->first_frame;
				last_frame = part->last_frame;
			}

			write_be32(p, cur_frame->duration);
			write_be32(p, cur_frame->size);
			if (cur_frame->key_frame)
			{
				write_be32(p, 0x00000000);
			}
			else
			{
				write_be32(p, 0x00010000);
			}
			write_be32(p, cur_frame->pts_delay);
		}
	}
	return p;
}
static u_char*
edash_packager_audio_write_encryption_atoms(void* context, u_char* p, size_t mdat_atom_start)
{
	mp4_encrypt_state_t* state = (mp4_encrypt_state_t*)context;
	size_t senc_data_size = MP4_AES_CTR_IV_SIZE * state->sequence->total_frame_count;
	size_t senc_atom_size = ATOM_HEADER_SIZE + sizeof(senc_atom_t) + senc_data_size;

	// saiz / saio
	p = mp4_encrypt_audio_write_saiz_saio(state, p, mdat_atom_start - senc_data_size);

	// senc
	write_atom_header(p, senc_atom_size, 's', 'e', 'n', 'c');
	write_be32(p, 0x0);		// flags
	write_be32(p, state->sequence->total_frame_count);
	p = mp4_encrypt_audio_write_auxiliary_data(state, p);

	return p;
}
static u_char*
edash_packager_video_write_encryption_atoms(void* context, u_char* p, size_t mdat_atom_start)
{
	mp4_encrypt_video_state_t* state = (mp4_encrypt_video_state_t*)context;
	size_t senc_data_size = state->auxiliary_data.pos - state->auxiliary_data.start;
	size_t senc_atom_size = ATOM_HEADER_SIZE + sizeof(senc_atom_t) + senc_data_size;

	// saiz / saio
	p = mp4_encrypt_video_write_saiz_saio(state, p, mdat_atom_start - senc_data_size);

	// senc
	write_atom_header(p, senc_atom_size, 's', 'e', 'n', 'c');
	write_be32(p, 0x2);		// flags
	write_be32(p, state->base.sequence->total_frame_count);
	p = vod_copy(p, state->auxiliary_data.start, senc_data_size);

	return p;
}
Example #22
0
static u_char*
dash_packager_write_sidx64_atom(
	u_char* p,
	sidx_params_t* sidx_params,
	uint32_t reference_size)
{
	size_t atom_size = ATOM_HEADER_SIZE + sizeof(sidx64_atom_t);

	write_atom_header(p, atom_size, 's', 'i', 'd', 'x');
	write_dword(p, 0x01000000);			// version + flags
	write_dword(p, 1);					// reference id
	write_dword(p, sidx_params->timescale);			// timescale
	write_qword(p, sidx_params->earliest_pres_time);	// earliest presentation time
	write_qword(p, 0LL);					// first offset
	write_dword(p, 1);					// reserved + reference count
	write_dword(p, reference_size);		// referenced size
	write_dword(p, sidx_params->total_frames_duration);		// subsegment duration
	write_dword(p, 0x90000000);			// starts with SAP / SAP type
	return p;
}
Example #23
0
static u_char*
edash_packager_write_pssh(void* context, u_char* p)
{
	mp4_encrypt_system_info_array_t* pssh_array = (mp4_encrypt_system_info_array_t*)context;
	mp4_encrypt_system_info_t* cur_info;
	size_t pssh_atom_size;

	for (cur_info = pssh_array->first; cur_info < pssh_array->last; cur_info++)
	{
		pssh_atom_size = ATOM_HEADER_SIZE + sizeof(pssh_atom_t) + cur_info->data.len;

		write_atom_header(p, pssh_atom_size, 'p', 's', 's', 'h');
		write_dword(p, 0);						// version + flags
		p = vod_copy(p, cur_info->system_id, MP4_ENCRYPT_SYSTEM_ID_SIZE);	// system id
		write_dword(p, cur_info->data.len);		// data size
		p = vod_copy(p, cur_info->data.data, cur_info->data.len);
	}

	return p;
}
static u_char*
dash_packager_write_sidx_atom(
	u_char* p,
	mpeg_stream_metadata_t* stream_metadata,
	uint32_t earliest_pres_time,
	uint32_t reference_size)
{
	size_t atom_size = ATOM_HEADER_SIZE + sizeof(sidx_atom_t);

	write_atom_header(p, atom_size, 's', 'i', 'd', 'x');
	write_dword(p, 0);					// version + flags
	write_dword(p, 1);					// reference id
	write_dword(p, stream_metadata->media_info.timescale);				// timescale
	write_dword(p, earliest_pres_time);	// earliest presentation time
	write_dword(p, 0);					// first offset
	write_dword(p, 1);					// reserved + reference count
	write_dword(p, reference_size);		// referenced size
	write_dword(p, stream_metadata->total_frames_duration);		// subsegment duration
	write_dword(p, 0x90000000);			// starts with SAP / SAP type
	return p;
}
Example #25
0
static u_char*
edash_packager_write_stsd(void* ctx, u_char* p)
{
	stsd_writer_context_t* context = (stsd_writer_context_t*)ctx;
	u_char format_by_media_type[MEDIA_TYPE_COUNT] = { 'v', 'a' };

	// stsd
	write_atom_header(p, context->stsd_atom_size, 's', 't', 's', 'd');
	write_dword(p, 0);		// version + flags
	write_dword(p, context->has_clear_lead ? 2 : 1);		// entries

	// stsd encrypted entry
	write_dword(p, context->encrypted_stsd_entry_size);		// size
	write_atom_name(p, 'e', 'n', 'c', format_by_media_type[context->media_type]);	// format
	p = vod_copy(p, context->original_stsd_entry + 1, context->original_stsd_entry_size - sizeof(stsd_entry_header_t));

	// sinf
	write_atom_header(p, context->sinf_atom_size, 's', 'i', 'n', 'f');
	
	// sinf.frma
	write_atom_header(p, context->frma_atom_size, 'f', 'r', 'm', 'a');
	write_dword(p, context->original_stsd_entry_format);

	// sinf.schm
	write_atom_header(p, context->schm_atom_size, 's', 'c', 'h', 'm');
	write_dword(p, 0);							// version + flags
	write_atom_name(p, 'c', 'e', 'n', 'c');		// scheme type
	write_dword(p, 0x10000);					// scheme version

	// sinf.schi
	write_atom_header(p, context->schi_atom_size, 's', 'c', 'h', 'i');

	// sinf.schi.tenc
	write_atom_header(p, context->tenc_atom_size, 't', 'e', 'n', 'c');
	write_dword(p, 0);							// version + flags
	write_dword(p, 0x108);						// default is encrypted (1) + iv size (8)
	p = vod_copy(p, context->default_kid, MP4_ENCRYPT_KID_SIZE);			// default key id

	// clear entry
	if (context->has_clear_lead)
	{
		p = vod_copy(p, context->original_stsd_entry, context->original_stsd_entry_size);
	}

	return p;
}
Example #26
0
static u_char*
dash_packager_write_tfhd_atom(u_char* p, uint32_t track_id, uint32_t sample_description_index)
{
	size_t atom_size;
	uint32_t flags;

	flags = 0x020000;				// default-base-is-moof
	atom_size = ATOM_HEADER_SIZE + sizeof(tfhd_atom_t);
	if (sample_description_index > 0)
	{
		flags |= 0x02;				// sample-description-index-present
		atom_size += sizeof(uint32_t);
	}

	write_atom_header(p, atom_size, 't', 'f', 'h', 'd');
	write_dword(p, flags);			// flags
	write_dword(p, track_id);		// track id
	if (sample_description_index > 0)
	{
		write_dword(p, sample_description_index);
	}
	return p;
}
static u_char*
mss_playready_passthrough_write_encryption_atoms(void* ctx, u_char* p, size_t mdat_atom_start)
{
	mp4_encrypt_passthrough_context_t* context = ctx;
	media_clip_filtered_t* cur_clip;
	media_sequence_t* sequence = context->sequence;
	media_track_t* cur_track;
	size_t auxiliary_data_offset;
	size_t uuid_atom_size;
	uint32_t flags;

	// uuid piff
	uuid_atom_size = ATOM_HEADER_SIZE + sizeof(uuid_piff_atom_t) + context->auxiliary_info_size;
	write_atom_header(p, uuid_atom_size, 'u', 'u', 'i', 'd');
	p = vod_copy(p, piff_uuid, sizeof(piff_uuid));
	flags = context->use_subsamples ? 0x2 : 0x0;
	write_be32(p, flags);		// flags
	write_be32(p, sequence->total_frame_count);
	for (cur_clip = sequence->filtered_clips; cur_clip < sequence->filtered_clips_end; cur_clip++)
	{
		cur_track = cur_clip->first_track;
		p = vod_copy(p,
			cur_track->encryption_info.auxiliary_info,
			cur_track->encryption_info.auxiliary_info_end - cur_track->encryption_info.auxiliary_info);
	}

	// saiz / saio
	auxiliary_data_offset = mdat_atom_start -
		(context->auxiliary_info_size +
		context->saiz_atom_size +
		context->saio_atom_size);

	p = mp4_encrypt_passthrough_write_saiz_saio(ctx, p, auxiliary_data_offset);

	return p;
}
static u_char*
hds_write_single_video_frame_trun_atom(u_char* p, input_frame_t* frame, uint32_t offset)
{
	size_t atom_size;

	atom_size = TRUN_SIZE_SINGLE_VIDEO_FRAME;

	write_atom_header(p, atom_size, 't', 'r', 'u', 'n');
	write_be32(p, 0xF01);				// flags = data offset, duration, size, key, delay
	write_be32(p, 1);					// frame count
	write_be32(p, offset);				// offset from mdat start to frame raw data (excluding the tag)
	write_be32(p, frame->duration);
	write_be32(p, frame->size);
	if (frame->key_frame)
	{
		write_be32(p, 0x02000000);		// I-frame
	}
	else
	{
		write_be32(p, 0x01010000);		// not I-frame + non key sample
	}
	write_be32(p, frame->pts_delay);
	return p;
}
Example #29
0
static u_char*
hds_write_abst_atom(
	u_char* p, 
	segment_durations_t* segment_durations)
{
	segment_duration_item_t* cur_item;
	segment_duration_item_t* last_item = segment_durations->items + segment_durations->item_count;
	uint64_t start_offset = 0;
	uint64_t timestamp;
	uint32_t duration;
	size_t afrt_atom_size = AFRT_BASE_ATOM_SIZE;
	size_t asrt_atom_size = ASRT_ATOM_SIZE;
	size_t abst_atom_size = ABST_BASE_ATOM_SIZE;

	afrt_atom_size += (segment_durations->item_count + 1) * sizeof(afrt_entry_t);
	abst_atom_size += (segment_durations->item_count + 1) * sizeof(afrt_entry_t);

	// abst
	write_atom_header(p, abst_atom_size, 'a', 'b', 's', 't');
	write_dword(p, 0);					// version + flags
	write_dword(p, 1);					// bootstrap info version
	*p++ = 0;							// profile, live, update
	write_dword(p, HDS_TIMESCALE);		// timescale
	write_dword(p, 0);					// current media time - high
	write_dword(p, segment_durations->duration_millis);	// current media time - low
	write_qword(p, 0LL);				// smpte offset
	*p++ = 0;							// movie identifier
	*p++ = 0;							// server entries
	*p++ = 0;							// quality entries
	*p++ = 0;							// drm data
	*p++ = 0;							// metadata
	*p++ = 1;							// segment run table count

	// abst.asrt
	write_atom_header(p, asrt_atom_size, 'a', 's', 'r', 't');
	write_dword(p, 0);					// version + flags
	*p++ = 0;							// quality entries
	write_dword(p, 1);					// segment run entries
	// entry #1
	write_dword(p, 1);					// first segment
	write_dword(p, segment_durations->segment_count);		// fragments per segment

	// abst
	*p++ = 1;							// fragment run table count

	// abst.afrt
	write_atom_header(p, afrt_atom_size, 'a', 'f', 'r', 't');
	write_dword(p, 0);					// version + flags
	write_dword(p, HDS_TIMESCALE);		// timescale
	*p++ = 0;							// quality entries
	write_dword(p, segment_durations->item_count + 1);	// fragment run entries

	// write the afrt entries
	for (cur_item = segment_durations->items; cur_item < last_item; cur_item++)
	{
		timestamp = rescale_time(start_offset, segment_durations->timescale, HDS_TIMESCALE);
		duration = rescale_time(cur_item->duration, segment_durations->timescale, HDS_TIMESCALE);

		write_dword(p, cur_item->segment_index + 1);		// first fragment
		write_qword(p, timestamp);	// first fragment timestamp
		write_dword(p, duration);			// fragment duration
		start_offset += cur_item->duration * cur_item->repeat_count;
	}

	// last entry
	write_dword(p, 0);					// first fragment
	write_qword(p, 0LL);				// first fragment timestamp
	write_dword(p, 0);					// fragment duration
	*p++ = 0;							// discontinuity indicator (0 = end of presentation)

	return p;
}
Example #30
0
static u_char*
hds_write_abst_atom(
	u_char* p,
	media_set_t* media_set,
	hds_segment_durations_t* segments)
{
	segment_durations_t* segment_durations = &segments->durations;
	segment_duration_item_t* cur_item;
	segment_duration_item_t* last_item = segment_durations->items + segment_durations->item_count;
	uint64_t timestamp;
	uint32_t fragment_run_entries;
	uint32_t segment_index;
	uint32_t duration;
	size_t afrt_atom_size = AFRT_BASE_ATOM_SIZE;
	size_t asrt_atom_size = ASRT_ATOM_SIZE;
	size_t abst_atom_size = ABST_BASE_ATOM_SIZE;
	size_t extra_afrt_size = 0;

	fragment_run_entries = segment_durations->item_count;
	if (media_set->presentation_end)
	{
		fragment_run_entries++;					// zero entry
		extra_afrt_size += sizeof(u_char);		// discontinuity indicator
	}

	fragment_run_entries += segment_durations->discontinuities;					// zero entry
	extra_afrt_size += fragment_run_entries * sizeof(afrt_entry_t) +
		sizeof(u_char) * (segment_durations->discontinuities + segments->zero_segments);	// discontinuity indicator

	afrt_atom_size += extra_afrt_size;
	abst_atom_size += extra_afrt_size;

	// abst
	write_atom_header(p, abst_atom_size, 'a', 'b', 's', 't');
	write_be32(p, 0);					// version + flags
	write_be32(p, 1);					// bootstrap info version
	*p++ = (media_set->type == MEDIA_SET_LIVE ? 0x20 : 0);	// profile, live, update
	write_be32(p, HDS_TIMESCALE);		// timescale
	write_be64(p, segment_durations->end_time);	// current media time
	write_be64(p, 0LL);					// smpte offset
	*p++ = 0;							// movie identifier
	*p++ = 0;							// server entries
	*p++ = 0;							// quality entries
	*p++ = 0;							// drm data
	*p++ = 0;							// metadata
	*p++ = 1;							// segment run table count

	// abst.asrt
	write_atom_header(p, asrt_atom_size, 'a', 's', 'r', 't');
	write_be32(p, 0);					// version + flags
	*p++ = 0;							// quality entries
	write_be32(p, 1);					// segment run entries
	// entry #1
	write_be32(p, 1);					// first segment
	write_be32(p, segment_durations->segment_count);		// fragments per segment

	// abst
	*p++ = 1;							// fragment run table count

	// abst.afrt
	write_atom_header(p, afrt_atom_size, 'a', 'f', 'r', 't');
	write_be32(p, 0);					// version + flags
	write_be32(p, HDS_TIMESCALE);		// timescale
	*p++ = 0;							// quality entries
	write_be32(p, fragment_run_entries);	// fragment run entries

	// write the afrt entries
	for (cur_item = segment_durations->items; cur_item < last_item; cur_item++)
	{
		segment_index = cur_item->segment_index + 1;
		timestamp = cur_item->time;
		duration = cur_item->duration;

		write_be32(p, segment_index);	// first fragment
		write_be64(p, timestamp);		// first fragment timestamp
		write_be32(p, duration);		// fragment duration
		if (duration == 0)
		{
			*p++ = 1;					// discontinuity indicator (1 = discontinuity in fragment numbering)
		}

		if (cur_item + 1 < last_item && cur_item[1].discontinuity)
		{
			segment_index += cur_item->repeat_count;
			timestamp += duration * cur_item->repeat_count;
			write_be32(p, segment_index);		// first fragment
			write_be64(p, timestamp);			// first fragment timestamp
			write_be32(p, 0);					// fragment duration
			*p++ = 3;							// discontinuity indicator (3 = discontinuity in both timestamps and fragment numbering)
		}
	}

	if (media_set->presentation_end)
	{
		// last entry
		write_be32(p, 0);					// first fragment
		write_be64(p, 0LL);					// first fragment timestamp
		write_be32(p, 0);					// fragment duration
		*p++ = 0;							// discontinuity indicator (0 = end of presentation)
	}

	return p;
}