[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