Opened 9 years ago
Last modified 3 months ago
#4954 open defect
joint stereo indicator missing from mp3 headers
Reported by: | pico4743 | Owned by: | |
---|---|---|---|
Priority: | normal | Component: | avformat |
Version: | git-master | Keywords: | mp3 |
Cc: | Blocked By: | ||
Blocking: | Reproduced by developer: | no | |
Analyzed by developer: | no |
Description
Summary of the bug:
mp3 header files created by ffmpeg do not specify a channel mode of joint_stereo when joint_stereo is performed by libmp3lame.
Details:
libmp3lame provides a switch (-joint_stereo) to select either joint_stereo or plain stereo. The interface to lame works correctly so that the audio frames are fine, but ffmpeg doesn't use the lame library to write the mp3 header.
Instead libavformat/mp3enc.c sets the channel mode to either MONO or STEREO based on how many channels there are.
switch (codec->channels) { case 1: channels = MPA_MONO; break; case 2: channels = MPA_STEREO; break; default: av_log(s, AV_LOG_WARNING, "Unsupported number of channels, " "not writing Xing header.\n"); return -1; } ... header |= channels << 6;
MPA_JSTEREO should be used when appropriate. The repair doesn't seem simple, but I'd be willing to help if someone wants to discuss approaches.
How to reproduce:
use a version with libmp3lame enabled % ffmpeg -i input.mp3 -joint_stereo 1 output.mp3 The relevant bits of the output.mp3 header will be 0 == MPA_STEREO ffmpeg version -- git master fb4d350
Change History (14)
comment:1 by , 9 years ago
Keywords: | joint_stereo header removed |
---|
comment:2 by , 7 years ago
comment:3 by , 4 years ago
Not only does it not set the channel mode bit properly on encoding, it doesn't recognize it on decoding. Using an externally created joint stereo MP3 file (verified with mediainfo
), ffmpeg -i joint_stereo.mp3
will just show stereo.
follow-up: 5 comment:4 by , 4 years ago
Status: | new → open |
---|
doesn't recognize it on decoding
But it decodes it correctly? Then why does this matter? If on the other hand we will add support for this will no it break other players or even hardware ones?
comment:5 by , 4 years ago
Replying to Balling:
But it decodes it correctly? Then why does this matter?
Yes, but it misreports to the end-user.
If on the other hand we will add support for this will no it break other players or even hardware ones?
how? joint-stereo is already enabled by default, but the header is not set to indicate it was used. that itself might lead to issues in some players. how can fixing this discrepancy lead to issues?
comment:6 by , 4 years ago
I do not know what you used to read the data, but joint stereo 2 bit and MS Stereo two bit are set (and on some SS mode is set), just not from the first Frame 0 - Tag (Xing) frame. From the Frame 1.
Much bigger problem is CRC absence, IMHO (at least in the header, by LAME).
Also -joint_stereo 1 is the default, just FYI and not MS/SS was not supported for a long time.
comment:7 by , 16 months ago
This longstanding bug still exists in ffmpeg. It has to do with the way ffmpeg uses libmp3lame. It does set the header to Joint Stereo, but doesn't actually encode in Joint Stereo. MP3 players that require Joint Stereo will choke on these files (a common requirement among older MP3 players, generally not an issue with newer players). The -joint_stereo 1 option does NOT work as a parameter in ffmpeg.
Because it changes the header to "claim" it's Joint Stereo, that's why many here mistakenly believe that there is no bug. There absolutely is a bug and has been for years (see my prior comment here 6 years ago).
For an easy test if the data itself is encoded in Joint Stereo, if you don't have access to an old player to see it fail to play, fortunately there are applications that check the audio data in place of the header/metadata, like the freely available Mp3tag. Its "Mode" column shows "Stereo" for output from ffmpeg.
Here's an example of a simplified ffmpeg command that always yields a Stereo file and NOT a Joint Stereo file:
ffmpeg -i input_file.mp3 -f mp3 -joint_stereo 1 -id3v2_version 3 Joint_Test_output_file.mp3
Another way to confirm that the problem exists is to use another program to correctly convert to Joint Stereo and then compare. For example, here is my current work-around (so this should also help anyone else having the problem), where SoX does correctly convert to Joint Stereo. This is a command I use in Windows to convert files and get around the bug in ffmpeg (where I use a WAV file intermediary to reduce loss from MP3, but this does strip out other metadata, which keeping at as MP3 would not, nor would it be necessary to use SoX if ffmpeg did not have the Joint Stereo bug):
for %x in ("*.mp3") do (ffmpeg -i "%x" -f wav -af dynaudnorm -id3v2_version 3 "int_%x.wav" & sox --norm=-3.25 "int_%x.wav" -c 2 -C 192 -r 44100 "ready-%x")
If you look at the those resulting files in Mp3tag, you will see that unlike the pure ffmpeg command, after the SoX command, they show a Mode value of "Joint Stereo."
This comment should provide enough information to reproduce the problem and confirm if it's fixed. Please correct this longstanding bug in ffmpeg.
comment:8 by , 16 months ago
Sorry but you got it wrong and provide no valuable info to solve this bug at all. Joint encoding is working fine, just Xing header that is not written by default by mp3 muxer is not providing any info of encoder params used by libmp3lame encoder.
comment:9 by , 16 months ago
And mediainfo shows correct info when encoder is join or not without xing headers present
comment:10 by , 16 months ago
There is still an issue in #9755. The gapless information gets destroyed in some cases as in during -c copy and in some race cases where there is a specific amount of samples.
comment:11 by , 8 months ago
Correction to my prior post: While this bug still exists in ffmpeg, I was wrong about where the problem lies. After looking inside the MP3 files including with the developer of Mp3tag that reports Joint Stereo output files as Stereo, we can see the bug, as originally posted by pico4743, is a better description. Specifically, ffmpeg DOES output to Joint Stereo, but the header incorrectly says that the file is in Stereo. This confuses several apps that check the MP3 file for stereo format. SoX and libmp3lame do not have this problem, it's specific to ffmpeg's implementation and use of libmp3lame.
The examples in the prior post remain correct to demonstrate the problem, just that the problem is the reverse of what I had described. This better aligns with the original poster, @pico4743, who correctly described the problem as being with the header, rather than the encoding itself.
comment:12 by , 8 months ago
Specifically, ffmpeg DOES output to Joint Stereo, but the header incorrectly says that the file is in Stereo.
That is what I said too. I just used Mediatrace to check the bitstream.
comment:13 by , 3 months ago
Confirmed that the bug still exists in version 7.0.1 of ffmpeg. Given the age of the bug, I am concerned that because this is not a problem for some important users, this bug is just being dismissed or ignored as low-priority.
I accept that there may be other issues that are higher priority for some users. However, please understand that for our use case across a large number of users (including all our clients), this is the single biggest problem we have with ffmpeg and has been so for several years. This issue alone forces us to run all MP3 files through both ffmpeg and SoX to get them generated properly with the correct header, where all that SoX is doing at this point is correcting the ffmpeg Joint Stereo header bug.
As ffmpeg has become faster and because it supports multithreading continually improving its performance (which is excellent for ffmpeg), the use of SoX, which has not similarly improved, for any components of batch file modifications is a severe encumbrance. While this was only a minor annoyance years ago when ffmpeg and SoX had similar performance profiles, the performance gap between ffmpeg and SoX has grown to the point that this is a bigger problem now than it had been.
Before dismissing the severity of this bug to us as a false claim, this is necessary for us because the diagnostic tools we must use for volume checks in SoX rely on the header, which ffmpeg sets to Stereo instead of Joint Stereo. Customer friendly diagnostic tools that our users use, specifically Mp3tag, also rely on the header and therefore misreport as Stereo. And because Stereo files are not acceptable, with many legacy players requiring Joint Stereo specifically and failing to play Stereoe files at all (and providing worse sound quality in all cases even for players that can handle both), we must reject any files that show "Stereo" as the format in the header. Hence the need to use SoX just to fix the header to avoid these automatic rejections.
Please put fixing this bug into the development queue for 2024 or as soon as is reasonably possible.
comment:14 by , 3 months ago
the use of SoX, which has not similarly improved,
This makes no sense. Both we and Sox use the only encoder, lame. Other encoders exist, I know of two and also something from apple, but they are not reference level.
Apple: https://hydrogenaud.io/index.php/topic,104575.msg857777.html#msg857777
This problem is still a problem. It's very easy to reproduce per pico4743's explanation above.
Another way to reproduce: Install the current released version of ffmpeg for Windows (don't think the OS matters, but that's what I happened to be using) 3.3.2 as of this post. Convert a file from WAV to MP3 using the '-joint stereo 1' flag. Test the status of the file with Mp3tag -- shows Stereo instead of Joint Stereo. Note that the same LAME library used in Audacity correctly sets the file to Joint Stereo.
In my case, I was banging my head against this before finding this bug report which confirms the problem I was seeing. Basically, the -joint_stereo switch is useless, because anything playing the file thinks it's still in stereo, and NOT joint stereo. Programs like Mp3tag report the output files as Stereo and not as Joint Stereo making this easy to test and validate.