[FFmpeg-trac] #6156(undetermined:reopened): Issue with FFMPEG ALSA CPU usage

FFmpeg trac at avcodec.org
Wed Apr 18 12:23:31 EEST 2018


#6156: Issue with FFMPEG ALSA CPU usage
-------------------------------------+-------------------------------------
             Reporter:  mushm0m      |                    Owner:
                 Type:  defect       |                   Status:  reopened
             Priority:  normal       |                Component:
              Version:  git-master   |  undetermined
             Keywords:  alsa         |               Resolution:
             Blocking:               |               Blocked By:
Analyzed by developer:  0            |  Reproduced by developer:  0
-------------------------------------+-------------------------------------
Changes (by kainz):

 * status:  closed => reopened
 * resolution:  invalid =>


Comment:

 So on a pi0w using a similar setup, but with a PCM line mic that i've got
 rigged to show up as a alsa PCM capture device @48000/s16le, I can
 absolutely reproduce the CPU usage issue when running `ffmpeg -f alsa -i
 default -acodec pcm_s16le out.wav`, which produces the following output:

 ```
 ffmpeg -f alsa -i default -acodec pcm_s16le out.wav
 ffmpeg version N-90737-gb3b3a3e3ce Copyright (c) 2000-2018 the FFmpeg
 developers
   built with gcc 6.3.0 (Raspbian 6.3.0-18+rpi1+deb9u1) 20170516
   configuration: --prefix=/usr/local --arch=armhf --target-os=linux
 --enable-gpl --enable-mmal --enable-omx --enable-omx-rpi --enable-nonfree
 --enable-libopus
   libavutil      56. 15.100 / 56. 15.100
   libavcodec     58. 19.100 / 58. 19.100
   libavformat    58. 13.100 / 58. 13.100
   libavdevice    58.  4.100 / 58.  4.100
   libavfilter     7. 17.100 /  7. 17.100
   libswscale      5.  2.100 /  5.  2.100
   libswresample   3.  2.100 /  3.  2.100
   libpostproc    55.  2.100 / 55.  2.100
 Guessed Channel Layout for Input Stream #0.0 : stereo
 Input #0, alsa, from 'default':
   Duration: N/A, start: 1524040707.062083, bitrate: 1536 kb/s
     Stream #0:0: Audio: pcm_s16le, 48000 Hz, stereo, s16, 1536 kb/s
 Stream mapping:
   Stream #0:0 -> #0:0 (pcm_s16le (native) -> pcm_s16le (native))
 Press [q] to stop, [?] for help
 Output #0, wav, to 'out.wav':
   Metadata:
     ISFT            : Lavf58.13.100
     Stream #0:0: Audio: pcm_s16le ([1][0][0][0] / 0x0001), 48000 Hz,
 stereo, s16, 1536 kb/s
     Metadata:
       encoder         : Lavc58.19.100 pcm_s16le
 size=     893kB time=00:00:04.76 bitrate=1536.5kbits/s speed=1.01x
 video:0kB audio:893kB subtitle:0kB other streams:0kB global headers:0kB
 muxing overhead: 0.008531%
 ```

 Looking at the general in/filter/out process, `libavdevice/alsa_dec.c`
 (http://git.videolan.org/?p=ffmpeg.git;a=blob;f=libavdevice/alsa_dec.c;h=c50ce715064ad20f21c7d3c41d1e3003c69fef3f;hb=refs/heads/master#l116)
 returns `AVERROR(EAGAIN)` when `snd_pcm_readi` does not have ready data.
 This triggers the root cause of this issue, which is that in most places
 in `fftools/ffmpeg.c`, when a loop receives EAGAIN, it immediately loops.
 This means that if you are running faster than the sample rate, you are
 going to be pegging the CPU looping in and out of audio_read_packet.

 I suppose this behavior is not unique to `alsa_dec.c`. In fact, if we take
 a quick survey of other libavdevice implementations, we can see a
 difference of implementation choices --

  * `jack.c` - here, a jack thread runs to deal with jackd's realtime
 callbacks to fill a FIFO that then gets 'polled' by audio_read_packet.  If
 a packet is not available, the jack 'frontend' waits up to two seconds and
 then hardfails.
  * `oss.c` - the lower layer file read error is returned directly.  I
 presume this includes -EAGAIN from the driver interface.
  * `iec61883.c` - raw1394 polls its file descriptor to wait.
  * `openal-dec.c` - `AVERROR(EAGAIN)` pattern is used here.
  * `pulse_audio_dec.c` - here we call into the pulseaudio main loop wait-
 on-the-event-thread and let it deal with things. Unless pulseaudio dies or
 the connection fails somehow (or the stream is terminated/deleted), this
 loop will not terminate.

 Given a lack of consensus in the code base on how this loop is handled,
 I'd propose implementing use of `snd_pcm_wait`.  That said, there's also a
 possible API shortcoming in general here -- should libavdevices/AVFormats
 implement a wait/ready/whats-my-pollfd callback and push this handling out
 somewhere more generic?

 Barring the above, I'm going to drop a `snd_pcm_wait(s->h, 16);` into my
 alsa_dec.c and report back.  That should induce a roughly 1/60th second
 wait if data is not yet available.

 Presuming the above would work, any reccomendations/ideas on implementing
 a proper fix?

--
Ticket URL: <https://trac.ffmpeg.org/ticket/6156#comment:5>
FFmpeg <https://ffmpeg.org>
FFmpeg issue tracker


More information about the FFmpeg-trac mailing list