static vod_status_t
mss_playready_audio_build_fragment_header(
	mp4_encrypt_state_t* state,
	bool_t size_only,
	vod_str_t* fragment_header,
	size_t* total_fragment_size)
{
	vod_status_t rc;
	mss_playready_audio_extra_traf_atoms_context writer_context;

	writer_context.uuid_piff_atom_size = ATOM_HEADER_SIZE + sizeof(uuid_piff_atom_t) + mp4_encrypt_audio_get_auxiliary_data_size(state);
	writer_context.state = state;

	rc = mss_packager_build_fragment_header(
		state->request_context,
		state->media_set,
		state->segment_index,
		writer_context.uuid_piff_atom_size + state->saiz_atom_size + state->saio_atom_size,
		mss_playready_audio_write_extra_traf_atoms,
		&writer_context,
		size_only,
		fragment_header,
		total_fragment_size);
	if (rc != VOD_OK)
	{
		vod_log_debug1(VOD_LOG_DEBUG_LEVEL, state->request_context->log, 0,
			"mss_playready_audio_build_fragment_header: mss_packager_build_fragment_header failed %i", rc);
		return rc;
	}

	return VOD_OK;
}
Example #2
0
static vod_status_t
mss_playready_video_write_fragment_header(mp4_encrypt_video_state_t* state)
{
	mss_playready_video_extra_traf_atoms_context writer_context;
	vod_str_t fragment_header;
	size_t total_fragment_size;
	bool_t reuse_buffer;
	vod_status_t rc;

	writer_context.uuid_piff_atom_size = ATOM_HEADER_SIZE + sizeof(uuid_piff_atom_t) + state->auxiliary_data.pos - state->auxiliary_data.start;
	writer_context.state = state;

	rc = mss_packager_build_fragment_header(
		state->base.request_context,
		state->base.sequence,
		state->base.segment_index,
		writer_context.uuid_piff_atom_size + state->base.saiz_atom_size + state->base.saio_atom_size,
		mss_playready_video_write_extra_traf_atoms,
		&writer_context,
		FALSE,
		&fragment_header,
		&total_fragment_size);
	if (rc != VOD_OK)
	{
		vod_log_debug1(VOD_LOG_DEBUG_LEVEL, state->base.request_context->log, 0,
			"mss_playready_video_write_fragment_header: mss_packager_build_fragment_header failed %i", rc);
		return rc;
	}

	rc = state->base.segment_writer.write_head(
		state->base.segment_writer.context,
		fragment_header.data,
		fragment_header.len,
		&reuse_buffer);
	if (rc != VOD_OK)
	{
		vod_log_debug1(VOD_LOG_DEBUG_LEVEL, state->base.request_context->log, 0,
			"mss_playready_video_write_fragment_header: write_head failed %i", rc);
		return rc;
	}

	return VOD_OK;
}
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)
{
	mp4_encrypt_passthrough_context_t passthrough_context;
	uint32_t media_type = media_set->sequences[0].media_type;
	vod_status_t rc;

	if (mp4_encrypt_passthrough_init(&passthrough_context, media_set->sequences))
	{
		vod_log_debug0(VOD_LOG_DEBUG_LEVEL, request_context->log, 0,
			"mss_playready_get_fragment_writer: using encryption passthrough");

		// build the fragment header
		rc = mss_packager_build_fragment_header(
			request_context,
			media_set,
			segment_index,
			passthrough_context.total_size + ATOM_HEADER_SIZE + sizeof(uuid_piff_atom_t),
			mss_playready_passthrough_write_encryption_atoms, 
			&passthrough_context,
			size_only,
			fragment_header,
			total_fragment_size);
		if (rc != VOD_OK)
		{
			vod_log_debug1(VOD_LOG_DEBUG_LEVEL, request_context->log, 0,
				"mss_playready_get_fragment_writer: mss_packager_build_fragment_header failed %i", rc);
			return rc;
		}

		// use original writer
		vod_memzero(result, sizeof(*result));

		return VOD_OK;
	}

	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;
}
static ngx_int_t
ngx_http_vod_mss_init_frame_processor(
	ngx_http_vod_submodule_context_t* submodule_context,
	read_cache_state_t* read_cache_state,
	segment_writer_t* segment_writer,
	ngx_http_vod_frame_processor_t* frame_processor,
	void** frame_processor_state,
	ngx_str_t* output_buffer,
	size_t* response_size,
	ngx_str_t* content_type)
{
	fragment_writer_state_t* state;
	segment_writer_t drm_writer;
	vod_status_t rc;
	bool_t size_only = ngx_http_vod_submodule_size_only(submodule_context);

	if (submodule_context->conf->drm_enabled)
	{
		rc = mss_playready_get_fragment_writer(
			&drm_writer,
			&submodule_context->request_context,
			submodule_context->mpeg_metadata.first_stream,
			submodule_context->request_params.segment_index,
			segment_writer,
			submodule_context->cur_suburi->file_key,		// iv
			size_only,
			output_buffer,
			response_size);
		if (rc != VOD_OK)
		{
			ngx_log_debug1(NGX_LOG_DEBUG_HTTP, submodule_context->request_context.log, 0,
				"ngx_http_vod_mss_init_frame_processor: mss_playready_get_fragment_writer failed %i", rc);
			return ngx_http_vod_status_to_ngx_error(rc);
		}

		segment_writer = &drm_writer;
	}
	else
	{
		rc = mss_packager_build_fragment_header(
			&submodule_context->request_context,
			submodule_context->mpeg_metadata.first_stream,
			submodule_context->request_params.segment_index,
			0,
			NULL,
			NULL,
			size_only,
			output_buffer,
			response_size);
		if (rc != VOD_OK)
		{
			ngx_log_debug1(NGX_LOG_DEBUG_HTTP, submodule_context->request_context.log, 0,
				"ngx_http_vod_mss_init_frame_processor: mss_packager_build_fragment_header failed %i", rc);
			return ngx_http_vod_status_to_ngx_error(rc);
		}
	}

	if (!size_only || *response_size == 0)
	{
		rc = mp4_builder_frame_writer_init(
			&submodule_context->request_context,
			submodule_context->mpeg_metadata.first_stream,
			read_cache_state,
			segment_writer->write_tail,
			segment_writer->context,
			&state);
		if (rc != VOD_OK)
		{
			ngx_log_debug1(NGX_LOG_DEBUG_HTTP, submodule_context->request_context.log, 0,
				"ngx_http_vod_mss_init_frame_processor: mp4_builder_frame_writer_init failed %i", rc);
			return ngx_http_vod_status_to_ngx_error(rc);
		}

		*frame_processor = (ngx_http_vod_frame_processor_t)mp4_builder_frame_writer_process;
		*frame_processor_state = state;
	}

	// set the 'Content-type' header
	if (submodule_context->mpeg_metadata.stream_count[MEDIA_TYPE_VIDEO])
	{
		content_type->len = sizeof(mp4_video_content_type) - 1;
		content_type->data = mp4_video_content_type;
	}
	else
	{
		content_type->len = sizeof(mp4_audio_content_type) - 1;
		content_type->data = mp4_audio_content_type;
	}

	return NGX_OK;
}
static ngx_int_t
ngx_http_vod_mss_init_frame_processor(
	ngx_http_vod_submodule_context_t* submodule_context,
	segment_writer_t* segment_writer,
	ngx_http_vod_frame_processor_t* frame_processor,
	void** frame_processor_state,
	ngx_str_t* output_buffer,
	size_t* response_size,
	ngx_str_t* content_type)
{
	fragment_writer_state_t* state;
	segment_writer_t drm_writer;
	vod_status_t rc;
	bool_t reuse_buffers = FALSE;
	bool_t size_only = ngx_http_vod_submodule_size_only(submodule_context);

	if (submodule_context->conf->drm_enabled)
	{
		rc = mss_playready_get_fragment_writer(
			&drm_writer,
			&submodule_context->request_context,
			&submodule_context->media_set,
			submodule_context->request_params.segment_index,
			segment_writer,
			submodule_context->media_set.sequences[0].encryption_key,		// iv
			size_only,
			output_buffer,
			response_size);
		if (rc != VOD_OK)
		{
			ngx_log_debug1(NGX_LOG_DEBUG_HTTP, submodule_context->request_context.log, 0,
				"ngx_http_vod_mss_init_frame_processor: mss_playready_get_fragment_writer failed %i", rc);
			return ngx_http_vod_status_to_ngx_error(rc);
		}

		if (drm_writer.write_tail != NULL)
		{
			segment_writer = &drm_writer;
			reuse_buffers = TRUE;		// mp4_encrypt allocates new buffers
		}
	}
	else
	{
		rc = mss_packager_build_fragment_header(
			&submodule_context->request_context,
			&submodule_context->media_set,
			submodule_context->request_params.segment_index,
			0,
			NULL,
			NULL,
			size_only,
			output_buffer,
			response_size);
		if (rc != VOD_OK)
		{
			ngx_log_debug1(NGX_LOG_DEBUG_HTTP, submodule_context->request_context.log, 0,
				"ngx_http_vod_mss_init_frame_processor: mss_packager_build_fragment_header failed %i", rc);
			return ngx_http_vod_status_to_ngx_error(rc);
		}
	}

	if (!size_only || *response_size == 0)
	{
		rc = mp4_builder_frame_writer_init(
			&submodule_context->request_context,
			submodule_context->media_set.sequences,
			segment_writer->write_tail,
			segment_writer->context,
			reuse_buffers,
			&state);
		if (rc != VOD_OK)
		{
			ngx_log_debug1(NGX_LOG_DEBUG_HTTP, submodule_context->request_context.log, 0,
				"ngx_http_vod_mss_init_frame_processor: mp4_builder_frame_writer_init failed %i", rc);
			return ngx_http_vod_status_to_ngx_error(rc);
		}

		*frame_processor = (ngx_http_vod_frame_processor_t)mp4_builder_frame_writer_process;
		*frame_processor_state = state;
	}

	// set the 'Content-type' header
	if (submodule_context->media_set.track_count[MEDIA_TYPE_VIDEO])
	{
		content_type->len = sizeof(mp4_video_content_type) - 1;
		content_type->data = mp4_video_content_type;
	}
	else
	{
		content_type->len = sizeof(mp4_audio_content_type) - 1;
		content_type->data = mp4_audio_content_type;
	}

	return NGX_OK;
}