After an evaluation, GNOME has moved from Bugzilla to GitLab. Learn more about GitLab.
No new issues can be reported in GNOME Bugzilla anymore.
To report an issue in a GNOME project, go to GNOME GitLab.
Do not go to GNOME Gitlab for: Bluefish, Doxygen, GnuCash, GStreamer, java-gnome, LDTP, NetworkManager, Tomboy.
Bug 620322 - lame mp3 encoder does not save lame tags
lame mp3 encoder does not save lame tags
Status: RESOLVED INCOMPLETE
Product: GStreamer
Classification: Platform
Component: gst-plugins-ugly
git master
Other Linux
: Normal enhancement
: NONE
Assigned To: GStreamer Maintainers
GStreamer Maintainers
Depends on:
Blocks:
 
 
Reported: 2010-06-02 00:32 UTC by nyall
Modified: 2017-08-20 16:31 UTC
See Also:
GNOME target: ---
GNOME version: ---



Description nyall 2010-06-02 00:32:15 UTC
As originally reported here:
https://thomas.apestaart.org/morituri/trac/ticket/40

It seems the gstreamer lame mp3 encoder isn't correctly saving the lame tags to the files it creates. These tags are required in order to make the mp3s gaplessly playback. For comparison, here's the tags from a gstreamer encoded mp3 and one made using lame directly:


GSTREAMER:

$ eyeD3 --lametag 01.\ Café\ Tacvba\ -\ Seguir\ siendo.mp3

01. Café Tacvba - Seguir siendo.mp3 [ 4.02 MB ]

No LAME Tag



FROM LAME:

$eyeD3 --lametag Track01.mp3

Track01.mp3 [ 3.77 MB ]

Encoder Version : LAME3.98r
LAME Tag Revision : 0
VBR Method : Variable Bitrate method2 (mtrh)
Lowpass Filter : 18500
Radio Replay Gain : -2.0 dB (Set automatically)
Encoding Flags : --nspsytune --nssafejoint
ATH Type : 4
Bitrate (Minimum) : 192
Encoder Delay : 576 samples
Encoder Padding : 960 samples
Noise Shaping : 1
Stereo Mode : Joint
Unwise Settings : False
Sample Frequency : 44.1 kHz
MP3 Gain : 0 (+0.0 dB)
Preset : V2
Surround Info : None
Music Length : 3.77 MB
Music CRC-16 : 07F9
LAME Tag CRC-16 : E5BF



It's the encoder delay and padding tags which are especially important for gapless playback, since this information is impossible to retrieve after encoding.
Comment 1 Sebastian Dröge (slomo) 2010-06-02 08:10:41 UTC
Which mp3 encoder element was used here? lamemp3enc or lame?
Comment 2 nyall 2010-06-02 08:19:39 UTC
This is using the lame element.
Comment 3 Sebastian Dröge (slomo) 2010-06-02 08:29:40 UTC
Is it included with the lamemp3enc element? (You shouldn't use lame anymore...)
Comment 4 nyall 2010-06-02 10:22:39 UTC
A little different there... this time I get the lame encoder version tag, but nothing else.


$ gst-launch-0.10 filesrc location=test.flac ! flacdec ! audioconvert ! lamemp3enc ! filesink location=test.mp3
Setting pipeline to PAUSED ...
Pipeline is PREROLLING ...
Pipeline is PREROLLED ...
Setting pipeline to PLAYING ...
New clock: GstSystemClock
Got EOS from element "pipeline0".
Execution ended after 9880881396 ns.
Setting pipeline to PAUSED ...
Setting pipeline to READY ...
Setting pipeline to NULL ...
Freeing pipeline ...

$ eyeD3 --lame test.mp3
test.mp3	[ 2.82 MB ]
-------------------------------------------------------------------------------
Encoder Version: LAME3.98.2


Incidentally, where would I find information about lamemp3enc? It's not listed at http://gstreamer.freedesktop.org/data/doc/gstreamer/head/gst-plugins-ugly-plugins/html/
Comment 5 Sebastian Dröge (slomo) 2010-06-02 10:26:02 UTC
Someone should update the -ugly docs on the website... Could you file a new bug for that? :)



What needs to be done to get lame output additional things in the lametag?
Comment 6 nyall 2010-06-02 10:31:31 UTC
Do you mean when using lame manually? If so, nothing special needs to be done, lame adds them by default:

$ flac -dc test.flac | lame -V0 - test2.mp3

