Exemplo n.º 1
0
/* Play the stream (global decoder_stream) using the given decoder. */
static void play_stream (const struct decoder *f, struct out_buf *out_buf)
{
	void *decoder_data;
	struct sound_params sound_params = { 0, 0, 0 };
	struct decoder_error err;
	struct md5_data null_md5;

	null_md5.okay = false;
	out_buf_reset (out_buf);

	assert (f->open_stream != NULL);

	decoder_data = f->open_stream (decoder_stream);
	f->get_error (decoder_data, &err);
	if (err.type != ERROR_OK) {
		LOCK (decoder_stream_mut);
		decoder_stream = NULL;
		UNLOCK (decoder_stream_mut);

		f->close (decoder_data);
		error ("%s", err.err);
		decoder_error_clear (&err);
		logit ("Can't open file");
	}
	else {
		audio_state_started_playing ();
		bitrate_list_init (&bitrate_list);
		decode_loop (f, decoder_data, NULL, out_buf, &sound_params,
				&null_md5, 0.0);
	}
}
Exemplo n.º 2
0
static int wav_decode (void *prv_data, char *buf, int buf_len,
		struct sound_params *sound_params)
{
	struct wavpack_data *data = (struct wavpack_data *)prv_data;
	int ret, i, s_num, iBps, oBps;

	int8_t * buf8 = (int8_t *)buf;
	int16_t * buf16 = (int16_t *)buf;
	int32_t * buf32 = (int32_t *)buf;


	iBps = data->channels * WavpackGetBytesPerSample (data->wpc);
	oBps = (iBps == 6) ? 8 : iBps;
	s_num = buf_len / oBps;

	decoder_error_clear (&data->error);

	int32_t *dbuf = (int32_t *)xcalloc (
			 s_num, data->channels * 4);

	ret = WavpackUnpackSamples (data->wpc, dbuf, s_num );

	if (ret == 0) {
		free (dbuf);
		return 0;
	}

	if (data->mode & MODE_FLOAT) {
		sound_params->fmt = SFMT_FLOAT;
		memcpy (buf, dbuf, ret * oBps);
	} else	{
		debug ("iBps %d", iBps);
		switch (iBps / data->channels){
		case 4: for (i = 0; i < ret * data->channels; i++)
				buf32[i] = dbuf[i];
			sound_params->fmt = SFMT_S32 | SFMT_NE;
			break;
		case 3: for (i = 0; i < ret * data->channels; i++)
				buf32[i] = dbuf[i] * 256;
			sound_params->fmt = SFMT_S32 | SFMT_NE;
			break;
		case 2: for (i = 0; i < ret * data->channels; i++)
				buf16[i] = dbuf[i];
			sound_params->fmt = SFMT_S16 | SFMT_NE;
			break;
		case 1: for (i = 0; i < ret * data->channels; i++)
				buf8[i] = dbuf[i];
			sound_params->fmt = SFMT_S8 | SFMT_NE;
		}
	}

	sound_params->channels = data->channels;
	sound_params->rate = data->sample_rate;

