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