/* player thread; for every song a new thread is started * @param audioPlayer structure * @return PLAYER_RET_* */ void *BarPlayerThread (void *data) { assert (data != NULL); player_t * const player = data; uintptr_t pret = PLAYER_RET_OK; bool retry; do { retry = false; if (openStream (player)) { if (openFilter (player) && openDevice (player)) { player->mode = PLAYER_PLAYING; BarPlayerSetVolume (player); retry = play (player) == AVERROR_INVALIDDATA && !player->interrupted; } else { /* filter missing or audio device busy */ pret = PLAYER_RET_HARDFAIL; } } else { /* stream not found */ pret = PLAYER_RET_SOFTFAIL; } player->mode = PLAYER_WAITING; finish (player); } while (retry); player->mode = PLAYER_FINISHED; return (void *) pret; }
/* setup filter chain */ static bool openFilter (player_t * const player) { /* filter setup */ char strbuf[256]; int ret = 0; AVCodecContext * const cctx = player->st->codec; if ((player->fgraph = avfilter_graph_alloc ()) == NULL) { softfail ("graph_alloc"); } /* abuffer */ AVRational time_base = player->st->time_base; snprintf (strbuf, sizeof (strbuf), "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=0x%"PRIx64, time_base.num, time_base.den, cctx->sample_rate, av_get_sample_fmt_name (cctx->sample_fmt), cctx->channel_layout); if ((ret = avfilter_graph_create_filter (&player->fabuf, avfilter_get_by_name ("abuffer"), NULL, strbuf, NULL, player->fgraph)) < 0) { softfail ("create_filter abuffer"); } /* volume */ if ((ret = avfilter_graph_create_filter (&player->fvolume, avfilter_get_by_name ("volume"), NULL, NULL, NULL, player->fgraph)) < 0) { softfail ("create_filter volume"); } BarPlayerSetVolume (player); /* aformat: convert float samples into something more usable */ AVFilterContext *fafmt = NULL; snprintf (strbuf, sizeof (strbuf), "sample_fmts=%s", av_get_sample_fmt_name (avformat)); if ((ret = avfilter_graph_create_filter (&fafmt, avfilter_get_by_name ("aformat"), NULL, strbuf, NULL, player->fgraph)) < 0) { softfail ("create_filter aformat"); } /* abuffersink */ if ((ret = avfilter_graph_create_filter (&player->fbufsink, avfilter_get_by_name ("abuffersink"), NULL, NULL, NULL, player->fgraph)) < 0) { softfail ("create_filter abuffersink"); } /* connect filter: abuffer -> volume -> aformat -> abuffersink */ if (avfilter_link (player->fabuf, 0, player->fvolume, 0) != 0 || avfilter_link (player->fvolume, 0, fafmt, 0) != 0 || avfilter_link (fafmt, 0, player->fbufsink, 0) != 0) { softfail ("filter_link"); } if ((ret = avfilter_graph_config (player->fgraph, NULL)) < 0) { softfail ("graph_config"); } return true; }