Esempio n. 1
0
vod_status_t
segmenter_get_start_end_ranges_discontinuity(
	get_clip_ranges_params_t* params,
	get_clip_ranges_result_t* result)
{
	align_to_key_frames_context_t align_context;
	request_context_t* request_context = params->request_context;
	segmenter_conf_t* conf = params->conf;
	uint64_t clip_start_offset;
	uint64_t start;
	uint64_t end;
	uint64_t ignore;
	uint32_t* end_duration = params->clip_durations + params->total_clip_count;
	uint32_t* cur_duration;
	uint32_t clip_index_segment_index = 0;
	uint32_t last_segment_limit = params->initial_segment_index;
	uint32_t cur_segment_limit;
	uint32_t segment_index = params->segment_index;
	uint32_t clip_index = params->clip_index;
	media_range_t* cur_clip_range;
	uint64_t prev_clips_duration = 0;

	SEGMENT_CHOOSE_HEADER(conf);

	for (cur_duration = params->clip_durations;; cur_duration++)
	{
		if (cur_duration >= end_duration)
		{
			vod_log_error(VOD_LOG_ERR, request_context->log, 0,
				"segmenter_get_start_end_ranges_discontinuity: invalid segment index %uD or clip index", segment_index);
			return VOD_BAD_REQUEST;
		}

		// get the clip start offset
		segmenter_get_start_end_offsets(conf, last_segment_limit, &clip_start_offset, &ignore);

		// get segment limit for the current clip
		cur_segment_limit = conf->get_segment_count(conf, clip_start_offset + *cur_duration);
		if (cur_segment_limit == INVALID_SEGMENT_COUNT)
		{
			vod_log_error(VOD_LOG_ERR, request_context->log, 0,
				"segmenter_get_start_end_ranges_discontinuity: invalid segment count");
			return VOD_BAD_DATA;
		}

		if (cur_segment_limit <= last_segment_limit)
		{
			cur_segment_limit = last_segment_limit + 1;
		}

		if (clip_index == 1)
		{
			clip_index_segment_index = cur_segment_limit - params->initial_segment_index;
			segment_index += clip_index_segment_index;
		}

		if (clip_index > 0 && clip_index != INVALID_CLIP_INDEX)
		{
			clip_index--;
		}
		else if (segment_index < cur_segment_limit)
		{
			// the segment index is within this clip, break
			break;
		}

		// move to the next clip
		prev_clips_duration += *cur_duration;
		last_segment_limit = cur_segment_limit;
	}

	if (segment_index < last_segment_limit)
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"segmenter_get_start_end_ranges_discontinuity: segment index %uD smaller than last segment index %uD",
			segment_index, last_segment_limit);
		return VOD_BAD_REQUEST;
	}

	// get start / end position relative to the clip start
	segmenter_get_start_end_offsets(
		conf,
		segment_index,
		&start,
		&end);

	start -= clip_start_offset;
	if (segment_index + 1 >= cur_segment_limit)
	{
		end = *cur_duration;		// last segment in clip
	}
	else
	{
		end -= clip_start_offset;
	}

	if (params->key_frame_durations != NULL)
	{
		align_context.request_context = request_context;
		align_context.part = params->key_frame_durations;
		align_context.offset = params->first_key_frame_offset - prev_clips_duration;
		align_context.cur_pos = align_context.part->first;

		start = segmenter_align_to_key_frames(&align_context, start, *cur_duration);
		end = segmenter_align_to_key_frames(&align_context, end, *cur_duration);
	}

	// initialize the clip range
	cur_clip_range = vod_alloc(request_context->pool, sizeof(cur_clip_range[0]));
	if (cur_clip_range == NULL)
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0,
			"segmenter_get_start_end_ranges_discontinuity: vod_alloc failed");
		return VOD_ALLOC_FAILED;
	}

	cur_clip_range->timescale = 1000;
	cur_clip_range->start = start;
	cur_clip_range->end = end;

	// initialize the result
	result->initial_sequence_offset = prev_clips_duration;
	result->min_clip_index = result->max_clip_index = cur_duration - params->clip_durations;
	result->clip_count = 1;
	result->clip_ranges = cur_clip_range;
	result->clip_index_segment_index = clip_index_segment_index;
	result->first_clip_segment_index = last_segment_limit;

	return VOD_OK;
}
Esempio n. 2
0
static vod_status_t
segmenter_get_segment_durations_estimate_internal(
	request_context_t* request_context,
	segmenter_conf_t* conf,
	media_set_t* media_set,
	media_sequence_t* sequence,
	uint32_t* clip_durations,
	uint32_t total_clip_count,
	uint64_t cur_clip_duration,
	segment_durations_t* result)
{
	align_to_key_frames_context_t align_context;
	segment_duration_item_t* cur_item;
	uint64_t clip_start_offset;
	uint64_t ignore;
	uint64_t next_clip_offset;
	uint64_t next_aligned_offset;
	uint64_t aligned_offset = 0;
	uint64_t clip_offset = 0;
	uint32_t* end_duration = clip_durations + total_clip_count;
	uint32_t* cur_duration = clip_durations;
	uint32_t bootstrap_segment_limit;
	uint32_t segment_index = media_set->initial_segment_index;
	uint32_t clip_segment_limit;
	uint32_t segment_duration;
	uint32_t alloc_count;
	bool_t discontinuity;

	if (sequence->key_frame_durations != NULL)
	{
		align_context.request_context = request_context;
		align_context.part = sequence->key_frame_durations;
		align_context.offset = sequence->first_key_frame_offset;
		align_context.cur_pos = align_context.part->first;
		alloc_count = conf->bootstrap_segments_count + total_clip_count +
			vod_div_ceil(result->end_time - result->start_time, conf->segment_duration);
	}
	else
	{
		vod_memzero(&align_context, sizeof(align_context));
		alloc_count = conf->bootstrap_segments_count + 2 * total_clip_count;
	}

	// allocate the result buffer
	result->items = vod_alloc(request_context->pool, sizeof(result->items[0]) * alloc_count);
	if (result->items == NULL)
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0,
			"segmenter_get_segment_durations_estimate_internal: vod_alloc failed");
		return VOD_ALLOC_FAILED;
	}

	cur_item = result->items - 1;

	discontinuity = FALSE;
	for (;;)
	{
		// find the clip start offset
		segmenter_get_start_end_offsets(conf, segment_index, &clip_start_offset, &ignore);

		// get segment limit for the current clip
		clip_segment_limit = conf->get_segment_count(conf, clip_start_offset + cur_clip_duration);
		if (clip_segment_limit == INVALID_SEGMENT_COUNT)
		{
			vod_log_error(VOD_LOG_ERR, request_context->log, 0,
				"segmenter_get_segment_durations_estimate_internal: segment count is invalid");
			return VOD_BAD_DATA;
		}

		if (clip_segment_limit <= segment_index)
		{
			clip_segment_limit = segment_index + 1;
		}

		next_clip_offset = clip_offset + cur_clip_duration;

		// bootstrap segments
		bootstrap_segment_limit = vod_min(clip_segment_limit - 1, conf->bootstrap_segments_count);
		for (; segment_index < bootstrap_segment_limit; segment_index++)
		{
			segment_duration = conf->bootstrap_segments_durations[segment_index];

			clip_offset += segment_duration;

			if (sequence->key_frame_durations != NULL)
			{
				next_aligned_offset = segmenter_align_to_key_frames(&align_context, clip_offset, next_clip_offset);
				segment_duration = next_aligned_offset - aligned_offset;
				aligned_offset = next_aligned_offset;
			}

			if (cur_item < result->items || segment_duration != cur_item->duration || discontinuity)
			{
				cur_item++;
				cur_item->repeat_count = 0;
				cur_item->segment_index = segment_index;
				cur_item->duration = segment_duration;
				cur_item->discontinuity = discontinuity;
				discontinuity = FALSE;
			}
			cur_item->repeat_count++;
		}

		// remaining segments
		if (sequence->key_frame_durations != NULL)
		{
			for (; segment_index + 1 < clip_segment_limit; segment_index++)
			{
				clip_offset += conf->segment_duration;

				next_aligned_offset = segmenter_align_to_key_frames(&align_context, clip_offset, next_clip_offset);
				segment_duration = next_aligned_offset - aligned_offset;
				aligned_offset = next_aligned_offset;

				if (cur_item < result->items || segment_duration != cur_item->duration || discontinuity)
				{
					cur_item++;
					cur_item->repeat_count = 0;
					cur_item->segment_index = segment_index;
					cur_item->duration = segment_duration;
					cur_item->discontinuity = discontinuity;
					discontinuity = FALSE;
				}
				cur_item->repeat_count++;
			}

			clip_offset = aligned_offset; // the last segment duration should be calcuated according to the aligned offset
		}
		else if (segment_index + 1 < clip_segment_limit)
		{
			segment_duration = conf->segment_duration;
			if (cur_item < result->items || segment_duration != cur_item->duration || discontinuity)
			{
				cur_item++;
				cur_item->repeat_count = 0;
				cur_item->segment_index = segment_index;
				cur_item->duration = segment_duration;
				cur_item->discontinuity = discontinuity;
				discontinuity = FALSE;
			}
			cur_item->repeat_count += clip_segment_limit - segment_index - 1;

			clip_offset += (uint64_t)segment_duration * (clip_segment_limit - segment_index - 1);
			segment_index = clip_segment_limit - 1;
		}

		// last segment
		if (segment_index < clip_segment_limit && clip_offset < next_clip_offset)
		{
			segment_duration = next_clip_offset - clip_offset;
			if (cur_item < result->items || segment_duration != cur_item->duration || discontinuity)
			{
				cur_item++;
				cur_item->repeat_count = 0;
				cur_item->segment_index = segment_index;
				cur_item->duration = segment_duration;
				cur_item->discontinuity = discontinuity;
			}
			cur_item->repeat_count++;

			segment_index = clip_segment_limit;
		}

		// move to the next clip
		cur_duration++;
		if (cur_duration >= end_duration)
		{
			break;
		}

		clip_offset = next_clip_offset;
		cur_clip_duration = *cur_duration;

		// update clip_start_offset
		discontinuity = TRUE;
	}

	// finalize the result
	result->segment_count = clip_segment_limit - media_set->initial_segment_index;
	if (result->segment_count > MAX_SEGMENT_COUNT)
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"segmenter_get_segment_durations_estimate_internal: segment count %uD is invalid", result->segment_count);
		return VOD_BAD_MAPPING;
	}

	result->item_count = cur_item + 1 - result->items;
	result->timescale = 1000;
	result->discontinuities = total_clip_count - 1;

	return VOD_OK;
}
Esempio n. 3
0
vod_status_t
segmenter_get_start_end_ranges_no_discontinuity(
	get_clip_ranges_params_t* params,
	get_clip_ranges_result_t* result)
{
	align_to_key_frames_context_t align_context;
	request_context_t* request_context = params->request_context;
	uint64_t start_time = params->start_time;
	uint64_t clip_start_offset = start_time;
	uint64_t next_start_offset;
	uint64_t start;
	uint64_t end;
	media_range_t* cur_clip_range;
	uint32_t* clip_durations = params->clip_durations;
	uint32_t* end_duration = clip_durations + params->total_clip_count;
	uint32_t* cur_duration;
	uint32_t segment_count;
	uint32_t index;

	SEGMENT_CHOOSE_HEADER(params->conf);

	result->clip_index_segment_index = 0;
	result->first_clip_segment_index = 0;

	// get the segment count
	segment_count = params->conf->get_segment_count(params->conf, params->end_time);
	if (segment_count == INVALID_SEGMENT_COUNT)
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"segmenter_get_start_end_ranges_no_discontinuity: segment count is invalid for total duration %uL", params->end_time);
		return VOD_BAD_DATA;
	}

	if (params->segment_index >= segment_count)
	{
		result->clip_count = 0;
		result->min_clip_index = 1;
		result->max_clip_index = 0;
		return VOD_OK;
	}

	// get the start / end offsets
	segmenter_get_start_end_offsets(
		params->conf,
		params->segment_index,
		&start,
		&end);

	if (start < start_time)
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"segmenter_get_start_end_ranges_no_discontinuity: segment start time %uL is less than sequence start time %uL",
			start, start_time);
		return VOD_BAD_REQUEST;
	}

	if (params->key_frame_durations != NULL)
	{
		align_context.request_context = request_context;
		align_context.part = params->key_frame_durations;
		align_context.offset = start_time + params->first_key_frame_offset;
		align_context.cur_pos = align_context.part->first;
		start = segmenter_align_to_key_frames(&align_context, start, params->last_segment_end);
		end = segmenter_align_to_key_frames(&align_context, end, params->last_segment_end);
	}

	if (params->segment_index + 1 >= segment_count)
	{
		end = params->last_segment_end;
	}

	// find min/max clip indexes and initial sequence offset
	result->min_clip_index = INVALID_CLIP_INDEX;
	result->max_clip_index = params->total_clip_count - 1;

	for (cur_duration = clip_durations; cur_duration < end_duration; cur_duration++, clip_start_offset = next_start_offset)
	{
		next_start_offset = clip_start_offset + *cur_duration;
		if (start >= next_start_offset)
		{
			continue;
		}

		if (start >= clip_start_offset)
		{
			result->min_clip_index = cur_duration - clip_durations;
			result->initial_sequence_offset = clip_start_offset;
		}

		if (end <= next_start_offset)
		{
			result->max_clip_index = cur_duration - clip_durations;
			break;
		}
	}

	if (result->min_clip_index == INVALID_CLIP_INDEX)
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"segmenter_get_start_end_ranges_no_discontinuity: invalid segment index %uD", params->segment_index);
		return VOD_BAD_REQUEST;
	}

	// allocate the clip ranges
	result->clip_count = result->max_clip_index - result->min_clip_index + 1;
	cur_clip_range = vod_alloc(request_context->pool, sizeof(result->clip_ranges[0]) * result->clip_count);
	if (cur_clip_range == NULL)
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0,
			"segmenter_get_start_end_ranges_no_discontinuity: vod_alloc failed");
		return VOD_ALLOC_FAILED;
	}

	result->clip_ranges = cur_clip_range;

	// initialize the clip ranges
	start -= result->initial_sequence_offset;
	end -= result->initial_sequence_offset;
	for (index = result->min_clip_index;; index++, cur_clip_range++)
	{
		cur_clip_range->timescale = 1000;
		cur_clip_range->start = start;
		if (index >= result->max_clip_index)
		{
			cur_clip_range->end = end;
			break;
		}

		cur_clip_range->end = clip_durations[index];

		start = 0;
		end -= clip_durations[index];
	}

	result->initial_sequence_offset -= start_time;

	return VOD_OK;
}
Esempio n. 4
0
vod_status_t
segmenter_get_segment_index_discontinuity(
	request_context_t* request_context,
	segmenter_conf_t* conf,
	uint32_t initial_segment_index,
	uint32_t* clip_durations,
	uint32_t total_clip_count,
	uint64_t time_millis,
	uint32_t* result)
{
	uint64_t clip_start_offset;
	uint64_t prev_clips_duration = 0;
	uint64_t ignore;
	uint32_t* cur_duration;
	uint32_t* end_duration = clip_durations + total_clip_count;
	uint32_t clip_segment_limit;
	uint32_t segment_index = initial_segment_index;

	SEGMENT_CHOOSE_HEADER(conf);

	for (cur_duration = clip_durations; ; cur_duration++)
	{
		if (cur_duration >= end_duration)
		{
			vod_log_error(VOD_LOG_ERR, request_context->log, 0,
				"segmenter_get_segment_index_discontinuity: invalid segment time %uD", time_millis);
			return VOD_BAD_REQUEST;
		}

		// get the clip start offset
		segmenter_get_start_end_offsets(conf, segment_index, &clip_start_offset, &ignore);

		// get segment limit for the current clip
		clip_segment_limit = conf->get_segment_count(conf, clip_start_offset + *cur_duration);
		if (clip_segment_limit == INVALID_SEGMENT_COUNT)
		{
			vod_log_error(VOD_LOG_ERR, request_context->log, 0,
				"segmenter_get_segment_index_discontinuity: segment count is invalid");
			return VOD_BAD_DATA;
		}

		if (clip_segment_limit <= segment_index)
		{
			clip_segment_limit = segment_index + 1;
		}

		// check whether the time stamp falls within the current clip
		if (time_millis < prev_clips_duration + *cur_duration)
		{
			break;
		}

		prev_clips_duration += *cur_duration;

		// move to the next clip
		segment_index = clip_segment_limit;
	}

	// check bootstrap segments
	time_millis -= prev_clips_duration;

	for (; segment_index < conf->bootstrap_segments_count; segment_index++)
	{
		if (time_millis < conf->bootstrap_segments_durations[segment_index])
		{
			*result = segment_index;
			return VOD_OK;
		}

		time_millis -= conf->bootstrap_segments_durations[segment_index];
	}

	*result = segment_index + time_millis / conf->segment_duration;
	return VOD_OK;
}
Esempio n. 5
0
static vod_status_t
segmenter_get_segment_durations_estimate_internal(
	request_context_t* request_context,
	segmenter_conf_t* conf,
	uint32_t* clip_durations,
	uint32_t total_clip_count,
	segment_durations_t* result)
{
	segment_duration_item_t* cur_item;
	uint64_t clip_start_offset = 0;
	uint64_t ignore;
	uint32_t* end_duration = clip_durations + total_clip_count;
	uint32_t* cur_duration;
	uint32_t bootstrap_segment_limit;
	uint32_t segment_index = 0;
	uint32_t clip_segment_limit = 0;
	uint32_t clip_offset;
	uint32_t segment_duration;
	bool_t discontinuity;

	// allocate the result buffer
	result->items = vod_alloc(request_context->pool, sizeof(result->items[0]) * (conf->bootstrap_segments_count + 2 * total_clip_count));
	if (result->items == NULL)
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0,
			"segmenter_get_segment_durations_estimate_internal: vod_alloc failed");
		return VOD_ALLOC_FAILED;
	}

	cur_item = result->items - 1;

	discontinuity = FALSE;
	for (cur_duration = clip_durations; cur_duration < end_duration; cur_duration++)
	{
		// get segment limit for the current clip
		clip_segment_limit = conf->get_segment_count(conf, clip_start_offset + *cur_duration);
		if (clip_segment_limit == INVALID_SEGMENT_COUNT)
		{
			vod_log_error(VOD_LOG_ERR, request_context->log, 0,
				"segmenter_get_segment_durations_estimate_internal: segment count is invalid");
			return VOD_BAD_DATA;
		}

		if (clip_segment_limit <= segment_index)
		{
			clip_segment_limit = segment_index + 1;
		}

		clip_offset = 0;

		// bootstrap segments
		bootstrap_segment_limit = vod_min(clip_segment_limit - 1, conf->bootstrap_segments_count);
		for (; segment_index < bootstrap_segment_limit; segment_index++)
		{
			segment_duration = conf->bootstrap_segments_durations[segment_index];
			if (cur_item < result->items || segment_duration != cur_item->duration || discontinuity)
			{
				cur_item++;
				cur_item->repeat_count = 0;
				cur_item->segment_index = segment_index;
				cur_item->duration = segment_duration;
				cur_item->discontinuity = discontinuity;
				discontinuity = FALSE;
			}
			cur_item->repeat_count++;

			clip_offset += segment_duration;
		}

		// remaining segments
		if (segment_index + 1 < clip_segment_limit)
		{
			segment_duration = conf->segment_duration;
			if (cur_item < result->items || segment_duration != cur_item->duration || discontinuity)
			{
				cur_item++;
				cur_item->repeat_count = 0;
				cur_item->segment_index = segment_index;
				cur_item->duration = segment_duration;
				cur_item->discontinuity = discontinuity;
				discontinuity = FALSE;
			}
			cur_item->repeat_count += clip_segment_limit - segment_index - 1;

			clip_offset += segment_duration * (clip_segment_limit - segment_index - 1);
			segment_index = clip_segment_limit - 1;
		}

		// last segment
		if (segment_index < clip_segment_limit && clip_offset < *cur_duration)
		{
			segment_duration = *cur_duration - clip_offset;
			if (cur_item < result->items || segment_duration != cur_item->duration || discontinuity)
			{
				cur_item++;
				cur_item->repeat_count = 0;
				cur_item->segment_index = segment_index;
				cur_item->duration = segment_duration;
				cur_item->discontinuity = discontinuity;
			}
			cur_item->repeat_count++;
			segment_index = clip_segment_limit;
		}

		// update clip_start_offset
		segmenter_get_start_end_offsets(conf, clip_segment_limit, &clip_start_offset, &ignore);

		discontinuity = TRUE;
	}

	// finalize the result
	result->segment_count = clip_segment_limit;
	result->item_count = cur_item + 1 - result->items;
	result->timescale = 1000;
	result->discontinuities = total_clip_count - 1;

	return VOD_OK;
}
Esempio n. 6
0
vod_status_t
segmenter_get_start_end_ranges_discontinuity(
	request_context_t* request_context,
	segmenter_conf_t* conf,
	uint32_t clip_index,
	uint32_t segment_index,
	uint32_t* clip_durations,
	uint32_t total_clip_count,
	uint64_t total_duration,
	get_clip_ranges_result_t* result)
{
	uint64_t clip_start_offset = 0;
	uint64_t start;
	uint64_t end;
	uint64_t ignore;
	uint32_t* end_duration = clip_durations + total_clip_count;
	uint32_t* cur_duration;
	uint32_t cur_segment_limit;
	uint32_t last_segment_limit = 0;
	uint32_t clip_first_segment_index = 0;
	media_range_t* cur_clip_range;
	uint64_t prev_clips_duration = 0;

	for (cur_duration = clip_durations; ; cur_duration++)
	{
		if (cur_duration >= end_duration)
		{
			vod_log_error(VOD_LOG_ERR, request_context->log, 0,
				"segmenter_get_start_end_ranges_discontinuity: invalid segment index %uD or clip index", segment_index);
			return VOD_BAD_REQUEST;
		}

		// get segment limit for the current clip
		cur_segment_limit = conf->get_segment_count(conf, clip_start_offset + *cur_duration);
		if (cur_segment_limit == INVALID_SEGMENT_COUNT)
		{
			vod_log_error(VOD_LOG_ERR, request_context->log, 0,
				"segmenter_get_start_end_ranges_discontinuity: invalid segment count");
			return VOD_BAD_DATA;
		}

		if (cur_segment_limit <= last_segment_limit)
		{
			cur_segment_limit = last_segment_limit + 1;
		}

		if (clip_index == 1)
		{
			clip_first_segment_index = cur_segment_limit;
			segment_index += clip_first_segment_index;
		}
		
		if (clip_index > 0 && clip_index != INVALID_CLIP_INDEX)
		{
			clip_index--;
		}
		else if (segment_index < cur_segment_limit)
		{
			// the segment index is within this clip, break
			break;
		}

		// move to the next clip
		prev_clips_duration += *cur_duration;
		segmenter_get_start_end_offsets(conf, cur_segment_limit, &clip_start_offset, &ignore);
		last_segment_limit = cur_segment_limit;
	}

	// get start / end position relative to the clip start
	segmenter_get_start_end_offsets(
		conf,
		segment_index,
		&start,
		&end);

	start -= clip_start_offset;
	if (segment_index + 1 >= cur_segment_limit)
	{
		end = *cur_duration;		// last segment in clip
	}
	else
	{
		end -= clip_start_offset;
	}

	// initialize the clip range
	cur_clip_range = vod_alloc(request_context->pool, sizeof(cur_clip_range[0]));
	if (cur_clip_range == NULL)
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0,
			"segmenter_get_start_end_ranges_discontinuity: vod_alloc failed");
		return VOD_ALLOC_FAILED;
	}

	cur_clip_range->timescale = 1000;
	cur_clip_range->start = start;
	cur_clip_range->end = end;

	// initialize the result
	result->initial_sequence_offset = prev_clips_duration;
	result->min_clip_index = result->max_clip_index = cur_duration - clip_durations;
	result->clip_count = 1;
	result->clip_ranges = cur_clip_range;
	result->clip_first_segment_index = clip_first_segment_index;

	return VOD_OK;
}
Esempio n. 7
0
vod_status_t
segmenter_get_start_end_ranges_no_discontinuity(
	request_context_t* request_context,
	segmenter_conf_t* conf,
	uint32_t segment_index,
	uint32_t* clip_durations,
	uint32_t total_clip_count,
	uint64_t total_duration,
	uint64_t last_segment_end,
	get_clip_ranges_result_t* result)
{
	uint64_t clip_start_offset = 0;
	uint64_t next_start_offset;
	uint64_t start;
	uint64_t end;
	media_range_t* cur_clip_range;
	uint32_t* end_duration = clip_durations + total_clip_count;
	uint32_t* cur_duration;
	uint32_t segment_count;
	uint32_t index;

	result->clip_first_segment_index = 0;

	// get the segment count
	segment_count = conf->get_segment_count(conf, total_duration);
	if (segment_count == INVALID_SEGMENT_COUNT)
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"segmenter_get_start_end_ranges_no_discontinuity: segment count is invalid for total duration %uL", total_duration);
		return VOD_BAD_DATA;
	}

	if (segment_index >= segment_count)
	{
		result->clip_count = 0;
		result->min_clip_index = 1;
		result->max_clip_index = 0;
		return VOD_OK;
	}

	// get the start / end offsets
	segmenter_get_start_end_offsets(
		conf,
		segment_index,
		&start,
		&end);

	if (segment_index + 1 >= segment_count)
	{
		end = last_segment_end;
	}

	// find min/max clip indexes and initial sequence offset
	result->min_clip_index = INVALID_CLIP_INDEX;
	result->max_clip_index = total_clip_count - 1;

	for (cur_duration = clip_durations; cur_duration < end_duration; cur_duration++, clip_start_offset = next_start_offset)
	{
		next_start_offset = clip_start_offset + *cur_duration;
		if (start >= next_start_offset)
		{
			continue;
		}

		if (start >= clip_start_offset)
		{
			result->min_clip_index = cur_duration - clip_durations;
			result->initial_sequence_offset = clip_start_offset;
		}

		if (end <= next_start_offset)
		{
			result->max_clip_index = cur_duration - clip_durations;
			break;
		}
	}

	if (result->min_clip_index == INVALID_CLIP_INDEX)
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"segmenter_get_start_end_ranges_no_discontinuity: invalid segment index %uD", segment_index);
		return VOD_BAD_REQUEST;
	}

	// allocate the clip ranges
	result->clip_count = result->max_clip_index - result->min_clip_index + 1;
	cur_clip_range = vod_alloc(request_context->pool, sizeof(result->clip_ranges[0]) * result->clip_count);
	if (cur_clip_range == NULL)
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0,
			"segmenter_get_start_end_ranges_no_discontinuity: vod_alloc failed");
		return VOD_ALLOC_FAILED;
	}

	result->clip_ranges = cur_clip_range;

	// initialize the clip ranges
	start -= result->initial_sequence_offset;
	end -= result->initial_sequence_offset;
	for (index = result->min_clip_index;; index++, cur_clip_range++)
	{
		cur_clip_range->timescale = 1000;
		cur_clip_range->start = start;
		if (index >= result->max_clip_index)
		{
			cur_clip_range->end = end;
			break;
		}

		cur_clip_range->end = clip_durations[index];

		start = 0;
		end -= clip_durations[index];
	}

	return VOD_OK;
}