	free (dbuf);
	return ret * oBps ;
}
Exemplo n.º 3
0
static void aac_close (void *prv_data)
{
	struct aac_data *data = (struct aac_data *)prv_data;

	NeAACDecClose (data->decoder);
	io_close (data->stream);
	decoder_error_clear (&data->error);
	free (data);
}
Exemplo n.º 4
0
static void sndfile_close (void *void_data)
{
	struct sndfile_data *data = (struct sndfile_data *)void_data;

	if (data->sndfile)
		sf_close (data->sndfile);

	decoder_error_clear (&data->error);
	free (data);
}
Exemplo n.º 5
0
static void timidity_close (void *void_data)
{
  struct timidity_data *data = (struct timidity_data *)void_data;

  if (data->midisong) {
    mid_song_free(data->midisong);
  }

  decoder_error_clear (&data->error);
  free (data);
}
Exemplo n.º 6
0
static void wav_close (void *prv_data)
{
	struct wavpack_data *data = (struct wavpack_data *)prv_data;

	if (data->ok) {
		WavpackCloseFile (data->wpc);
	}

	decoder_error_clear (&data->error);
	free (data);
	logit ("File closed");
}
Exemplo n.º 7
0
static void mp3_close (void *void_data)
{
	struct mp3_data *data = (struct mp3_data *)void_data;

	if (data->ok) {
		io_close (data->io_stream);
		mad_stream_finish (&data->stream);
		mad_frame_finish (&data->frame);
		mad_synth_finish (&data->synth);
	}
	decoder_error_clear (&data->error);
	free (data);
}
Exemplo n.º 8
0
static void ffmpeg_close (void *prv_data)
{
	struct ffmpeg_data *data = (struct ffmpeg_data *)prv_data;

	if (data->ok) {
		avcodec_close (data->enc);
		av_close_input_file (data->ic);

		if (data->remain_buf)
			free (data->remain_buf);
	}

	decoder_error_clear (&data->error);
	free (data);
}
Exemplo n.º 9
0
Arquivo: speex.c Projeto: gitkaste/moc
static void spx_close (void *prv_data)
{
	struct spx_data *data = (struct spx_data *)prv_data;

	if (data->ok) {
		if (data->st)
			speex_decoder_destroy (data->st);
		if (data->comment_packet)
			free (data->comment_packet);
		if (data->output)
			free (data->output);
		speex_bits_destroy (&data->bits);
		ogg_stream_clear (&data->os);
		ogg_sync_clear (&data->oy);
		io_close (data->stream);
	}
	
	decoder_error_clear (&data->error);

	free (data);
}
Exemplo n.º 10
0
static int ffmpeg_decode (void *prv_data, char *buf, int buf_len,
		struct sound_params *sound_params)
{
	struct ffmpeg_data *data = (struct ffmpeg_data *)prv_data;
	int ret;
	int data_size;
	AVPacket pkt, pkt_tmp;
	uint8_t *pkt_data;
	int pkt_size = 0;
	int filled = 0;

	/* The sample buffer should be 16 byte aligned (because SSE), a segmentation
	 * fault may occur otherwise.
	 * 
	 * See: avcodec.h in ffmpeg
	 */
	char avbuf[(AVCODEC_MAX_AUDIO_FRAME_SIZE * 3) / 2] __attribute__((aligned(16)));

	decoder_error_clear (&data->error);

	sound_params->channels = data->enc->channels;
	sound_params->rate = data->enc->sample_rate;
	sound_params->fmt = SFMT_S16 | SFMT_NE;
	
	if (data->remain_buf) {
		int to_copy = MIN (buf_len, data->remain_buf_len);
		
		debug ("Copying %d bytes from the remain buf", to_copy);
		
		memcpy (buf, data->remain_buf, to_copy);
		
		if (to_copy < data->remain_buf_len) {
			memmove (data->remain_buf, data->remain_buf + to_copy,
					data->remain_buf_len - to_copy);
			data->remain_buf_len -= to_copy;
		}
		else {
			debug ("Remain buf is now empty");
			free (data->remain_buf);
			data->remain_buf = NULL;
			data->remain_buf_len = 0;
		}

		return to_copy;
	}

	do {
		ret = av_read_frame (data->ic, &pkt);
		if (ret < 0)
			return 0;

		memcpy(&pkt_tmp, &pkt, sizeof(pkt));
		pkt_data = pkt.data;
		pkt_size = pkt.size;
		debug ("Got %dB packet", pkt_size);
		
		while (pkt_size) {
			int len;

#if LIBAVCODEC_VERSION_INT >= ((52<<16)+(26<<8)+0)
			data_size = sizeof (avbuf);
			len = avcodec_decode_audio3 (data->enc, (int16_t *)avbuf,
					&data_size, &pkt);
#elif LIBAVCODEC_VERSION_INT >= ((51<<16)+(50<<8)+0)
			data_size = sizeof (avbuf);
			len = avcodec_decode_audio2 (data->enc, (int16_t *)avbuf,
					&data_size, pkt_data, pkt_size);
#else
			len = avcodec_decode_audio (data->enc, (int16_t *)avbuf,
					&data_size, pkt_data, pkt_size);
#endif

			debug ("Decoded %dB", data_size);

			if (len < 0)  {
				/* skip frame */
				decoder_error (&data->error, ERROR_STREAM, 0,
						"Error in the stream!");
				break;
			}

			pkt_data += len;
			pkt_size -= len;

			if (buf_len) {
				int to_copy = MIN (data_size, buf_len);
			
				memcpy (buf, avbuf, to_copy);

				buf += to_copy;
				filled += to_copy;
				buf_len -= to_copy;

				debug ("Copying %dB (%dB filled)", to_copy,
						filled);

				if (to_copy < data_size)
					put_in_remain_buf (data,
							avbuf + to_copy,
							data_size - to_copy);
			}
			else if (data_size)
				add_to_remain_buf (data, avbuf, data_size);
			
		}
	} while (!filled);
	