flac 1.2.1, Copyright (C) 2000,2001,2002,2003,2004,2005,2006,2007  Josh Coalson
flac comes with ABSOLUTELY NO WARRANTY.  This is free software, and you are
welcome to redistribute it under certain conditions.  Type `flac' for details.

test.flac: done         
LAME 3.98.2 64bits (http://www.mp3dev.org/)
Using polyphase lowpass filter, transition band: 19383 Hz - 19916 Hz
Encoding <stdin> to test2.mp3
Encoding as 44.1 kHz j-stereo MPEG-1 Layer III VBR(q=0)


$ eyeD3 --lame test2.mp3
test2.mp3	[ 4.26 MB ]
-------------------------------------------------------------------------------
Encoder Version     : LAME3.98r
LAME Tag Revision   : 0
VBR Method          : Variable Bitrate method2 (mtrh)
Lowpass Filter      : 19500
Radio Replay Gain   : -2.0 dB (Set automatically)
Encoding Flags      : --nspsytune --nssafejoint
ATH Type            : 4
Bitrate (Minimum)   : 32
Encoder Delay       : 576 samples
Encoder Padding     : 2112 samples
Noise Shaping       : 1
Stereo Mode         : Joint
Unwise Settings     : False
Sample Frequency    : 44.1 kHz
MP3 Gain            : 0 (+0.0 dB)
Preset              : V0
Surround Info       : None
Music Length        : 4.26 MB
Music CRC-16        : E8F2
LAME Tag CRC-16     : DD49
Comment 7 Sebastian Dröge (slomo) 2010-06-02 15:47:57 UTC
Ok, so I have no idea how to get liblame to write the lame tag :) I'll try to fix the element in the next days if I find something to generate the lame tag.
Comment 8 Benjamin Otte (Company) 2010-06-02 15:57:53 UTC
Do you want to put that into a GstTagList or emit it directly into the stream?
Comment 9 Sebastian Dröge (slomo) 2010-06-02 17:06:36 UTC
Directly into the stream, it's a valid MP3 frame containing no samples IIRC.

I guess an element like xingmux might make sense for the lametag too though, but I'm not sure if we can easily get all required information from an mp3 stream...
Comment 10 Benjamin Otte (Company) 2010-06-02 19:50:34 UTC
I've never been too happy about lame emitting tags into the bitstream. It used to confuse muxers and other elements that expected each mp3 frame to contain 1440 samples. That was one of the reasons for why I originally removed all tag-writing from it.

I'm not sure if that's still a problem, but I certainly wouldn't want gapless playback tags inside my AVI files.
Comment 11 Tim-Philipp Müller 2010-06-02 22:26:04 UTC
> (...) That was one of the reasons for why I originally removed all
> tag-writing from it.

Oh it was you, wasn't it? ;-) Your reasons all seem very good, but tag writing in lame was also pretty broken for all practical purposes, see bug #329184 for details (and a whole bunch of related bugs).


> I guess an element like xingmux might make sense for the lametag too though,
> but I'm not sure if we can easily get all required information from an mp3
> stream...

If we want to support this special lame tag, maybe we can just send a custom event with a buffer containing the tag downstream, xingmux and/or id3*mux can then pick that up?
Comment 12 phil 2010-07-30 10:44:49 UTC
Surely gapless encoding is something that would be an option to the encoder? The lame binary doesn't do it by default, so neither should gstreamer. That solves the AVI issue :)

From rootling around in lame.h, it looks like you're supposed to call lame_encode_flush_nogap() at the end of each track followed by lame_init_bitstream() to get lame to write the header tags (assuming it can seek() the output stream?)

When you start encoding a set of gapless tracks, call lame_set_nogap_total() with the total number & then call lame_set_nogap_currentindex() for each track along the way.

There are some more lametag specific functions, but it looks like those are deprecated.

The probably would probably be that the above calls assume that liblame can seek() around the output stream, which might not mesh very well with the way gstreamer structures things. It also needs to not fire off a new instantiation of liblame for each track, but do them all in a single pass.
Comment 13 phil 2010-07-30 10:50:04 UTC
Oh wait, lame_mp3_tags_fid() is deprecated, but lame_get_lametag_frame()  isn't. I guess what you're supposed to do if you're driving liblame yourself like gstreamer is to call lame_encode_flush_nogap() then call lame_get_lametag_frame() to get the LAME tag frame which you write over the blank frame at the beginning of the mp3 data stream for that track. Then you call lame_set_nogap_currentindex() and pick up encoding where you left off within the same liblame instance.
Comment 14 phil 2010-07-31 15:06:10 UTC
Further poking around the lame mailing lists reveals that they pretty much regard the gapless bits as being deprecated: the padding data in the lametag should be all that's required, in which case there's no need to faff around with lame_set_nogap_current_index() and friends: the only thing that's required to insert the lametag at the beginning of the generated mp3 data for each track. Passing the tag down the stream for xingmux or id3mux to pick up would seem sensible.
Comment 15 Edward Hervey 2013-08-14 08:16:10 UTC
Phil, is this still an issue with GStreamer 1.x ?
Comment 16 phil 2013-08-14 08:34:10 UTC
I'll check.
Comment 17 phil 2014-08-20 14:29:20 UTC
Definitely still an issue with GStreamer 1.x.

If I use the invocation:

gst-launch-1.0 audiotestsrc num-buffers=1000 ! audioconvert ! lamemp3enc ! xingmux ! filesink location=test.mp3

Then the resultant file has no lametag according to eyeD3. If I omit the xingmux filter, then the output file has a lametag with no data in it.

This means that it's still impossible to rip a gapless mp3 from a CD with sound-juicer.
Comment 18 Tim-Philipp Müller 2014-08-21 09:49:29 UTC
Phil, perhaps you could try your hand at a patch? Or at least start a patch that gets us the data that should be communicated to xingmux?

I can see something that looks like LAME tags at first glance in:

gst-launch-1.0 audiotestsrc num-buffers=1000 ! audioconvert ! lamemp3enc ! xingmux ! fakesink dump=true | more

(But should there be some in the initial xing buffer too?)

It would also be helpful if you could attach the first 100kB or so of a file that is tagged properly.