Merge lp:~jamesh/mediascanner2/m4a-coverart into lp:mediascanner2

Proposed by James Henstridge
Status: Merged
Approved by: Michi Henning
Approved revision: 311
Merged at revision: 311
Proposed branch: lp:~jamesh/mediascanner2/m4a-coverart
Merge into: lp:mediascanner2
Diff against target: 135 lines (+60/-12)
2 files modified
src/daemon/MetadataExtractor.cc (+12/-1)
test/test_metadataextractor.cc (+48/-11)
To merge this branch: bzr merge lp:~jamesh/mediascanner2/m4a-coverart
Reviewer Review Type Date Requested Status
PS Jenkins bot (community) continuous-integration Approve
Mediascanner Team Pending
Review via email: mp+273673@code.launchpad.net

Commit message

Fix the metadata extractor so that it correctly extracts the date and presence of cover art from MPEG 4 audio files.

Description of the change

Add a test for metadata extraction of MPEG 4 audio files. This showed a few problems in the extraction support for this file format:

1. presence of cover art was not being detected correctly (it is exposed as a preview image rather than an image, as detailed in bug 1492407).

2. the release date was not being extracted correctly (it is also exposed as a different tag by the GStreamer element).

This branch fixes both of those issues.

I also altered the supports_decoder() test helper so that it can distinguish between the different MPEG audio types (MP3 and M4A).

To post a comment you must log in.
Revision history for this message
Michi Henning (michihenning) wrote :

Looks good to me. On line 76 and 79 of the diff, that appears to be left-behind debug trace?

Revision history for this message
James Henstridge (jamesh) wrote :

I've pulled the debug printfs now.

311. By James Henstridge

Remove debug printfs.

