Opened 13 months ago

Last modified 12 months ago

#5718 open defect

ffmpeg not remapping channels for libopus automatically

Reported by: agressiv Owned by:
Priority: important Component: avcodec
Version: git-master Keywords: libopus regression
Cc: michael Blocked By:
Blocking: Reproduced by developer: yes
Analyzed by developer: no


[libopus @ 00000000026ad020] Invalid channel layout 5.1(side) for specified mapping family -1.

Summary of the bug:
Encode a 5.1 audio file with 5.1(side) channel map
How to reproduce:

% ffmpeg -i movie-with-51side.mkv -c:a libopus -b:a 256k output.mkv
ffmpeg version N-81025-g25ca74d
built on July 15 2016

ffmpeg version N-80101-gd970f7b automatically remapped these to the rear channels since libopus doesn't seem to allow side channels. I now have to explicitly add:

-af "channelmap=channel_layout=5.1"

Not sure if this is expected behavior or not. Without this channelmap, it aborts. Command-line opusenc automatically remaps as well.

Attachments (1)

0001-libavcodec-libopusenc.c-patch-channel_layouts-back-i.patch (939 bytes) - added by Peter.White 12 months ago.
Reenable channel_layouts

Download all attachments as: .zip

Change History (12)

comment:1 Changed 13 months ago by heleppkes

Probably a regression since 37941878f193a2316c514bd5ba55bfe9d2dfdfcf. Removing the supported channel_layouts from the codec definition was really not a good idea for on obscure feature.

comment:2 Changed 13 months ago by jamrial

  • Component changed from undetermined to avcodec
  • Keywords channelmap removed
  • Priority changed from normal to important
  • Reproduced by developer set
  • Status changed from new to open
  • Version changed from unspecified to git-master

Definitely a regression, and indeed started by 37941878f193a2316c514bd5ba55bfe9d2dfdfcf.

New defaults shouldn't make a simple "ffmpeg -i INPUT -c:a libopus OUTPUT" start failing.

Last edited 13 months ago by jamrial (previous) (diff)

comment:3 Changed 13 months ago by cehoyos

  • Keywords regression added

comment:4 Changed 13 months ago by michael

  • Cc michael added

comment:5 Changed 13 months ago by mgraczyk

When I wrote this patch, I did not realize that channel_layouts was used to automatically remix the channel layout from 5.1(side) to 5.1. I did not intend to change default behavior with that patch.

However, my understanding was that the error here is potentially desirable. The ogg audio stream in output.mkv has a different channel layout than the audio in the input file.

I see that in most cases remapping 5.1(side) to 5.1 is the right thing to do. Is there any way to get this automatic remapping only when the mapping_family parameter is not provided?

Also, what do you mean by "Command-line opusenc automatically remaps as well"? How do you process mkv files with opusenc? Are you sure the process used to extract audio from the mkv file didn't do the remapping?

comment:6 Changed 13 months ago by agressiv

I will pipe it from eac3to. opusenc can take piped input.

eac3to.exe source.mkv stdout.wav | opusenc.exe --bitrate 256k --ignorelength - out.opus
WARNING: WAV file uses side surround instead of rear for 5.1;
remapping side speakers to rear in encoding.
Encoding using libopus 1.1 (audio)

comment:7 Changed 13 months ago by mgraczyk

agressiv, thanks for that. I see that opusenc has a few special cases for moving rear to side and side to rear. I would have liked to preserve the behavior in this case as it was before 37941878f by default. I am hopeful we can restore this behavior without removing the mapping_family argument.

Would it make sense to add these special cases explicitly to libopusenc.c, and log a warning as is done by opusenc?

comment:8 Changed 13 months ago by heleppkes

I would prefer if opusenc had the channel_layouts setting again so that ffmpeg.c and other user apps know which layouts opus supports and can decide based on that which layout to use and potentially remix to, instead of hoping opusenc supports that internally.

channel_layouts is not only meant to limit the input to an encoder, its also information for the calling code so it can pick the best format on its own and not error out later.

comment:9 Changed 13 months ago by mgraczyk


libopusenc can accept many channel layouts that are not possible to express using the channel_layouts bitfield system. There are channel layouts which are supported by libopus which are not expressible by the channel_layouts member. I removed channel_layouts from the codec definition to prevent ffmpeg.c from halting with an error when one of these unexpressible layouts was passed in.

Is there a way to specify at the command line "no channel layout", or "unknown layout"? With such a flag, I could add channel_layouts back to libopusenc and also add code to handle the "no layout" case. I believe last time I asked about this, it was problematic because the channel count is represented by the popcount of the layout bitfield, and the "no channel layout" layout could have any channel count.

Changed 12 months ago by Peter.White

Reenable channel_layouts

comment:10 Changed 12 months ago by Peter.White

I just added a quick patch to get channel_layouts back. I just got bitten by this as well.

@mgraczyk I don't exactly understand what you are talking about when saying libopusenc can accept many inexpressible layouts. But is it more likely to encounter those than the most prominent ones, like 5.1(side)? I think for the time being, adding channel_layouts back in is the better compromise.

Anyway, the attached patch is there for anyone wanting to workaround this issue. To be honest, though, I did not check any implications, since I wouldn't know how, I am not a developer. But adding this one line back in seems easy enough. Correct me if I am wrong.

comment:11 Changed 12 months ago by Peter.White

A more general workaround, without patching is to use the aformat filter, like i.e.:
ffmpeg -i surround_input -af aformat=channel_layouts="7.1|5.1|stereo" output.opus
This way one does not need to manually set an appropriate channel map with differing input layouts and channel numbers. Put this in a script and select the relevant layouts. The above example is just a quick one.

Note: See TracTickets for help on using tickets.