	/* 2.0 - 16bit/sample*/
	data->bitrate = pkt.size * 8 / ((filled + data->remain_buf_len) / 2.0 /
			sound_params->channels / sound_params->rate) / 1000;

	av_free_packet (&pkt_tmp);
	
	return filled;
}
Exemplo n.º 11
0
/* Play a file (disk file) using the given decoder. next_file is precached. */
static void play_file (const char *file, const struct decoder *f,
		const char *next_file, struct out_buf *out_buf)
{
	void *decoder_data;
	struct sound_params sound_params = { 0, 0, 0 };
	float already_decoded_time;
	struct md5_data md5;

#if !defined(NDEBUG) && defined(DEBUG)
	md5.okay = true;
	md5.len = 0;
	md5_init_ctx (&md5.ctx);
#endif

	out_buf_reset (out_buf);

	precache_wait (&precache);

	if (precache.ok && strcmp(precache.file, file)) {
		logit ("The precached file is not the file we want.");
		precache.f->close (precache.decoder_data);
		precache_reset (&precache);
	}

	if (precache.ok && !strcmp(precache.file, file)) {
		struct decoder_error err;

		logit ("Using precached file");

		assert (f == precache.f);

		sound_params = precache.sound_params;
		decoder_data = precache.decoder_data;
		set_info_channels (sound_params.channels);
		set_info_rate (sound_params.rate / 1000);

		if (!audio_open(&sound_params)) {
			md5.okay = false;
			precache.f->close (precache.decoder_data);
			precache_reset (&precache);
			return;
		}

#if !defined(NDEBUG) && defined(DEBUG)
		md5.len += precache.buf_fill;
		md5_process_bytes (precache.buf, precache.buf_fill, &md5.ctx);
#endif

		audio_send_buf (precache.buf, precache.buf_fill);

		precache.f->get_error (precache.decoder_data, &err);
		if (err.type != ERROR_OK) {
			md5.okay = false;
			if (err.type != ERROR_STREAM
					|| options_get_int(
						"ShowStreamErrors"))
				error ("%s", err.err);
			decoder_error_clear (&err);
		}

		already_decoded_time = precache.decoded_time;

		if(f->get_avg_bitrate)
			set_info_avg_bitrate (f->get_avg_bitrate(decoder_data));
		else
			set_info_avg_bitrate (0);

		bitrate_list_init (&bitrate_list);
		bitrate_list.head = precache.bitrate_list.head;
		bitrate_list.tail = precache.bitrate_list.tail;

		/* don't free list elements when reseting precache */
		precache.bitrate_list.head = NULL;
		precache.bitrate_list.tail = NULL;
	}
	else {
		struct decoder_error err;

		status_msg ("Opening...");
		decoder_data = f->open(file);
		f->get_error (decoder_data, &err);
		if (err.type != ERROR_OK) {
			f->close (decoder_data);
			status_msg ("");
			error ("%s", err.err);
			decoder_error_clear (&err);
			logit ("Can't open file, exiting");
			return;
		}

		already_decoded_time = 0.0;
		if(f->get_avg_bitrate)
			set_info_avg_bitrate (f->get_avg_bitrate(decoder_data));
		bitrate_list_init (&bitrate_list);
	}

	audio_plist_set_time (file, f->get_duration(decoder_data));
	audio_state_started_playing ();
	precache_reset (&precache);

	decode_loop (f, decoder_data, next_file, out_buf, &sound_params,
			&md5, already_decoded_time);

#if !defined(NDEBUG) && defined(DEBUG)
	if (md5.okay) {
		uint8_t buf[MD5_DIGEST_SIZE];

		md5_finish_ctx (&md5.ctx, buf);
		log_md5_sum (file, sound_params, f, buf, md5.len);
	}
#endif
}
Exemplo n.º 12
0
/* Decoder loop for already opened and probably running for some time decoder.
 * next_file will be precached at eof. */
