diff options
Diffstat (limited to 'src/player_thread.c')
-rw-r--r-- | src/player_thread.c | 94 |
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; |