KFileMetaData

ffmpegextractor.cpp
1/*
2 SPDX-FileCopyrightText: 2012-2014 Vishesh Handa <me@vhanda.in>
3
4 Code adapted from Strigi FFmpeg Analyzer -
5 SPDX-FileCopyrightText: 2010 Evgeny Egorochkin <phreedom.stdin@gmail.com>
6 SPDX-FileCopyrightText: 2011 Tirtha Chatterjee <tirtha.p.chatterjee@gmail.com>
7
8 SPDX-License-Identifier: LGPL-2.1-or-later
9*/
10
11
12#include "ffmpegextractor.h"
13#include "kfilemetadata_debug.h"
14
15#include "config-kfilemetadata.h"
16
17#ifdef __cplusplus
18#define __STDC_CONSTANT_MACROS
19#ifdef _STDINT_H
20#undef _STDINT_H
21#endif
22# include <stdint.h>
23#endif
24
25extern "C" {
26#include <libavcodec/avcodec.h>
27#include <libavformat/avformat.h>
28#include <libavutil/avutil.h>
29#include <libavutil/dict.h>
30#include <libavutil/pixdesc.h>
31}
32
33using namespace KFileMetaData;
34
35FFmpegExtractor::FFmpegExtractor(QObject* parent)
36 : ExtractorPlugin(parent)
37{
38}
39
40const QStringList supportedMimeTypes = {
41 QStringLiteral("video/mp2t"),
42 QStringLiteral("video/mp4"),
43 QStringLiteral("video/mpeg"),
44 QStringLiteral("video/ogg"),
45 QStringLiteral("video/quicktime"),
46 QStringLiteral("video/vnd.avi"),
47 QStringLiteral("video/webm"),
48 QStringLiteral("video/x-flv"),
49 QStringLiteral("video/x-matroska"),
50 QStringLiteral("video/x-ms-asf"),
51 QStringLiteral("video/x-ms-wmv"),
52 QStringLiteral("video/x-msvideo"),
53};
54
55QStringList FFmpegExtractor::mimetypes() const
56{
57 return supportedMimeTypes;
58}
59
60void FFmpegExtractor::extract(ExtractionResult* result)
61{
62 AVFormatContext* fmt_ctx = nullptr;
63
64#if LIBAVFORMAT_VERSION_MAJOR < 58
65 av_register_all();
66#endif
67
68 QByteArray arr = result->inputUrl().toUtf8();
69
70 fmt_ctx = avformat_alloc_context();
71 if (int ret = avformat_open_input(&fmt_ctx, arr.data(), nullptr, nullptr)) {
72 qCWarning(KFILEMETADATA_LOG) << "avformat_open_input error: " << ret;
73 return;
74 }
75
76 int ret = avformat_find_stream_info(fmt_ctx, nullptr);
77 if (ret < 0) {
78 qCWarning(KFILEMETADATA_LOG) << "avform_find_stream_info error: " << ret;
79 return;
80 }
81
82 result->addType(Type::Video);
83
84 if (result->inputFlags() & ExtractionResult::ExtractMetaData) {
85 int totalSecs = fmt_ctx->duration / AV_TIME_BASE;
86 int bitrate = fmt_ctx->bit_rate;
87
88 result->add(Property::Duration, totalSecs);
89 result->add(Property::BitRate, bitrate);
90
91 const int index_stream = av_find_default_stream_index(fmt_ctx);
92 if (index_stream >= 0) {
93 AVStream* stream = fmt_ctx->streams[index_stream];
94
95 const AVCodecParameters* codec = stream->codecpar;
96
97 if (codec->codec_type == AVMEDIA_TYPE_VIDEO) {
98 result->add(Property::Width, codec->width);
99 result->add(Property::Height, codec->height);
100
101 AVRational avSampleAspectRatio = av_guess_sample_aspect_ratio(fmt_ctx, stream, nullptr);
102 AVRational avDisplayAspectRatio;
103 av_reduce(&avDisplayAspectRatio.num, &avDisplayAspectRatio.den,
104 codec->width * avSampleAspectRatio.num,
105 codec->height * avSampleAspectRatio.den,
106 1024*1024);
107 double displayAspectRatio = avDisplayAspectRatio.num;
108 if (avDisplayAspectRatio.den) {
109 displayAspectRatio /= avDisplayAspectRatio.den;
110 }
111 if (displayAspectRatio) {
112 result->add(Property::AspectRatio, displayAspectRatio);
113 }
114
115 AVRational avFrameRate = av_guess_frame_rate(fmt_ctx, stream, nullptr);
116 double frameRate = avFrameRate.num;
117 if (avFrameRate.den) {
118 frameRate /= avFrameRate.den;
119 }
120 if (frameRate) {
121 result->add(Property::FrameRate, frameRate);
122 }
123
124 result->add(Property::VideoCodec, QString::fromUtf8(avcodec_get_name(codec->codec_id)));
125
126 const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get((AVPixelFormat)codec->format);
127 if (desc) {
128 result->add(Property::PixelFormat, QString::fromUtf8(desc->name));
129 }
130
131 result->add(Property::ColorSpace, QString::fromUtf8(av_color_space_name(codec->color_space)));
132 }
133 }
134
135 const auto audio_index_stream = av_find_best_stream(fmt_ctx, AVMEDIA_TYPE_AUDIO, -1, -1, nullptr, 0);
136 if (audio_index_stream >= 0) {
137 AVStream* stream = fmt_ctx->streams[audio_index_stream];
138
139 const AVCodecParameters* codec = stream->codecpar;
140 result->add(Property::AudioCodec, QString::fromUtf8(avcodec_get_name(codec->codec_id)));
141 }
142
143 AVDictionary* dict = fmt_ctx->metadata;
144 // In Ogg, the internal comment metadata headers are attached to a single content stream.
145 // By convention, it's the first logical bitstream occuring.
146 if (!dict && fmt_ctx->nb_streams > 0) {
147 dict = fmt_ctx->streams[0]->metadata;
148 }
149
150 AVDictionaryEntry* entry;
151
152 entry = av_dict_get(dict, "title", nullptr, 0);
153 if (entry) {
154 result->add(Property::Title, QString::fromUtf8(entry->value));
155 }
156
157
158 entry = av_dict_get(dict, "author", nullptr, 0);
159 if (entry) {
160 result->add(Property::Author, QString::fromUtf8(entry->value));
161 }
162
163 entry = av_dict_get(dict, "copyright", nullptr, 0);
164 if (entry) {
165 result->add(Property::Copyright, QString::fromUtf8(entry->value));
166 }
167
168 entry = av_dict_get(dict, "comment", nullptr, 0);
169 if (entry) {
170 result->add(Property::Comment, QString::fromUtf8(entry->value));
171 }
172
173 entry = av_dict_get(dict, "album", nullptr, 0);
174 if (entry) {
175 result->add(Property::Album, QString::fromUtf8(entry->value));
176 }
177
178 entry = av_dict_get(dict, "genre", nullptr, 0);
179 if (entry) {
180 result->add(Property::Genre, QString::fromUtf8(entry->value));
181 }
182
183 entry = av_dict_get(dict, "track", nullptr, 0);
184 if (entry) {
185 QString value = QString::fromUtf8(entry->value);
186
187 bool ok = false;
188 int track = value.toInt(&ok);
189 if (ok && track) {
190 result->add(Property::TrackNumber, track);
191 }
192 }
193
194 entry = av_dict_get(dict, "year", nullptr, 0);
195 if (entry) {
196 int year = QString::fromUtf8(entry->value).toInt();
197 result->add(Property::ReleaseYear, year);
198 }
199 }
200
201 avformat_close_input(&fmt_ctx);
202}
203
204#include "moc_ffmpegextractor.cpp"
The ExtractionResult class is where all the data extracted by the indexer is saved.
QString inputUrl() const
The input URL which the plugins will use to locate the file.
virtual void addType(Type::Type type)=0
This function is called by the plugins.
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...
Flags inputFlags() const
The flags which the extraction plugin should considering following when extracting metadata from the ...
The ExtractorPlugin is the base class for all file metadata extractors.
@ Album
Represents the album of a media file.
Definition properties.h:90
@ Width
Represents the width of the Media in pixels.
Definition properties.h:189
@ VideoCodec
A string description of the codec used.
Definition properties.h:357
@ TrackNumber
Represents the track number in a set.
Definition properties.h:65
@ Title
Refers to the Title of the content of the file.
Definition properties.h:121
@ FrameRate
Number of frames per second.
Definition properties.h:206
@ Author
The Author field indicated the primary creator of a document.
Definition properties.h:114
@ Genre
The Genre of an Audio file.
Definition properties.h:52
@ Height
Represents the height of the Media in pixels.
Definition properties.h:195
@ AspectRatio
The Aspect Ratio of the visual image or video.
Definition properties.h:201
@ Comment
Represents a comment stored in the file.
Definition properties.h:77
@ BitRate
The Bit Rate of the Audio in the File.
Definition properties.h:33
@ PixelFormat
The Pixel format used by the media (image or video).
Definition properties.h:368
@ ColorSpace
The Color space used by the media (image or video)
Definition properties.h:373
@ AudioCodec
A string description of the codec used.
Definition properties.h:362
@ Copyright
The copyright of the file.
Definition properties.h:164
@ Duration
The duration of the media in the file.
Definition properties.h:45
@ ReleaseYear
Indicates the year a track was released.
Definition properties.h:71
@ Video
Any file which contains Video.
Definition types.h:51
The KFileMetaData namespace.
char * data()
QString fromUtf8(QByteArrayView str)
int toInt(bool *ok, int base) const const
QByteArray toUtf8() const const
This file is part of the KDE documentation.
Documentation copyright © 1996-2025 The KDE developers.
Generated on Fri Apr 11 2025 11:55:34 by doxygen 1.13.2 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.