00001
00002
00003 #include "metaiomp4.h"
00004 #include "metadata.h"
00005
00006
00007 #include <mythlogging.h>
00008 #include <mythcontext.h>
00009
00010
00011 extern "C" {
00012 #include <libavformat/avformat.h>
00013 #include <libavcodec/avcodec.h>
00014 }
00015
00016 MetaIOMP4::MetaIOMP4(void)
00017 : MetaIO()
00018 {
00019 QMutexLocker locker(avcodeclock);
00020 av_register_all();
00021 }
00022
00023 MetaIOMP4::~MetaIOMP4(void)
00024 {
00025 }
00026
00030 bool MetaIOMP4::write(const Metadata* mdata)
00031 {
00032 if (!mdata)
00033 return false;
00034
00035 mdata = mdata;
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076 return true;
00077 }
00078
00082 Metadata* MetaIOMP4::read(const QString &filename)
00083 {
00084 QString title, artist, album, genre;
00085 int year = 0, tracknum = 0, length = 0;
00086 bool compilation = false;
00087
00088 AVFormatContext* p_context = NULL;
00089 AVInputFormat* p_inputformat = NULL;
00090
00091 QByteArray local8bit = filename.toLocal8Bit();
00092 if ((avformat_open_input(&p_context, local8bit.constData(),
00093 p_inputformat, NULL) < 0))
00094 {
00095 return NULL;
00096 }
00097
00098 if (avformat_find_stream_info(p_context, NULL) < 0)
00099 return NULL;
00100
00101 #if 0
00102
00103
00104 AVDictionaryEntry *tag = av_dict_get(p_context->metadata, "\0", NULL,
00105 AV_METADATA_IGNORE_SUFFIX);
00106 while (tag != NULL)
00107 {
00108 LOG(VB_GENERAL, LOG_DEBUG, QString("Tag: %1 Value: %2")
00109 .arg(tag->key) .arg(QString::fromUtf8(tag->value)));
00110 tag = av_dict_get(p_context->metadata, "\0", tag,
00111 AV_METADATA_IGNORE_SUFFIX);
00112 }
00113
00114 #endif
00115
00116 title = getFieldValue(p_context, "title");
00117 if (title.isEmpty())
00118 {
00119 readFromFilename(filename, artist, album, title, genre, tracknum);
00120 }
00121 else
00122 {
00123 title = getFieldValue(p_context, "title");
00124 artist = getFieldValue(p_context, "author");
00125
00126
00127 if (artist.isEmpty())
00128 artist = getFieldValue(p_context, "artist");
00129 album = getFieldValue(p_context, "album");
00130 year = getFieldValue(p_context, "year").toInt();
00131 genre = getFieldValue(p_context, "genre");
00132 tracknum = getFieldValue(p_context, "track").toInt();
00133 compilation = getFieldValue(p_context, "").toInt();
00134 length = getTrackLength(p_context);
00135 }
00136
00137 metadataSanityCheck(&artist, &album, &title, &genre);
00138
00139 Metadata *retdata = new Metadata(filename,
00140 artist,
00141 compilation ? artist : "",
00142 album,
00143 title,
00144 genre,
00145 year,
00146 tracknum,
00147 length);
00148
00149 retdata->setCompilation(compilation);
00150
00151 avformat_close_input(&p_context);
00152
00153 return retdata;
00154 }
00155
00163 QString MetaIOMP4::getFieldValue(AVFormatContext* context, const char* tagname)
00164 {
00165 AVDictionaryEntry *tag = av_dict_get(context->metadata, tagname, NULL, 0);
00166
00167 QString value;
00168
00169 if (tag)
00170 value = QString::fromUtf8(tag->value);
00171
00172 return value;
00173 }
00174
00181 int MetaIOMP4::getTrackLength(const QString &filename)
00182 {
00183 AVFormatContext* p_context = NULL;
00184 AVInputFormat* p_inputformat = NULL;
00185
00186
00187 QByteArray local8bit = filename.toLocal8Bit();
00188 if ((avformat_open_input(&p_context, local8bit.constData(),
00189 p_inputformat, NULL) < 0))
00190 {
00191 return 0;
00192 }
00193
00194 if (avformat_find_stream_info(p_context, NULL) < 0)
00195 return 0;
00196
00197 int rv = getTrackLength(p_context);
00198
00199 avformat_close_input(&p_context);
00200
00201 return rv;
00202 }
00203
00210 int MetaIOMP4::getTrackLength(AVFormatContext* pContext)
00211 {
00212 if (!pContext)
00213 return 0;
00214
00215 av_estimate_timings(pContext, 0);
00216
00217 return (pContext->duration / AV_TIME_BASE) * 1000;
00218 }
00219
00228 void MetaIOMP4::metadataSanityCheck(QString *artist, QString *album,
00229 QString *title, QString *genre)
00230 {
00231 if (artist->isEmpty())
00232 artist->append("Unknown Artist");
00233
00234 if (album->isEmpty())
00235 album->append("Unknown Album");
00236
00237 if (title->isEmpty())
00238 title->append("Unknown Title");
00239
00240 if (genre->isEmpty())
00241 genre->append("Unknown Genre");
00242 }