1 ///
2 /// Adapter from a ffmpeg audio player to a generic audio output.
3 ///	@file		ffmpegadapter.cpp - pianod2
4 ///	@author		Perette Barella
5 ///	@date		2015-11-18
6 ///	@copyright	Copyright (c) 2015-2018 Devious Fish. All rights reserved.
7 ///
8 
9 #include <config.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <strings.h>
13 #include <stdarg.h>
14 
15 #include <stdexcept>
16 #include <chrono>
17 #include <thread>
18 
19 #pragma GCC diagnostic push
20 #pragma GCC diagnostic ignored "-Wdocumentation"
21 extern "C" {
22 #include <libavformat/avformat.h>
23 #include <libavcodec/avcodec.h>
24 #include <libavutil/samplefmt.h>
25 #include <libavutil/avutil.h>
26 #include <libavutil/opt.h>
27 #include <libavutil/channel_layout.h>
28 #include <libavfilter/buffersink.h>
29 #include <libavfilter/buffersrc.h>
30 }
31 #pragma GCC diagnostic pop
32 
33 #include "fundamentals.h"
34 #include "utility.h"
35 #include "logging.h"
36 #include "audiooutput.h"
37 #include "ffmpegplayer.h"
38 
39 
40 
41 
42 namespace Audio {
43     using namespace std;
44 
45     /** Log an ffmpeg error.
46         @param func The function name causing the error.
47         @param err The ffmpeg error number. */
flogav(const char * func,int err)48     void flogav (const char *func, int err) {
49         char buffer [256];
50         av_strerror (err, buffer, sizeof (buffer));
51         flog (LOG_ERROR, func, ": ", buffer);
52     }
53 
54     /** Create an AudioException from a ffmpeg error.
55         @param func The name of the function originating the error.
56         @param error The ffmpeg error number. */
LavAudioException(const char * func,int error)57     LavAudioException::LavAudioException (const char *func, int error) {
58         char buffer [256];
59         av_strerror (error, buffer, sizeof (buffer));
60         reason = string (func) + ": " + buffer;
61         flog (LOG_ERROR, reason);
62     }
63 
64     /*
65      * LavAdapter - infastructure to adapt ffmpeg output to other things.
66      */
67 
68     /** Add a filter to the filter stack.
69         @param prior_filter The prior filter, or nullptr if it is the first.
70         (used to wire the filters into sequence).
71         @param name The ffmpeg name of the filter.
72         @param options_format A printf-style format string (and values to follow)
73         to create an options string for the filter.
74         @return The new filter.
75         @throw AudioException if anything goes wrong. */
pushFilter(AVFilterContext * prior_filter,const char * name,const char * options_format,...)76     AVFilterContext *LavAdapter::pushFilter (AVFilterContext *prior_filter,
77             const char *name,
78             const char *options_format, ...) {
79         assert (name);
80 
81         const AVFilter *filter_type = avfilter_get_by_name (name);
82         if (!filter_type)
83             throw AudioException (string ("Filter not found: ") + name);
84         char *options = nullptr;
85         if (options_format) {
86             // If there are options, format a string for them.
87             va_list parameters;
88             va_start (parameters, options_format);
89             int length = vasprintf (&options, options_format, parameters);
90             if (length < 0)
91                 throw bad_alloc ();
92 
93         }
94         AVFilterContext *new_filter = nullptr;
95         int status = avfilter_graph_create_filter (&new_filter,
96                      filter_type, NULL, options, NULL,
97                      filter_stack.get());
98         free (options);
99         if (status < 0)
100             throw LavAudioException ("avfilter_graph_create_filter", status);
101 
102         if (prior_filter) {
103             status = avfilter_link (prior_filter, 0, new_filter, 0);
104             if (status < 0) {
105                 throw LavAudioException ("avfilter_link", status);
106             }
107         }
108         return new_filter;
109     }
110 
111     /** Adapt whatever output for input from ffmpeg.
112         @param output_format The format required by the outputter.
113         @param codec The ffmpeg codec context. */
LavAdapter(const AVCodecContext * codec,const AVStream * stream,const AVSampleFormat output_format)114     LavAdapter::LavAdapter (const AVCodecContext *codec,
115                             const AVStream *stream,
116                             const AVSampleFormat output_format) {
117         assert (codec);
118         assert (stream);
119 
120         int status;
121 
122         filter_stack.reset (avfilter_graph_alloc ());
123         if (!filter_stack)
124             throw bad_alloc();
125 
126         output_frame.reset (av_frame_alloc());
127         if (!output_frame)
128             throw bad_alloc();
129 
130         // Unput buffer
131         AVRational time_base = stream->time_base;
132         char channel_layout [256];
133         av_get_channel_layout_string (channel_layout, sizeof (channel_layout),
134                                       codec->channels, codec->channel_layout);
135         // Provide sanity where ffmpeg's avcodec doesn't.
136         if (codec->channel_layout == 0) {
137             switch (codec->channels) {
138                 case 1:
139                     strcpy (channel_layout, "mono");
140                     break;
141                 case 2:
142                     strcpy (channel_layout, "stereo");
143                     break;
144                 case 4:
145                     strcpy (channel_layout, "quad");
146                     break;
147                 default:
148                     // do nothing and let the filter creation.
149                     break;
150             }
151         }
152         buffer_filter = pushFilter (nullptr, "abuffer",
153                                     "time_base=%d/%d:sample_rate=%d:sample_fmt=%s:channel_layout=%s",
154                                     time_base.num, time_base.den, codec->sample_rate,
155                                     av_get_sample_fmt_name (codec->sample_fmt),
156                                     channel_layout);
157 
158         // Volume filter
159         volume_filter = pushFilter (buffer_filter, "volume");
160 
161         if (output_format != codec->sample_fmt) {
162             /* Convert samples to required format */
163             format_filter = pushFilter (volume_filter, "aformat",
164                                         "sample_fmts=%s",
165                                         av_get_sample_fmt_name (output_format));
166         }
167 
168         // Buffer from which to retrieve filter output
169         endpoint_filter = pushFilter(format_filter ? format_filter : volume_filter,
170                                      "abuffersink");
171 
172         status = avfilter_graph_config (filter_stack.get(), NULL);
173         if (status < 0) {
174             throw LavAudioException ("avfilter_graph_config", status);
175         }
176     };
177 
~LavAdapter()178     LavAdapter::~LavAdapter() { }
179 
180     /** Play any frames buffered in the filter.
181         This must be invoked by subclasses during their destruction, as their
182         specializations are gone by the time this class's destructor is called. */
flush()183     void LavAdapter::flush () {
184         play (NULL);
185         const int quanta = 100;
186         int timeout;
187         bool status;
188         for (timeout = 0; (status = playFilteredPackets (false)) && timeout < 2000; timeout += quanta) {
189             std::this_thread::sleep_for (std::chrono::milliseconds (quanta));
190         }
191         if (status) {
192             flog (LOG_WHERE (LOG_WARNING), "Filter did not fully flush.");
193         }
194 #ifndef NDEBUG
195         else if (timeout) {
196             flog (LOG_WHERE (LOG_GENERAL), "Filter took ", timeout, "ms to flush");
197 
198         }
199 #endif
200     }
201 
202     /** Play a frame from a ffmpeg decoder.
203         This involves passing it through the filter stack to adjust
204         volume and format in accordance with the output's needs.
205         @param frame The audio frame to play.
206         @return True on success, false on error. */
play(AVFrame * frame)207     bool LavAdapter::play (AVFrame *frame) {
208         // Push the frame through the filter stack
209         lock_guard<mutex> lock (adapter_mutex);
210         int status = av_buffersrc_write_frame (buffer_filter, frame);
211         if (status < 0) {
212             flogav("av_buffersrc_write_frame", status);
213             return false;
214         }
215 
216         return playFilteredPackets();
217     }
218 
219 
220     /** Read all the resulting frames coming out of the filter stack,
221         and push them to the outputter.
222         @param eof_return_value Value to return if EOF is encountered.
223         @return On error, false.  On eof, up to caller. Otherwise true. */
playFilteredPackets(const bool eof_return_value)224     bool LavAdapter::playFilteredPackets (const bool eof_return_value) {
225         bool ok;
226         do {
227             int status = av_buffersink_get_frame (endpoint_filter, output_frame.get());
228             if (status == AVERROR_EOF)
229                 return eof_return_value;
230             if (status == AVERROR (EAGAIN))
231                 return true;
232             if (status < 0) {
233                 flogav("av_buffersink_get_frame", status);
234                 return false;
235             }
236             ok = playFrame (output_frame.get());
237             av_frame_unref (output_frame.get());
238         } while (ok);
239         return false;
240     }
241 
242 
setVolume(float level)243     void LavAdapter::setVolume (float level) {
244         /* Mutex is needed to prevent crash if player thread and main
245            thread try to concurrently adjust volume (cross-fading
246            makes this especially likely) or if the main thread tries
247            to set the volume while the player thread is actively
248            adding/removing packets from the filter. */
249         lock_guard<mutex> lock (adapter_mutex);
250 
251         assert (filter_stack);
252         assert (volume_filter);
253 #ifdef HAVE_AVFILTER_GRAPH_SEND_COMMAND
254         // ffmpeg approach
255         string gain = to_string (level) + "dB";
256         int status = avfilter_graph_send_command (filter_stack.get(), "volume", "volume",
257                      gain.c_str(), NULL, 0, 0);
258         if (status < 0) {
259             flogav("avfilter_graph_send_command", status);
260         }
261 #else
262         // decibels to multiplier
263         const double volume = pow (10, (level) / 20);
264         int status = av_opt_set_double (volume_filter->priv, "volume", volume, 0);
265         if (status < 0) {
266             flogav("av_opt_set_double", status);
267         }
268 #endif
269     }
270 
271 
272     /*
273      * LavGenericAdapter - Concrete adapter to non-ffmpeg outputs.
274      */
275 
276     /** Adapt whatever output for input from ffmpeg.
277         @param out An output mechanism.
278         @param output_format The format required by the outputter.
279         @param codec The ffmpeg codec context. */
LavGenericAdapter(const AVCodecContext * codec,const AVStream * stream,Output * out,const AVSampleFormat output_format)280     LavGenericAdapter::LavGenericAdapter (const AVCodecContext *codec,
281                                           const AVStream *stream,
282                                           Output *out,
283                                           const AVSampleFormat output_format) :
284         output (out), LavAdapter (codec, stream, output_format) {
285         assert (out);
286     }
287 
~LavGenericAdapter()288     LavGenericAdapter::~LavGenericAdapter() {
289         flush();
290     }
291 
292     /** Send a processed frame to the audio output device.
293         @param frame The audio frame to play.
294         @return True on success, false on error. */
playFrame(AVFrame * frame)295     bool LavGenericAdapter::playFrame (AVFrame *frame) {
296         const int channels = av_get_channel_layout_nb_channels (frame->channel_layout);
297         const int sample_bytes = av_get_bytes_per_sample ((AVSampleFormat) frame->format);
298         assert (sample_bytes * channels == output->bytesPerSample());
299         return output->play (frame->data[0], frame->nb_samples * channels * sample_bytes);
300     }
301 
302     /*
303      * Factory to assemble output and adapter.
304      */
305 
306     /** Choose an output, then get an adapter for LibAO
307         and set it up to match the output's format.
308         @param settings Where to send the audio output.
309         @return A ready-to-go output stack.
310         @throw AudioException or a derivative if a suitable output was
311         not located, opening/setting up the device failed, or
312         the adapter setup failed. */
getOutput(const AudioSettings & settings,const AVCodecContext * codec,const AVStream * stream)313     LavAdapter *LavAdapter::getOutput (const AudioSettings &settings,
314                                        const AVCodecContext *codec,
315                                        const AVStream *stream) {
316         AudioFormat output_format;
317         AVSampleFormat adapter_format;
318 
319         switch (codec->sample_fmt) {
320             case AV_SAMPLE_FMT_U8:
321             case AV_SAMPLE_FMT_U8P:
322                 output_format.bits = 8;
323                 output_format.signedness = SampleSignedness::Unsigned;
324                 adapter_format = AV_SAMPLE_FMT_U8;
325                 break;
326             case AV_SAMPLE_FMT_S16:
327             case AV_SAMPLE_FMT_S16P:
328                 adapter_format = AV_SAMPLE_FMT_S16;
329                 break;
330             case AV_SAMPLE_FMT_S32:
331             case AV_SAMPLE_FMT_S32P:
332             default: // Floats, doubles and 32-bit formats
333                 output_format.bits = 32;
334                 adapter_format = AV_SAMPLE_FMT_S32;
335                 break;
336         }
337         output_format.channels = codec->channels;
338         output_format.rate = codec->sample_rate;
339 
340         Output *out = nullptr;
341         try {
342             out = Output::getOutput (settings, output_format);
343         } catch (const AudioException &e) {
344             // Some outputs may not support the more eclectic combinations.
345             // Consider something commonplace.
346             if (output_format.bits == 16 &&
347                     output_format.signedness == SampleSignedness::Signed) {
348                 throw;
349             }
350             output_format.bits = 16;
351             output_format.signedness = SampleSignedness::Signed;
352             adapter_format = AV_SAMPLE_FMT_S16;
353         }
354         if (!out)
355             out = Output::getOutput (settings, output_format);
356         if (!out)
357             throw AudioException ("Could not acquire audio output");
358         try {
359             return new LavGenericAdapter (codec, stream, out, adapter_format);
360         } catch (...) {
361             delete out;
362             throw;
363         }
364     }
365 }
366