JamesHeinrich / getID3

http://www.getid3.org/
Other
1.13k stars 245 forks source link

Bit rate for MP4 audio tracks #414

Closed gino0631 closed 1 year ago

gino0631 commented 1 year ago

I have noticed that getID3 does not output bit rate for MP4 audio, while other tools, like MediaInfo and ffprobe, do that. This can be seen with the sample provided for #413. It would be nice to have this feature in getID3 too.

Technically, it is possible to extract the bit rate from esds extension atom.

Sound Sample Descriptions may contain extensions which are made using atoms. MPEG-4 Elementary Stream Descriptor Atom ('esds') contains Elementary Stream Descriptor as defined in the MPEG-4 specification ISO/IEC 14496, which in turn contains DecoderConfigDescriptor with maxBitrate and avgBitrate fields.

To read this information, the following logic can be used:

  1. Determine if there is some additional data after Sound Sample Description. Size of the description depends on its version, so version field has to be read and analyzed first (while it is documented that "extensions were first added with sound sample description v1", the sample in question has version 0 but nevertheless does contain an extension). It is also worth mentioning that the current code in getID3 ignores the version and always reads version 0 description, which means the values will be incorrect in case of version 2.
  2. If there is additional data, read the atoms.
  3. If esds atom is found, parse it. For example, the sample in question contains the following atom: 00000033 65736473 00000000 03 80808022 0002 00 04 80808014 40 15 000000 0004e211 0004e211 05 80808002 1190 06 80808001 02 with header: 00000033 - size 51 bytes 65736473 - esds 00000000 - version (0) and Elementary Stream Descriptor (see ISO/IEC 14496-1:2010 7.2.6.5 and 7.2.6.6): 03 - ES_DescrTag 80808022 - size 34 bytes 0002 - ES_ID 00 - flags ----- 04 - DecoderConfigDescrTag 80808014 - size 20 bytes 40 - objectTypeIndication ("Audio ISO/IEC 14496-3") 15 - streamType plus flags ("AudioStream") 000000 - bufferSizeDB 0004e211 - maxBitrate (320017) 0004e211 - avgBitrate (320017) 05 - DecSpecificInfoTag 80808002 - size 2 bytes 1190 - DecoderSpecificInfo ----- 06 - SLConfigDescrTag 80808001 - size 1 byte 02 - SLConfigDescriptor ("Reserved for use in MP4 files")

An example of parsing can also be found here.

JamesHeinrich commented 1 year ago

Thank you for the detailed breakdown, and links to the Chromium example, that was helpful. I've implemented it at https://github.com/JamesHeinrich/getID3/commit/ce4a1591d3168969b3a43fd78c67ff7723d02caa Please feel free to suggest any changes or improvements, PRs (very) welcome.

gino0631 commented 1 year ago

Thanks for the implementation, I am so glad the references were helpful!

It is difficult with PRs without knowing the code well enough. As for the improvements, I think you already had a function to read the sizes - quicktime_read_mp4_descr_length() is quite similar to quicktime_readESsize().

JamesHeinrich commented 1 year ago

Sometimes I don't know the code that well myself -- most of getID3 was written 20 years ago...

You're right, quicktime_read_mp4_descr_length is a better implementation, I have removed quicktime_readESsize.