static void decode_loop (const struct decoder *f, void *decoder_data,
		const char *next_file, struct out_buf *out_buf,
		struct sound_params *sound_params, struct md5_data *md5,
		const float already_decoded_sec)
{
	bool eof = false;
	bool stopped = false;
	char buf[PCM_BUF_SIZE];
	int decoded = 0;
	struct sound_params new_sound_params;
	bool sound_params_change = false;
	float decode_time = already_decoded_sec; /* the position of the decoder
						    (in seconds) */

	out_buf_set_free_callback (out_buf, buf_free_callback);

	LOCK (curr_tags_mut);
	curr_tags = tags_new ();
	UNLOCK (curr_tags_mut);

	if (f->get_stream) {
		LOCK (decoder_stream_mut);
		decoder_stream = f->get_stream (decoder_data);
		UNLOCK (decoder_stream_mut);
	}
	else
		logit ("No get_stream() function");

	status_msg ("Playing...");

	while (1) {
		debug ("loop...");

		LOCK (request_cond_mutex);
		if (!eof && !decoded) {
			struct decoder_error err;

			UNLOCK (request_cond_mutex);

			if (decoder_stream && out_buf_get_fill(out_buf)
					< PREBUFFER_THRESHOLD) {
				prebuffering = 1;
				io_prebuffer (decoder_stream,
						options_get_int("Prebuffering")
						* 1024);
				prebuffering = 0;
				status_msg ("Playing...");
			}

			decoded = f->decode (decoder_data, buf, sizeof(buf),
					&new_sound_params);

			if (decoded)
				decode_time += decoded / (float)(sfmt_Bps(
							new_sound_params.fmt) *
						new_sound_params.rate *
						new_sound_params.channels);

			f->get_error (decoder_data, &err);
			if (err.type != ERROR_OK) {
				md5->okay = false;
				if (err.type != ERROR_STREAM
						|| options_get_int(
							"ShowStreamErrors"))
					error ("%s", err.err);
				decoder_error_clear (&err);
			}

			if (!decoded) {
				eof = true;
				logit ("EOF from decoder");
			}
			else {
				debug ("decoded %d bytes", decoded);
				if (!sound_params_eq(new_sound_params, *sound_params))
					sound_params_change = true;

				bitrate_list_add (&bitrate_list, decode_time,
						f->get_bitrate(decoder_data));
				update_tags (f, decoder_data, decoder_stream);
			}
		}

		/* Wait, if there is no space in the buffer to put the decoded
		 * data or EOF occurred and there is something in the buffer. */
		else if (decoded > out_buf_get_free(out_buf)
					|| (eof && out_buf_get_fill(out_buf))) {
			debug ("waiting...");
			if (eof && !precache.file && next_file
					&& file_type(next_file) == F_SOUND
					&& options_get_int("Precache")
					&& options_get_bool("AutoNext"))
				start_precache (&precache, next_file);
			pthread_cond_wait (&request_cond, &request_cond_mutex);
			UNLOCK (request_cond_mutex);
		}
		else
			UNLOCK (request_cond_mutex);

		/* When clearing request, we must make sure, that another
		 * request will not arrive at the moment, so we check if
		 * the request has changed. */
		if (request == REQ_STOP) {
			logit ("stop");
			stopped = true;
			md5->okay = false;
			out_buf_stop (out_buf);

			LOCK (request_cond_mutex);
			if (request == REQ_STOP)
				request = REQ_NOTHING;
			UNLOCK (request_cond_mutex);

			break;
		}
		else if (request == REQ_SEEK) {
			int decoder_seek;

			logit ("seeking");
			md5->okay = false;
			req_seek = MAX(0, req_seek);
			if ((decoder_seek = f->seek(decoder_data, req_seek))
					== -1)
				logit ("error when seeking");
			else {
				out_buf_stop (out_buf);
				out_buf_reset (out_buf);
				out_buf_time_set (out_buf, decoder_seek);
				bitrate_list_empty (&bitrate_list);
				decode_time = decoder_seek;
				eof = false;
				decoded = 0;
			}

			LOCK (request_cond_mutex);
			if (request == REQ_SEEK)
				request = REQ_NOTHING;
			UNLOCK (request_cond_mutex);

		}
		else if (!eof && decoded <= out_buf_get_free(out_buf)
				&& !sound_params_change) {
			debug ("putting into the buffer %d bytes", decoded);
#if !defined(NDEBUG) && defined(DEBUG)
			if (md5->okay) {
				md5->len += decoded;
				md5_process_bytes (buf, decoded, &md5->ctx);
			}
#endif
			audio_send_buf (buf, decoded);
			decoded = 0;
		}
		else if (!eof && sound_params_change
				&& out_buf_get_fill(out_buf) == 0) {
			logit ("Sound parameters have changed.");
			*sound_params = new_sound_params;
			sound_params_change = false;
			set_info_channels (sound_params->channels);
			set_info_rate (sound_params->rate / 1000);
			out_buf_wait (out_buf);
			if (!audio_open(sound_params)) {
				md5->okay = false;
				break;
			}
		}
		else if (eof && out_buf_get_fill(out_buf) == 0) {
			logit ("played everything");
			break;
		}
	}

	status_msg ("");

	LOCK (decoder_stream_mut);
	decoder_stream = NULL;
	f->close (decoder_data);
	UNLOCK (decoder_stream_mut);

	bitrate_list_destroy (&bitrate_list);

	LOCK (curr_tags_mut);
	if (curr_tags) {
		tags_free (curr_tags);
		curr_tags = NULL;
	}
	UNLOCK (curr_tags_mut);

	out_buf_wait (out_buf);

	if (precache.ok && (stopped || !options_get_bool ("AutoNext"))) {
		precache_wait (&precache);
		precache.f->close (precache.decoder_data);
		precache_reset (&precache);
	}
}
Exemplo n.º 13
0
static void *precache_thread (void *data)
{
	struct precache *precache = (struct precache *)data;
	int decoded;
	struct sound_params new_sound_params;
	struct decoder_error err;

	precache->buf_fill = 0;
	precache->sound_params.channels = 0; /* mark that sound_params were not
						yet filled. */
	precache->decoded_time = 0.0;
	precache->f = get_decoder (precache->file);
	assert (precache->f != NULL);

	precache->decoder_data = precache->f->open(precache->file);
	precache->f->get_error(precache->decoder_data, &err);
	if (err.type != ERROR_OK) {
		logit ("Failed to open the file for precache: %s", err.err);
		decoder_error_clear (&err);
		precache->f->close (precache->decoder_data);
		return NULL;
	}

	audio_plist_set_time (precache->file,
			precache->f->get_duration(precache->decoder_data));

	/* Stop at PCM_BUF_SIZE, because when we decode too much, there is no
	 * place where we can put the data that doesn't fit into the buffer. */
	while (precache->buf_fill < PCM_BUF_SIZE) {
		decoded = precache->f->decode (precache->decoder_data,
				precache->buf + precache->buf_fill,
				PCM_BUF_SIZE, &new_sound_params);

		if (!decoded) {

			/* EOF so fast? We can't pass this information
			 * in precache, so give up. */
			logit ("EOF when precaching.");
			precache->f->close (precache->decoder_data);
			return NULL;
		}

		precache->f->get_error (precache->decoder_data, &err);

		if (err.type == ERROR_FATAL) {
			logit ("Error reading file for precache: %s", err.err);
			decoder_error_clear (&err);
			precache->f->close (precache->decoder_data);
			return NULL;
		}

		if (!precache->sound_params.channels)
			precache->sound_params = new_sound_params;
		else if (!sound_params_eq(precache->sound_params,
					new_sound_params)) {

			/* There is no way to store sound with two different
			 * parameters in the buffer, give up with
			 * precaching. (this should never happen). */
			logit ("Sound parameters have changed when precaching.");
			decoder_error_clear (&err);
			precache->f->close (precache->decoder_data);
			return NULL;
		}

		bitrate_list_add (&precache->bitrate_list,
				precache->decoded_time,
				precache->f->get_bitrate(
					precache->decoder_data));

		precache->buf_fill += decoded;
		precache->decoded_time += decoded / (float)(sfmt_Bps(
					new_sound_params.fmt) *
				new_sound_params.rate *
				new_sound_params.channels);

		if (err.type != ERROR_OK) {
			decoder_error_clear (&err);
			break; /* Don't lose the error message */
		}
	}

	precache->ok = 1;
	logit ("Successfully precached file (%d bytes)", precache->buf_fill);
	return NULL;
}