KFileMetaData

ffmpegextractor.cpp
1 /*
2  Copyright (C) 2012-2014 Vishesh Handa <[email protected]>
3 
4  Code adapted from Strigi FFmpeg Analyzer -
5  Copyright (C) 2010 Evgeny Egorochkin <[email protected]>
6  Copyright (C) 2011 Tirtha Chatterjee <[email protected]>
7 
8  This library is free software; you can redistribute it and/or
9  modify it under the terms of the GNU Lesser General Public
10  License as published by the Free Software Foundation; either
11  version 2.1 of the License, or (at your option) any later version.
12 
13  This library is distributed in the hope that it will be useful,
14  but WITHOUT ANY WARRANTY; without even the implied warranty of
15  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16  Lesser General Public License for more details.
17 
18  You should have received a copy of the GNU Lesser General Public
19  License along with this library; if not, write to the Free Software
20  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
22 
23 
24 #include "ffmpegextractor.h"
25 
26 #include "config-kfilemetadata.h"
27 
28 #ifdef __cplusplus
29 #define __STDC_CONSTANT_MACROS
30 #ifdef _STDINT_H
31 #undef _STDINT_H
32 #endif
33 # include <stdint.h>
34 #endif
35 
36 extern "C" {
37 #include <libavformat/avformat.h>
38 #include <libavutil/dict.h>
39 #include <libavcodec/avcodec.h>
40 }
41 
42 #include <QDebug>
43 
44 using namespace KFileMetaData;
45 
46 FFmpegExtractor::FFmpegExtractor(QObject* parent)
47  : ExtractorPlugin(parent)
48 {
49 }
50 
51 const QStringList supportedMimeTypes = {
52  QStringLiteral("video/mp4"),
53  QStringLiteral("video/mpeg"),
54  QStringLiteral("video/quicktime"),
55  QStringLiteral("video/webm"),
56  QStringLiteral("video/ogg"),
57  QStringLiteral("video/mp2t"),
58  QStringLiteral("video/x-flv"),
59  QStringLiteral("video/x-matroska"),
60  QStringLiteral("video/x-ms-wmv"),
61  QStringLiteral("video/x-ms-asf"),
62  QStringLiteral("video/x-msvideo"),
63 };
64 
65 QStringList FFmpegExtractor::mimetypes() const
66 {
67  return supportedMimeTypes;
68 }
69 
70 void FFmpegExtractor::extract(ExtractionResult* result)
71 {
72  AVFormatContext* fmt_ctx = nullptr;
73 
74  av_register_all();
75 
76  QByteArray arr = result->inputUrl().toUtf8();
77 
78  fmt_ctx = avformat_alloc_context();
79  if (int ret = avformat_open_input(&fmt_ctx, arr.data(), nullptr, nullptr)) {
80  qWarning() << "avformat_open_input error: " << ret;
81  return;
82  }
83 
84  int ret = avformat_find_stream_info(fmt_ctx, nullptr);
85  if (ret < 0) {
86  qWarning() << "avform_find_stream_info error: " << ret;
87  return;
88  }
89 
90  result->addType(Type::Video);
91 
92  if (result->inputFlags() & ExtractionResult::ExtractMetaData) {
93  int totalSecs = fmt_ctx->duration / AV_TIME_BASE;
94  int bitrate = fmt_ctx->bit_rate;
95 
96  result->add(Property::Duration, totalSecs);
97  result->add(Property::BitRate, bitrate);
98 
99  for (uint i = 0; i < fmt_ctx->nb_streams; i++) {
100  AVStream* stream = fmt_ctx->streams[i];
101 #if defined HAVE_AVSTREAM_CODECPAR && HAVE_AVSTREAM_CODECPAR
102  const AVCodecParameters* codec = stream->codecpar;
103 #else
104  const AVCodecContext* codec = stream->codec;
105 #endif
106 
107  if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
108  result->add(Property::Width, codec->width);
109  result->add(Property::Height, codec->height);
110 
111  AVRational avSampleAspectRatio = av_guess_sample_aspect_ratio(fmt_ctx, stream, nullptr);
112  AVRational avDisplayAspectRatio;
113  av_reduce(&avDisplayAspectRatio.num, &avDisplayAspectRatio.den,
114  codec->width * avSampleAspectRatio.num,
115  codec->height * avSampleAspectRatio.den,
116  1024*1024);
117  double displayAspectRatio = avDisplayAspectRatio.num;
118  if (avDisplayAspectRatio.den)
119  displayAspectRatio /= avDisplayAspectRatio.den;
120  if (displayAspectRatio)
121  result->add(Property::AspectRatio, displayAspectRatio);
122 
123  AVRational avFrameRate = av_guess_frame_rate(fmt_ctx, stream, nullptr);
124  double frameRate = avFrameRate.num;
125  if (avFrameRate.den)
126  frameRate /= avFrameRate.den;
127  if (frameRate)
128  result->add(Property::FrameRate, frameRate);
129  }
130  }
131 
132  AVDictionary* dict = fmt_ctx->metadata;
133  AVDictionaryEntry* entry;
134 
135  entry = av_dict_get(dict, "title", nullptr, 0);
136  if (entry) {
137  result->add(Property::Title, QString::fromUtf8(entry->value));
138  }
139 
140 
141  entry = av_dict_get(dict, "author", nullptr, 0);
142  if (entry) {
143  result->add(Property::Author, QString::fromUtf8(entry->value));
144  }
145 
146  entry = av_dict_get(dict, "copyright", nullptr, 0);
147  if (entry) {
148  result->add(Property::Copyright, QString::fromUtf8(entry->value));
149  }
150 
151  entry = av_dict_get(dict, "comment", nullptr, 0);
152  if (entry) {
153  result->add(Property::Comment, QString::fromUtf8(entry->value));
154  }
155 
156  entry = av_dict_get(dict, "album", nullptr, 0);
157  if (entry) {
158  result->add(Property::Album, QString::fromUtf8(entry->value));
159  }
160 
161  entry = av_dict_get(dict, "genre", nullptr, 0);
162  if (entry) {
163  result->add(Property::Genre, QString::fromUtf8(entry->value));
164  }
165 
166  entry = av_dict_get(dict, "track", nullptr, 0);
167  if (entry) {
168  QString value = QString::fromUtf8(entry->value);
169 
170  bool ok = false;
171  int track = value.toInt(&ok);
172  if (ok && track)
173  result->add(Property::TrackNumber, track);
174  }
175 
176  entry = av_dict_get(dict, "year", nullptr, 0);
177  if (entry) {
178  int year = QString::fromUtf8(entry->value).toInt();
179  result->add(Property::ReleaseYear, year);
180  }
181  }
182 
183  avformat_close_input(&fmt_ctx);
184 }
virtual void add(Property::Property property, const QVariant &value)=0
This function is called by the plugins when they wish to add a key value pair which should be indexed...
The ExtractorPlugin is the base class for all file metadata extractors.
virtual void addType(Type::Type type)=0
This function is called by the plugins.
QString fromUtf8(const char *str, int size)
int toInt(bool *ok, int base) const const
char * data()
The ExtractionResult class is where all the data extracted by the indexer is saved.
Flags inputFlags() const
The flags which the extraction plugin should considering following when extracting metadata from the ...
QString inputUrl() const
The input url which the plugins will use to locate the file.
QByteArray toUtf8() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2020 The KDE developers.
Generated on Tue Jun 2 2020 22:55:51 by doxygen 1.8.11 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.