From 563fbaf82aa363940394ea1f91ec1c758f2e0621 Mon Sep 17 00:00:00 2001 From: Urs Fleisch Date: Sun, 27 Dec 2020 10:17:34 +0100 Subject: [PATCH] Handle the case when MP4 file header has zero bitrate This incorporates [6ca536b5] (mp4 properties: handle the case when mp4 file header has zero bitrate) from PR #899 with a more accurate bitrate calculation and a unit test. --- taglib/mp4/mp4properties.cpp | 9 ++++++++- tests/test_mp4.cpp | 23 +++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/taglib/mp4/mp4properties.cpp b/taglib/mp4/mp4properties.cpp index a577ac3e..6c6976fa 100644 --- a/taglib/mp4/mp4properties.cpp +++ b/taglib/mp4/mp4properties.cpp @@ -234,7 +234,14 @@ MP4::Properties::read(File *file, Atoms *atoms) pos += 3; } pos += 10; - d->bitrate = static_cast((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((bitrateValue + 500) / 1000.0 + 0.5); + } + else { + d->bitrate = static_cast( + (calculateMdatLength(atoms->atoms) * 8) / d->length); + } } } } diff --git a/tests/test_mp4.cpp b/tests/test_mp4.cpp index 13c17b22..ba38c0f0 100644 --- a/tests/test_mp4.cpp +++ b/tests/test_mp4.cpp @@ -43,6 +43,7 @@ class TestMP4 : public CppUnit::TestFixture { CPPUNIT_TEST_SUITE(TestMP4); CPPUNIT_TEST(testPropertiesAAC); + CPPUNIT_TEST(testPropertiesAACWithoutBitrate); CPPUNIT_TEST(testPropertiesALAC); CPPUNIT_TEST(testPropertiesALACWithoutBitrate); CPPUNIT_TEST(testPropertiesM4V); @@ -81,6 +82,28 @@ public: CPPUNIT_ASSERT_EQUAL(MP4::Properties::AAC, f.audioProperties()->codec()); } + void testPropertiesAACWithoutBitrate() + { + ByteVector aacData = PlainFile(TEST_FILE_PATH_C("has-tags.m4a")).readAll(); + CPPUNIT_ASSERT_GREATER(1960U, aacData.size()); + CPPUNIT_ASSERT_EQUAL(ByteVector("mp4a"), aacData.mid(1890, 4)); + // Set the bitrate to zero + for (int offset = 1956; offset < 1960; ++offset) { + aacData[offset] = 0; + } + ByteVectorStream aacStream(aacData); + MP4::File f(&aacStream); + CPPUNIT_ASSERT(f.audioProperties()); + CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->lengthInSeconds()); + CPPUNIT_ASSERT_EQUAL(3708, f.audioProperties()->lengthInMilliseconds()); + CPPUNIT_ASSERT_EQUAL(3, f.audioProperties()->bitrate()); + CPPUNIT_ASSERT_EQUAL(2, f.audioProperties()->channels()); + CPPUNIT_ASSERT_EQUAL(44100, f.audioProperties()->sampleRate()); + CPPUNIT_ASSERT_EQUAL(16, f.audioProperties()->bitsPerSample()); + CPPUNIT_ASSERT_EQUAL(false, f.audioProperties()->isEncrypted()); + CPPUNIT_ASSERT_EQUAL(MP4::Properties::AAC, f.audioProperties()->codec()); + } + void testPropertiesALAC() { MP4::File f(TEST_FILE_PATH_C("empty_alac.m4a"));