diff --git a/autotests/ffmpegextractortest.cpp b/autotests/ffmpegextractortest.cpp index a6d8f4a..54638ec 100644 --- a/autotests/ffmpegextractortest.cpp +++ b/autotests/ffmpegextractortest.cpp @@ -1,102 +1,115 @@ /* * Copyright (C) 2019 Alexander Stippich * * 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 "ffmpegextractortest.h" #include "simpleextractionresult.h" #include "indexerextractortestsconfig.h" #include "extractors/ffmpegextractor.h" #include using namespace KFileMetaData; namespace { QString testFilePath(const QString& baseName, const QString& extension) { return QLatin1String(INDEXER_TESTS_SAMPLE_FILES_PATH) + QLatin1Char('/') + baseName + QLatin1Char('.') + extension; } } // namespace void ffmpegExtractorTest::testVideoProperties_data() { QTest::addColumn("fileType"); QTest::addColumn("mimeType"); QTest::addRow("WebM") << QStringLiteral("webm") << QStringLiteral("video/webm"); QTest::addRow("Matroska Video") << QStringLiteral("mkv") << QStringLiteral("video/x-matroska"); + + QTest::addRow("Vorbis Video") + << QStringLiteral("ogv") + << QStringLiteral("video/ogg"); + + QTest::addRow("MPEG Transport") + << QStringLiteral("ts") + << QStringLiteral("video/mp2t"); } // only for testing of intrinsic video properties void ffmpegExtractorTest::testVideoProperties() { QFETCH(QString, fileType); QFETCH(QString, mimeType); FFmpegExtractor plugin{this}; SimpleExtractionResult result(testFilePath(QLatin1String("test"), fileType), mimeType); plugin.extract(&result); QCOMPARE(result.types().size(), 1); QCOMPARE(result.types().constFirst(), Type::Video); QCOMPARE(result.properties().value(Property::Width).toInt(), 1280); QCOMPARE(result.properties().value(Property::Height).toInt(), 720); QCOMPARE(result.properties().value(Property::FrameRate).toDouble(), 24.0/1.001); QCOMPARE(result.properties().value(Property::AspectRatio).toDouble(), 16.0/9); } void ffmpegExtractorTest::testMetaData_data() { QTest::addColumn("fileType"); QTest::addColumn("mimeType"); QTest::addRow("WebM") << QStringLiteral("webm") << QStringLiteral("video/webm"); QTest::addRow("Matroska Video") << QStringLiteral("mkv") << QStringLiteral("video/x-matroska"); + + QTest::addRow("Vorbis Video") + << QStringLiteral("ogv") + << QStringLiteral("video/ogg"); } void ffmpegExtractorTest::testMetaData() { QFETCH(QString, fileType); QFETCH(QString, mimeType); FFmpegExtractor plugin{this}; SimpleExtractionResult result(testFilePath(QLatin1String("test"), fileType), mimeType); plugin.extract(&result); + QEXPECT_FAIL("Vorbis Video", "Not yet supported", Abort); QCOMPARE(result.properties().value(Property::Title).toString(), QStringLiteral("Title")); QCOMPARE(result.properties().value(Property::Copyright).toString(), QStringLiteral("Copyright")); QCOMPARE(result.properties().value(Property::Author).toString(), QStringLiteral("Author")); QCOMPARE(result.properties().value(Property::ReleaseYear).toInt(), 2019); } QTEST_GUILESS_MAIN(ffmpegExtractorTest) diff --git a/autotests/samplefiles/test.ogv b/autotests/samplefiles/test.ogv new file mode 100644 index 0000000..78b0032 Binary files /dev/null and b/autotests/samplefiles/test.ogv differ diff --git a/autotests/samplefiles/test.ts b/autotests/samplefiles/test.ts new file mode 100644 index 0000000..157c69e Binary files /dev/null and b/autotests/samplefiles/test.ts differ diff --git a/src/extractors/ffmpegextractor.cpp b/src/extractors/ffmpegextractor.cpp index 0f4258e..480813e 100644 --- a/src/extractors/ffmpegextractor.cpp +++ b/src/extractors/ffmpegextractor.cpp @@ -1,181 +1,183 @@ /* Copyright (C) 2012-2014 Vishesh Handa Code adapted from Strigi FFmpeg Analyzer - Copyright (C) 2010 Evgeny Egorochkin Copyright (C) 2011 Tirtha Chatterjee 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 "ffmpegextractor.h" #include "config-kfilemetadata.h" #ifdef __cplusplus #define __STDC_CONSTANT_MACROS #ifdef _STDINT_H #undef _STDINT_H #endif # include #endif extern "C" { #include #include #include } #include #include using namespace KFileMetaData; FFmpegExtractor::FFmpegExtractor(QObject* parent) : ExtractorPlugin(parent) { } const QStringList supportedMimeTypes = { QStringLiteral("video/mp4"), QStringLiteral("video/mpeg"), QStringLiteral("video/quicktime"), QStringLiteral("video/webm"), + QStringLiteral("video/ogg"), + QStringLiteral("video/mp2t"), QStringLiteral("video/x-flv"), QStringLiteral("video/x-matroska"), QStringLiteral("video/x-ms-wmv"), QStringLiteral("video/x-ms-asf"), QStringLiteral("video/x-msvideo"), }; QStringList FFmpegExtractor::mimetypes() const { return supportedMimeTypes; } void FFmpegExtractor::extract(ExtractionResult* result) { AVFormatContext* fmt_ctx = nullptr; av_register_all(); QByteArray arr = result->inputUrl().toUtf8(); fmt_ctx = avformat_alloc_context(); if (int ret = avformat_open_input(&fmt_ctx, arr.data(), nullptr, nullptr)) { qWarning() << "avformat_open_input error: " << ret; return; } int ret = avformat_find_stream_info(fmt_ctx, nullptr); if (ret < 0) { qWarning() << "avform_find_stream_info error: " << ret; return; } result->addType(Type::Video); int totalSecs = fmt_ctx->duration / AV_TIME_BASE; int bitrate = fmt_ctx->bit_rate; result->add(Property::Duration, totalSecs); result->add(Property::BitRate, bitrate); for (uint i = 0; i < fmt_ctx->nb_streams; i++) { AVStream* stream = fmt_ctx->streams[i]; #if defined HAVE_AVSTREAM_CODECPAR && HAVE_AVSTREAM_CODECPAR const AVCodecParameters* codec = stream->codecpar; #else const AVCodecContext* codec = stream->codec; #endif if (codec->codec_type == AVMEDIA_TYPE_VIDEO) { result->add(Property::Width, codec->width); result->add(Property::Height, codec->height); AVRational avSampleAspectRatio = av_guess_sample_aspect_ratio(fmt_ctx, stream, NULL); AVRational avDisplayAspectRatio; av_reduce(&avDisplayAspectRatio.num, &avDisplayAspectRatio.den, codec->width * avSampleAspectRatio.num, codec->height * avSampleAspectRatio.den, 1024*1024); double displayAspectRatio = avDisplayAspectRatio.num; if (avDisplayAspectRatio.den) displayAspectRatio /= avDisplayAspectRatio.den; if (displayAspectRatio) result->add(Property::AspectRatio, displayAspectRatio); AVRational avFrameRate = av_guess_frame_rate(fmt_ctx, stream, NULL); double frameRate = avFrameRate.num; if (avFrameRate.den) frameRate /= avFrameRate.den; if (frameRate) result->add(Property::FrameRate, frameRate); } } AVDictionary* dict = fmt_ctx->metadata; AVDictionaryEntry* entry; entry = av_dict_get(dict, "title", nullptr, 0); if (entry) { result->add(Property::Title, QString::fromUtf8(entry->value)); } entry = av_dict_get(dict, "author", nullptr, 0); if (entry) { result->add(Property::Author, QString::fromUtf8(entry->value)); } entry = av_dict_get(dict, "copyright", nullptr, 0); if (entry) { result->add(Property::Copyright, QString::fromUtf8(entry->value)); } entry = av_dict_get(dict, "comment", nullptr, 0); if (entry) { result->add(Property::Comment, QString::fromUtf8(entry->value)); } entry = av_dict_get(dict, "album", nullptr, 0); if (entry) { result->add(Property::Album, QString::fromUtf8(entry->value)); } entry = av_dict_get(dict, "genre", nullptr, 0); if (entry) { result->add(Property::Genre, QString::fromUtf8(entry->value)); } entry = av_dict_get(dict, "track", nullptr, 0); if (entry) { QString value = QString::fromUtf8(entry->value); bool ok = false; int track = value.toInt(&ok); if (ok && track) result->add(Property::TrackNumber, track); } entry = av_dict_get(dict, "year", nullptr, 0); if (entry) { int year = QString::fromUtf8(entry->value).toInt(); result->add(Property::ReleaseYear, year); } avformat_close_input(&fmt_ctx); } diff --git a/src/extractors/ffmpegextractor.json b/src/extractors/ffmpegextractor.json index 58a9a49..6c7cf13 100644 --- a/src/extractors/ffmpegextractor.json +++ b/src/extractors/ffmpegextractor.json @@ -1,16 +1,18 @@ { "Name" : "FFMpegExtractor", "Id" : "org.kde.ffmpegextractor", "MimeTypes" : { "video/mp4" : { "Version" : "0.0" }, "video/mpeg" : { "Version" : "0.0" }, + "video/mp2t" : { "Version" : "0.0" }, + "video/ogg" : { "Version" : "0.0" }, "video/quicktime" : { "Version" : "0.0" }, "video/webm" : { "Version" : "0.0" }, "video/x-flv" : { "Version" : "0.0" }, "video/x-matroska" : { "Version" : "0.0" }, "video/x-ms-wmv" : { "Version" : "0.0" }, "video/x-ms-asf" : { "Version" : "0.0" }, "video/x-msvideo" : { "Version" : "0.0" } } }