From 507a3bdaaee9724e694b949deeb9cfaf7df89c1a Mon Sep 17 00:00:00 2001 From: emeric Date: Thu, 13 Mar 2014 13:52:16 +0100 Subject: [PATCH] Switching to Av libs to handle cover pictures --- av/Common.cpp | 5 +++++ av/Common.hpp | 4 ++++ av/InputFormatContext.cpp | 18 ++++++++++++++++++ av/InputFormatContext.hpp | 10 +++++++--- av/Stream.cpp | 6 ++++++ av/Stream.hpp | 1 + main/main.cpp | 14 +++++++------- transcode/AvConvTranscoder.cpp | 3 ++- transcode/InputMediaFile.cpp | 33 +++++++++++++++++++++------------ transcode/InputMediaFile.hpp | 5 +++++ ui/audio/AudioWidget.cpp | 14 ++++++-------- 11 files changed, 82 insertions(+), 31 deletions(-) diff --git a/av/Common.cpp b/av/Common.cpp index 769d4f67..a35e18cb 100644 --- a/av/Common.cpp +++ b/av/Common.cpp @@ -2,6 +2,9 @@ #include +namespace Av +{ + std::string AvError::to_str(void) const { @@ -27,3 +30,5 @@ void AvInit() av_register_all(); std::cout << "AVCDOEC VERSION = " << avcodec_version() << std::endl; } + +} // namespace Av diff --git a/av/Common.hpp b/av/Common.hpp index 259cf511..06737558 100644 --- a/av/Common.hpp +++ b/av/Common.hpp @@ -17,6 +17,9 @@ extern "C" { #include +namespace Av +{ + void AvInit(); @@ -40,5 +43,6 @@ class AvError int _errnum; }; +} // namespace Av #endif diff --git a/av/InputFormatContext.cpp b/av/InputFormatContext.cpp index adee7fc3..2f582dff 100644 --- a/av/InputFormatContext.cpp +++ b/av/InputFormatContext.cpp @@ -96,4 +96,22 @@ InputFormatContext::getMetadata(void) } +void +InputFormatContext::getPictures(std::vector< std::vector >& pictures) const +{ + for (std::size_t i = 0; i < native()->nb_streams; ++i) + { + if (native()->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC) + { + std::cout << "Found album art..." << std::endl; + AVPacket pkt = native()->streams[i]->attached_pic; + + std::vector data; + std::copy(pkt.data, pkt.data + pkt.size, std::back_inserter(data)); + + pictures.push_back( data ); + } + } +} + } //namespace Av diff --git a/av/InputFormatContext.hpp b/av/InputFormatContext.hpp index 17978b33..6ac7a72f 100644 --- a/av/InputFormatContext.hpp +++ b/av/InputFormatContext.hpp @@ -25,11 +25,15 @@ class InputFormatContext : public FormatContext // Scan file void findStreamInfo(); - std::vector getStreams(void); - bool getBestStreamIdx(enum AVMediaType type, Stream::Idx& idx); + // Get attached pictures + void getPictures(std::vector< std::vector >& pictures) const; - std::size_t getDurationSecs() const; + // Get the streams + std::vector getStreams(void); + + bool getBestStreamIdx(enum AVMediaType type, Stream::Idx& idx); + std::size_t getDurationSecs() const; private: boost::filesystem::path _path; diff --git a/av/Stream.cpp b/av/Stream.cpp index 3d606b5b..ccf195b4 100644 --- a/av/Stream.cpp +++ b/av/Stream.cpp @@ -23,4 +23,10 @@ Stream::getMetadata(void) return Dictionary(_stream->metadata); } +bool +Stream::hasAttachedPic(void) const +{ + return (_stream->disposition & AV_DISPOSITION_ATTACHED_PIC); +} + } // namespace Av diff --git a/av/Stream.hpp b/av/Stream.hpp index f9111299..44eb64b6 100644 --- a/av/Stream.hpp +++ b/av/Stream.hpp @@ -21,6 +21,7 @@ class Stream // Idx getIdx() const { return _stream->index; } + bool hasAttachedPic(void) const; Dictionary getMetadata(void); CodecContext getCodecContext(void); diff --git a/main/main.cpp b/main/main.cpp index 035ada75..0b73992a 100644 --- a/main/main.cpp +++ b/main/main.cpp @@ -22,31 +22,31 @@ Wt::WApplication *createApplication(const Wt::WEnvironment& env) int main(int argc, char* argv[]) { + Av::AvInit(); + Transcode::AvConvTranscoder::init(); + // std::locale::global(std::locale("")); MetaData::AvFormat metadataParser; // MetaData::Extractor metadataParser; - Transcode::AvConvTranscoder::init(); - // Set up the long living database session Database database("test.db", metadataParser); // database.watchDirectory( WatchedDirectory("/storage/common/Media/Son", WatchedDirectory::Audio )); -// database.watchDirectory(WatchedDirectory("/storage/common/Media/Son/Metal", WatchedDirectory::Audio)); + database.watchDirectory(WatchedDirectory("/storage/common/Media/Son/Metal", WatchedDirectory::Audio)); // database.watchDirectory("/storage/common/Media/Son/Metal/Iced Earth/2004 - The Glorious Burden"); // database.watchDirectory("/storage/common/Media/Son/Metal/System Of a Down"); // database.watchDirectory("/storage/common/Media/Son/Metal/Leprous"); // database.watchDirectory("/storage/common/Media/Son/Electro"); // database.watchDirectory( WatchedDirectory("/storage/common/Media/Son/Electro", WatchedDirectory::Audio) ); // database.watchDirectory("/storage/common/Media/Son/Metal/Lacuna Coil"); -// database.watchDirectory( WatchedDirectory("/storage/common/Media/Video", WatchedDirectory::Video) ); + database.watchDirectory( WatchedDirectory("/storage/common/Media/Video", WatchedDirectory::Video) ); // database.watchDirectory( WatchedDirectory("/storage/common/Media/Video/Films", WatchedDirectory::Video) ); - database.watchDirectory( WatchedDirectory("/storage/common/Media/Video/Series", WatchedDirectory::Video) ); +// database.watchDirectory( WatchedDirectory("/storage/common/Media/Video/Series", WatchedDirectory::Video) ); std::cout << "Starting refresh..." << std::endl; -// boost::thread refreshThread(boost::bind(&Database::refresh, &database)); + boost::thread refreshThread(boost::bind(&Database::refresh, &database)); - AvInit(); return Wt::WRun(argc, argv, &createApplication); } diff --git a/transcode/AvConvTranscoder.cpp b/transcode/AvConvTranscoder.cpp index 23958e89..53a08001 100644 --- a/transcode/AvConvTranscoder.cpp +++ b/transcode/AvConvTranscoder.cpp @@ -49,7 +49,8 @@ AvConvTranscoder::AvConvTranscoder(const Parameters& parameters) oss << "avconv"; // input Offset - oss << " -ss " << _parameters.getOffset().total_seconds(); // to be placed before '-i' to speed up seeking + if (_parameters.getOffset().total_seconds() > 0) + oss << " -ss " << _parameters.getOffset().total_seconds(); // to be placed before '-i' to speed up seeking // Input file oss << " -i \"" << _parameters.getInputMediaFile().getPath().string() << "\""; diff --git a/transcode/InputMediaFile.cpp b/transcode/InputMediaFile.cpp index 8b1afacc..6e65d58a 100644 --- a/transcode/InputMediaFile.cpp +++ b/transcode/InputMediaFile.cpp @@ -33,28 +33,37 @@ InputMediaFile::InputMediaFile(const boost::filesystem::path& p) _duration = boost::posix_time::seconds(input.getDurationSecs() + 1); // Get input streams - std::vector streams = input.getStreams(); + std::vector avStreams = input.getStreams(); - std::list types; - for (std::size_t streamId = 0; streamId < streams.size(); ++streamId) + std::list avMediaTypes; // List of encountered streams + for (std::size_t avStreamId = 0; avStreamId < avStreams.size(); ++avStreamId) { - Stream::Type type; + Av::Stream& avStream(avStreams[avStreamId]); + Stream::Type type; - if (getStreamType(streams[streamId].getCodecContext().getType(), type)) + if (getStreamType(avStream.getCodecContext().getType(), type)) { - types.push_back(streams[streamId].getCodecContext().getType()); + // Reject Video stream hat are in fact cover arts + if (avStream.hasAttachedPic()) + { + std::cout << "Rejecting stream since it is an attached picture!" << std::endl; + continue; + } - _streams.push_back( Stream(streamId, + + avMediaTypes.push_back(avStream.getCodecContext().getType()); + + _streams.push_back( Stream(avStreamId, type, - streams[streamId].getMetadata().get("language"), // TODO define somewhere else? - streams[streamId].getCodecContext().getCodecDesc() + avStream.getMetadata().get("language"), // TODO define somewhere else? + avStream.getCodecContext().getCodecDesc() )); } } - types.unique(); + avMediaTypes.unique(); // Scan for best streams - BOOST_FOREACH(enum AVMediaType type, types) + BOOST_FOREACH(enum AVMediaType type, avMediaTypes) { Av::Stream::Idx index; @@ -68,6 +77,7 @@ InputMediaFile::InputMediaFile(const boost::filesystem::path& p) std::cerr << "Cannot find best stream for type " << type << std::endl; } + input.getPictures( _coverPictures ); } std::vector @@ -82,6 +92,5 @@ InputMediaFile::getStreams(Stream::Type type) const return res; } - } // namespace Transcode diff --git a/transcode/InputMediaFile.hpp b/transcode/InputMediaFile.hpp index 73bc03d5..874235d8 100644 --- a/transcode/InputMediaFile.hpp +++ b/transcode/InputMediaFile.hpp @@ -32,6 +32,9 @@ class InputMediaFile boost::filesystem::path getPath(void) const {return _path;} boost::posix_time::time_duration getDuration(void) const {return _duration;} + // Pictures + const std::vector< std::vector >& getCoverPictures(void) const { return _coverPictures; } + // Stream handling std::vector getStreams(Stream::Type type) const; const std::map& getBestStreams(void) const {return _bestStreams;} @@ -43,6 +46,8 @@ class InputMediaFile std::vector _streams; std::map _bestStreams; + + std::vector< std::vector > _coverPictures; }; diff --git a/ui/audio/AudioWidget.cpp b/ui/audio/AudioWidget.cpp index 356710b7..de87a98c 100644 --- a/ui/audio/AudioWidget.cpp +++ b/ui/audio/AudioWidget.cpp @@ -49,15 +49,13 @@ AudioWidget::playTrack(boost::filesystem::path p) // Refresh cover { - MetaData::Extractor parser; - MetaData::GenericData cover; - if (parser.parseCover( p, cover)) { - std::cout << "Cover parsed!" << std::endl; - std::cout << "mime type = " << cover.mimeType << ", size = " << cover.data.size(); - - _imgResource->setMimeType(cover.mimeType); - _imgResource->setData(cover.data); + const std::vector< std::vector >& pictures = inputFile.getCoverPictures(); + if (!pictures.empty()) + { + std::cout << "Cover found!" << std::endl; +// _imgResource->setMimeType(cover.mimeType); + _imgResource->setData(pictures.front()); } else { std::cout << "No cover found!" << std::endl;