aboutsummaryrefslogtreecommitdiffstats
path: root/taglib/mp4/mp4properties.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'taglib/mp4/mp4properties.cpp')
-rw-r--r--taglib/mp4/mp4properties.cpp37
1 files changed, 36 insertions, 1 deletions
diff --git a/taglib/mp4/mp4properties.cpp b/taglib/mp4/mp4properties.cpp
index faa43c27..6c6976fa 100644
--- a/taglib/mp4/mp4properties.cpp
+++ b/taglib/mp4/mp4properties.cpp
@@ -31,6 +31,27 @@
using namespace TagLib;
+namespace
+{
+ // Calculate the total bytes used by audio data, used to calculate the bitrate
+ long long calculateMdatLength(const MP4::AtomList &list)
+ {
+ long long totalLength = 0;
+ for(MP4::AtomList::ConstIterator it = list.begin(); it != list.end(); ++it) {
+ long length = (*it)->length;
+ if(length == 0)
+ return 0; // for safety, see checkValid() in mp4file.cpp
+
+ if((*it)->name == "mdat")
+ totalLength += length;
+
+ totalLength += calculateMdatLength((*it)->children);
+ }
+
+ return totalLength;
+ }
+}
+
class MP4::Properties::PropertiesPrivate
{
public:
@@ -213,7 +234,14 @@ MP4::Properties::read(File *file, Atoms *atoms)
pos += 3;
}
pos += 10;
- d->bitrate = static_cast<int>((data.toUInt(pos) + 500) / 1000.0 + 0.5);
+ const unsigned int bitrateValue = data.toUInt(pos);
+ if(bitrateValue != 0 || d->length <= 0) {
+ d->bitrate = static_cast<int>((bitrateValue + 500) / 1000.0 + 0.5);
+ }
+ else {
+ d->bitrate = static_cast<int>(
+ (calculateMdatLength(atoms->atoms) * 8) / d->length);
+ }
}
}
}
@@ -224,6 +252,13 @@ MP4::Properties::read(File *file, Atoms *atoms)
d->channels = data.at(73);
d->bitrate = static_cast<int>(data.toUInt(80U) / 1000.0 + 0.5);
d->sampleRate = data.toUInt(84U);
+
+ if(d->bitrate == 0 && d->length > 0) {
+ // There are files which do not contain a nominal bitrate, e.g. those
+ // generated by refalac64.exe. Calculate the bitrate from the audio
+ // data size (mdat atoms) and the duration.
+ d->bitrate = (calculateMdatLength(atoms->atoms) * 8) / d->length;
+ }
}
}