/****************************************************************************** QtAV: Multimedia framework based on Qt and FFmpeg Copyright (C) 2012-2022 Wang Bin * This file is part of QtAV (from 2014) This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA ******************************************************************************/ #include "QmlAV/MediaMetaData.h" #include #include #include #include using namespace QtAV; MediaMetaData::MediaMetaData(QObject *parent) : QObject(parent) { } void MediaMetaData::setValuesFromStatistics(const QtAV::Statistics &st) { m_metadata.clear(); //setValue(Size, st.); setValue(Duration, (qint64)QTime(0, 0, 0).msecsTo(st.duration)); setValue(StartTime, (qint64)QTime(0, 0, 0).msecsTo(st.start_time)); if (st.video.available) { setValue(MediaType, QStringLiteral("video")); setValue(VideoFrameRate, st.video.frame_rate); setValue(VideoBitRate, st.video.bit_rate); setValue(VideoCodec, st.video.codec); setValue(Resolution, QSize(st.video_only.width, st.video_only.height)); setValue(PixelFormat, st.video_only.pix_fmt); setValue(VideoFrames, st.video.frames); } if (st.audio.available) { // TODO: what if thumbnail? if (!st.video.available) setValue(MediaType, QStringLiteral("audio")); setValue(AudioBitRate, st.audio.bit_rate); setValue(AudioCodec, st.audio.codec); setValue(ChannelCount, st.audio_only.channels); setValue(SampleRate, st.audio_only.sample_rate); setValue(ChannelLayout, st.audio_only.channel_layout); setValue(SampleFormat, st.audio_only.sample_fmt); } QHash md(st.metadata); if (md.isEmpty()) return; QHash::const_iterator it = md.constBegin(); for (; it != md.constEnd(); ++it) { Key key = fromFFmpegName(it.key()); if ((int)key >= 0) { setValue(key, it.value()); continue; } const QString keyName(it.key().toLower()); if (keyName == QLatin1String("track")) { int slash = it.value().indexOf(QLatin1Char('/')); if (slash < 0) { setValue(TrackNumber, it.value().toInt()); continue; } setValue(TrackNumber, it.value().left(slash).toInt()); //QStringRef.toInt(): Qt5.2 setValue(TrackCount, it.value().mid(slash+1).toInt()); continue; } if (keyName == QLatin1String("date") || it.key().toLower() == QLatin1String("creation_time") ) { // ISO 8601 is preferred in ffmpeg bool ok = false; int year = it.value().toInt(&ok); if (ok) { //if (year > 1000) //? setValue(Year, year); continue; } setValue(Date, QDate::fromString(it.value(), Qt::ISODate)); continue; } if (keyName.contains(QLatin1String("genre"))) { setValue(Genre, it.value().split(QLatin1Char(','))); // ',' ? not sure continue; } } // qtmm read Size from metadata on win QFile f(st.url); if (f.exists()) setValue(Size, f.size()); } MediaMetaData::Key MediaMetaData::fromFFmpegName(const QString &name) const { typedef struct { Key key; const char* name; } key_t; key_t key_map[] = { { AlbumTitle, "album" }, //? { AlbumArtist, "album_artist" }, { Author, "artist" }, //? { Comment, "comment" }, { Composer, "composer" }, { Copyright, "copyright" }, // { Date, "date" }, //QDate { Language, "language" }, //maybe a list in ffmpeg { Language, "lang" }, { Publisher, "publisher" }, { Title, "title" }, //{ TrackNumber, "track" }, // can be "current/total" //{ TrackCount, "track" }, // can be "current/total" // below are keys not listed in ffmpeg generic tag names and value is a QString { Description, "description" }, //dx { (Key)-1, 0 }, }; for (int i = 0; (int)key_map[i].key >= 0; ++i) { if (name.toLower() == QLatin1String(key_map[i].name)) return key_map[i].key; } // below are keys not listed in ffmpeg generic tag names and value is a QString key_t wm_key[] = { { UserRating, "rating" }, //dx, WM/ { ParentalRating, "parentalrating" }, //dx, WM/ //{ RatingOrganization, "rating_organization" }, { Conductor, "conductor" }, //dx, WM/ { Lyrics, "lyrics" }, //dx, WM/ { Mood, "mood" }, //dx, WM/ { (Key)-1, 0 }, }; for (int i = 0; (int)wm_key[i].key >= 0; ++i) { if (name.toLower().contains(QLatin1String(wm_key[i].name))) return wm_key[i].key; } return (Key)-1; } void MediaMetaData::setValue(Key k, const QVariant &v) { if (value(k) == v) return; m_metadata[k] = v; emit metaDataChanged(); } QVariant MediaMetaData::value(Key k, const QVariant &defaultValue) const { return m_metadata.value(k, defaultValue); } QString MediaMetaData::name(Key k) const { int idx = staticMetaObject.indexOfEnumerator("Key"); const QMetaEnum me = staticMetaObject.enumerator(idx); return QString::fromLatin1(me.valueToKey(k)); }