Пример #1
0
vod_status_t
audio_filter_process(void* context)
{
	audio_filter_state_t* state = context;
	audio_filter_source_t* source;
	u_char* read_buffer;
	uint32_t read_size;
	uint64_t offset;
	bool_t processed_data = FALSE;
	vod_status_t rc;

	for (;;)
	{
		// choose a source if needed
		if (state->cur_source == NULL)
		{
			rc = audio_filter_choose_source(state, &source);
			if (rc != VOD_OK)
			{
				return rc;
			}

			if (source == NULL)
			{
				// done
				return audio_filter_flush_encoder(state);
			}

			state->cur_source = source;
		}
		else
		{
			source = state->cur_source;
		}

		// read some data from the frame
		offset = *source->cur_frame_offset + state->cur_frame_pos;
		if (!read_cache_get_from_cache(
			state->read_cache_state,
			source->cur_frame->size - state->cur_frame_pos,
			source->cache_slot_id,
			source->frames_source,
			offset,
			&read_buffer,
			&read_size))
		{
			if (!processed_data && !state->first_time)
			{
				vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
					"audio_filter_process: no data was handled, probably a truncated file");
				return VOD_BAD_DATA;
			}

			state->first_time = FALSE;
			return VOD_AGAIN;
		}

		processed_data = TRUE;

		if (state->cur_frame_pos == 0 && read_size >= source->cur_frame->size)
		{
			// have the whole frame in one piece
			rc = audio_filter_process_frame(state, read_buffer);
			if (rc != VOD_OK)
			{
				return rc;
			}

			// move to the next frame
			source->cur_frame++;
			source->cur_frame_offset++;
			state->cur_source = NULL;
			continue;
		}

		if (read_size < source->cur_frame->size - state->cur_frame_pos)
		{
			// didn't finish the frame, append to the frame buffer
			vod_memcpy(state->frame_buffer + state->cur_frame_pos, read_buffer, read_size);
			state->cur_frame_pos += read_size;
			continue;
		}

		// finished the frame
		vod_memcpy(state->frame_buffer + state->cur_frame_pos, read_buffer, source->cur_frame->size - state->cur_frame_pos);

		rc = audio_filter_process_frame(state, state->frame_buffer);
		if (rc != VOD_OK)
		{
			return rc;
		}

		source->cur_frame++;
		source->cur_frame_offset++;
		state->cur_frame_pos = 0;
		state->cur_source = NULL;
	}
}
Пример #2
0
vod_status_t
audio_filter_process(void* context)
{
	audio_filter_state_t* state = context;
	audio_filter_source_t* source;
	u_char* read_buffer;
	uint32_t read_size;
	bool_t processed_data = FALSE;
	vod_status_t rc;
	bool_t frame_done;

	for (;;)
	{
		// choose a source if needed
		if (state->cur_source == NULL)
		{
			rc = audio_filter_choose_source(state, &source);
			if (rc != VOD_OK)
			{
				return rc;
			}

			if (source == NULL)
			{
				// done
				return audio_filter_flush_encoder(state);
			}

			state->cur_source = source;

			// start the frame
			rc = source->cur_frame_part.frames_source->start_frame(
				source->cur_frame_part.frames_source_context, 
				source->cur_frame);
			if (rc != VOD_OK)
			{
				return rc;
			}
		}
		else
		{
			source = state->cur_source;
		}

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

			if (!processed_data && !state->first_time)
			{
				vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
					"audio_filter_process: no data was handled, probably a truncated file");
				return VOD_BAD_DATA;
			}

			state->first_time = FALSE;
			return VOD_AGAIN;
		}

		processed_data = TRUE;

		if (!frame_done)
		{
			// didn't finish the frame, append to the frame buffer
			vod_memcpy(state->frame_buffer + state->cur_frame_pos, read_buffer, read_size);
			state->cur_frame_pos += read_size;
			continue;
		}

		if (state->cur_frame_pos != 0)
		{
			// copy the remainder
			vod_memcpy(state->frame_buffer + state->cur_frame_pos, read_buffer, read_size);
			state->cur_frame_pos = 0;
			read_buffer = state->frame_buffer;
		}

		// process the frame
		rc = audio_filter_process_frame(state, read_buffer);
		if (rc != VOD_OK)
		{
			return rc;
		}

		// move to the next frame
		source->cur_frame++;
		state->cur_source = NULL;
	}
}
Пример #3
0
vod_status_t 
audio_filter_process_frame(void* context, input_frame_t* frame, u_char* buffer)
{
	audio_filter_state_t* state = (audio_filter_state_t*)context;
	vod_status_t rc;
	AVPacket output_packet;
	AVPacket input_packet;
	int got_packet;
	int got_frame;
	int ret;
#ifdef AUDIO_FILTER_DEBUG
	size_t data_size;
#endif // AUDIO_FILTER_DEBUG
	
	if (frame == NULL)
	{
		return audio_filter_flush_encoder(state);
	}

#ifdef AUDIO_FILTER_DEBUG
	audio_filter_append_debug_data(AUDIO_FILTER_DEBUG_FILENAME_INPUT, buffer, frame->size);
#endif // AUDIO_FILTER_DEBUG
	
	vod_memzero(&input_packet, sizeof(input_packet));
	input_packet.data = buffer;
	input_packet.size = frame->size;
	input_packet.dts = state->dts;
	input_packet.pts = (state->dts + frame->pts_delay);
	input_packet.duration = frame->duration;
	input_packet.flags = AV_PKT_FLAG_KEY;
	state->dts += frame->duration;
	
	avcodec_get_frame_defaults(state->decoded_frame);

	got_frame = 0;
	ret = avcodec_decode_audio4(state->decoder, state->decoded_frame, &got_frame, &input_packet);
	if (ret < 0) 
	{
		vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
			"audio_filter_process_frame: avcodec_decode_audio4 failed %d", ret);
		return VOD_BAD_DATA;
	}

	if (!got_frame)
	{
		return VOD_OK;
	}

