Пример #1
0
static vod_status_t
mp4_encrypt_write_encrypted(
	mp4_encrypt_state_t* state,
	u_char* cur_pos, 
	uint32_t write_size)
{
	uint32_t cur_write_size;
	size_t alloc_size;
	u_char* write_end;
	u_char* output;
	vod_status_t rc;

	write_end = cur_pos + write_size;
	while (cur_pos < write_end)
	{
		rc = write_buffer_get_bytes(&state->write_buffer, MIN_ALLOC_SIZE, &alloc_size, &output);
		if (rc != VOD_OK)
		{
			return rc;
		}

		cur_write_size = write_end - cur_pos;
		cur_write_size = vod_min(cur_write_size, alloc_size);

		rc = mp4_aes_ctr_process(&state->cipher, output, cur_pos, cur_write_size);
		if (rc != VOD_OK)
		{
			return rc;
		}
		cur_pos += cur_write_size;
		state->write_buffer.cur_pos += cur_write_size;
	}

	return VOD_OK;
}
Пример #2
0
static vod_status_t
hds_muxer_end_frame(hds_muxer_state_t* state)
{
	uint32_t packet_size = state->frame_header_size + state->cur_frame->size;
	vod_status_t rc;
	u_char* p;

	// write the frame size
	rc = write_buffer_get_bytes(&state->write_buffer_state, sizeof(uint32_t), NULL, &p);
	if (rc != VOD_OK)
	{
		vod_log_debug1(VOD_LOG_DEBUG_LEVEL, state->request_context->log, 0,
			"hds_muxer_end_frame: write_buffer_get_bytes failed %i", rc);
		return rc;
	}
	write_be32(p, packet_size);

	return VOD_OK;
}
Пример #3
0
static vod_status_t
hds_muxer_start_frame(hds_muxer_state_t* state)
{
	hds_muxer_stream_state_t* selected_stream;
	uint64_t cur_frame_offset;
	uint64_t cur_frame_dts;
	size_t alloc_size;
	u_char* p;
	vod_status_t rc;

	rc = hds_muxer_choose_stream(state, &selected_stream);
	if (rc != VOD_OK)
	{
		return rc;
	}

	// init the frame
	state->cur_frame = selected_stream->cur_frame;
	state->frames_source = selected_stream->frames_source;
	state->frames_source_context = selected_stream->frames_source_context;
	selected_stream->cur_frame++;
	cur_frame_offset = *selected_stream->cur_frame_input_offset;
	selected_stream->cur_frame_input_offset++;
	selected_stream->cur_frame_output_offset++;

	selected_stream->next_frame_time_offset += state->cur_frame->duration;
	cur_frame_dts = selected_stream->next_frame_dts + selected_stream->clip_start_time;
	selected_stream->next_frame_dts = rescale_time(selected_stream->next_frame_time_offset, selected_stream->timescale, HDS_TIMESCALE);

	state->cache_slot_id = selected_stream->media_type;

	// allocate room for the mux packet header
	state->frame_header_size = tag_size_by_media_type[selected_stream->media_type];

	alloc_size = state->frame_header_size;
	if (selected_stream->media_type == MEDIA_TYPE_VIDEO && state->cur_frame->key_frame)
	{
		alloc_size += state->codec_config_size;
	}

	rc = write_buffer_get_bytes(&state->write_buffer_state, alloc_size, NULL, &p);
	if (rc != VOD_OK)
	{
		vod_log_debug1(VOD_LOG_DEBUG_LEVEL, state->request_context->log, 0,
			"hds_muxer_start_frame: write_buffer_get_bytes failed %i", rc);
		return rc;
	}

	// write the mux packet header and optionally codec config
	if (selected_stream->media_type == MEDIA_TYPE_VIDEO && state->cur_frame->key_frame)
	{
		p = hds_muxer_write_codec_config(p, state, cur_frame_dts);
	}

	switch (selected_stream->media_type)
	{
	case MEDIA_TYPE_VIDEO:
		hds_write_video_tag_header(
			p,
			state->cur_frame->size,
			cur_frame_dts,
			state->cur_frame->key_frame ? FRAME_TYPE_KEY_FRAME : FRAME_TYPE_INTER_FRAME,
			AVC_PACKET_TYPE_NALU,
			rescale_time(state->cur_frame->pts_delay, selected_stream->timescale, HDS_TIMESCALE));
		break;

	case MEDIA_TYPE_AUDIO:
		hds_write_audio_tag_header(
			p,
			state->cur_frame->size,
			cur_frame_dts,
			selected_stream->sound_info,
			AAC_PACKET_TYPE_RAW);
	}

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

	return VOD_OK;
}
Пример #4
0
static vod_status_t
mp4_encrypt_video_write_buffer(void* context, u_char* buffer, uint32_t size)
{
	mp4_encrypt_video_state_t* state = (mp4_encrypt_video_state_t*)context;
	vod_str_t fragment_header;
	u_char* buffer_end = buffer + size;
	u_char* cur_pos = buffer;
	u_char* output;
	uint32_t write_size;
	int32_t cur_shift;
	size_t ignore;
	bool_t init_track;
	vod_status_t rc;

	while (cur_pos < buffer_end)
	{
		switch (state->cur_state)
		{
		case STATE_PACKET_SIZE:
			if (state->base.frame_size_left <= 0)
			{
				rc = mp4_encrypt_video_start_frame(state);
				if (rc != VOD_OK)
				{
					return rc;
				}

				if (state->base.frame_size_left <= 0)
				{
					state->cur_state = STATE_PACKET_DATA;
					break;
				}
			}

			for (; state->length_bytes_left && cur_pos < buffer_end; state->length_bytes_left--)
			{
				state->packet_size_left = (state->packet_size_left << 8) | *cur_pos++;
			}

			if (cur_pos >= buffer_end)
			{
				break;
			}

			if (state->base.frame_size_left < state->nal_packet_size_length + state->packet_size_left)
			{
				vod_log_error(VOD_LOG_ERR, state->base.request_context->log, 0,
					"mp4_encrypt_video_write_buffer: frame size %uD too small, nalu size %uD packet size %uD",
					state->base.frame_size_left, state->nal_packet_size_length, state->packet_size_left);
				return VOD_BAD_DATA;
			}

			state->base.frame_size_left -= state->nal_packet_size_length + state->packet_size_left;

			state->cur_state++;
			// fall through

		case STATE_NAL_TYPE:

			// write the packet size and nal type
			rc = write_buffer_get_bytes(&state->base.write_buffer, state->nal_packet_size_length + 1, NULL, &output);
			if (rc != VOD_OK)
			{
				return rc;
			}

			for (cur_shift = (state->nal_packet_size_length - 1) * 8; cur_shift >= 0; cur_shift -= 8)
			{
				*output++ = (state->packet_size_left >> cur_shift) & 0xff;
			}

			*output++ = *cur_pos++;		// nal type

			// update the packet size
			if (state->packet_size_left <= 0)
			{
				vod_log_error(VOD_LOG_ERR, state->base.request_context->log, 0,
					"mp4_encrypt_video_write_buffer: zero size packet");
				return VOD_BAD_DATA;
			}
			state->packet_size_left--;

			// add the subsample
			rc = mp4_encrypt_video_add_subsample(state, state->nal_packet_size_length + 1, state->packet_size_left);
			if (rc != VOD_OK)
			{
				return rc;
			}

			state->cur_state++;
			// fall through

		case STATE_PACKET_DATA:
			write_size = (uint32_t)(buffer_end - cur_pos);
			write_size = vod_min(write_size, state->packet_size_left);
			
			rc = mp4_encrypt_write_encrypted(&state->base, cur_pos, write_size);
			if (rc != VOD_OK)
			{
				return rc;
			}

			cur_pos += write_size;
			state->packet_size_left -= write_size;
			if (state->packet_size_left > 0)
			{
				break;
			}

			// finished a packet
			state->cur_state = STATE_PACKET_SIZE;
			state->length_bytes_left = state->nal_packet_size_length;
			state->packet_size_left = 0;

			if (state->base.frame_size_left > 0)
			{
				break;
			}

			// finished a frame
			rc = mp4_encrypt_video_end_frame(state);
			if (rc != VOD_OK)
			{
				return rc;
			}

			// move to the next frame
			if (mp4_encrypt_move_to_next_frame(&state->base, &init_track))
			{
				if (init_track)
				{
					rc = mp4_encrypt_video_init_track(state, state->base.cur_clip->first_track);
					if (rc != VOD_OK)
					{
						return rc;
					}
				}

				break;
			}

			// finished all frames
			rc = write_buffer_flush(&state->base.write_buffer, FALSE);
			if (rc != VOD_OK)
			{
				return rc;
			}

			mp4_encrypt_video_prepare_saiz_saio(state);

			rc = state->build_fragment_header(state, &fragment_header, &ignore);
			if (rc != VOD_OK)
			{
				return rc;
			}

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

			break;
		}
	}

	return VOD_OK;
}
Пример #5
0
static vod_status_t
mp4_encrypt_video_snpf_write_buffer(void* context, u_char* buffer, uint32_t size)
{
	mp4_encrypt_video_state_t* state = (mp4_encrypt_video_state_t*)context;
	u_char* buffer_end = buffer + size;
	u_char* cur_pos = buffer;
	u_char* cur_end_pos;
	u_char* output;
	uint32_t write_size;
	bool_t init_track;
	vod_status_t rc;

	while (cur_pos < buffer_end)
	{
		switch (state->cur_state)
		{
		case STATE_CLEAR_BYTES:
			// start a new frame if needed
			if (state->base.frame_size_left <= 0)
			{
				rc = mp4_encrypt_start_frame(&state->base);
				if (rc != VOD_OK)
				{
					return rc;
				}

				if (state->base.frame_size_left <= 0)
				{
					state->cur_state = STATE_ENCRYPTED_BYTES;
					break;
				}
			}

			// copy the clear bytes
			write_size = (uint32_t)(buffer_end - cur_pos);
			write_size = vod_min(write_size, state->length_bytes_left + 1);

			rc = write_buffer_get_bytes(&state->base.write_buffer, write_size, NULL, &output);
			if (rc != VOD_OK)
			{
				return rc;
			}

			// copy the nalu length
			if (write_size >= state->length_bytes_left)
			{
				cur_end_pos = cur_pos + state->length_bytes_left;
				state->length_bytes_left = 0;
			}
			else
			{
				cur_end_pos = cur_pos + write_size;
				state->length_bytes_left -= write_size;
			}

			while (cur_pos < cur_end_pos)
			{
				state->packet_size_left = (state->packet_size_left << 8) | *cur_pos;
				*output++ = *cur_pos++;
			}

			if (cur_pos >= buffer_end)
			{
				break;
			}

			// copy the nalu type
			*output++ = *cur_pos++;

			if (state->base.frame_size_left < state->nal_packet_size_length + 1)
			{
				vod_log_error(VOD_LOG_ERR, state->base.request_context->log, 0,
					"mp4_encrypt_video_snpf_write_buffer: frame size %uD too small, nalu size %uD",
					state->base.frame_size_left, state->nal_packet_size_length);
				return VOD_BAD_DATA;
			}

			state->base.frame_size_left -= state->nal_packet_size_length;

			if (state->packet_size_left != state->base.frame_size_left && 
				!state->single_nalu_warning_printed)
			{
				vod_log_error(VOD_LOG_WARN, state->base.request_context->log, 0,
					"mp4_encrypt_video_snpf_write_buffer: frame does not contain a single nalu, "
					"consider changing vod_min_single_nalu_per_frame_segment, "
					"packet size=%uD, frame size=%uD",
					state->packet_size_left, state->base.frame_size_left);
				state->single_nalu_warning_printed = TRUE;
			}

			state->base.frame_size_left--;

			state->cur_state++;
			// fall through

		case STATE_ENCRYPTED_BYTES:
			write_size = (uint32_t)(buffer_end - cur_pos);
			write_size = vod_min(write_size, state->base.frame_size_left);

			rc = mp4_encrypt_write_encrypted(&state->base, cur_pos, write_size);
			if (rc != VOD_OK)
			{
				return rc;
			}

			cur_pos += write_size;

			state->base.frame_size_left -= write_size;
			if (state->base.frame_size_left > 0)
			{
				break;
			}

			// finished a packet
			state->cur_state = STATE_CLEAR_BYTES;
			state->length_bytes_left = state->nal_packet_size_length;
			state->packet_size_left = 0;

			// move to the next frame
			if (mp4_encrypt_move_to_next_frame(&state->base, &init_track))
			{
				if (init_track)
				{
					rc = mp4_encrypt_video_init_track(state, state->base.cur_clip->first_track);
					if (rc != VOD_OK)
					{
						return rc;
					}
				}

				break;
			}

			// finished all frames
			rc = write_buffer_flush(&state->base.write_buffer, FALSE);
			if (rc != VOD_OK)
			{
				return rc;
			}

			break;
		}
	}

	return VOD_OK;
}