Understanding ID3 MCDI frame size


I'm a little bit how Mp3Tag handle MCDI frame and specifically around such frame size.

I'm expecting such frame to be organized as follows:

  • MCDI (4 bytes)
  • xx xx xx xx (4 bytes for size)
  • xx xx (2 bytes for flags)
  • size bytes for MCDI content
  • Next frame starting here.

For a reason I don't understand Mp3Tag considers size + 1 bytes of content.

Can someone explain where this is coming from ?


Here is the definition by the id3 org.
Here you find the list of fields in MP3tag:

Where is MCDI?

As you can see in the spec you pointed, MCDI is a valid frame.
"4.5 MCDI [#sec4.5 Music CD identifier]"

But I don't understand how Mp3Tag consider this and basically tell if tag is bad or not.

I've found some MP3 with bad MCDI frame size but Mp3tag says it is a valid tag while if I fix this size, it becomes "bad id3".

Any ideas ?

Perhaps the testing equipment is not right?
Perhaps the method to "correct" an alleged fault is not correct?

Mp3tag is the name of the program for tagging. It does not explain mp3 tags in general.

The point is that Mp3Tag does not say TAG is bad when it should.
Who can answer this if I give you a MP3 file with tag corrupted (MCDI wrong size) ?

This is an old thread, but since I ran into the exact same issue, and this thread was the only source I could find on the web that even raises the question of MCDI frame size, I thought I should add the answer that I found out eventually.

What's the issue?

Like the OP, I encountered various files with an MCDI frame in their ID3v2.3 tag. In many (all?) these cases, the size of that frame appeared to be off-by-one and the following tag (typically TLEN) started one byte later than expected. This threw off my own decoder.

It didn't help that the content of that frame was binary data (the dump of a CD's TOC), whose format I had trouble finding accurate documentation for.

What's the reason?

In short, the unsynchronisation scheme.

It turns out the unsynchronisation bit was set in the offending ID3v2.3 header. That causes all sequences of $FF Fx bytes in the body of the tag to be replaced with $FF 00 Fx.

Most frames do not contain data where such byte sequences would even show up. But the binary data contained in the MCDI frame seems to regularly end in $FF FF ā€“ which becomes $FF 00 FF after unsynchronisation is applied.

Now, unfortunately, this feature is documented somewhat poorly. The ID3v2.3 spec clearly says that the size field in the tag header is computed after unsynchronisation is applied. However, what it does not say explicitly is that the size of frames apparently is computed before unsynchronisation ā€“ that's because unsynchronisation is applied to the tag as a whole.

Moreover, this was changed in ID3v2.4, where unsynchronisation is now applied per frame, such that frame sizes are finally 'correct'.

What's the implication

More fun and special casing for decoders... For ID3v2.3, you cannot decode or skip frames without looking at every byte in them.

Worse, in 2.3, the frame size itself actually is subject to the unsynchronisation scheme. That is, if a size value happens to contain a $FF byte, you better check whether it's followed by $00 and skip that.

1 Like

Welcome and thanks for your detailed explanation!