aboutsummaryrefslogtreecommitdiff
path: root/src/player_thread.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/player_thread.c')
-rw-r--r--src/player_thread.c94
1 files changed, 46 insertions, 48 deletions
diff --git a/src/player_thread.c b/src/player_thread.c
index 3995ce34..8efff1ad 100644
--- a/src/player_thread.c
+++ b/src/player_thread.c
@@ -32,11 +32,14 @@
#include "chunk.h"
#include "idle.h"
#include "main.h"
-#include "buffer.h"
#include "mpd_error.h"
#include <glib.h>
+#include <libavutil/channel_layout.h>
+#include <libavutil/frame.h>
+#include <libavutil/samplefmt.h>
+
#undef G_LOG_DOMAIN
#define G_LOG_DOMAIN "player_thread"
@@ -124,8 +127,6 @@ struct player {
float elapsed_time;
};
-static struct music_buffer *player_buffer;
-
static void
player_command_finished_locked(struct player_control *pc)
{
@@ -148,8 +149,7 @@ player_command_finished(struct player_control *pc)
*
* Player lock is not held.
*/
-static void
-player_dc_start(struct player *player, struct music_pipe *pipe)
+static void player_dc_start(struct player *player, struct music_pipe *pipe)
{
struct player_control *pc = player->pc;
struct decoder_control *dc = player->dc;
@@ -162,8 +162,8 @@ player_dc_start(struct player *player, struct music_pipe *pipe)
start_ms += (unsigned)(pc->seek_where * 1000);
dc_start(dc, pc->next_song,
- start_ms, pc->next_song->end_ms,
- player_buffer, pipe);
+ start_ms, pc->next_song->end_ms,
+ pc->buffer_chunks * 2048, pipe);
}
/**
@@ -207,7 +207,7 @@ player_dc_stop(struct player *player)
if (dc->pipe != NULL) {
/* clear and free the decoder pipe */
- music_pipe_clear(dc->pipe, player_buffer);
+ music_pipe_clear(dc->pipe);
if (dc->pipe != player->pipe)
music_pipe_free(dc->pipe);
@@ -304,7 +304,7 @@ player_open_output(struct player *player)
assert(pc->state == PLAYER_STATE_PLAY ||
pc->state == PLAYER_STATE_PAUSE);
- if (audio_output_all_open(&player->play_audio_format, player_buffer)) {
+ if (audio_output_all_open(&player->play_audio_format)) {
player->output_open = true;
player->paused = false;
@@ -405,11 +405,15 @@ player_check_decoder_startup(struct player *player)
static bool
player_send_silence(struct player *player)
{
+ struct music_chunk *chunk = NULL;
+ AVFrame *frame;
+ int ret;
+
assert(player->output_open);
assert(audio_format_defined(&player->play_audio_format));
- struct music_chunk *chunk = music_buffer_allocate(player_buffer);
- if (chunk == NULL) {
+ chunk = music_chunk_alloc();
+ if (!chunk) {
g_warning("Failed to allocate silence buffer");
return false;
}
@@ -418,22 +422,30 @@ player_send_silence(struct player *player)
chunk->audio_format = player->play_audio_format;
#endif
- size_t frame_size =
- audio_format_frame_size(&player->play_audio_format);
- /* this formula ensures that we don't send
- partial frames */
- unsigned num_frames = sizeof(chunk->data) / frame_size;
+ chunk->frame = frame = av_frame_alloc();
+ if (!chunk->frame)
+ goto fail;
+ frame->nb_samples = 2048;
+ frame->format = sample_fmt_native_to_libav(player->play_audio_format.format);
+ frame->sample_rate = player->play_audio_format.sample_rate;
+ frame->channel_layout = av_get_default_channel_layout(player->play_audio_format.channels);
+
+ ret = av_frame_get_buffer(frame, 32);
+ if (ret < 0)
+ goto fail;
+
+ av_samples_set_silence(frame->extended_data, 0, frame->nb_samples,
+ player->play_audio_format.channels, frame->format);
chunk->times = -1.0; /* undefined time stamp */
- chunk->length = num_frames * frame_size;
- memset(chunk->data, 0, chunk->length);
- if (!audio_output_all_play(chunk)) {
- music_buffer_return(player_buffer, chunk);
- return false;
- }
+ if (!audio_output_all_play(chunk))
+ goto fail;
return true;
+fail:
+ music_chunk_free(chunk);
+ return false;
}
/**
@@ -457,7 +469,7 @@ static bool player_seek_decoder(struct player *player)
/* clear music chunks which might still reside in the
pipe */
- music_pipe_clear(player->pipe, player_buffer);
+ music_pipe_clear(player->pipe);
/* re-start the decoder */
player_dc_start(player, player->pipe);
@@ -470,7 +482,7 @@ static bool player_seek_decoder(struct player *player)
if (!player_dc_at_current_song(player)) {
/* the decoder is already decoding the "next" song,
but it is the same song file; exchange the pipe */
- music_pipe_clear(player->pipe, player_buffer);
+ music_pipe_clear(player->pipe);
music_pipe_free(player->pipe);
player->pipe = dc->pipe;
}
@@ -656,8 +668,8 @@ play_chunk(struct player_control *pc,
if (chunk->tag != NULL)
update_song_tag(song, chunk->tag);
- if (chunk->length == 0) {
- music_buffer_return(player_buffer, chunk);
+ if (!chunk->frame) {
+ music_chunk_free(chunk);
return true;
}
@@ -670,8 +682,7 @@ play_chunk(struct player_control *pc,
if (!audio_output_all_play(chunk))
return false;
- pc->total_play_time += (double)chunk->length /
- audio_format_time_to_size(format);
+ pc->total_play_time += (double)chunk->frame->nb_samples / chunk->frame->sample_rate;
return true;
}
@@ -687,7 +698,7 @@ play_next_chunk(struct player *player)
struct player_control *pc = player->pc;
struct decoder_control *dc = player->dc;
- if (!audio_output_all_wait(pc, 64))
+ if (!audio_output_all_wait(pc, 64 * 2048))
/* the output pipe is still large enough, don't send
another chunk */
return true;
@@ -739,8 +750,7 @@ play_next_chunk(struct player *player)
beginning of the new song, we can
easily recover by throwing it away
now */
- music_buffer_return(player_buffer,
- other_chunk);
+ music_chunk_free(other_chunk);
other_chunk = NULL;
}
@@ -784,7 +794,7 @@ play_next_chunk(struct player *player)
if (!play_chunk(player->pc, player->song, chunk,
&player->play_audio_format)) {
- music_buffer_return(player_buffer, chunk);
+ music_chunk_free(chunk);
player_lock(pc);
@@ -806,7 +816,7 @@ play_next_chunk(struct player *player)
decoder_lock(dc);
if (!decoder_is_idle(dc) &&
music_pipe_size(dc->pipe) <= (pc->buffered_before_play +
- music_buffer_size(player_buffer) * 3) / 4)
+ pc->buffer_chunks * 3) / 4)
decoder_signal(dc);
decoder_unlock(dc);
@@ -910,7 +920,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
if (!player.paused &&
player.output_open &&
- audio_output_all_check() < 4 &&
+ audio_output_all_check() < 4 * 2048 &&
!player_send_silence(&player))
break;
@@ -970,8 +980,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
dc->mixramp_prev_end,
&dc->out_audio_format,
&player.play_audio_format,
- music_buffer_size(player_buffer) -
- pc->buffered_before_play);
+ pc->buffer_chunks - pc->buffered_before_play);
if (player.cross_fade_chunks > 0) {
player.xfade = XFADE_ENABLED;
player.cross_fading = false;
@@ -1027,7 +1036,7 @@ static void do_play(struct player_control *pc, struct decoder_control *dc)
player_dc_stop(&player);
- music_pipe_clear(player.pipe, player_buffer);
+ music_pipe_clear(player.pipe);
music_pipe_free(player.pipe);
if (player.cross_fade_tag != NULL)
@@ -1057,8 +1066,6 @@ player_task(gpointer arg)
struct decoder_control *dc = dc_new(pc->cond);
decoder_thread_start(dc);
- player_buffer = music_buffer_new(pc->buffer_chunks);
-
player_lock(pc);
while (1) {
@@ -1090,14 +1097,6 @@ player_task(gpointer arg)
player_lock(pc);
player_command_finished_locked(pc);
-#ifndef NDEBUG
- /* in the DEBUG build, check for leaked
- music_chunk objects by freeing the
- music_buffer */
- music_buffer_free(player_buffer);
- player_buffer = music_buffer_new(pc->buffer_chunks);
-#endif
-
break;
case PLAYER_COMMAND_UPDATE_AUDIO:
@@ -1113,7 +1112,6 @@ player_task(gpointer arg)
dc_quit(dc);
dc_free(dc);
audio_output_all_close();
- music_buffer_free(player_buffer);
player_command_finished(pc);
return NULL;