Revision history for this message
PS Jenkins bot (ps-jenkins) wrote :
review: Approve (continuous-integration)

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'src/daemon/MetadataExtractor.cc'
2--- src/daemon/MetadataExtractor.cc 2015-07-07 04:36:02 +0000
3+++ src/daemon/MetadataExtractor.cc 2015-10-09 05:33:28 +0000
4@@ -150,7 +150,7 @@
5 int i, num;
6 string tagname(tag);
7
8- if(tagname == GST_TAG_IMAGE) {
9+ if(tagname == GST_TAG_IMAGE || tagname == GST_TAG_PREVIEW_IMAGE) {
10 mfb->setHasThumbnail(true);
11 return;
12 }
13@@ -180,6 +180,17 @@
14 mfb->setDate(dt_string);
15 g_free(dt_string);
16 }
17+ } else if (G_VALUE_HOLDS(val, G_TYPE_DATE)) {
18+ if (tagname == GST_TAG_DATE) {
19+ GDate *dt = static_cast<GDate*>(g_value_get_boxed(val));
20+ if (!dt) {
21+ continue;
22+ }
23+ char buf[100];
24+ if (g_date_strftime(buf, sizeof(buf), "%Y-%m-%d", dt) != 0) {
25+ mfb->setDate(buf);
26+ }
27+ }
28 } else if (G_VALUE_HOLDS_UINT(val)) {
29 if (tagname == GST_TAG_TRACK_NUMBER) {
30 mfb->setTrackNumber(g_value_get_uint(val));
31
32=== added file 'test/media/testfile.m4a'
33Binary files test/media/testfile.m4a 1970-01-01 00:00:00 +0000 and test/media/testfile.m4a 2015-10-09 05:33:28 +0000 differ
34=== modified file 'test/test_metadataextractor.cc'
35--- test/test_metadataextractor.cc 2015-07-07 04:36:02 +0000
36+++ test/test_metadataextractor.cc 2015-10-09 05:33:28 +0000
37@@ -40,7 +40,8 @@
38
39 bool supports_decoder(const std::string& format)
40 {
41- static std::set<std::string> formats;
42+ typedef std::unique_ptr<GstCaps, decltype(&gst_caps_unref)> CapsPtr;
43+ static std::vector<CapsPtr> formats;
44
45 if (formats.empty())
46 {
47@@ -59,19 +60,29 @@
48 {
49 continue;
50 }
51-
52- std::unique_ptr<GstCaps, decltype(&gst_caps_unref)> caps(gst_static_caps_get(&t->static_caps),
53- gst_caps_unref);
54- for (unsigned int i = 0; i < gst_caps_get_size(caps.get()); i++)
55- {
56- const auto structure = gst_caps_get_structure(caps.get(), i);
57- formats.emplace(gst_structure_get_name(structure));
58+ CapsPtr caps(gst_static_caps_get(&t->static_caps),
59+ gst_caps_unref);
60+ if (gst_caps_is_any(caps.get())) {
61+ continue;
62 }
63+ formats.emplace_back(std::move(caps));
64 }
65 }
66 }
67
68- return formats.find(format) != formats.end();
69+ char *end = nullptr;
70+ GstStructure *structure = gst_structure_from_string(format.c_str(), &end);
71+ assert(structure != nullptr);
72+ assert(end == format.c_str() + format.size());
73+ // GstCaps adopts the GstStructure
74+ CapsPtr caps(gst_caps_new_full(structure, nullptr), gst_caps_unref);
75+
76+ for (const auto &other : formats) {
77+ if (gst_caps_is_always_compatible(caps.get(), other.get())) {
78+ return true;
79+ }
80+ }
81+ return false;
82 }
83
84 }
85@@ -142,7 +153,7 @@
86 }
87
88 TEST_F(MetadataExtractorTest, extract_mp3) {
89- if (!supports_decoder("audio/mpeg")) {
90+ if (!supports_decoder("audio/mpeg, mpegversion=(int)1, layer=(int)3")) {
91 printf("MP3 codec not supported\n");
92 return;
93 }
94@@ -163,6 +174,32 @@
95 EXPECT_EQ(st.st_mtime, file.getModificationTime());
96 }
97
98+TEST_F(MetadataExtractorTest, extract_m4a) {
99+ if (!supports_decoder("audio/mpeg, mpegversion=(int)4, stream-format=(string)raw")) {
100+ printf("M4A codec not supported\n");
101+ return;
102+ }
103+
104+ MetadataExtractor e;
105+ string testfile = SOURCE_DIR "/media/testfile.m4a";
106+ MediaFile file = e.extract(e.detect(testfile));
107+
108+ EXPECT_EQ(AudioMedia, file.getType());
109+ EXPECT_EQ("Title", file.getTitle());
110+ EXPECT_EQ("Artist", file.getAuthor());
111+ EXPECT_EQ("Album", file.getAlbum());
112+ EXPECT_EQ("Album Artist", file.getAlbumArtist());
113+ EXPECT_EQ("2015-10-07", file.getDate());
114+ EXPECT_EQ(4, file.getTrackNumber());
115+ EXPECT_EQ(1, file.getDiscNumber());
116+ EXPECT_EQ(1, file.getDuration());
117+ EXPECT_EQ("Rock", file.getGenre());
118+ EXPECT_EQ(true, file.getHasThumbnail());
119+ struct stat st;
120+ ASSERT_EQ(0, stat(testfile.c_str(), &st));
121+ EXPECT_EQ(st.st_mtime, file.getModificationTime());
122+}
123+
124 TEST_F(MetadataExtractorTest, extract_video) {
125 MetadataExtractor e;
126
127@@ -220,7 +257,7 @@
128 }
129
130 TEST_F(MetadataExtractorTest, extract_mp3_bad_date) {
131- if (!supports_decoder("audio/mpeg")) {
132+ if (!supports_decoder("audio/mpeg, mpegversion=(int)1, layer=(int)3")) {
133 printf("MP3 codec not supported\n");
134 return;
135 }

Subscribers

People subscribed via source and target branches