Esempio n. 1
0
static vod_status_t
hds_get_sound_info(request_context_t* request_context, media_info_t* media_info, uint8_t* result)
{
	int sound_rate;
	int sound_size;
	int sound_type;

	if (media_info->u.audio.sample_rate <= 8000)
	{
		sound_rate = SOUND_RATE_5_5_KHZ;
	}
	else if (media_info->u.audio.sample_rate <= 16000)
	{
		sound_rate = SOUND_RATE_11_KHZ;
	}
	else if (media_info->u.audio.sample_rate <= 32000)
	{
		sound_rate = SOUND_RATE_22_KHZ;
	}
	else
	{
		sound_rate = SOUND_RATE_44_KHZ;
	}

	switch (media_info->u.audio.bits_per_sample)
	{
	case 8:
		sound_size = SOUND_SIZE_8_BIT;
		break;
	case 16:
		sound_size = SOUND_SIZE_16_BIT;
		break;
	default:
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"hds_get_sound_info: unsupported bits per sample %uD", (uint32_t)media_info->u.audio.bits_per_sample);
		return VOD_BAD_DATA;
	}

	switch (media_info->u.audio.channels)
	{
	case 1:
		sound_type = SOUND_TYPE_MONO;
		break;
	case 2:
		sound_type = SOUND_TYPE_STEREO;
		break;
	default:
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"hds_get_sound_info: unsupported channels %uD", (uint32_t)media_info->u.audio.channels);
		return VOD_BAD_DATA;
	}

	*result = (SOUND_FORMAT_AAC << 4) | (sound_rate << 2) | (sound_size << 1) | (sound_type);

	return VOD_OK;
}
Esempio n. 2
0
static vod_status_t
mp4_decrypt_start_frame(void* ctx, input_frame_t* frame)
{
	mp4_decrypt_state_t* state = ctx;
	vod_status_t rc;

	rc = state->frames_source->start_frame(state->frames_source_context, frame);
	if (rc != VOD_OK)
	{
		return rc;
	}

	// get the iv
	if (state->auxiliary_info_pos + MP4_AES_CTR_IV_SIZE > state->auxiliary_info_end)
	{
		vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
			"mp4_decrypt_start_frame: failed to get iv from auxiliary info");
		return VOD_BAD_DATA;
	}

	mp4_aes_ctr_set_iv(&state->cipher, state->auxiliary_info_pos);
	state->auxiliary_info_pos += MP4_AES_CTR_IV_SIZE;

	if (!state->use_subsamples)
	{
		state->encrypted_bytes = UINT_MAX;
		return VOD_OK;
	}

	// get the subsample info
	if (state->auxiliary_info_pos + sizeof(uint16_t) + sizeof(cenc_sample_auxiliary_data_subsample_t) > state->auxiliary_info_end)
	{
		vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
			"mp4_decrypt_start_frame: failed to get subsample info from auxiliary info");
		return VOD_BAD_DATA;
	}

	read_be16(state->auxiliary_info_pos, state->subsample_count);
	if (state->subsample_count <= 0)
	{
		vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
			"mp4_decrypt_start_frame: invalid subsample count");
		return VOD_BAD_DATA;
	}

	read_be16(state->auxiliary_info_pos, state->clear_bytes);
	read_be32(state->auxiliary_info_pos, state->encrypted_bytes);

	state->subsample_count--;

	return VOD_OK;
}
Esempio n. 3
0
vod_status_t
rate_filter_create_from_string(
	request_context_t* request_context, 
	vod_str_t* str, 
	media_clip_t* source, 
	media_clip_rate_filter_t** result)
{
	media_clip_rate_filter_t* filter;
	vod_int_t nom;

	nom = vod_atofp(str->data, str->len, 2);
	if (nom < 0)
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"rate_filter_create_from_string: failed to parse playback rate \"%V\", expecting a float with up to 2 digits precision", str);
		return VOD_BAD_REQUEST;
	}

	if (nom < 50 || nom > 200)
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"rate_filter_create_from_string: invalid playback rate value %i/100, must be between 0.5 and 2", nom);
		return VOD_BAD_REQUEST;
	}

	filter = vod_alloc(request_context->pool, sizeof(*filter) + sizeof(filter->base.sources[0]));
	if (filter == NULL)
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0,
			"rate_filter_create_from_string: vod_alloc failed");
		return VOD_ALLOC_FAILED;
	}

	filter->base.parent = NULL;
	filter->base.sources = (void*)(filter + 1);
	filter->base.sources[0] = source;
	filter->base.source_count = 1;

	filter->base.type = MEDIA_CLIP_RATE_FILTER;
	filter->base.audio_filter = &rate_filter;
	filter->rate.nom = nom;
	filter->rate.denom = 100;

	source->parent = &filter->base;

	*result = filter;

	return VOD_OK;
}
Esempio n. 4
0
static vod_status_t
edash_packager_init_stsd_writer_context(
	request_context_t* request_context,
	uint32_t media_type, 
	raw_atom_t* original_stsd, 
	bool_t has_clear_lead,
	u_char* default_kid,
	stsd_writer_context_t* result)
{
	result->media_type = media_type;
	result->has_clear_lead = has_clear_lead;
	result->default_kid = default_kid;

	if (original_stsd->size < original_stsd->header_size + sizeof(stsd_atom_t) + sizeof(stsd_entry_header_t))
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"edash_packager_init_stsd_writer_context: invalid stsd size %uL", original_stsd->size);
		return VOD_BAD_DATA;
	}

	result->original_stsd_entry = (stsd_entry_header_t*)(original_stsd->ptr + original_stsd->header_size + sizeof(stsd_atom_t));
	result->original_stsd_entry_size = parse_be32(result->original_stsd_entry->size);
	result->original_stsd_entry_format = parse_be32(result->original_stsd_entry->format);

	if (result->original_stsd_entry_size < sizeof(stsd_entry_header_t))
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"edash_packager_init_stsd_writer_context: invalid stsd entry size %uD", result->original_stsd_entry_size);
		return VOD_BAD_DATA;
	}

	result->tenc_atom_size = ATOM_HEADER_SIZE + sizeof(tenc_atom_t);
	result->schi_atom_size = ATOM_HEADER_SIZE + result->tenc_atom_size;
	result->schm_atom_size = ATOM_HEADER_SIZE + sizeof(schm_atom_t);
	result->frma_atom_size = ATOM_HEADER_SIZE + sizeof(frma_atom_t);
	result->sinf_atom_size = ATOM_HEADER_SIZE + 
		result->frma_atom_size + 
		result->schm_atom_size + 
		result->schi_atom_size;
	result->encrypted_stsd_entry_size = result->original_stsd_entry_size + result->sinf_atom_size;
	result->stsd_atom_size = ATOM_HEADER_SIZE + sizeof(stsd_atom_t) + result->encrypted_stsd_entry_size;
	if (has_clear_lead)
	{
		result->stsd_atom_size += result->original_stsd_entry_size;
	}

	return VOD_OK;
}
Esempio n. 5
0
vod_status_t
audio_encoder_flush(
	void* context)
{
	audio_encoder_state_t* state = context;
	AVPacket output_packet;
	vod_status_t rc;
	int avrc;

	avrc = avcodec_send_frame(state->encoder, NULL);
	if (avrc < 0)
	{
		vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
			"audio_encoder_flush: avcodec_send_frame failed %d", avrc);
		return VOD_UNEXPECTED;
	}

	for (;;)
	{
		av_init_packet(&output_packet);
		output_packet.data = NULL; // packet data will be allocated by the encoder
		output_packet.size = 0;

		avrc = avcodec_receive_packet(state->encoder, &output_packet);
		if (avrc == AVERROR_EOF)
		{
			break;
		}

		if (avrc < 0)
		{
			vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
				"audio_encoder_flush: avcodec_receive_packet failed %d", avrc);
			return VOD_UNEXPECTED;
		}

		rc = audio_encoder_write_packet(state, &output_packet);

		av_packet_unref(&output_packet);

		if (rc != VOD_OK)
		{
			return rc;
		}
	}

	return VOD_OK;
}
Esempio n. 6
0
static vod_status_t
codec_config_get_avc_codec_name(request_context_t* request_context, media_info_t* media_info)
{
	avcc_config_t* config;
	u_char* p;

	if (media_info->extra_data_size < sizeof(avcc_config_t))
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"codec_config_get_avc_codec_name: extra data too small");
		return VOD_BAD_DATA;
	}

	config = (avcc_config_t*)media_info->extra_data;

	p = vod_sprintf(media_info->codec_name.data, "%*s.%02uxD%02uxD%02uxD",
		(size_t)sizeof(uint32_t),
		&media_info->format,
		(uint32_t)config->profile,
		(uint32_t)config->compatibility,
		(uint32_t)config->level);

	media_info->codec_name.len = p - media_info->codec_name.data;

	return VOD_OK;
}
Esempio n. 7
0
vod_status_t
mp4_aes_ctr_init(
	mp4_aes_ctr_state_t* state,
	request_context_t* request_context, 
	u_char* key)
{
	vod_pool_cleanup_t *cln;

	state->request_context = request_context;

	cln = vod_pool_cleanup_add(request_context->pool, 0);
	if (cln == NULL)
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0,
			"mp4_aes_ctr_init: vod_pool_cleanup_add failed");
		return VOD_ALLOC_FAILED;
	}

	cln->handler = (vod_pool_cleanup_pt)mp4_aes_ctr_cleanup;
	cln->data = state;

	EVP_CIPHER_CTX_init(&state->cipher);

	if (1 != EVP_EncryptInit_ex(&state->cipher, EVP_aes_128_ecb(), NULL, key, NULL))
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"mp4_aes_ctr_init: EVP_EncryptInit_ex failed");
		return VOD_ALLOC_FAILED;
	}

	return VOD_OK;
}
Esempio n. 8
0
vod_status_t 
aes_cbc_encrypt_write(
	aes_cbc_encrypt_context_t* state, 
	u_char* buffer, 
	uint32_t size)
{
	int out_size;

	u_char* encrypted_buffer;

	encrypted_buffer = vod_alloc(state->request_context->pool, aes_round_to_block(size));
	if (encrypted_buffer == NULL)
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, state->request_context->log, 0,
			"aes_cbc_encrypt_write: vod_alloc failed");
		return VOD_ALLOC_FAILED;
	}

	if (1 != EVP_EncryptUpdate(&state->cipher, encrypted_buffer, &out_size, buffer, size))
	{
		vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
			"aes_cbc_encrypt_write: EVP_EncryptUpdate failed");
		return VOD_UNEXPECTED;
	}

	if (out_size == 0)
	{
		return VOD_OK;
	}

	return state->callback(state->callback_context, encrypted_buffer, out_size);
}
vod_status_t
sample_aes_avc_start_nal_unit(void* context, int unit_type, uint32_t unit_size)
{
	sample_aes_avc_filter_state_t* state = (sample_aes_avc_filter_state_t*)context;

	if ((unit_type != AVC_NAL_SLICE && unit_type != AVC_NAL_IDR_SLICE) || unit_size <= MAX_UNENCRYPTED_UNIT_SIZE)
	{
		state->encrypt = FALSE;
		return VOD_OK;
	}

	state->encrypt = TRUE;
	state->cur_offset = 0;
	state->next_encrypt_offset = FIRST_ENCRYPTED_OFFSET;
	state->max_encrypt_offset = unit_size - AES_BLOCK_SIZE;
	state->last_three_bytes = 1;

	// reset the IV (it is ok to call EVP_EncryptInit_ex several times without cleanup)
	if (1 != EVP_EncryptInit_ex(&state->cipher, EVP_aes_128_cbc(), NULL, state->key, state->iv))
	{
		vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
			"sample_aes_avc_start_nal_unit: EVP_EncryptInit_ex failed");
		return VOD_ALLOC_FAILED;
	}

	return VOD_OK;
}
Esempio n. 10
0
static void 
hls_muxer_simulation_reset(hls_muxer_state_t* state)
{
	hls_muxer_stream_state_t* cur_stream;
	vod_status_t rc;

	mpegts_encoder_simulated_start_segment(&state->queue);

	if (state->clips_end > state->clips_start + 1)
	{
		state->cur_clip = state->clips_start;
		rc = hls_muxer_reinit_tracks(state);
		if (rc != VOD_OK)
		{
			vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
				"hls_muxer_simulation_reset: unexpected - hls_muxer_reinit_tracks failed %i", rc);
		}
	}
	else
	{
		for (cur_stream = state->first_stream; cur_stream < state->last_stream; cur_stream++)
		{
			cur_stream->cur_frame_part = *cur_stream->first_frame_part;
			cur_stream->cur_frame = cur_stream->cur_frame_part.first_frame;
			cur_stream->next_frame_time_offset = cur_stream->first_frame_time_offset;
		}
	}

	state->cur_frame = NULL;
}
Esempio n. 11
0
void 
audio_filter_process_init(vod_log_t* log)
{
	avcodec_register_all();
	avfilter_register_all();

	buffersrc_filter = avfilter_get_by_name(BUFFERSRC_FILTER_NAME);
	if (buffersrc_filter == NULL)
	{
		vod_log_error(VOD_LOG_WARN, log, 0,
			"audio_filter_process_init: failed to get buffer source filter, audio filtering is disabled");
		return;
	}

	buffersink_filter = avfilter_get_by_name(BUFFERSINK_FILTER_NAME);
	if (buffersink_filter == NULL)
	{
		vod_log_error(VOD_LOG_WARN, log, 0,
			"audio_filter_process_init: failed to get buffer sink filter, audio filtering is disabled");
		return;
	}

	decoder_codec = avcodec_find_decoder(AV_CODEC_ID_AAC);
	if (decoder_codec == NULL)
	{
		vod_log_error(VOD_LOG_WARN, log, 0,
			"audio_filter_process_init: failed to get AAC decoder, audio filtering is disabled");
		return;
	}

	encoder_codec = avcodec_find_encoder_by_name(AAC_ENCODER_NAME);
	if (encoder_codec == NULL)
	{
		vod_log_error(VOD_LOG_WARN, log, 0,
			"audio_filter_process_init: failed to get AAC encoder, audio filtering is disabled. recompile libavcodec with libfdk_aac to enable it");
		return;
	}

	if (!audio_filter_is_format_supported(encoder_codec, ENCODER_INPUT_SAMPLE_FORMAT))
	{
		vod_log_error(VOD_LOG_WARN, log, 0,
			"audio_filter_process_init: encoder does not support the required input format, audio filtering is disabled");
		return;
	}

	initialized = TRUE;
}
Esempio n. 12
0
vod_status_t
audio_encoder_write_frame(
	void* context,
	AVFrame* frame)
{
	audio_encoder_state_t* state = context;
	vod_status_t rc;
	AVPacket output_packet;
	int avrc;

	// send frame
	avrc = avcodec_send_frame(state->encoder, frame);

	av_frame_unref(frame);

	if (avrc < 0)
	{
		vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
			"audio_encoder_write_frame: avcodec_send_frame failed %d", avrc);
		return VOD_UNEXPECTED;
	}

	// receive packet
	av_init_packet(&output_packet);
	output_packet.data = NULL; // packet data will be allocated by the encoder
	output_packet.size = 0;

	avrc = avcodec_receive_packet(state->encoder, &output_packet);

	if (avrc == AVERROR(EAGAIN))
	{
		return VOD_OK;
	}

	if (avrc < 0)
	{
		vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
			"audio_encoder_write_frame: avcodec_receive_packet failed %d", avrc);
		return VOD_ALLOC_FAILED;
	}

	rc = audio_encoder_write_packet(state, &output_packet);

	av_packet_unref(&output_packet);

	return rc;
}
Esempio n. 13
0
static vod_status_t
audio_filter_choose_source(audio_filter_state_t* state, audio_filter_source_t** result)
{
	audio_filter_source_t* sources_cur;
	audio_filter_source_t* best_source;
	int failed_requests_max;
	int failed_requests;
	int ret;
	vod_status_t rc;

	for (;;)
	{
		ret = avfilter_graph_request_oldest(state->filter_graph);
		if (ret < 0)
		{
			break;
		}

		rc = audio_filter_read_filter_sink(state);
		if (rc != VOD_OK)
		{
			return rc;
		}
	}

	if (ret != AVERROR(EAGAIN))
	{
		vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
			"audio_filter_choose_source: avfilter_graph_request_oldest failed %d", ret);
		return VOD_UNEXPECTED;
	}

	failed_requests_max = -1;
	best_source = NULL;
	for (sources_cur = state->sources; sources_cur < state->sources_end; sources_cur++)
	{
		if (sources_cur->cur_frame >= sources_cur->cur_frame_part.last_frame)
		{
			if (sources_cur->cur_frame_part.next == NULL)
			{
				continue;
			}

			sources_cur->cur_frame_part = *sources_cur->cur_frame_part.next;
			sources_cur->cur_frame = sources_cur->cur_frame_part.first_frame;
		}

		failed_requests = av_buffersrc_get_nb_failed_requests(sources_cur->buffer_src);
		if (failed_requests > failed_requests_max)
		{
			failed_requests_max = failed_requests;
			best_source = sources_cur;
		}
	}

	*result = best_source;

	return VOD_OK;
}
Esempio n. 14
0
vod_status_t 
mss_playready_get_fragment_writer(
	segment_writer_t* result,
	request_context_t* request_context,
	media_set_t* media_set,
	uint32_t segment_index,
	segment_writer_t* segment_writer,
	const u_char* iv,
	bool_t size_only,
	vod_str_t* fragment_header,
	size_t* total_fragment_size)
{
	uint32_t media_type = media_set->sequences[0].media_type;
	vod_status_t rc;

	switch (media_type)
	{
	case MEDIA_TYPE_VIDEO:
		return mp4_encrypt_video_get_fragment_writer(
			result,
			request_context,
			media_set,
			segment_index,
			mss_playready_video_write_fragment_header,
			segment_writer,
			iv);

	case MEDIA_TYPE_AUDIO:
		rc = mp4_encrypt_audio_get_fragment_writer(
			result,
			request_context,
			media_set,
			segment_index,
			segment_writer,
			iv);
		if (rc != VOD_OK)
		{
			return rc;
		}

		rc = mss_playready_audio_build_fragment_header(
			result->context,
			size_only,
			fragment_header,
			total_fragment_size);
		if (rc != VOD_OK)
		{
			return rc;
		}

		return VOD_OK;
	}

	vod_log_error(VOD_LOG_ERR, request_context->log, 0,
		"mss_playready_get_fragment_writer: invalid media type %uD", media_type);
	return VOD_UNEXPECTED;
}
Esempio n. 15
0
vod_status_t 
dash_packager_build_init_mp4(
	request_context_t* request_context,
	media_set_t* media_set,
	bool_t size_only,
	atom_writer_t* extra_moov_atoms_writer,
	atom_writer_t* stsd_atom_writer,
	vod_str_t* result)
{
	init_mp4_sizes_t sizes;
	u_char* p;

	// get the result size
	dash_packager_init_mp4_calc_size(
		media_set,
		extra_moov_atoms_writer,
		stsd_atom_writer,
		&sizes);

	// head request optimization
	if (size_only)
	{
		result->len = sizes.total_size;
		return VOD_OK;
	}

	// allocate the buffer
	result->data = vod_alloc(request_context->pool, sizes.total_size);
	if (result->data == NULL)
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0,
			"dash_packager_build_init_mp4: vod_alloc failed");
		return VOD_ALLOC_FAILED;
	}

	// write the init mp4
	p = dash_packager_init_mp4_write(
		result->data,
		request_context,
		media_set,
		&sizes,
		extra_moov_atoms_writer,
		stsd_atom_writer);

	result->len = p - result->data;

	if (result->len != sizes.total_size)
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"dash_packager_build_init_mp4: result length %uz different than allocated length %uz",
			result->len, sizes.total_size);
		return VOD_UNEXPECTED;
	}

	return VOD_OK;
}
Esempio n. 16
0
vod_status_t 
audio_filter_alloc_state(
	request_context_t* request_context,
	mpeg_stream_metadata_t* stream_metadata,
	void** result)
{
	vod_log_error(VOD_LOG_ERR, request_context->log, 0,
		"audio_filter_alloc_state: audio filtering not supported, recompile with avcodec/avfilter to enable it");
	return VOD_UNEXPECTED;
}
Esempio n. 17
0
vod_status_t
audio_filter_alloc_state(
	request_context_t* request_context,
	media_sequence_t* sequence,
	media_clip_t* clip,
	media_track_t* output_track,
	size_t* cache_buffer_count,
	void** result)
{
	audio_filter_init_context_t init_context;
	vod_status_t rc;

	// get the source count and graph desc size
	init_context.request_context = request_context;
	init_context.graph_desc_size = 0;
	init_context.source_count = 0;
	init_context.output_frame_count = 0;

	rc = audio_filter_walk_filters_prepare_init(&init_context, &clip, 100, 100);
	if (rc != VOD_OK)
	{
		return rc;
	}

	if (clip == NULL || init_context.source_count <= 0)
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"audio_filter_alloc_state: unexpected - no sources found");
		return VOD_UNEXPECTED;
	}

	if (clip->type == MEDIA_CLIP_SOURCE)
	{
		// got left with a source, following a mix of a single source, nothing to do
		return VOD_OK;
	}

	vod_log_error(VOD_LOG_ERR, request_context->log, 0,
		"audio_filter_alloc_state: audio filtering not supported, recompile with avcodec/avfilter to enable it");
	return VOD_UNEXPECTED;
}
Esempio n. 18
0
vod_status_t 
audio_filter_alloc_state(
	request_context_t* request_context,
	read_cache_state_t* read_cache_state,
	media_clip_t* clip,
	media_track_t* output_track,
	void** result)
{
	vod_log_error(VOD_LOG_ERR, request_context->log, 0,
		"audio_filter_alloc_state: audio filtering not supported, recompile with avcodec/avfilter to enable it");
	return VOD_UNEXPECTED;
}
Esempio n. 19
0
void
audio_encoder_process_init(vod_log_t* log)
{
	#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(58, 18, 100)
		avcodec_register_all();
	#endif

	encoder_codec = avcodec_find_encoder_by_name(AAC_ENCODER_NAME);
	if (encoder_codec == NULL)
	{
		vod_log_error(VOD_LOG_WARN, log, 0,
			"audio_encoder_process_init: failed to get AAC encoder, audio encoding is disabled. recompile libavcodec with libfdk_aac to enable it");
		return;
	}

	if (!audio_encoder_is_format_supported(encoder_codec, AUDIO_ENCODER_INPUT_SAMPLE_FORMAT))
	{
		vod_log_error(VOD_LOG_WARN, log, 0,
			"audio_encoder_process_init: encoder does not support the required input format, audio encoding is disabled");
		return;
	}

	initialized = TRUE;
}
Esempio n. 20
0
vod_status_t 
aes_cbc_encrypt_init(
	aes_cbc_encrypt_context_t** context,
	request_context_t* request_context,
	write_callback_t callback,
	void* callback_context,
	const u_char* key,
	const u_char* iv)
{
	aes_cbc_encrypt_context_t* state;
	vod_pool_cleanup_t *cln;

	state = vod_alloc(request_context->pool, sizeof(*state));
	if (state == NULL)
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0,
			"aes_cbc_encrypt_init: vod_alloc failed");
		return VOD_ALLOC_FAILED;
	}

	cln = vod_pool_cleanup_add(request_context->pool, 0);
	if (cln == NULL)
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0,
			"aes_cbc_encrypt_init: vod_pool_cleanup_add failed");
		return VOD_ALLOC_FAILED;
	}

	cln->handler = (vod_pool_cleanup_pt)aes_cbc_encrypt_cleanup;
	cln->data = state;	

	state->callback = callback;
	state->callback_context = callback_context;
	state->request_context = request_context;

	EVP_CIPHER_CTX_init(&state->cipher);
	
	if (1 != EVP_EncryptInit_ex(&state->cipher, EVP_aes_128_cbc(), NULL, key, iv))
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"aes_cbc_encrypt_init: EVP_EncryptInit_ex failed");
		return VOD_ALLOC_FAILED;
	}
	
	*context = state;

	return VOD_OK;
}
Esempio n. 21
0
vod_status_t
hds_packager_build_bootstrap(
	request_context_t* request_context,
	media_set_t* media_set,
	vod_str_t* result)
{
	hds_segment_durations_t segment_durations;
	segmenter_conf_t* segmenter_conf = media_set->segmenter_conf;
	vod_status_t rc;
	size_t result_size;

	rc = segmenter_conf->get_segment_durations(
		request_context,
		segmenter_conf,
		media_set,
		NULL,
		MEDIA_TYPE_NONE,
		&segment_durations.durations);
	if (rc != VOD_OK)
	{
		return rc;
	}

	hds_scale_segment_durations(&segment_durations);

	result_size = hds_get_abst_atom_size(media_set, &segment_durations);

	result->data = vod_alloc(request_context->pool, result_size);
	if (result->data == NULL)
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0,
			"hds_packager_build_bootstrap: vod_alloc failed");
		return VOD_ALLOC_FAILED;
	}

	result->len = hds_write_abst_atom(result->data, media_set, &segment_durations) - result->data;

	if (result->len > result_size)
	{
		vod_log_error(VOD_LOG_ERR, request_context->log, 0,
			"hds_packager_build_bootstrap: result length %uz exceeded allocated length %uz",
			result->len, result_size);
		return VOD_UNEXPECTED;
	}

	return VOD_OK;
}
Esempio n. 22
0
static vod_status_t
mp4_encrypt_video_init_track(mp4_encrypt_video_state_t* state, media_track_t* track)
{
	state->nal_packet_size_length = track->media_info.u.video.nal_packet_size_length;

	if (state->nal_packet_size_length < 1 || state->nal_packet_size_length > 4)
	{
		vod_log_error(VOD_LOG_ERR, state->base.request_context->log, 0,
			"mp4_encrypt_video_init_track: invalid nal packet size length %uD", state->nal_packet_size_length);
		return VOD_BAD_DATA;
	}

	state->cur_state = STATE_PACKET_SIZE;
	state->length_bytes_left = state->nal_packet_size_length;
	state->packet_size_left = 0;

	return VOD_OK;
}
Esempio n. 23
0
vod_status_t
mp4_aes_ctr_process(mp4_aes_ctr_state_t* state, u_char* dest, const u_char* src, uint32_t size)
{
	const u_char* src_end = src + size;
	const u_char* cur_end_pos;
	u_char* encrypted_counter_pos;
	int out_size;

	while (src < src_end)
	{
		if (state->block_offset == 0)
		{
			if (1 != EVP_EncryptUpdate(
				&state->cipher,
				state->encrypted_counter,
				&out_size,
				state->counter,
				sizeof(state->counter)) ||
				out_size != sizeof(state->encrypted_counter))
			{
				vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
					"mp4_aes_ctr_process: EVP_EncryptUpdate failed");
				return VOD_UNEXPECTED;
			}

			mp4_aes_ctr_increment_be64(state->counter + 8);
		}

		encrypted_counter_pos = state->encrypted_counter + state->block_offset;
		cur_end_pos = src + MP4_AES_CTR_COUNTER_SIZE - state->block_offset;
		cur_end_pos = vod_min(cur_end_pos, src_end);

		state->block_offset += cur_end_pos - src;
		state->block_offset &= (MP4_AES_CTR_COUNTER_SIZE - 1);

		while (src < cur_end_pos)
		{
			*dest++ = *src++ ^ *encrypted_counter_pos++;
		}
	}

	return VOD_OK;
}
Esempio n. 24
0
vod_status_t 
aes_cbc_encrypt_flush(aes_cbc_encrypt_context_t* state)
{
	int last_block_len;

	if (1 != EVP_EncryptFinal_ex(&state->cipher, state->last_block, &last_block_len))
	{
		vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
			"aes_cbc_encrypt_flush: EVP_EncryptFinal_ex failed");
		return VOD_UNEXPECTED;
	}

	if (last_block_len == 0)
	{
		return VOD_OK;
	}

	return state->callback(state->callback_context, state->last_block, last_block_len);
}
Esempio n. 25
0
buffer_pool_t*
buffer_pool_create(vod_pool_t* pool, vod_log_t* log, size_t buffer_size, size_t count)
{
	buffer_pool_t* buffer_pool;
	u_char* cur_buffer;
	void* head;

	if ((buffer_size & 0x0F) != 0)
	{
		vod_log_error(VOD_LOG_ERR, log, 0,
			"buffer_pool_create: invalid size %uz must be a multiple of 16", buffer_size);
		return NULL;
	}

	buffer_pool = vod_alloc(pool, sizeof(*buffer_pool));
	if (buffer_pool == NULL) 
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, log, 0,
			"buffer_pool_create: vod_alloc failed (1)");
		return NULL;
	}

	cur_buffer = vod_alloc(pool, buffer_size * count);
	if (cur_buffer == NULL)
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, log, 0,
			"buffer_pool_create: vod_alloc failed (2)");
		return NULL;
	}

	head = NULL;
	for (; count > 0; count--, cur_buffer += buffer_size)
	{
		next_buffer(cur_buffer) = head;
		head = cur_buffer;
	}

	buffer_pool->size = buffer_size;
	buffer_pool->head = head;

	return buffer_pool;
}
Esempio n. 26
0
static int64_t
segmenter_align_to_key_frames(
	align_to_key_frames_context_t* context,
	int64_t offset,
	int64_t limit)
{
	int64_t cur_duration;

	for (;
		context->offset < offset;
		context->cur_pos++)
	{
		if ((void*)context->cur_pos >= context->part->last)
		{
			if (context->part->next == NULL)
			{
				return limit;
			}

			context->part = context->part->next;
			context->cur_pos = context->part->first;
		}

		cur_duration = *context->cur_pos;

		if (cur_duration <= 0 || cur_duration > MAX_CLIP_DURATION)
		{
			vod_log_error(VOD_LOG_WARN, context->request_context->log, 0,
				"segmenter_align_to_key_frames: ignoring invalid key frame duration %L", cur_duration);
			continue;
		}

		context->offset += cur_duration;
		if (context->offset >= limit)
		{
			return limit;
		}
	}

	return vod_min(context->offset, limit);
}
Esempio n. 27
0
static vod_status_t
mp4_encrypt_start_frame(mp4_encrypt_state_t* state)
{
	// make sure we have a frame
	if (state->cur_frame >= state->last_frame)
	{
		vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
		"mp4_encrypt_start_frame: no more frames");
		return VOD_BAD_DATA;
	}

	// get the frame size
	state->frame_size_left = state->cur_frame->size;
	state->cur_frame++;

	// set and increment the iv
	mp4_aes_ctr_set_iv(&state->cipher, state->iv);
	mp4_aes_ctr_increment_be64(state->iv);

	return VOD_OK;
}
Esempio n. 28
0
static void 
hls_muxer_simulation_reset(hls_muxer_state_t* state)
{
	hls_muxer_stream_state_t* cur_stream;
	vod_status_t rc;

	mpegts_encoder_simulated_start_segment(&state->queue);

	if (state->media_set->clip_count > 1)
	{
		state->first_clip_track = state->media_set->filtered_tracks;
		rc = hls_muxer_reinit_tracks(state);
		if (rc != VOD_OK)
		{
			vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
				"hls_muxer_simulation_reset: unexpected - hls_muxer_reinit_tracks failed %i", rc);
		}

		// need to explicitly reset the id3 stream since reinit tracks skips it
		cur_stream = state->last_stream - 1;
		if (cur_stream->media_type == MEDIA_TYPE_NONE)
		{
			cur_stream->cur_frame_part = *cur_stream->first_frame_part;
			cur_stream->cur_frame = cur_stream->cur_frame_part.first_frame;
			cur_stream->next_frame_time_offset = cur_stream->first_frame_time_offset;
		}
	}
	else
	{
		for (cur_stream = state->first_stream; cur_stream < state->last_stream; cur_stream++)
		{
			cur_stream->cur_frame_part = *cur_stream->first_frame_part;
			cur_stream->cur_frame = cur_stream->cur_frame_part.first_frame;
			cur_stream->source = get_frame_part_source_clip(cur_stream->cur_frame_part);
			cur_stream->next_frame_time_offset = cur_stream->first_frame_time_offset;
		}
	}

	state->cur_frame = NULL;
}
Esempio n. 29
0
static vod_status_t
audio_filter_flush_encoder(audio_filter_state_t* state)
{
	AVPacket output_packet;
	vod_status_t rc;
	int got_packet;
	int avrc;
	
	for (;;)
	{
		av_init_packet(&output_packet);
		output_packet.data = NULL; // packet data will be allocated by the encoder
		output_packet.size = 0;
		
		got_packet = 0;
		avrc = avcodec_encode_audio2(state->sink.encoder, &output_packet, NULL, &got_packet);
		if (avrc < 0)
		{
			vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
				"audio_filter_flush_encoder: avcodec_encode_audio2 failed %d", avrc);
			return VOD_UNEXPECTED;
		}
		
		if (!got_packet)
		{
			break;
		}

		rc = audio_filter_write_frame(state, &output_packet);

		av_free_packet(&output_packet);

		if (rc != VOD_OK)
		{
			return rc;
		}
	}
	
	return audio_filter_update_track(state);
}
Esempio n. 30
0
vod_status_t
audio_encoder_update_media_info(
	void* context,
	media_info_t* media_info)
{
	audio_encoder_state_t* state = context;
	AVCodecContext *encoder = state->encoder;
	u_char* new_extra_data;

	if (encoder->time_base.num != 1)
	{
		vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
			"audio_encoder_update_media_info: unexpected encoder time base %d/%d",
			encoder->time_base.num, encoder->time_base.den);
		return VOD_UNEXPECTED;
	}

	media_info->timescale = encoder->time_base.den;
	media_info->bitrate = encoder->bit_rate;

	media_info->u.audio.object_type_id = 0x40;		// ffmpeg always writes 0x40 (ff_mp4_obj_type)
	media_info->u.audio.channels = encoder->channels;
	media_info->u.audio.bits_per_sample = AUDIO_ENCODER_BITS_PER_SAMPLE;
	media_info->u.audio.packet_size = 0;			// ffmpeg always writes 0 (mov_write_audio_tag)
	media_info->u.audio.sample_rate = encoder->sample_rate;

	new_extra_data = vod_alloc(state->request_context->pool, encoder->extradata_size);
	if (new_extra_data == NULL)
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, state->request_context->log, 0,
			"audio_encoder_update_media_info: vod_alloc failed");
		return VOD_ALLOC_FAILED;
	}
	vod_memcpy(new_extra_data, encoder->extradata, encoder->extradata_size);

	media_info->extra_data.data = new_extra_data;
	media_info->extra_data.len = encoder->extradata_size;

	return VOD_OK;
}