#ifdef AUDIO_FILTER_DEBUG
	data_size = av_samples_get_buffer_size(
		NULL, 
		state->decoder->channels,
		state->decoded_frame->nb_samples,
		state->decoder->sample_fmt, 
		1);
	audio_filter_append_debug_data(AUDIO_FILTER_DEBUG_FILENAME_DECODED, state->decoded_frame->data[0], data_size);
#endif // AUDIO_FILTER_DEBUG
	
	ret = av_buffersrc_add_frame_flags(state->buffer_src, state->decoded_frame, AV_BUFFERSRC_FLAG_PUSH);
	if (ret < 0) 
	{
		vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
			"audio_filter_process_frame: av_buffersrc_add_frame_flags failed %d", ret);
		return VOD_ALLOC_FAILED;
	}

	for (;;)
	{
		ret = av_buffersink_get_frame_flags(state->buffer_sink, state->filtered_frame, AV_BUFFERSINK_FLAG_NO_REQUEST);
		if (ret == AVERROR(EAGAIN) || ret == AVERROR_EOF)
		{
			break;
		}
		
		if (ret < 0)
		{
			vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
				"audio_filter_process_frame: av_buffersink_get_frame_flags failed %d", ret);
			return VOD_UNEXPECTED;
		}

#ifdef AUDIO_FILTER_DEBUG
		data_size = av_samples_get_buffer_size(
			NULL, 
			state->encoder->channels,
			state->filtered_frame->nb_samples,
			state->encoder->sample_fmt, 
			1);
		audio_filter_append_debug_data(AUDIO_FILTER_DEBUG_FILENAME_FILTERED, state->filtered_frame->data[0], data_size);
#endif // AUDIO_FILTER_DEBUG

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

		got_packet = 0;
		ret = avcodec_encode_audio2(state->encoder, &output_packet, state->filtered_frame, &got_packet);
		if (ret < 0)
		{
			vod_log_error(VOD_LOG_ERR, state->request_context->log, 0,
				"audio_filter_process_frame: avcodec_encode_audio2 failed %d", ret);
			return VOD_ALLOC_FAILED;
		}
		
		if (got_packet)
		{
			rc = audio_filter_write_frame(state, &output_packet);

			av_free_packet(&output_packet);
			
			if (rc != VOD_OK)
			{
				return rc;
			}
		}
		
		av_frame_unref(state->filtered_frame);
	}
	
	return VOD_OK;
}