Exemplo n.º 1
0
vod_status_t 
mp4_builder_frame_writer_init(
	request_context_t* request_context,
	media_sequence_t* sequence,
	write_callback_t write_callback,
	void* write_context, 
	bool_t reuse_buffers,
	fragment_writer_state_t** result)
{
	fragment_writer_state_t* state;

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

	state->request_context = request_context;
	state->write_callback = write_callback;
	state->write_context = write_context;
	state->reuse_buffers = reuse_buffers;
	state->frame_started = FALSE;
	state->sequence = sequence;
	state->cur_clip = sequence->filtered_clips;

	mp4_builder_init_track(state, state->cur_clip->first_track);

	*result = state;
	return VOD_OK;
}
Exemplo n.º 2
0
static bool_t
mp4_builder_move_to_next_frame(fragment_writer_state_t* state)
{
	while (state->cur_frame >= state->cur_frame_part.last_frame)
	{
		if (state->cur_frame_part.next != NULL)
		{
			state->cur_frame_part = *state->cur_frame_part.next;
			state->cur_frame = state->cur_frame_part.first_frame;
			state->first_time = TRUE;
			break;
		}

		state->cur_clip++;
		if (state->cur_clip >= state->sequence->filtered_clips_end)
		{
			return FALSE;
		}

		mp4_builder_init_track(state, state->cur_clip->first_track);
	}

	return TRUE;
}
Exemplo n.º 3
0
vod_status_t
mp4_builder_frame_writer_process(fragment_writer_state_t* state)
{
	u_char* read_buffer;
	uint32_t read_size;
	u_char* write_buffer = NULL;
	uint32_t write_buffer_size = 0;
	vod_status_t rc;
	bool_t frame_done;

	if (!state->frame_started)
	{
		while (state->cur_frame >= state->last_frame)
		{
			state->cur_clip++;
			if (state->cur_clip >= state->sequence->filtered_clips_end)
			{
				return VOD_OK;
			}

			mp4_builder_init_track(state, state->cur_clip->first_track);
		}

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

		state->frame_started = TRUE;
	}


	for (;;)
	{
		// read some data from the frame
		rc = state->frames_source->read(state->frames_source_context, &read_buffer, &read_size, &frame_done);
		if (rc != VOD_OK)
		{
			if (rc != VOD_AGAIN)
			{
				return rc;
			}

			if (write_buffer != NULL)
			{
				// flush the write buffer
				rc = state->write_callback(state->write_context, write_buffer, write_buffer_size);
				if (rc != VOD_OK)
				{
					return rc;
				}
			}
			else if (!state->first_time)
			{
				vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
					"mp4_builder_frame_writer_process: no data was handled, probably a truncated file");
				return VOD_BAD_DATA;
			}

			state->first_time = FALSE;
			return VOD_AGAIN;
		}

		if (write_buffer != NULL)
		{
			// if the buffers are contiguous, just increment the size
			if (!state->reuse_buffers && write_buffer + write_buffer_size == read_buffer)
			{
				write_buffer_size += read_size;
			}
			else
			{
				// buffers not contiguous, flush the write buffer
				rc = state->write_callback(state->write_context, write_buffer, write_buffer_size);
				if (rc != VOD_OK)
				{
					return rc;
				}

				// reset the write buffer
				write_buffer = read_buffer;
				write_buffer_size = read_size;
			}
		}
		else
		{
			// reset the write buffer
			write_buffer = read_buffer;
			write_buffer_size = read_size;
		}

		if (!frame_done)
		{
			continue;
		}

		// move to the next frame
		state->cur_frame++;
		state->cur_frame_offset++;

		while (state->cur_frame >= state->last_frame)
		{
			if (write_buffer != NULL)
			{
				// flush the write buffer
				rc = state->write_callback(state->write_context, write_buffer, write_buffer_size);
				if (rc != VOD_OK)
				{
					return rc;
				}

				write_buffer = NULL;
			}

			state->cur_clip++;
			if (state->cur_clip >= state->sequence->filtered_clips_end)
			{
				return VOD_OK;
			}

			mp4_builder_init_track(state, state->cur_clip->first_track);
		}

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