[AV] Removed unused code, merged av and transcode
This commit is contained in:
@@ -39,6 +39,14 @@ AS_IF([test "$enable_lmsapi" = "yes"],
|
|||||||
AM_CONDITIONAL([LMSAPI], [test x$lmsapi = xtrue])
|
AM_CONDITIONAL([LMSAPI], [test x$lmsapi = xtrue])
|
||||||
AS_IF([test x$lmsapi = xtrue], [AC_DEFINE(HAVE_LMSAPI, [1], [Enable LMS API support])])
|
AS_IF([test x$lmsapi = xtrue], [AC_DEFINE(HAVE_LMSAPI, [1], [Enable LMS API support])])
|
||||||
|
|
||||||
|
AC_ARG_ENABLE([video], AS_HELP_STRING([--enable-video],
|
||||||
|
[Enable Video support. Default to yes.])],
|
||||||
|
[enable_video="$enableval"],
|
||||||
|
[enable_video="yes"])
|
||||||
|
|
||||||
|
AM_CONDITIONAL([VIDEO], [test x$enable_video = xyes])
|
||||||
|
|
||||||
|
|
||||||
AC_CHECK_HEADERS([Wt/WApplication jpeglib.h],
|
AC_CHECK_HEADERS([Wt/WApplication jpeglib.h],
|
||||||
[],
|
[],
|
||||||
[AC_MSG_ERROR([Header not found or unusable !])])
|
[AC_MSG_ERROR([Header not found or unusable !])])
|
||||||
|
|||||||
+10
-14
@@ -2,12 +2,8 @@ bin_PROGRAMS = lms
|
|||||||
|
|
||||||
lms_SOURCES = \
|
lms_SOURCES = \
|
||||||
$(srcdir)/main/main.cpp \
|
$(srcdir)/main/main.cpp \
|
||||||
$(srcdir)/av/CodecContext.cpp \
|
$(srcdir)/av/AvInfo.cpp \
|
||||||
$(srcdir)/av/Common.cpp \
|
$(srcdir)/av/AvTranscoder.cpp \
|
||||||
$(srcdir)/av/Dictionary.cpp \
|
|
||||||
$(srcdir)/av/FormatContext.cpp \
|
|
||||||
$(srcdir)/av/InputFormatContext.cpp \
|
|
||||||
$(srcdir)/av/Stream.cpp \
|
|
||||||
$(srcdir)/cover/CoverArt.cpp \
|
$(srcdir)/cover/CoverArt.cpp \
|
||||||
$(srcdir)/cover/CoverArtGrabber.cpp \
|
$(srcdir)/cover/CoverArtGrabber.cpp \
|
||||||
$(srcdir)/database/Artist.cpp \
|
$(srcdir)/database/Artist.cpp \
|
||||||
@@ -27,10 +23,6 @@ lms_SOURCES = \
|
|||||||
$(srcdir)/metadata/Utils.cpp \
|
$(srcdir)/metadata/Utils.cpp \
|
||||||
$(srcdir)/service/ServiceManager.cpp \
|
$(srcdir)/service/ServiceManager.cpp \
|
||||||
$(srcdir)/service/DatabaseUpdateService.cpp \
|
$(srcdir)/service/DatabaseUpdateService.cpp \
|
||||||
$(srcdir)/transcode/AvConvTranscoder.cpp \
|
|
||||||
$(srcdir)/transcode/Format.cpp \
|
|
||||||
$(srcdir)/transcode/Parameters.cpp \
|
|
||||||
$(srcdir)/transcode/InputMediaFile.cpp \
|
|
||||||
$(srcdir)/ui/LmsApplication.cpp \
|
$(srcdir)/ui/LmsApplication.cpp \
|
||||||
$(srcdir)/ui/auth/LmsAuth.cpp \
|
$(srcdir)/ui/auth/LmsAuth.cpp \
|
||||||
$(srcdir)/ui/audio/desktop/DesktopAudio.cpp \
|
$(srcdir)/ui/audio/desktop/DesktopAudio.cpp \
|
||||||
@@ -49,10 +41,6 @@ lms_SOURCES = \
|
|||||||
$(srcdir)/ui/common/LineEdit.cpp \
|
$(srcdir)/ui/common/LineEdit.cpp \
|
||||||
$(srcdir)/ui/resource/AvConvTranscodeStreamResource.cpp \
|
$(srcdir)/ui/resource/AvConvTranscodeStreamResource.cpp \
|
||||||
$(srcdir)/ui/resource/CoverResource.cpp \
|
$(srcdir)/ui/resource/CoverResource.cpp \
|
||||||
$(srcdir)/ui/video/VideoWidget.cpp \
|
|
||||||
$(srcdir)/ui/video/VideoDatabaseWidget.cpp \
|
|
||||||
$(srcdir)/ui/video/VideoMediaPlayerWidget.cpp \
|
|
||||||
$(srcdir)/ui/video/VideoParametersDialog.cpp \
|
|
||||||
$(srcdir)/ui/settings/Settings.cpp \
|
$(srcdir)/ui/settings/Settings.cpp \
|
||||||
$(srcdir)/ui/settings/SettingsAccountFormView.cpp \
|
$(srcdir)/ui/settings/SettingsAccountFormView.cpp \
|
||||||
$(srcdir)/ui/settings/SettingsAudioFormView.cpp \
|
$(srcdir)/ui/settings/SettingsAudioFormView.cpp \
|
||||||
@@ -63,6 +51,14 @@ lms_SOURCES = \
|
|||||||
$(srcdir)/ui/settings/SettingsUserFormView.cpp \
|
$(srcdir)/ui/settings/SettingsUserFormView.cpp \
|
||||||
$(srcdir)/ui/settings/SettingsUsers.cpp
|
$(srcdir)/ui/settings/SettingsUsers.cpp
|
||||||
|
|
||||||
|
if VIDEO
|
||||||
|
lms_SOURCES += \
|
||||||
|
$(srcdir)/ui/video/VideoWidget.cpp \
|
||||||
|
$(srcdir)/ui/video/VideoDatabaseWidget.cpp \
|
||||||
|
$(srcdir)/ui/video/VideoMediaPlayerWidget.cpp \
|
||||||
|
$(srcdir)/ui/video/VideoParametersDialog.cpp
|
||||||
|
endif
|
||||||
|
|
||||||
if LMSAPI
|
if LMSAPI
|
||||||
lms_SOURCES += \
|
lms_SOURCES += \
|
||||||
$(srcdir)/lms-api/server/Connection.cpp \
|
$(srcdir)/lms-api/server/Connection.cpp \
|
||||||
|
|||||||
@@ -0,0 +1,306 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Emeric Poupon
|
||||||
|
*
|
||||||
|
* This file is part of LMS.
|
||||||
|
*
|
||||||
|
* LMS is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LMS 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <array>
|
||||||
|
|
||||||
|
#include "logger/Logger.hpp"
|
||||||
|
|
||||||
|
#include "AvInfo.hpp"
|
||||||
|
|
||||||
|
namespace Av {
|
||||||
|
|
||||||
|
static std::string streamType_to_string(Stream::Type type)
|
||||||
|
{
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case Stream::Type::Audio: return "audio";
|
||||||
|
case Stream::Type::Video: return "video";
|
||||||
|
case Stream::Type::Subtitle: return "subtitle";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "unknown";
|
||||||
|
}
|
||||||
|
|
||||||
|
static std::string averror_to_string(int error)
|
||||||
|
{
|
||||||
|
std::array<char, 128> buf = {0};
|
||||||
|
|
||||||
|
if (av_strerror(error, buf.data(), buf.size()) == 0)
|
||||||
|
return std::string(&buf[0]);
|
||||||
|
else
|
||||||
|
return "Unknown error";
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void AvInit()
|
||||||
|
{
|
||||||
|
/* register all the codecs */
|
||||||
|
avcodec_register_all();
|
||||||
|
av_register_all();
|
||||||
|
LMS_LOG(MOD_AV, SEV_INFO) << "avcodec version = " << avcodec_version();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
MediaFile::MediaFile(const boost::filesystem::path& p)
|
||||||
|
: _p(p), _context(nullptr)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
MediaFile::~MediaFile()
|
||||||
|
{
|
||||||
|
if (_context != nullptr)
|
||||||
|
avformat_close_input(&_context);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MediaFile::open(void)
|
||||||
|
{
|
||||||
|
if (_context != nullptr)
|
||||||
|
throw std::logic_error("inputfile '" + _p.string() + "' already open");
|
||||||
|
|
||||||
|
int error = avformat_open_input(&_context, _p.string().c_str(), nullptr, nullptr);
|
||||||
|
if (error < 0)
|
||||||
|
{
|
||||||
|
LMS_LOG(MOD_AV, SEV_ERROR) << "Cannot open '" << _p.string() << "', avformat_open_input returned " << averror_to_string(error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MediaFile::scan(void)
|
||||||
|
{
|
||||||
|
if (_context == nullptr)
|
||||||
|
throw std::logic_error("inputfile '" + _p.string() + "' not open");
|
||||||
|
|
||||||
|
int error = avformat_find_stream_info(_context, nullptr);
|
||||||
|
if (error < 0)
|
||||||
|
{
|
||||||
|
LMS_LOG(MOD_AV, SEV_ERROR) << "Cannot find stream information: '" << averror_to_string(error);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
boost::posix_time::time_duration
|
||||||
|
MediaFile::getDuration() const
|
||||||
|
{
|
||||||
|
if (_context == nullptr)
|
||||||
|
throw std::logic_error("inputfile '" + _p.string() + "' not open");
|
||||||
|
|
||||||
|
if (static_cast<int>(_context->duration) != AV_NOPTS_VALUE )
|
||||||
|
return boost::posix_time::seconds(_context->duration / AV_TIME_BASE);
|
||||||
|
else
|
||||||
|
return boost::posix_time::seconds(0); // TODO, do something better?
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
getMetaDataFromDictionnary(AVDictionary* dictionnary, std::map<std::string, std::string>& res)
|
||||||
|
{
|
||||||
|
if (!dictionnary)
|
||||||
|
return;
|
||||||
|
|
||||||
|
AVDictionaryEntry *tag = NULL;
|
||||||
|
while ((tag = av_dict_get(dictionnary, "", tag, AV_DICT_IGNORE_SUFFIX)))
|
||||||
|
{
|
||||||
|
res.insert( std::make_pair(tag->key, tag->value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::map<std::string, std::string>
|
||||||
|
MediaFile::getMetaData(void)
|
||||||
|
{
|
||||||
|
if (_context == nullptr)
|
||||||
|
throw std::logic_error("inputfile '" + _p.string() + "' not open");
|
||||||
|
|
||||||
|
std::map<std::string, std::string> res;
|
||||||
|
|
||||||
|
getMetaDataFromDictionnary(_context->metadata, res);
|
||||||
|
|
||||||
|
// HACK for OGG files
|
||||||
|
// If we did not find tags, search metadata in streams
|
||||||
|
if (res.empty())
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < _context->nb_streams; ++i)
|
||||||
|
{
|
||||||
|
getMetaDataFromDictionnary(_context->streams[i]->metadata, res);
|
||||||
|
|
||||||
|
if (!res.empty())
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Stream>
|
||||||
|
MediaFile::getStreams(Stream::Type type) const
|
||||||
|
{
|
||||||
|
if (_context == nullptr)
|
||||||
|
throw std::logic_error("inputfile '" + _p.string() + "' not open");
|
||||||
|
|
||||||
|
std::vector<Stream> res;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < _context->nb_streams; ++i)
|
||||||
|
{
|
||||||
|
AVStream* avstream = _context->streams[i];
|
||||||
|
|
||||||
|
// Skip attached pics
|
||||||
|
if (avstream->disposition & AV_DISPOSITION_ATTACHED_PIC)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (avstream->codec == nullptr)
|
||||||
|
{
|
||||||
|
LMS_LOG(MOD_AV, SEV_ERROR) << "Skipping stream " << i << " since no codec is set";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (type == Stream::Type::Audio && avstream->codec->codec_type != AVMEDIA_TYPE_AUDIO)
|
||||||
|
continue;
|
||||||
|
else if (type == Stream::Type::Video && avstream->codec->codec_type != AVMEDIA_TYPE_VIDEO)
|
||||||
|
continue;
|
||||||
|
else if (type == Stream::Type::Subtitle && avstream->codec->codec_type != AVMEDIA_TYPE_SUBTITLE)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
Stream stream;
|
||||||
|
|
||||||
|
stream.id = i; // or use stream->id ?
|
||||||
|
stream.type = type;
|
||||||
|
stream.bitrate = avstream->codec->bit_rate;
|
||||||
|
|
||||||
|
{
|
||||||
|
std::array<char, 256> buf = {0};
|
||||||
|
avcodec_string(buf.data(), buf.size(), avstream->codec, 0);
|
||||||
|
|
||||||
|
stream.desc = buf.data();
|
||||||
|
}
|
||||||
|
|
||||||
|
res.push_back(stream);
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
int
|
||||||
|
MediaFile::getBestStreamId(Stream::Type type) const
|
||||||
|
{
|
||||||
|
if (_context == nullptr)
|
||||||
|
throw std::logic_error("inputfile '" + _p.string() + "' not open");
|
||||||
|
|
||||||
|
enum AVMediaType avMediaType;
|
||||||
|
|
||||||
|
switch (type)
|
||||||
|
{
|
||||||
|
case Stream::Type::Audio: avMediaType = AVMEDIA_TYPE_AUDIO; break;
|
||||||
|
case Stream::Type::Video: avMediaType = AVMEDIA_TYPE_VIDEO; break;
|
||||||
|
case Stream::Type::Subtitle: avMediaType = AVMEDIA_TYPE_SUBTITLE; break;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int res = av_find_best_stream(_context,
|
||||||
|
avMediaType,
|
||||||
|
-1, // Auto
|
||||||
|
-1, // Auto
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
if (res < 0)
|
||||||
|
{
|
||||||
|
LMS_LOG(MOD_AV, SEV_ERROR) << "Cannot find best stream for type " << streamType_to_string(type);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
MediaFile::hasAttachedPictures(void) const
|
||||||
|
{
|
||||||
|
for (std::size_t i = 0; i < _context->nb_streams; ++i)
|
||||||
|
{
|
||||||
|
if (_context->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<Picture>
|
||||||
|
MediaFile::getAttachedPictures(std::size_t nbMaxPictures) const
|
||||||
|
{
|
||||||
|
if (_context == nullptr)
|
||||||
|
throw std::logic_error("inputfile '" + _p.string() + "' not open");
|
||||||
|
|
||||||
|
static const std::map<int, std::string> codecMimeMap =
|
||||||
|
{
|
||||||
|
{ AV_CODEC_ID_BMP, "image/x-bmp" },
|
||||||
|
{ AV_CODEC_ID_GIF, "image/gif" },
|
||||||
|
{ AV_CODEC_ID_MJPEG, "image/jpeg" },
|
||||||
|
{ AV_CODEC_ID_PNG, "image/png" },
|
||||||
|
{ AV_CODEC_ID_PNG, "image/x-png" },
|
||||||
|
{ AV_CODEC_ID_PPM, "image/x-portable-pixmap" },
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<Picture> pictures;
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < _context->nb_streams; ++i)
|
||||||
|
{
|
||||||
|
AVStream *avstream = _context->streams[i];
|
||||||
|
|
||||||
|
// Skip attached pics
|
||||||
|
if (!(avstream->disposition & AV_DISPOSITION_ATTACHED_PIC))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (avstream->codec == nullptr)
|
||||||
|
{
|
||||||
|
LMS_LOG(MOD_AV, SEV_ERROR) << "Skipping stream " << i << " since no codec is set";
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
Picture picture;
|
||||||
|
|
||||||
|
auto itMime = codecMimeMap.find(avstream->codec->codec_id);
|
||||||
|
if (itMime != codecMimeMap.end())
|
||||||
|
{
|
||||||
|
picture.mimeType = itMime->second;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
picture.mimeType = "application/octet-stream";
|
||||||
|
LMS_LOG(MOD_AV, SEV_ERROR) << "CODEC ID " << avstream->codec->codec_id << " not handled in mime type conversion";
|
||||||
|
}
|
||||||
|
|
||||||
|
AVPacket pkt = avstream->attached_pic;
|
||||||
|
|
||||||
|
std::copy(pkt.data, pkt.data + pkt.size, std::back_inserter(picture.data));
|
||||||
|
|
||||||
|
pictures.push_back( picture );
|
||||||
|
|
||||||
|
if (pictures.size() >= nbMaxPictures)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return pictures;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace Av
|
||||||
@@ -0,0 +1,97 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Emeric Poupon
|
||||||
|
*
|
||||||
|
* This file is part of LMS.
|
||||||
|
*
|
||||||
|
* LMS is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LMS 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/* This file contains some classes in order to get info from file using the libavconv */
|
||||||
|
|
||||||
|
#ifndef AV_INFO_HPP
|
||||||
|
#define AV_INFO_HPP
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#define __STDC_CONSTANT_MACROS
|
||||||
|
#include <libavcodec/avcodec.h>
|
||||||
|
#include <libavformat/avformat.h>
|
||||||
|
#include <libavutil/error.h>
|
||||||
|
}
|
||||||
|
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
#include <cstdint>
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
#include <boost/date_time/posix_time/posix_time_types.hpp> //no i/o just types
|
||||||
|
|
||||||
|
namespace Av
|
||||||
|
{
|
||||||
|
|
||||||
|
void AvInit();
|
||||||
|
|
||||||
|
struct Picture
|
||||||
|
{
|
||||||
|
std::string mimeType;
|
||||||
|
std::vector<uint8_t> data;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct Stream
|
||||||
|
{
|
||||||
|
enum class Type
|
||||||
|
{
|
||||||
|
Audio,
|
||||||
|
Video,
|
||||||
|
Subtitle,
|
||||||
|
};
|
||||||
|
|
||||||
|
int id;
|
||||||
|
Type type;
|
||||||
|
std::size_t bitrate;
|
||||||
|
std::string desc; // Description of the stream
|
||||||
|
};
|
||||||
|
|
||||||
|
class MediaFile
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
MediaFile(const boost::filesystem::path& p);
|
||||||
|
~MediaFile();
|
||||||
|
|
||||||
|
boost::filesystem::path getPath() const {return _p;};
|
||||||
|
|
||||||
|
bool open(void);
|
||||||
|
bool scan(void);
|
||||||
|
|
||||||
|
boost::posix_time::time_duration getDuration() const;
|
||||||
|
std::map<std::string, std::string> getMetaData(void);
|
||||||
|
|
||||||
|
std::vector<Stream> getStreams(Stream::Type type) const;
|
||||||
|
int getBestStreamId(Stream::Type type) const; // -1 if failure/unknown
|
||||||
|
bool hasAttachedPictures(void) const;
|
||||||
|
std::vector<Picture> getAttachedPictures(std::size_t nbMaxPictures) const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
boost::filesystem::path _p;
|
||||||
|
AVFormatContext* _context;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
} // namespace Av
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
* Copyright (C) 2015 Emeric Poupon
|
||||||
*
|
*
|
||||||
* This file is part of LMS.
|
* This file is part of LMS.
|
||||||
*
|
*
|
||||||
@@ -17,18 +17,29 @@
|
|||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <sstream>
|
|
||||||
|
|
||||||
#include <boost/iostreams/stream.hpp>
|
|
||||||
#include <boost/process.hpp>
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
|
|
||||||
#include "logger/Logger.hpp"
|
#include "logger/Logger.hpp"
|
||||||
|
|
||||||
#include "AvConvTranscoder.hpp"
|
#include "AvTranscoder.hpp"
|
||||||
|
|
||||||
namespace Transcode
|
namespace Av {
|
||||||
|
|
||||||
|
std::string encoding_to_mimetype(Encoding encoding)
|
||||||
{
|
{
|
||||||
|
switch(encoding)
|
||||||
|
{
|
||||||
|
case Encoding::MP3: return "audio/mp3";
|
||||||
|
case Encoding::OGA: return "audio/ogg";
|
||||||
|
case Encoding::OGV: return "video/ogg";
|
||||||
|
case Encoding::WEBMA: return "audio/webm";
|
||||||
|
case Encoding::WEBMV: return "video/webm";
|
||||||
|
case Encoding::FLA: return "audio/x-flv";
|
||||||
|
case Encoding::FLV: return "video/x-flv";
|
||||||
|
case Encoding::M4A: return "audio/mp4";
|
||||||
|
case Encoding::M4V: return "video/mp4";
|
||||||
|
}
|
||||||
|
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
// TODO, parametrize?
|
// TODO, parametrize?
|
||||||
const std::vector<std::string> execNames =
|
const std::vector<std::string> execNames =
|
||||||
@@ -37,15 +48,14 @@ const std::vector<std::string> execNames =
|
|||||||
"ffmpeg",
|
"ffmpeg",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
boost::mutex Transcoder::_mutex;
|
||||||
|
|
||||||
boost::mutex AvConvTranscoder::_mutex;
|
boost::filesystem::path Transcoder::_avConvPath = boost::filesystem::path();
|
||||||
|
|
||||||
boost::filesystem::path AvConvTranscoder::_avConvPath = boost::filesystem::path();
|
|
||||||
|
|
||||||
void
|
void
|
||||||
AvConvTranscoder::init()
|
Transcoder::init()
|
||||||
{
|
{
|
||||||
BOOST_FOREACH(std::string execName, execNames)
|
for (std::string execName : execNames)
|
||||||
{
|
{
|
||||||
const boost::filesystem::path p = boost::process::search_path(execName);
|
const boost::filesystem::path p = boost::process::search_path(execName);
|
||||||
if (!p.empty())
|
if (!p.empty())
|
||||||
@@ -62,26 +72,29 @@ AvConvTranscoder::init()
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
//boost::filesystem::path AvConvTranscoder::_avConvPath = "";
|
//boost::filesystem::path Transcoder::_avConvPath = "";
|
||||||
|
|
||||||
AvConvTranscoder::AvConvTranscoder(const Parameters& parameters)
|
Transcoder::Transcoder(boost::filesystem::path filePath, TranscodeParameters parameters)
|
||||||
: _parameters(parameters),
|
: _filePath(filePath),
|
||||||
|
_parameters(parameters),
|
||||||
_outputPipe(boost::process::create_pipe()),
|
_outputPipe(boost::process::create_pipe()),
|
||||||
_source(_outputPipe.source, boost::iostreams::close_handle),
|
_source(_outputPipe.source, boost::iostreams::close_handle),
|
||||||
_is(_source),
|
_is(_source),
|
||||||
_in(&_is),
|
_in(&_is),
|
||||||
_isComplete(false),
|
_isComplete(false)
|
||||||
_outputBytes(0)
|
|
||||||
{
|
{
|
||||||
|
|
||||||
if (!boost::filesystem::exists(_parameters.getInputMediaFile().getPath())) {
|
}
|
||||||
throw std::runtime_error("File " + _parameters.getInputMediaFile().getPath().string() + " does not exists!");
|
|
||||||
}
|
|
||||||
else if (!boost::filesystem::is_regular( _parameters.getInputMediaFile().getPath())) {
|
|
||||||
throw std::runtime_error("File " + _parameters.getInputMediaFile().getPath().string() + " is not regular!");
|
|
||||||
}
|
|
||||||
|
|
||||||
LMS_LOG(MOD_TRANSCODE, SEV_INFO) << "Transcoding file '" << _parameters.getInputMediaFile().getPath() << "'";
|
bool
|
||||||
|
Transcoder::start()
|
||||||
|
{
|
||||||
|
if (!boost::filesystem::exists(_filePath))
|
||||||
|
return false;
|
||||||
|
else if (!boost::filesystem::is_regular( _filePath) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
LMS_LOG(MOD_TRANSCODE, SEV_INFO) << "Transcoding file '" << _filePath << "'";
|
||||||
|
|
||||||
// Launch a process to handle the conversion
|
// Launch a process to handle the conversion
|
||||||
boost::iostreams::file_descriptor_sink sink(_outputPipe.sink, boost::iostreams::close_handle);
|
boost::iostreams::file_descriptor_sink sink(_outputPipe.sink, boost::iostreams::close_handle);
|
||||||
@@ -92,62 +105,55 @@ AvConvTranscoder::AvConvTranscoder(const Parameters& parameters)
|
|||||||
|
|
||||||
// input Offset
|
// input Offset
|
||||||
if (_parameters.getOffset().total_seconds() > 0)
|
if (_parameters.getOffset().total_seconds() > 0)
|
||||||
oss << " -ss " << _parameters.getOffset().total_seconds(); // to be placed before '-i' to speed up seeking
|
oss << " -ss " << _parameters.getOffset().total_seconds(); // to be placed before '-i' to speed up seeking?
|
||||||
|
|
||||||
// Input file
|
// Input file
|
||||||
oss << " -i \"" << _parameters.getInputMediaFile().getPath().string() << "\"";
|
oss << " -i " << _filePath;
|
||||||
|
|
||||||
// Output bitrates
|
// Output bitrates
|
||||||
oss << " -b:a " << _parameters.getOutputBitrate(Stream::Audio) ;
|
oss << " -b:a " << _parameters.getBitrate(Stream::Type::Audio) ;
|
||||||
if (_parameters.getOutputFormat().getType() == Format::Video)
|
// if (_parameters.getOutputFormat().getType() == Format::Video)
|
||||||
oss << " -b:v " << _parameters.getOutputBitrate(Stream::Video);
|
// oss << " -b:v " << _parameters.getOutputBitrate(Stream::Video);
|
||||||
|
|
||||||
// Stream mapping
|
// Stream mapping
|
||||||
|
for (int streamId : _parameters.getSelectedStreamIds())
|
||||||
{
|
{
|
||||||
typedef std::map<Stream::Type, Stream::Id> StreamMap;
|
// 0 means the first input file
|
||||||
|
oss << " -map 0:" << streamId;
|
||||||
const StreamMap& streamMap = _parameters.getInputStreams();
|
|
||||||
|
|
||||||
BOOST_FOREACH(const StreamMap::value_type& inputStream, streamMap)
|
|
||||||
{
|
|
||||||
// HACK (no subtitle support yet)
|
|
||||||
if (inputStream.first != Stream::Subtitle)
|
|
||||||
oss << " -map 0:" << inputStream.second; // 0 means input file index
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Codecs and formats
|
// Codecs and formats
|
||||||
switch( _parameters.getOutputFormat().getEncoding())
|
switch( _parameters.getEncoding())
|
||||||
{
|
{
|
||||||
case Format::MP3:
|
case Encoding::MP3:
|
||||||
oss << " -f mp3";
|
oss << " -f mp3";
|
||||||
break;
|
break;
|
||||||
case Format::OGA:
|
case Encoding::OGA:
|
||||||
oss << " -acodec libvorbis -f ogg";
|
oss << " -acodec libvorbis -f ogg";
|
||||||
break;
|
break;
|
||||||
case Format::OGV:
|
case Encoding::OGV:
|
||||||
oss << " -acodec libvorbis -ac 2 -ar 44100 -vcodec libtheora -threads 4 -f ogg";
|
oss << " -acodec libvorbis -ac 2 -ar 44100 -vcodec libtheora -threads 4 -f ogg";
|
||||||
break;
|
break;
|
||||||
case Format::WEBMA:
|
case Encoding::WEBMA:
|
||||||
oss << " -codec:a libvorbis -f webm";
|
oss << " -codec:a libvorbis -f webm";
|
||||||
break;
|
break;
|
||||||
case Format::WEBMV:
|
case Encoding::WEBMV:
|
||||||
oss << " -acodec libvorbis -ac 2 -ar 44100 -vcodec libvpx -threads 4 -f webm";
|
oss << " -acodec libvorbis -ac 2 -ar 44100 -vcodec libvpx -threads 4 -f webm";
|
||||||
break;
|
break;
|
||||||
case Format::M4A:
|
case Encoding::M4A:
|
||||||
oss << " -acodec aac -f mp4 -strict experimental";
|
oss << " -acodec aac -f mp4 -strict experimental";
|
||||||
break;
|
break;
|
||||||
case Format::M4V:
|
case Encoding::M4V:
|
||||||
oss << " -acodec aac -strict experimental -ac 2 -ar 44100 -vcodec libx264 -f m4v";
|
oss << " -acodec aac -strict experimental -ac 2 -ar 44100 -vcodec libx264 -f m4v";
|
||||||
break;
|
break;
|
||||||
case Format::FLV:
|
case Encoding::FLV:
|
||||||
oss << " -acodec libmp3lame -ac 2 -ar 44100 -vcodec libx264 -f flv";
|
oss << " -acodec libmp3lame -ac 2 -ar 44100 -vcodec libx264 -f flv";
|
||||||
break;
|
break;
|
||||||
case Format::FLA:
|
case Encoding::FLA:
|
||||||
oss << " -acodec libmp3lame -f flv";
|
oss << " -acodec libmp3lame -f flv";
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
return false;
|
||||||
}
|
}
|
||||||
oss << " -"; // output to stdout
|
oss << " -"; // output to stdout
|
||||||
|
|
||||||
@@ -167,10 +173,11 @@ AvConvTranscoder::AvConvTranscoder(const Parameters& parameters)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AvConvTranscoder::process(std::vector<unsigned char>& output, std::size_t maxSize)
|
Transcoder::process(std::vector<unsigned char>& output, std::size_t maxSize)
|
||||||
{
|
{
|
||||||
std::size_t readDataSize = 0;
|
std::size_t readDataSize = 0;
|
||||||
|
|
||||||
@@ -181,7 +188,6 @@ AvConvTranscoder::process(std::vector<unsigned char>& output, std::size_t maxSiz
|
|||||||
while(readDataSize < maxSize && _in && _in.get(ch)) {
|
while(readDataSize < maxSize && _in && _in.get(ch)) {
|
||||||
output.push_back(ch);
|
output.push_back(ch);
|
||||||
readDataSize++;
|
readDataSize++;
|
||||||
_outputBytes++; // stats
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!_in || _in.fail() || _in.eof()) {
|
if (!_in || _in.fail() || _in.eof()) {
|
||||||
@@ -193,9 +199,9 @@ AvConvTranscoder::process(std::vector<unsigned char>& output, std::size_t maxSiz
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
AvConvTranscoder::~AvConvTranscoder()
|
Transcoder::~Transcoder()
|
||||||
{
|
{
|
||||||
LMS_LOG(MOD_TRANSCODE, SEV_DEBUG) << "~AvConvTranscoder called!";
|
LMS_LOG(MOD_TRANSCODE, SEV_DEBUG) << "~Transcoder called!";
|
||||||
|
|
||||||
if (_in.eof())
|
if (_in.eof())
|
||||||
waitChild();
|
waitChild();
|
||||||
@@ -204,7 +210,7 @@ AvConvTranscoder::~AvConvTranscoder()
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AvConvTranscoder::waitChild()
|
Transcoder::waitChild()
|
||||||
{
|
{
|
||||||
if (_child)
|
if (_child)
|
||||||
{
|
{
|
||||||
@@ -215,14 +221,14 @@ AvConvTranscoder::waitChild()
|
|||||||
LMS_LOG(MOD_TRANSCODE, SEV_DEBUG) << "Waiting for child: OK";
|
LMS_LOG(MOD_TRANSCODE, SEV_DEBUG) << "Waiting for child: OK";
|
||||||
|
|
||||||
if (ec)
|
if (ec)
|
||||||
LMS_LOG(MOD_TRANSCODE, SEV_ERROR) << "AvConvTranscoder::waitChild: error: " << ec.message();
|
LMS_LOG(MOD_TRANSCODE, SEV_ERROR) << "Transcoder::waitChild: error: " << ec.message();
|
||||||
|
|
||||||
_child.reset();
|
_child.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AvConvTranscoder::killChild()
|
Transcoder::killChild()
|
||||||
{
|
{
|
||||||
if (_child)
|
if (_child)
|
||||||
{
|
{
|
||||||
@@ -234,10 +240,16 @@ AvConvTranscoder::killChild()
|
|||||||
|
|
||||||
// If an error occured, force kill the child
|
// If an error occured, force kill the child
|
||||||
if (ec)
|
if (ec)
|
||||||
LMS_LOG(MOD_TRANSCODE, SEV_ERROR) << "AvConvTranscoder::killChild: error: " << ec.message();
|
LMS_LOG(MOD_TRANSCODE, SEV_ERROR) << "Transcoder::killChild: error: " << ec.message();
|
||||||
|
|
||||||
_child.reset();
|
_child.reset();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
Transcoder::isComplete(void)
|
||||||
|
{
|
||||||
|
return _isComplete;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace Transcode
|
} // namespace Transcode
|
||||||
@@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2015 Emeric Poupon
|
||||||
|
*
|
||||||
|
* This file is part of LMS.
|
||||||
|
*
|
||||||
|
* LMS is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU General Public License as published by
|
||||||
|
* the Free Software Foundation, either version 3 of the License, or
|
||||||
|
* (at your option) any later version.
|
||||||
|
*
|
||||||
|
* LMS 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
#include <set>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
|
#include <boost/iostreams/stream.hpp>
|
||||||
|
#include <boost/process.hpp>
|
||||||
|
#include <boost/filesystem.hpp>
|
||||||
|
#include <boost/thread.hpp>
|
||||||
|
|
||||||
|
#include <boost/date_time/posix_time/posix_time_types.hpp> //no i/o just types
|
||||||
|
#include <boost/filesystem/path.hpp>
|
||||||
|
|
||||||
|
#include "AvInfo.hpp"
|
||||||
|
|
||||||
|
namespace Av {
|
||||||
|
|
||||||
|
|
||||||
|
enum class Encoding
|
||||||
|
{
|
||||||
|
OGA,
|
||||||
|
OGV,
|
||||||
|
MP3,
|
||||||
|
WEBMA,
|
||||||
|
WEBMV,
|
||||||
|
FLA,
|
||||||
|
FLV,
|
||||||
|
M4A,
|
||||||
|
M4V,
|
||||||
|
};
|
||||||
|
|
||||||
|
std::string encoding_to_mimetype(Encoding encoding);
|
||||||
|
|
||||||
|
class TranscodeParameters
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
// Setters
|
||||||
|
void setEncoding(Encoding encoding) { _encoding = encoding; }
|
||||||
|
void setOffset(boost::posix_time::time_duration offset) {_offset = offset; }
|
||||||
|
void setBitrate(Stream::Type type, std::size_t bitrate) { _outputBitrate[type] = bitrate; }
|
||||||
|
|
||||||
|
// Manually add the streams to be transcoded
|
||||||
|
// If no stream is added, input streams are selected automatically
|
||||||
|
void addStream(int inputStreamId) { _selectedStreams.insert(inputStreamId); }
|
||||||
|
|
||||||
|
// Getters
|
||||||
|
Encoding getEncoding(void) const { return _encoding; }
|
||||||
|
boost::posix_time::time_duration getOffset(void) const { return _offset; }
|
||||||
|
std::set<int> getSelectedStreamIds(void) const { return _selectedStreams; }
|
||||||
|
std::size_t getBitrate(Stream::Type type) { return _outputBitrate[type]; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
Encoding _encoding = Encoding::MP3;
|
||||||
|
boost::posix_time::time_duration _offset = boost::posix_time::seconds(0);
|
||||||
|
std::set<int> _selectedStreams;
|
||||||
|
std::map<Stream::Type, std::size_t> _outputBitrate = { {Stream::Type::Audio, 0}, { Stream::Type::Video, 0}, { Stream::Type::Subtitle, 0} };
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class Transcoder
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
static void init();
|
||||||
|
|
||||||
|
Transcoder(boost::filesystem::path file, TranscodeParameters parameters);
|
||||||
|
~Transcoder();
|
||||||
|
|
||||||
|
bool start();
|
||||||
|
void process(std::vector<unsigned char>& output, std::size_t maxSize);
|
||||||
|
bool isComplete(void);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
boost::filesystem::path _filePath;
|
||||||
|
TranscodeParameters _parameters;
|
||||||
|
|
||||||
|
static boost::mutex _mutex;
|
||||||
|
|
||||||
|
boost::process::pipe _outputPipe;
|
||||||
|
boost::iostreams::file_descriptor_source _source;
|
||||||
|
boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_source> _is;
|
||||||
|
std::istream _in;
|
||||||
|
|
||||||
|
void waitChild();
|
||||||
|
void killChild();
|
||||||
|
|
||||||
|
std::shared_ptr<boost::process::child> _child;
|
||||||
|
|
||||||
|
static boost::filesystem::path _avConvPath;
|
||||||
|
bool _isComplete;
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace Av
|
||||||
|
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "logger/Logger.hpp"
|
|
||||||
|
|
||||||
#include "Codec.hpp"
|
|
||||||
|
|
||||||
Codec::Codec(enum CodecID codec, Type type )
|
|
||||||
: _codec(nullptr)
|
|
||||||
{
|
|
||||||
if (type == Encoder)
|
|
||||||
_codec = avcodec_find_encoder(codec);
|
|
||||||
else if (type == Decoder)
|
|
||||||
_codec = avcodec_find_decoder(codec);
|
|
||||||
|
|
||||||
if (_codec == nullptr) {
|
|
||||||
LMS_LOG(MOD_AV, SEV_ERROR) << "Codec constructor failed! codec = " << codec << ", type = " << type;
|
|
||||||
throw std::runtime_error("can't find codec using this id!");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Codec::Codec(const AVCodec* codec)
|
|
||||||
: _codec(codec)
|
|
||||||
{
|
|
||||||
assert(_codec != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
Codec::~Codec()
|
|
||||||
{
|
|
||||||
if (_codec == nullptr) {
|
|
||||||
// TODO release iif ownership has not been taken?
|
|
||||||
// av_codec_close(_codec);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const AVCodec*
|
|
||||||
Codec::get() const
|
|
||||||
{
|
|
||||||
assert(_codec != nullptr);
|
|
||||||
return _codec;
|
|
||||||
}
|
|
||||||
|
|
||||||
Codec::Id
|
|
||||||
Codec::getId() const
|
|
||||||
{
|
|
||||||
assert(_codec != nullptr);
|
|
||||||
return _codec->id;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
Codec::getName() const
|
|
||||||
{
|
|
||||||
assert(_codec != nullptr);
|
|
||||||
return _codec->name;
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,56 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CODEC_HPP__
|
|
||||||
#define CODEC_HPP__
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
#include <memory>
|
|
||||||
#include <boost/utility.hpp>
|
|
||||||
|
|
||||||
#include "Common.hpp"
|
|
||||||
|
|
||||||
class Codec : boost::noncopyable
|
|
||||||
{
|
|
||||||
friend class CodecContext;
|
|
||||||
friend class FormatContext;
|
|
||||||
friend class OutputFormatContext;
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
typedef enum AVCodecID Id;
|
|
||||||
enum Type {
|
|
||||||
Encoder,
|
|
||||||
Decoder,
|
|
||||||
};
|
|
||||||
|
|
||||||
Codec(Id codecId, Type type);
|
|
||||||
Codec(const AVCodec* codec); // Attach existing codec
|
|
||||||
~Codec();
|
|
||||||
|
|
||||||
Id getId() const;
|
|
||||||
std::string getName() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
const AVCodec* get() const;
|
|
||||||
const AVCodec* _codec;
|
|
||||||
};
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <iostream>
|
|
||||||
#include <iomanip>
|
|
||||||
#include <boost/array.hpp>
|
|
||||||
|
|
||||||
#include "CodecContext.hpp"
|
|
||||||
|
|
||||||
namespace Av
|
|
||||||
{
|
|
||||||
|
|
||||||
CodecContext::CodecContext(AVCodecContext* CodecContext)
|
|
||||||
: _codecContext(CodecContext)
|
|
||||||
{
|
|
||||||
assert(_codecContext != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
void
|
|
||||||
CodecContext::dumpInfo(std::ostream& ost) const
|
|
||||||
{
|
|
||||||
ost << "BitRate = " << getBitRate() << ", SampleFormat = " << getSampleFormat() << ", SampleRate = " << getSampleRate() << ", ChannelLayout = " << getChannelLayout() << ", NbChannels = " << getNbChannels() << ", Timebase = " << getTimeBase().num << "/" << getTimeBase().den;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::string
|
|
||||||
CodecContext::getCodecDesc(void) const
|
|
||||||
{
|
|
||||||
std::array<char, 256> buf;
|
|
||||||
avcodec_string(buf.data(), buf.size(), _codecContext, 0);
|
|
||||||
|
|
||||||
return std::string(buf.data());
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Av
|
|
||||||
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef CODEC_CONTEXT_HPP
|
|
||||||
#define CODEC_CONTEXT_HPP
|
|
||||||
|
|
||||||
#include <boost/utility.hpp>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "Codec.hpp"
|
|
||||||
|
|
||||||
namespace Av
|
|
||||||
{
|
|
||||||
|
|
||||||
class CodecContext
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
CodecContext(AVCodecContext* CodecContext); // Attach existing codec context (no free will be done)
|
|
||||||
|
|
||||||
// Codec getCodec();
|
|
||||||
|
|
||||||
enum AVMediaType getType(void) const { return _codecContext->codec_type; }
|
|
||||||
Codec::Id getCodecId(void) const { return _codecContext->codec_id; }
|
|
||||||
|
|
||||||
std::string getCodecDesc(void) const;
|
|
||||||
|
|
||||||
// Accessors
|
|
||||||
std::size_t getBitRate() const {return _codecContext->bit_rate;}
|
|
||||||
AVSampleFormat getSampleFormat() const {return _codecContext->sample_fmt;}
|
|
||||||
std::size_t getSampleRate() const {return _codecContext->sample_rate;}
|
|
||||||
std::uint64_t getChannelLayout() const {return _codecContext->channel_layout;}
|
|
||||||
std::size_t getNbChannels() const {return _codecContext->channels; }
|
|
||||||
AVRational getTimeBase() const {return _codecContext->time_base; }
|
|
||||||
|
|
||||||
void dumpInfo(std::ostream& ost) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
AVCodecContext* native() { return _codecContext; }
|
|
||||||
|
|
||||||
AVCodecContext* _codecContext;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Av
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <boost/array.hpp>
|
|
||||||
|
|
||||||
#include "logger/Logger.hpp"
|
|
||||||
|
|
||||||
#include "Common.hpp"
|
|
||||||
|
|
||||||
namespace Av
|
|
||||||
{
|
|
||||||
|
|
||||||
std::string
|
|
||||||
AvError::to_str(void) const
|
|
||||||
{
|
|
||||||
boost::array<char, 128> buf = {0};
|
|
||||||
if (av_strerror(_errnum, buf.data(), buf.size()) == 0)
|
|
||||||
return std::string(&buf[0]);
|
|
||||||
else
|
|
||||||
return "Unknown error";
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::ostream& operator<<(std::ostream& ost, const AvError& err)
|
|
||||||
{
|
|
||||||
ost << err.to_str();
|
|
||||||
return ost;
|
|
||||||
}
|
|
||||||
|
|
||||||
void AvInit()
|
|
||||||
{
|
|
||||||
/* register all the codecs */
|
|
||||||
avcodec_register_all();
|
|
||||||
av_register_all();
|
|
||||||
LMS_LOG(MOD_AV, SEV_INFO) << "avcodec version = " << avcodec_version();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Av
|
|
||||||
@@ -1,67 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TRANSCODE_COMMON_HPP__
|
|
||||||
#define TRANSCODE_COMMON_HPP__
|
|
||||||
|
|
||||||
// Hack to properly iinclude libavcodec/avcodec.h...
|
|
||||||
//
|
|
||||||
#define __STDC_CONSTANT_MACROS
|
|
||||||
#ifdef _STDINT_H
|
|
||||||
#undef _STDINT_H
|
|
||||||
#endif
|
|
||||||
# include <stdint.h>
|
|
||||||
extern "C" {
|
|
||||||
#include <libavcodec/avcodec.h>
|
|
||||||
#include <libavformat/avformat.h>
|
|
||||||
#include <libavutil/channel_layout.h>
|
|
||||||
#include <libavutil/mathematics.h>
|
|
||||||
}
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace Av
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
void AvInit();
|
|
||||||
|
|
||||||
class AvError
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
AvError() : _errnum(0) {}
|
|
||||||
AvError(int ernum) : _errnum(ernum) {}
|
|
||||||
|
|
||||||
void operator=(int errnum) { _errnum = errnum; }
|
|
||||||
|
|
||||||
operator bool() { return _errnum < 0; }
|
|
||||||
|
|
||||||
std::string to_str() const;
|
|
||||||
|
|
||||||
friend std::ostream& operator<<(std::ostream& ost, const AvError&);
|
|
||||||
|
|
||||||
bool eof() { return _errnum == AVERROR_EOF; } // TODO
|
|
||||||
|
|
||||||
private:
|
|
||||||
int _errnum;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Av
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "Dictionary.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Av
|
|
||||||
{
|
|
||||||
|
|
||||||
Dictionary::Dictionary(AVDictionary* dictionary)
|
|
||||||
: _dictionary(dictionary)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
Dictionary::get(std::map<std::string, std::string>& entries)
|
|
||||||
{
|
|
||||||
AVDictionaryEntry *tag = NULL;
|
|
||||||
while ((tag = av_dict_get(_dictionary, "", tag, AV_DICT_IGNORE_SUFFIX))) {
|
|
||||||
entries.insert( std::make_pair(tag->key, tag->value));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string
|
|
||||||
Dictionary::get(std::string key)
|
|
||||||
{
|
|
||||||
AVDictionaryEntry *tag = NULL;
|
|
||||||
tag = av_dict_get(_dictionary, key.c_str(), tag, 0);
|
|
||||||
|
|
||||||
return tag != NULL ? std::string(tag->value) : std::string();
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Av
|
|
||||||
|
|
||||||
@@ -1,47 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AV_DICTIONARY_HPP
|
|
||||||
#define AV_DICTIONARY_HPP
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include "Common.hpp"
|
|
||||||
|
|
||||||
namespace Av
|
|
||||||
{
|
|
||||||
|
|
||||||
class Dictionary
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
Dictionary(AVDictionary* dictionary);
|
|
||||||
|
|
||||||
// Get all
|
|
||||||
void get(std::map<std::string, std::string>& entries);
|
|
||||||
|
|
||||||
// get a single entry
|
|
||||||
std::string get(std::string key);
|
|
||||||
|
|
||||||
private:
|
|
||||||
AVDictionary* _dictionary;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Av
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,35 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "FormatContext.hpp"
|
|
||||||
|
|
||||||
namespace Av
|
|
||||||
{
|
|
||||||
|
|
||||||
FormatContext::FormatContext()
|
|
||||||
: _context(nullptr)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
FormatContext::~FormatContext()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Av
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef FORMAT_CONTEXT_HPP
|
|
||||||
#define FORMAT_CONTEXT_HPP
|
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
|
|
||||||
#include "Common.hpp"
|
|
||||||
|
|
||||||
namespace Av
|
|
||||||
{
|
|
||||||
|
|
||||||
class FormatContext
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
FormatContext();
|
|
||||||
~FormatContext();
|
|
||||||
|
|
||||||
|
|
||||||
protected:
|
|
||||||
void native(AVFormatContext* c) { _context = c;}
|
|
||||||
AVFormatContext* native() { return _context; }
|
|
||||||
const AVFormatContext* native() const { return _context; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
AVFormatContext* _context;
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Av
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,176 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <iostream>
|
|
||||||
|
|
||||||
#include "logger/Logger.hpp"
|
|
||||||
|
|
||||||
#include "InputFormatContext.hpp"
|
|
||||||
|
|
||||||
namespace Av
|
|
||||||
{
|
|
||||||
|
|
||||||
InputFormatContext::InputFormatContext(const boost::filesystem::path& p)
|
|
||||||
: _path(p)
|
|
||||||
{
|
|
||||||
AVFormatContext* context = nullptr;
|
|
||||||
|
|
||||||
// The last three parameters specify the file format, buffer size and
|
|
||||||
// format parameters. By simply specifying NULL or 0 we ask libavformat
|
|
||||||
// to auto-detect the format and use a default buffer size.
|
|
||||||
AvError error = avformat_open_input(&context, p.string().c_str(), nullptr, nullptr);
|
|
||||||
if (error)
|
|
||||||
{
|
|
||||||
LMS_LOG(MOD_AV, SEV_ERROR) << "Cannot open '" << p.string() << "', avformat_open_input returned " << error;
|
|
||||||
throw std::runtime_error("avformat_open_input failed: " + error.to_str());
|
|
||||||
}
|
|
||||||
|
|
||||||
native(context);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
InputFormatContext::~InputFormatContext()
|
|
||||||
{
|
|
||||||
AVFormatContext* context = native();
|
|
||||||
avformat_close_input(&context);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Stream>
|
|
||||||
InputFormatContext::getStreams(void)
|
|
||||||
{
|
|
||||||
std::vector<Stream> res;
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < native()->nb_streams; ++i) {
|
|
||||||
res.push_back( Stream(native()->streams[i]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
bool
|
|
||||||
InputFormatContext::getBestStreamIdx(AVMediaType type, Stream::Idx& index)
|
|
||||||
{
|
|
||||||
int res = av_find_best_stream(native(),
|
|
||||||
type,
|
|
||||||
-1, // Auto
|
|
||||||
-1, // Auto
|
|
||||||
NULL,
|
|
||||||
0
|
|
||||||
);
|
|
||||||
|
|
||||||
AvError error(res);
|
|
||||||
if (error) {
|
|
||||||
LMS_LOG(MOD_AV, SEV_DEBUG) << "Cannot get best stream for type " << type << ": " << error;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
index = res;
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
InputFormatContext::findStreamInfo(void)
|
|
||||||
{
|
|
||||||
AvError err = avformat_find_stream_info(native(), NULL);
|
|
||||||
if (err)
|
|
||||||
{
|
|
||||||
LMS_LOG(MOD_AV, SEV_ERROR) << "Couldn't find stream information: " << err;
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
std::size_t
|
|
||||||
InputFormatContext::getDurationSecs() const
|
|
||||||
{
|
|
||||||
if (static_cast<int>(native()->duration) != AV_NOPTS_VALUE )
|
|
||||||
return native()->duration / AV_TIME_BASE;
|
|
||||||
else
|
|
||||||
return 0; // TODO, do something better?
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary
|
|
||||||
InputFormatContext::getMetadata(void)
|
|
||||||
{
|
|
||||||
return Dictionary(native()->metadata);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t
|
|
||||||
InputFormatContext::getNbPictures(void) const
|
|
||||||
{
|
|
||||||
std::size_t res = 0;
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < native()->nb_streams; ++i)
|
|
||||||
{
|
|
||||||
if (native()->streams[i]->disposition & AV_DISPOSITION_ATTACHED_PIC)
|
|
||||||
++res;
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Picture>
|
|
||||||
InputFormatContext::getPictures(std::size_t nbMaxPictures) const
|
|
||||||
{
|
|
||||||
static const std::map<int, std::string> codecMimeMap =
|
|
||||||
{
|
|
||||||
{ AV_CODEC_ID_BMP, "image/x-bmp" },
|
|
||||||
{ AV_CODEC_ID_GIF, "image/gif" },
|
|
||||||
{ AV_CODEC_ID_MJPEG, "image/jpeg" },
|
|
||||||
{ AV_CODEC_ID_PNG, "image/png" },
|
|
||||||
{ AV_CODEC_ID_PNG, "image/x-png" },
|
|
||||||
{ AV_CODEC_ID_PPM, "image/x-portable-pixmap" },
|
|
||||||
};
|
|
||||||
|
|
||||||
std::vector<Picture> pictures;
|
|
||||||
|
|
||||||
for (std::size_t i = 0; i < native()->nb_streams; ++i)
|
|
||||||
{
|
|
||||||
Stream stream(native()->streams[i]);
|
|
||||||
|
|
||||||
if (stream.hasAttachedPic())
|
|
||||||
{
|
|
||||||
Picture picture;
|
|
||||||
|
|
||||||
auto itMime = codecMimeMap.find(stream.getCodecContext().getCodecId());
|
|
||||||
if (itMime != codecMimeMap.end())
|
|
||||||
picture.mimeType = itMime->second;
|
|
||||||
else
|
|
||||||
picture.mimeType = "application/octet-stream";
|
|
||||||
|
|
||||||
AVPacket pkt = native()->streams[i]->attached_pic;
|
|
||||||
|
|
||||||
std::copy(pkt.data, pkt.data + pkt.size, std::back_inserter(picture.data));
|
|
||||||
|
|
||||||
pictures.push_back( picture );
|
|
||||||
|
|
||||||
if (pictures.size() >= nbMaxPictures)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return pictures;
|
|
||||||
}
|
|
||||||
|
|
||||||
} //namespace Av
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef INPUT_FORMAT_CONTEXT_HPP
|
|
||||||
#define INPUT_FORMAT_CONTEXT_HPP
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
|
|
||||||
#include "FormatContext.hpp"
|
|
||||||
#include "Stream.hpp"
|
|
||||||
#include "Dictionary.hpp"
|
|
||||||
|
|
||||||
namespace Av
|
|
||||||
{
|
|
||||||
|
|
||||||
struct Picture {
|
|
||||||
std::string mimeType;
|
|
||||||
std::vector<unsigned char> data;
|
|
||||||
};
|
|
||||||
|
|
||||||
class InputFormatContext : public FormatContext
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
InputFormatContext(const boost::filesystem::path& p);
|
|
||||||
~InputFormatContext();
|
|
||||||
|
|
||||||
|
|
||||||
Dictionary getMetadata(void); // metadata access
|
|
||||||
|
|
||||||
// Scan file
|
|
||||||
bool findStreamInfo();
|
|
||||||
|
|
||||||
|
|
||||||
// Get attached pictures
|
|
||||||
std::size_t getNbPictures(void) const;
|
|
||||||
std::vector<Picture> getPictures(std::size_t nbMaxPictures) const;
|
|
||||||
|
|
||||||
// Get the streams
|
|
||||||
std::vector<Stream> getStreams(void);
|
|
||||||
|
|
||||||
bool getBestStreamIdx(enum AVMediaType type, Stream::Idx& idx);
|
|
||||||
std::size_t getDurationSecs() const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
boost::filesystem::path _path;
|
|
||||||
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace av
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,51 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <cassert>
|
|
||||||
#include "Stream.hpp"
|
|
||||||
|
|
||||||
namespace Av
|
|
||||||
{
|
|
||||||
|
|
||||||
Stream::Stream(AVStream* stream)
|
|
||||||
: _stream(stream)
|
|
||||||
{
|
|
||||||
assert(_stream != nullptr);
|
|
||||||
assert(_stream->codec != nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
CodecContext
|
|
||||||
Stream::getCodecContext()
|
|
||||||
{
|
|
||||||
return _stream->codec;
|
|
||||||
}
|
|
||||||
|
|
||||||
Dictionary
|
|
||||||
Stream::getMetadata(void)
|
|
||||||
{
|
|
||||||
return Dictionary(_stream->metadata);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
Stream::hasAttachedPic(void) const
|
|
||||||
{
|
|
||||||
return (_stream->disposition & AV_DISPOSITION_ATTACHED_PIC);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Av
|
|
||||||
@@ -1,55 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef STREAM_HPP__
|
|
||||||
#define STREAM_HPP__
|
|
||||||
|
|
||||||
#include "Common.hpp"
|
|
||||||
|
|
||||||
#include "CodecContext.hpp"
|
|
||||||
#include "Dictionary.hpp"
|
|
||||||
|
|
||||||
namespace Av
|
|
||||||
{
|
|
||||||
|
|
||||||
class Stream
|
|
||||||
{
|
|
||||||
friend class InputFormatContext;
|
|
||||||
|
|
||||||
public:
|
|
||||||
// Attach existing stream
|
|
||||||
Stream(AVStream* stream);
|
|
||||||
|
|
||||||
typedef size_t Idx;
|
|
||||||
|
|
||||||
// Idx getIdx() const { return _stream->index; }
|
|
||||||
|
|
||||||
bool hasAttachedPic(void) const;
|
|
||||||
Dictionary getMetadata(void);
|
|
||||||
CodecContext getCodecContext(void);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
AVStream* _stream;
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Av
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
+204
@@ -0,0 +1,204 @@
|
|||||||
|
!_TAG_FILE_FORMAT 2 /extended format; --format=1 will not append ;" to lines/
|
||||||
|
!_TAG_FILE_SORTED 2 /0=unsorted, 1=sorted, 2=foldcase/
|
||||||
|
!_TAG_PROGRAM_AUTHOR Darren Hiebert /dhiebert@users.sourceforge.net/
|
||||||
|
!_TAG_PROGRAM_NAME Exuberant Ctags //
|
||||||
|
!_TAG_PROGRAM_URL http://ctags.sourceforge.net /official site/
|
||||||
|
!_TAG_PROGRAM_VERSION 5.9~svn20110310 //
|
||||||
|
addStream /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ void addStream(int inputStreamId);$/;" p language:C++ class:Av::TranscodeParameters
|
||||||
|
Audio /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ Audio,$/;" m language:C++ class:Av::Stream::Type
|
||||||
|
Av /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^namespace Av {$/;" n language:C++ file:
|
||||||
|
Av /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^namespace Av$/;" n language:C++
|
||||||
|
Av /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^namespace Av {$/;" n language:C++ file:
|
||||||
|
Av /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^namespace Av {$/;" n language:C++
|
||||||
|
Av::averror_to_string /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^static std::string averror_to_string(int error)$/;" f language:C++ namespace:Av
|
||||||
|
Av::AvInit /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^void AvInit()$/;" f language:C++ namespace:Av
|
||||||
|
Av::AvInit /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^void AvInit();$/;" p language:C++ namespace:Av
|
||||||
|
Av::Encoding /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^enum class Encoding$/;" c language:C++ namespace:Av
|
||||||
|
Av::Encoding::FLA /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ FLA,$/;" m language:C++ class:Av::Encoding
|
||||||
|
Av::Encoding::FLV /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ FLV,$/;" m language:C++ class:Av::Encoding
|
||||||
|
Av::Encoding::M4A /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ M4A,$/;" m language:C++ class:Av::Encoding
|
||||||
|
Av::Encoding::M4V /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ M4V,$/;" m language:C++ class:Av::Encoding
|
||||||
|
Av::Encoding::MP3 /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ MP3,$/;" m language:C++ class:Av::Encoding
|
||||||
|
Av::Encoding::OGA /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ OGA,$/;" m language:C++ class:Av::Encoding
|
||||||
|
Av::Encoding::OGV /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ OGV,$/;" m language:C++ class:Av::Encoding
|
||||||
|
Av::Encoding::WEBMA /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ WEBMA,$/;" m language:C++ class:Av::Encoding
|
||||||
|
Av::Encoding::WEBMV /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ WEBMV,$/;" m language:C++ class:Av::Encoding
|
||||||
|
Av::encoding_to_mimetype /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^std::string encoding_to_mimetype(Encoding encoding)$/;" f language:C++ namespace:Av
|
||||||
|
Av::encoding_to_mimetype /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^std::string encoding_to_mimetype(Encoding encoding);$/;" p language:C++ namespace:Av
|
||||||
|
Av::execNames /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^const std::vector<std::string> execNames =$/;" m language:C++ namespace:Av file:
|
||||||
|
Av::getMetaDataFromDictionnary /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^getMetaDataFromDictionnary(AVDictionary* dictionnary, std::map<std::string, std::string>& res)$/;" f language:C++ namespace:Av
|
||||||
|
Av::MediaFile /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^class MediaFile$/;" c language:C++ namespace:Av
|
||||||
|
Av::MediaFile::getAttachedPictures /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::getAttachedPictures(std::size_t nbMaxPictures) const$/;" f language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::getAttachedPictures /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ std::vector<Picture> getAttachedPictures(std::size_t nbMaxPictures) const;$/;" p language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::getBestStreamId /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::getBestStreamId(Stream::Type type) const$/;" f language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::getBestStreamId /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ int getBestStreamId(Stream::Type type) const; \/\/ -1 if failure\/unknown$/;" p language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::getDuration /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::getDuration() const$/;" f language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::getDuration /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ boost::posix_time::time_duration getDuration() const;$/;" p language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::getMetaData /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::getMetaData(void)$/;" f language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::getMetaData /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ std::map<std::string, std::string> getMetaData(void);$/;" p language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::getPath /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ boost::filesystem::path getPath() const {return _p;};$/;" f language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::getStreams /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::getStreams(Stream::Type type) const$/;" f language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::getStreams /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ std::vector<Stream> getStreams(Stream::Type type) const;$/;" p language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::hasAttachedPictures /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::hasAttachedPictures(void) const$/;" f language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::hasAttachedPictures /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ bool hasAttachedPictures(void) const;$/;" p language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::MediaFile /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::MediaFile(const boost::filesystem::path& p)$/;" f language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::MediaFile /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ MediaFile(const boost::filesystem::path& p);$/;" p language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::open /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::open(void)$/;" f language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::open /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ bool open(void);$/;" p language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::scan /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::scan(void)$/;" f language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::scan /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ bool scan(void);$/;" p language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::_context /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ AVFormatContext* _context;$/;" m language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::_p /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ boost::filesystem::path _p;$/;" m language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::~MediaFile /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::~MediaFile()$/;" f language:C++ class:Av::MediaFile
|
||||||
|
Av::MediaFile::~MediaFile /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ ~MediaFile();$/;" p language:C++ class:Av::MediaFile
|
||||||
|
Av::Picture /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^struct Picture$/;" s language:C++ namespace:Av
|
||||||
|
Av::Picture::data /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ std::vector<uint8_t> data;$/;" m language:C++ struct:Av::Picture
|
||||||
|
Av::Picture::mimeType /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ std::string mimeType;$/;" m language:C++ struct:Av::Picture
|
||||||
|
Av::Stream /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^struct Stream$/;" s language:C++ namespace:Av
|
||||||
|
Av::Stream::bitrate /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ std::size_t bitrate;$/;" m language:C++ struct:Av::Stream
|
||||||
|
Av::Stream::desc /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ std::string desc; \/\/ Description of the stream$/;" m language:C++ struct:Av::Stream
|
||||||
|
Av::Stream::id /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ int id;$/;" m language:C++ struct:Av::Stream
|
||||||
|
Av::Stream::Type /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ enum class Type$/;" c language:C++ struct:Av::Stream
|
||||||
|
Av::Stream::type /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ Type type;$/;" m language:C++ struct:Av::Stream
|
||||||
|
Av::Stream::Type::Audio /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ Audio,$/;" m language:C++ class:Av::Stream::Type
|
||||||
|
Av::Stream::Type::Subtitle /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ Subtitle,$/;" m language:C++ class:Av::Stream::Type
|
||||||
|
Av::Stream::Type::Video /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ Video,$/;" m language:C++ class:Av::Stream::Type
|
||||||
|
Av::streamType_to_string /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^static std::string streamType_to_string(Stream::Type type)$/;" f language:C++ namespace:Av
|
||||||
|
Av::TranscodeParameters /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^class TranscodeParameters$/;" c language:C++ namespace:Av
|
||||||
|
Av::TranscodeParameters::addStream /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ void addStream(int inputStreamId);$/;" p language:C++ class:Av::TranscodeParameters
|
||||||
|
Av::TranscodeParameters::getBitrate /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ std::size_t getBitrate(Stream::Type type) { return _outputBitrate[type]; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
Av::TranscodeParameters::getEncoding /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ Encoding getEncoding(void) const { return _encoding; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
Av::TranscodeParameters::getFile /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ boost::filesystem::path getFile(void) const { return _path; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
Av::TranscodeParameters::getOffset /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ boost::posix_time::time_duration getOffset(void) const { return _offset; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
Av::TranscodeParameters::getSelectedStreamIds /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ std::vector<int> getSelectedStreamIds(void) const { return _selectedStreams; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
Av::TranscodeParameters::setBitrate /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ void setBitrate(Stream::Type type, std::size_t bitrate) { _outputBitrate[type] = bitrate; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
Av::TranscodeParameters::setEncoding /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ void setEncoding(Encoding encoding) { _encoding = encoding; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
Av::TranscodeParameters::setFile /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ void setFile(boost::filesystem::path p) {_path = p; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
Av::TranscodeParameters::setOffset /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ void setOffset(boost::posix_time::time_duration offset) {_offset = offset; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
Av::TranscodeParameters::_encoding /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ Encoding _encoding = Encoding::MP3;$/;" m language:C++ class:Av::TranscodeParameters
|
||||||
|
Av::TranscodeParameters::_offset /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ boost::posix_time::time_duration _offset = boost::posix_time::seconds(0);$/;" m language:C++ class:Av::TranscodeParameters
|
||||||
|
Av::TranscodeParameters::_outputBitrate /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ std::map<Stream::Type, std::size_t> _outputBitrate = { {Stream::Type::Audio, 0}, { Stream::Type::Video, 0}, { Stream::Type::Subtitle, 0} };$/;" m language:C++ class:Av::TranscodeParameters
|
||||||
|
Av::TranscodeParameters::_path /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ boost::filesystem::path _path;$/;" m language:C++ class:Av::TranscodeParameters
|
||||||
|
Av::TranscodeParameters::_selectedStreams /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ std::vector<int> _selectedStreams;$/;" m language:C++ class:Av::TranscodeParameters
|
||||||
|
Av::Transcoder /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^class Transcoder$/;" c language:C++ namespace:Av
|
||||||
|
Av::Transcoder::init /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^Transcoder::init()$/;" f language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::init /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ static void init();$/;" p language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::isComplete /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ bool isComplete(void);$/;" p language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::killChild /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^Transcoder::killChild()$/;" f language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::killChild /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ void killChild();$/;" p language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::process /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^Transcoder::process(std::vector<unsigned char>& output, std::size_t maxSize)$/;" f language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::process /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ void process(std::vector<unsigned char>& output, std::size_t maxSize);$/;" p language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::start /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^Transcoder::start()$/;" f language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::start /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ bool start();$/;" p language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::Transcoder /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^Transcoder::Transcoder(TrasncodeParameters parameters)$/;" f language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::Transcoder /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ Transcoder(TranscodeParameters parameters);$/;" p language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::waitChild /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^Transcoder::waitChild()$/;" f language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::waitChild /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ void waitChild();$/;" p language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::_avConvPath /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^boost::filesystem::path Transcoder::_avConvPath = boost::filesystem::path();$/;" m language:C++ class:Av::Transcoder file:
|
||||||
|
Av::Transcoder::_avConvPath /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ static boost::filesystem::path _avConvPath;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::_child /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ std::shared_ptr<boost::process::child> _child;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::_in /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ std::istream _in;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::_is /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_source> _is;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::_isComplete /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ bool _isComplete;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::_mutex /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^boost::mutex Transcoder::_mutex;$/;" m language:C++ class:Av::Transcoder file:
|
||||||
|
Av::Transcoder::_mutex /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ static boost::mutex _mutex;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::_outputPipe /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ boost::process::pipe _outputPipe;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::_parameters /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ TranscodeParameters _parameters;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::_source /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ boost::iostreams::file_descriptor_source _source;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
Av::Transcoder::~Transcoder /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^Transcoder::~Transcoder()$/;" f language:C++ class:Av::Transcoder
|
||||||
|
averror_to_string /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^static std::string averror_to_string(int error)$/;" f language:C++ namespace:Av
|
||||||
|
AvInit /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^void AvInit()$/;" f language:C++ namespace:Av
|
||||||
|
AvInit /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^void AvInit();$/;" p language:C++ namespace:Av
|
||||||
|
AV_INFO_HPP /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp 23;" d language:C++
|
||||||
|
bitrate /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ std::size_t bitrate;$/;" m language:C++ struct:Av::Stream
|
||||||
|
data /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ std::vector<uint8_t> data;$/;" m language:C++ struct:Av::Picture
|
||||||
|
desc /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ std::string desc; \/\/ Description of the stream$/;" m language:C++ struct:Av::Stream
|
||||||
|
Encoding /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^enum class Encoding$/;" c language:C++ namespace:Av
|
||||||
|
encoding_to_mimetype /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^std::string encoding_to_mimetype(Encoding encoding)$/;" f language:C++ namespace:Av
|
||||||
|
encoding_to_mimetype /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^std::string encoding_to_mimetype(Encoding encoding);$/;" p language:C++ namespace:Av
|
||||||
|
execNames /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^const std::vector<std::string> execNames =$/;" m language:C++ namespace:Av file:
|
||||||
|
FLA /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ FLA,$/;" m language:C++ class:Av::Encoding
|
||||||
|
FLV /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ FLV,$/;" m language:C++ class:Av::Encoding
|
||||||
|
getAttachedPictures /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::getAttachedPictures(std::size_t nbMaxPictures) const$/;" f language:C++ class:Av::MediaFile
|
||||||
|
getAttachedPictures /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ std::vector<Picture> getAttachedPictures(std::size_t nbMaxPictures) const;$/;" p language:C++ class:Av::MediaFile
|
||||||
|
getBestStreamId /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::getBestStreamId(Stream::Type type) const$/;" f language:C++ class:Av::MediaFile
|
||||||
|
getBestStreamId /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ int getBestStreamId(Stream::Type type) const; \/\/ -1 if failure\/unknown$/;" p language:C++ class:Av::MediaFile
|
||||||
|
getBitrate /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ std::size_t getBitrate(Stream::Type type) { return _outputBitrate[type]; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
getDuration /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::getDuration() const$/;" f language:C++ class:Av::MediaFile
|
||||||
|
getDuration /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ boost::posix_time::time_duration getDuration() const;$/;" p language:C++ class:Av::MediaFile
|
||||||
|
getEncoding /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ Encoding getEncoding(void) const { return _encoding; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
getFile /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ boost::filesystem::path getFile(void) const { return _path; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
getMetaData /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::getMetaData(void)$/;" f language:C++ class:Av::MediaFile
|
||||||
|
getMetaData /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ std::map<std::string, std::string> getMetaData(void);$/;" p language:C++ class:Av::MediaFile
|
||||||
|
getMetaDataFromDictionnary /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^getMetaDataFromDictionnary(AVDictionary* dictionnary, std::map<std::string, std::string>& res)$/;" f language:C++ namespace:Av
|
||||||
|
getOffset /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ boost::posix_time::time_duration getOffset(void) const { return _offset; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
getPath /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ boost::filesystem::path getPath() const {return _p;};$/;" f language:C++ class:Av::MediaFile
|
||||||
|
getSelectedStreamIds /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ std::vector<int> getSelectedStreamIds(void) const { return _selectedStreams; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
getStreams /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::getStreams(Stream::Type type) const$/;" f language:C++ class:Av::MediaFile
|
||||||
|
getStreams /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ std::vector<Stream> getStreams(Stream::Type type) const;$/;" p language:C++ class:Av::MediaFile
|
||||||
|
hasAttachedPictures /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::hasAttachedPictures(void) const$/;" f language:C++ class:Av::MediaFile
|
||||||
|
hasAttachedPictures /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ bool hasAttachedPictures(void) const;$/;" p language:C++ class:Av::MediaFile
|
||||||
|
id /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ int id;$/;" m language:C++ struct:Av::Stream
|
||||||
|
init /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^Transcoder::init()$/;" f language:C++ class:Av::Transcoder
|
||||||
|
init /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ static void init();$/;" p language:C++ class:Av::Transcoder
|
||||||
|
isComplete /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ bool isComplete(void);$/;" p language:C++ class:Av::Transcoder
|
||||||
|
killChild /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^Transcoder::killChild()$/;" f language:C++ class:Av::Transcoder
|
||||||
|
killChild /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ void killChild();$/;" p language:C++ class:Av::Transcoder
|
||||||
|
M4A /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ M4A,$/;" m language:C++ class:Av::Encoding
|
||||||
|
M4V /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ M4V,$/;" m language:C++ class:Av::Encoding
|
||||||
|
MediaFile /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::MediaFile(const boost::filesystem::path& p)$/;" f language:C++ class:Av::MediaFile
|
||||||
|
MediaFile /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ MediaFile(const boost::filesystem::path& p);$/;" p language:C++ class:Av::MediaFile
|
||||||
|
MediaFile /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^class MediaFile$/;" c language:C++ namespace:Av
|
||||||
|
mimeType /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ std::string mimeType;$/;" m language:C++ struct:Av::Picture
|
||||||
|
MP3 /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ MP3,$/;" m language:C++ class:Av::Encoding
|
||||||
|
OGA /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ OGA,$/;" m language:C++ class:Av::Encoding
|
||||||
|
OGV /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ OGV,$/;" m language:C++ class:Av::Encoding
|
||||||
|
open /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::open(void)$/;" f language:C++ class:Av::MediaFile
|
||||||
|
open /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ bool open(void);$/;" p language:C++ class:Av::MediaFile
|
||||||
|
Picture /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^struct Picture$/;" s language:C++ namespace:Av
|
||||||
|
process /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^Transcoder::process(std::vector<unsigned char>& output, std::size_t maxSize)$/;" f language:C++ class:Av::Transcoder
|
||||||
|
process /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ void process(std::vector<unsigned char>& output, std::size_t maxSize);$/;" p language:C++ class:Av::Transcoder
|
||||||
|
scan /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::scan(void)$/;" f language:C++ class:Av::MediaFile
|
||||||
|
scan /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ bool scan(void);$/;" p language:C++ class:Av::MediaFile
|
||||||
|
setBitrate /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ void setBitrate(Stream::Type type, std::size_t bitrate) { _outputBitrate[type] = bitrate; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
setEncoding /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ void setEncoding(Encoding encoding) { _encoding = encoding; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
setFile /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ void setFile(boost::filesystem::path p) {_path = p; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
setOffset /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ void setOffset(boost::posix_time::time_duration offset) {_offset = offset; }$/;" f language:C++ class:Av::TranscodeParameters
|
||||||
|
start /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^Transcoder::start()$/;" f language:C++ class:Av::Transcoder
|
||||||
|
start /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ bool start();$/;" p language:C++ class:Av::Transcoder
|
||||||
|
Stream /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^struct Stream$/;" s language:C++ namespace:Av
|
||||||
|
streamType_to_string /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^static std::string streamType_to_string(Stream::Type type)$/;" f language:C++ namespace:Av
|
||||||
|
Subtitle /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ Subtitle,$/;" m language:C++ class:Av::Stream::Type
|
||||||
|
TranscodeParameters /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^class TranscodeParameters$/;" c language:C++ namespace:Av
|
||||||
|
Transcoder /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^Transcoder::Transcoder(TrasncodeParameters parameters)$/;" f language:C++ class:Av::Transcoder
|
||||||
|
Transcoder /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ Transcoder(TranscodeParameters parameters);$/;" p language:C++ class:Av::Transcoder
|
||||||
|
Transcoder /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^class Transcoder$/;" c language:C++ namespace:Av
|
||||||
|
Type /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ enum class Type$/;" c language:C++ struct:Av::Stream
|
||||||
|
type /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ Type type;$/;" m language:C++ struct:Av::Stream
|
||||||
|
Video /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ Video,$/;" m language:C++ class:Av::Stream::Type
|
||||||
|
waitChild /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^Transcoder::waitChild()$/;" f language:C++ class:Av::Transcoder
|
||||||
|
waitChild /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ void waitChild();$/;" p language:C++ class:Av::Transcoder
|
||||||
|
WEBMA /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ WEBMA,$/;" m language:C++ class:Av::Encoding
|
||||||
|
WEBMV /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ WEBMV,$/;" m language:C++ class:Av::Encoding
|
||||||
|
_avConvPath /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^boost::filesystem::path Transcoder::_avConvPath = boost::filesystem::path();$/;" m language:C++ class:Av::Transcoder file:
|
||||||
|
_avConvPath /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ static boost::filesystem::path _avConvPath;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
_child /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ std::shared_ptr<boost::process::child> _child;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
_context /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ AVFormatContext* _context;$/;" m language:C++ class:Av::MediaFile
|
||||||
|
_encoding /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ Encoding _encoding = Encoding::MP3;$/;" m language:C++ class:Av::TranscodeParameters
|
||||||
|
_in /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ std::istream _in;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
_is /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_source> _is;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
_isComplete /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ bool _isComplete;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
_mutex /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^boost::mutex Transcoder::_mutex;$/;" m language:C++ class:Av::Transcoder file:
|
||||||
|
_mutex /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ static boost::mutex _mutex;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
_offset /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ boost::posix_time::time_duration _offset = boost::posix_time::seconds(0);$/;" m language:C++ class:Av::TranscodeParameters
|
||||||
|
_outputBitrate /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ std::map<Stream::Type, std::size_t> _outputBitrate = { {Stream::Type::Audio, 0}, { Stream::Type::Video, 0}, { Stream::Type::Subtitle, 0} };$/;" m language:C++ class:Av::TranscodeParameters
|
||||||
|
_outputPipe /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ boost::process::pipe _outputPipe;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
_p /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ boost::filesystem::path _p;$/;" m language:C++ class:Av::MediaFile
|
||||||
|
_parameters /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ TranscodeParameters _parameters;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
_path /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ boost::filesystem::path _path;$/;" m language:C++ class:Av::TranscodeParameters
|
||||||
|
_selectedStreams /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ std::vector<int> _selectedStreams;$/;" m language:C++ class:Av::TranscodeParameters
|
||||||
|
_source /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.hpp /^ boost::iostreams::file_descriptor_source _source;$/;" m language:C++ class:Av::Transcoder
|
||||||
|
__STDC_CONSTANT_MACROS /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp 27;" d language:C++
|
||||||
|
~MediaFile /home/emericp/Documents/Progs/lms/src/av/AvInfo.cpp /^MediaFile::~MediaFile()$/;" f language:C++ class:Av::MediaFile
|
||||||
|
~MediaFile /home/emericp/Documents/Progs/lms/src/av/AvInfo.hpp /^ ~MediaFile();$/;" p language:C++ class:Av::MediaFile
|
||||||
|
~Transcoder /home/emericp/Documents/Progs/lms/src/av/AvTranscoder.cpp /^Transcoder::~Transcoder()$/;" f language:C++ class:Av::Transcoder
|
||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#include "logger/Logger.hpp"
|
#include "logger/Logger.hpp"
|
||||||
#include "config/ConfigReader.hpp"
|
#include "config/ConfigReader.hpp"
|
||||||
#include "av/InputFormatContext.hpp"
|
#include "av/AvInfo.hpp"
|
||||||
|
|
||||||
#include "CoverArtGrabber.hpp"
|
#include "CoverArtGrabber.hpp"
|
||||||
|
|
||||||
@@ -55,23 +55,13 @@ Grabber::instance()
|
|||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CoverArt>
|
static std::vector<CoverArt>
|
||||||
Grabber::getFromInputFormatContext(const Av::InputFormatContext& input, std::size_t nbMaxCovers) const
|
getFromAvMediaFile(const Av::MediaFile& input, std::size_t nbMaxCovers)
|
||||||
{
|
{
|
||||||
std::vector<CoverArt> res;
|
std::vector<CoverArt> res;
|
||||||
|
|
||||||
try
|
for (Av::Picture& picture : input.getAttachedPictures(nbMaxCovers))
|
||||||
{
|
res.push_back( CoverArt(picture.mimeType, picture.data) );
|
||||||
std::vector<Av::Picture> pictures = input.getPictures(nbMaxCovers);
|
|
||||||
|
|
||||||
for (Av::Picture& picture : pictures)
|
|
||||||
res.push_back( CoverArt(picture.mimeType, picture.data) );
|
|
||||||
|
|
||||||
}
|
|
||||||
catch(std::exception& e)
|
|
||||||
{
|
|
||||||
LMS_LOG(MOD_COVER, SEV_ERROR) << "Cannot get pictures: " << e.what();
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
return res;
|
||||||
}
|
}
|
||||||
@@ -137,21 +127,12 @@ Grabber::getCoverPaths(const boost::filesystem::path& directoryPath, std::size_t
|
|||||||
std::vector<CoverArt>
|
std::vector<CoverArt>
|
||||||
Grabber::getFromTrack(const boost::filesystem::path& p, std::size_t nbMaxCovers) const
|
Grabber::getFromTrack(const boost::filesystem::path& p, std::size_t nbMaxCovers) const
|
||||||
{
|
{
|
||||||
std::vector<CoverArt> res;
|
Av::MediaFile input(p);
|
||||||
|
|
||||||
try
|
if (input.open())
|
||||||
{
|
return getFromAvMediaFile(input, nbMaxCovers);
|
||||||
Av::InputFormatContext input(p);
|
else
|
||||||
|
return std::vector<CoverArt>();
|
||||||
res = getFromInputFormatContext(input, nbMaxCovers);
|
|
||||||
|
|
||||||
}
|
|
||||||
catch(std::exception& e)
|
|
||||||
{
|
|
||||||
LMS_LOG(MOD_COVER, SEV_ERROR) << "Cannot get covers from file " << p << ": " << e.what();
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<CoverArt>
|
std::vector<CoverArt>
|
||||||
|
|||||||
@@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "av/InputFormatContext.hpp"
|
|
||||||
#include "database/Types.hpp"
|
#include "database/Types.hpp"
|
||||||
|
|
||||||
#include "CoverArt.hpp"
|
#include "CoverArt.hpp"
|
||||||
@@ -40,7 +39,6 @@ class Grabber
|
|||||||
|
|
||||||
std::vector<boost::filesystem::path> getCoverPaths(const boost::filesystem::path& directoryPath, std::size_t nbMaxCovers = 1) const;
|
std::vector<boost::filesystem::path> getCoverPaths(const boost::filesystem::path& directoryPath, std::size_t nbMaxCovers = 1) const;
|
||||||
std::vector<CoverArt> getFromDirectory(const boost::filesystem::path& path, std::size_t nbMaxCovers = 1) const;
|
std::vector<CoverArt> getFromDirectory(const boost::filesystem::path& path, std::size_t nbMaxCovers = 1) const;
|
||||||
std::vector<CoverArt> getFromInputFormatContext(const Av::InputFormatContext& input, std::size_t nbMaxCovers = 1) const;
|
|
||||||
std::vector<CoverArt> getFromTrack(const boost::filesystem::path& path, std::size_t nbMaxCovers = 1) const;
|
std::vector<CoverArt> getFromTrack(const boost::filesystem::path& path, std::size_t nbMaxCovers = 1) const;
|
||||||
std::vector<CoverArt> getFromTrack(Wt::Dbo::Session& session, Database::Track::id_type trackId, std::size_t nbMaxCovers = 1) const;
|
std::vector<CoverArt> getFromTrack(Wt::Dbo::Session& session, Database::Track::id_type trackId, std::size_t nbMaxCovers = 1) const;
|
||||||
std::vector<CoverArt> getFromRelease(Wt::Dbo::Session& session, Database::Release::id_type releaseId, std::size_t nbMaxCovers = 1) const;
|
std::vector<CoverArt> getFromRelease(Wt::Dbo::Session& session, Database::Release::id_type releaseId, std::size_t nbMaxCovers = 1) const;
|
||||||
|
|||||||
@@ -97,10 +97,10 @@ class Updater
|
|||||||
Database::Handler _db;
|
Database::Handler _db;
|
||||||
|
|
||||||
std::vector<boost::filesystem::path> _audioExtensions
|
std::vector<boost::filesystem::path> _audioExtensions
|
||||||
= {"mp3", "ogg", "oga", "aac", "m4a", "flac", "wav", "wma", "aif", "aiff", "ape", "mpc", "shn"};
|
= {".mp3", ".ogg", ".oga", ".aac", ".m4a", ".flac", ".wav", ".wma", ".aif", ".aiff", ".ape", ".mpc", ".shn"};
|
||||||
|
|
||||||
std::vector<boost::filesystem::path> _videoExtensions
|
std::vector<boost::filesystem::path> _videoExtensions
|
||||||
= {"flv", "avi", "mpg", "mpeg", "mp4", "m4v", "mkv", "mov", "wmv", "ogv", "divx", "m2ts"};
|
= {".flv", ".avi", ".mpg", ".mpeg", ".mp4", ".m4v", ".mkv", ".mov", ".wmv", ".ogv", ".divx", ".m2ts"};
|
||||||
|
|
||||||
MetaData::Parser& _metadataParser;
|
MetaData::Parser& _metadataParser;
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#define LOGGER_HPP__
|
#define LOGGER_HPP__
|
||||||
|
|
||||||
#include <Wt/WServer>
|
#include <Wt/WServer>
|
||||||
|
#include <Wt/WApplication>
|
||||||
#include <Wt/WLogger>
|
#include <Wt/WLogger>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
@@ -53,6 +54,6 @@ enum Module
|
|||||||
std::string getModuleName(Module mod);
|
std::string getModuleName(Module mod);
|
||||||
std::string getSeverityName(Severity sev);
|
std::string getSeverityName(Severity sev);
|
||||||
|
|
||||||
#define LMS_LOG(module, level) Wt::WServer::instance()->log(getSeverityName(level)) << Wt::WLogger::sep << "[" << getModuleName(module) << "]" << Wt::WLogger::sep
|
#define LMS_LOG(module, level) Wt::log(getSeverityName(level)) << Wt::WLogger::sep << "[" << getModuleName(module) << "]" << Wt::WLogger::sep
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
+5
-3
@@ -20,8 +20,8 @@
|
|||||||
#include <boost/filesystem.hpp>
|
#include <boost/filesystem.hpp>
|
||||||
|
|
||||||
#include "config/config.h"
|
#include "config/config.h"
|
||||||
#include "transcode/AvConvTranscoder.hpp"
|
#include "av/AvInfo.hpp"
|
||||||
#include "av/Common.hpp"
|
#include "av/AvTranscoder.hpp"
|
||||||
#include "logger/Logger.hpp"
|
#include "logger/Logger.hpp"
|
||||||
#include "cover/CoverArtGrabber.hpp"
|
#include "cover/CoverArtGrabber.hpp"
|
||||||
|
|
||||||
@@ -47,11 +47,13 @@ int main(int argc, char* argv[])
|
|||||||
Wt::WServer server(argv[0]);
|
Wt::WServer server(argv[0]);
|
||||||
server.setServerConfiguration (argc, argv);
|
server.setServerConfiguration (argc, argv);
|
||||||
|
|
||||||
|
Wt::WServer::instance()->logger().configure("*"); // log everything
|
||||||
|
|
||||||
Service::ServiceManager& serviceManager = Service::ServiceManager::instance();
|
Service::ServiceManager& serviceManager = Service::ServiceManager::instance();
|
||||||
|
|
||||||
// lib init
|
// lib init
|
||||||
Av::AvInit();
|
Av::AvInit();
|
||||||
Transcode::AvConvTranscoder::init();
|
Av::Transcoder::init();
|
||||||
Database::Handler::configureAuth();
|
Database::Handler::configureAuth();
|
||||||
|
|
||||||
// Initializing a connection pool to the database that will be shared along services
|
// Initializing a connection pool to the database that will be shared along services
|
||||||
|
|||||||
+46
-57
@@ -23,7 +23,7 @@
|
|||||||
#include <boost/algorithm/string.hpp>
|
#include <boost/algorithm/string.hpp>
|
||||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
#include <boost/date_time/posix_time/posix_time.hpp>
|
||||||
|
|
||||||
#include "av/InputFormatContext.hpp"
|
#include "av/AvInfo.hpp"
|
||||||
|
|
||||||
#include "logger/Logger.hpp"
|
#include "logger/Logger.hpp"
|
||||||
|
|
||||||
@@ -36,86 +36,75 @@ bool
|
|||||||
AvFormat::parse(const boost::filesystem::path& p, Items& items)
|
AvFormat::parse(const boost::filesystem::path& p, Items& items)
|
||||||
{
|
{
|
||||||
|
|
||||||
Av::InputFormatContext input(p);
|
Av::MediaFile mediaFile(p);
|
||||||
|
|
||||||
if (!input.findStreamInfo())
|
if (!mediaFile.open())
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
std::map<std::string, std::string> metadata;
|
if (!mediaFile.scan())
|
||||||
input.getMetadata().get(metadata);
|
return false;
|
||||||
|
|
||||||
// HACK or OGG files
|
|
||||||
// If we did not find tags, searched metadata in streams
|
|
||||||
if (metadata.empty())
|
|
||||||
{
|
|
||||||
// Get input streams
|
|
||||||
std::vector<Av::Stream> streams = input.getStreams();
|
|
||||||
|
|
||||||
BOOST_FOREACH(Av::Stream& stream, streams)
|
|
||||||
{
|
|
||||||
stream.getMetadata().get(metadata);
|
|
||||||
|
|
||||||
if (!metadata.empty())
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
std::map<std::string, std::string> metadata = mediaFile.getMetaData();
|
||||||
|
|
||||||
// Stream info
|
// Stream info
|
||||||
{
|
{
|
||||||
std::vector<Av::Stream> avStreams = input.getStreams();
|
std::vector<AudioStream> audioStreams;
|
||||||
|
|
||||||
std::vector<AudioStream> audioStreams;
|
std::vector<Av::Stream> streams = mediaFile.getStreams(Av::Stream::Type::Audio);
|
||||||
std::vector<VideoStream> videoStreams;
|
|
||||||
std::vector<SubtitleStream> subtitleStreams;
|
|
||||||
|
|
||||||
BOOST_FOREACH(Av::Stream& avStream, avStreams)
|
for (Av::Stream& stream : streams)
|
||||||
{
|
{
|
||||||
switch(avStream.getCodecContext().getType())
|
AudioStream audioStream;
|
||||||
{
|
audioStream.desc = stream.desc;
|
||||||
case AVMEDIA_TYPE_VIDEO:
|
audioStream.bitRate = stream.bitrate;
|
||||||
if (!avStream.hasAttachedPic())
|
|
||||||
{
|
|
||||||
VideoStream stream;
|
|
||||||
stream.bitRate = avStream.getCodecContext().getBitRate();
|
|
||||||
videoStreams.push_back(stream);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AVMEDIA_TYPE_AUDIO:
|
audioStreams.push_back(audioStream);
|
||||||
{
|
}
|
||||||
AudioStream stream;
|
|
||||||
stream.nbChannels = avStream.getCodecContext().getNbChannels();
|
|
||||||
stream.bitRate = avStream.getCodecContext().getBitRate();
|
|
||||||
audioStreams.push_back(stream);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case AVMEDIA_TYPE_SUBTITLE:
|
if (!audioStreams.empty())
|
||||||
{
|
items.insert( std::make_pair(MetaData::Type::AudioStreams, audioStreams));
|
||||||
subtitleStreams.push_back( SubtitleStream() );
|
}
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
{
|
||||||
break;
|
std::vector<VideoStream> videoStreams;
|
||||||
}
|
|
||||||
|
std::vector<Av::Stream> streams = mediaFile.getStreams(Av::Stream::Type::Video);
|
||||||
|
|
||||||
|
for (Av::Stream& stream : streams)
|
||||||
|
{
|
||||||
|
VideoStream videoStream;
|
||||||
|
videoStream.desc = stream.desc;
|
||||||
|
videoStream.bitRate = stream.bitrate;
|
||||||
|
|
||||||
|
videoStreams.push_back(videoStream);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!videoStreams.empty())
|
if (!videoStreams.empty())
|
||||||
items.insert( std::make_pair(MetaData::Type::VideoStreams, videoStreams));
|
items.insert( std::make_pair(MetaData::Type::VideoStreams, videoStreams));
|
||||||
if (!audioStreams.empty())
|
}
|
||||||
items.insert( std::make_pair(MetaData::Type::AudioStreams, audioStreams));
|
|
||||||
|
{
|
||||||
|
std::vector<SubtitleStream> subtitleStreams;
|
||||||
|
|
||||||
|
std::vector<Av::Stream> streams = mediaFile.getStreams(Av::Stream::Type::Subtitle);
|
||||||
|
|
||||||
|
for (Av::Stream& stream : streams)
|
||||||
|
{
|
||||||
|
SubtitleStream subtitleStream;
|
||||||
|
subtitleStream.desc = stream.desc;
|
||||||
|
|
||||||
|
subtitleStreams.push_back(subtitleStream);
|
||||||
|
}
|
||||||
|
|
||||||
if (!subtitleStreams.empty())
|
if (!subtitleStreams.empty())
|
||||||
items.insert( std::make_pair(MetaData::Type::SubtitleStreams, subtitleStreams));
|
items.insert( std::make_pair(MetaData::Type::SubtitleStreams, subtitleStreams));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Duration
|
// Duration
|
||||||
items.insert( std::make_pair(MetaData::Type::Duration, boost::posix_time::time_duration( boost::posix_time::seconds( input.getDurationSecs() )) ));
|
items.insert( std::make_pair(MetaData::Type::Duration, mediaFile.getDuration() ));
|
||||||
|
|
||||||
// Cover
|
// Cover
|
||||||
items.insert( std::make_pair(MetaData::Type::HasCover, input.getNbPictures() > 0));
|
items.insert( std::make_pair(MetaData::Type::HasCover, mediaFile.hasAttachedPictures()));
|
||||||
|
|
||||||
// Embedded MetaData
|
// Embedded MetaData
|
||||||
// Make sure to convert strings into UTF-8
|
// Make sure to convert strings into UTF-8
|
||||||
|
|||||||
@@ -48,17 +48,21 @@ namespace MetaData
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Used by Streams
|
// Used by Streams
|
||||||
struct AudioStream {
|
struct AudioStream
|
||||||
std::size_t nbChannels;
|
{
|
||||||
|
std::string desc;
|
||||||
std::size_t bitRate;
|
std::size_t bitRate;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VideoStream {
|
struct VideoStream
|
||||||
|
{
|
||||||
|
std::string desc;
|
||||||
std::size_t bitRate;
|
std::size_t bitRate;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SubtitleStream {
|
struct SubtitleStream
|
||||||
;
|
{
|
||||||
|
std::string desc;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Type and associated data
|
// Type and associated data
|
||||||
|
|||||||
@@ -1,82 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef AVCONV_TRANSCODER_HPP
|
|
||||||
#define AVCONV_TRANSCODER_HPP
|
|
||||||
|
|
||||||
#include <memory>
|
|
||||||
#include <iostream>
|
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
#include <boost/iostreams/stream.hpp>
|
|
||||||
#include <boost/process.hpp>
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
#include <boost/thread.hpp>
|
|
||||||
|
|
||||||
#include "Parameters.hpp"
|
|
||||||
|
|
||||||
namespace Transcode
|
|
||||||
{
|
|
||||||
|
|
||||||
class AvConvTranscoder
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
static void init();
|
|
||||||
|
|
||||||
~AvConvTranscoder();
|
|
||||||
|
|
||||||
AvConvTranscoder(const Parameters& parameters);
|
|
||||||
|
|
||||||
const Parameters& getParameters(void) const { return _parameters; }
|
|
||||||
|
|
||||||
// Get a bunch of input data
|
|
||||||
// Place it at the end of the parameter, no more that maxSize bytes
|
|
||||||
void process(std::vector<unsigned char>& output, std::size_t maxSize);
|
|
||||||
|
|
||||||
bool isComplete(void) const { return _isComplete;};
|
|
||||||
std::size_t getOutputBytes(void) const { return _outputBytes; }
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
typedef std::shared_ptr<boost::process::child> ChildPtr;
|
|
||||||
|
|
||||||
void waitChild();
|
|
||||||
void killChild();
|
|
||||||
|
|
||||||
const Parameters _parameters;
|
|
||||||
|
|
||||||
static boost::mutex _mutex;
|
|
||||||
|
|
||||||
boost::process::pipe _outputPipe;
|
|
||||||
boost::iostreams::file_descriptor_source _source;
|
|
||||||
boost::iostreams::stream_buffer<boost::iostreams::file_descriptor_source> _is;
|
|
||||||
std::istream _in;
|
|
||||||
|
|
||||||
std::shared_ptr<boost::process::child> _child;
|
|
||||||
|
|
||||||
static boost::filesystem::path _avConvPath;
|
|
||||||
|
|
||||||
bool _isComplete;
|
|
||||||
std::size_t _outputBytes; // Bytes produced so far
|
|
||||||
};
|
|
||||||
|
|
||||||
} // naspace Transcode
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,84 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <stdexcept>
|
|
||||||
#include <cassert>
|
|
||||||
|
|
||||||
#include "Format.hpp"
|
|
||||||
|
|
||||||
namespace Transcode
|
|
||||||
{
|
|
||||||
|
|
||||||
const std::vector<Format> Format::_supportedFormats
|
|
||||||
{
|
|
||||||
{Format::OGA, Format::Audio, "audio/ogg", "Ogg"},
|
|
||||||
{Format::OGV, Format::Video, "video/ogg", "Ogg"},
|
|
||||||
{Format::MP3, Format::Audio, "audio/mpeg", "MP3"},
|
|
||||||
{Format::WEBMA, Format::Audio, "audio/webm", "WebM"},
|
|
||||||
{Format::WEBMV, Format::Video, "video/webm", "WebM"},
|
|
||||||
{Format::FLA, Format::Audio, "audio/x-flv", "Flash Audio"},
|
|
||||||
{Format::FLV, Format::Video, "video/x-flv", "Flash Video"},
|
|
||||||
{Format::M4A, Format::Audio, "audio/mp4", "MP4"},
|
|
||||||
{Format::M4V, Format::Video, "video/mp4", "MP4"},
|
|
||||||
};
|
|
||||||
|
|
||||||
Format::Format(Encoding encoding, Type type, std::string mimeType, std::string desc)
|
|
||||||
:
|
|
||||||
_encoding(encoding),
|
|
||||||
_type(type),
|
|
||||||
_mineType(mimeType),
|
|
||||||
_desc(desc)
|
|
||||||
{}
|
|
||||||
|
|
||||||
|
|
||||||
const Format&
|
|
||||||
Format::get(Encoding encoding)
|
|
||||||
{
|
|
||||||
BOOST_FOREACH(const Format& format, _supportedFormats)
|
|
||||||
{
|
|
||||||
if (format.getEncoding() == encoding)
|
|
||||||
return format;
|
|
||||||
}
|
|
||||||
|
|
||||||
throw std::runtime_error("Cannot find format");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Format>
|
|
||||||
Format::get(Type type)
|
|
||||||
{
|
|
||||||
std::vector<Format> res;
|
|
||||||
BOOST_FOREACH(const Format& format, _supportedFormats)
|
|
||||||
{
|
|
||||||
if (format.getType() == type)
|
|
||||||
res.push_back( format );
|
|
||||||
}
|
|
||||||
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool
|
|
||||||
Format::operator==(const Format& other) const
|
|
||||||
{
|
|
||||||
return getEncoding() == other.getEncoding();
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Transcode
|
|
||||||
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TRANSCODE_FORMAT_HPP
|
|
||||||
#define TRANSCODE_FORMAT_HPP
|
|
||||||
|
|
||||||
#include <vector>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace Transcode
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
class Format
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
// Output format
|
|
||||||
enum Encoding {
|
|
||||||
OGA,
|
|
||||||
OGV,
|
|
||||||
MP3,
|
|
||||||
WEBMA,
|
|
||||||
WEBMV,
|
|
||||||
FLA,
|
|
||||||
FLV,
|
|
||||||
M4A,
|
|
||||||
M4V,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum Type {
|
|
||||||
Video,
|
|
||||||
Audio,
|
|
||||||
};
|
|
||||||
|
|
||||||
// Utility
|
|
||||||
static const Format& get(Encoding encoding);
|
|
||||||
static std::vector<Format> get(Type type);
|
|
||||||
|
|
||||||
Format(Encoding format, Type type, std::string mimeType, std::string desc);
|
|
||||||
|
|
||||||
Encoding getEncoding(void) const { return _encoding;}
|
|
||||||
Type getType(void) const { return _type;}
|
|
||||||
const std::string& getMimeType(void) const { return _mineType;}
|
|
||||||
const std::string& getDesc(void) const { return _desc;}
|
|
||||||
|
|
||||||
bool operator==(const Format& other) const;
|
|
||||||
|
|
||||||
private:
|
|
||||||
Encoding _encoding;
|
|
||||||
Type _type;
|
|
||||||
std::string _mineType;
|
|
||||||
std::string _desc;
|
|
||||||
|
|
||||||
static const std::vector<Format> _supportedFormats;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Transcode
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
#include "logger/Logger.hpp"
|
|
||||||
|
|
||||||
#include "av/InputFormatContext.hpp"
|
|
||||||
#include "cover/CoverArtGrabber.hpp"
|
|
||||||
|
|
||||||
#include "InputMediaFile.hpp"
|
|
||||||
|
|
||||||
namespace Transcode
|
|
||||||
{
|
|
||||||
|
|
||||||
bool getStreamType(enum AVMediaType type, Transcode::Stream::Type& streamType)
|
|
||||||
{
|
|
||||||
switch (type) {
|
|
||||||
case AVMEDIA_TYPE_VIDEO: streamType = Transcode::Stream::Video; return true;
|
|
||||||
case AVMEDIA_TYPE_AUDIO: streamType = Transcode::Stream::Audio; return true;
|
|
||||||
case AVMEDIA_TYPE_SUBTITLE: streamType = Transcode::Stream::Subtitle; return true;
|
|
||||||
default:
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
InputMediaFile::InputMediaFile(const boost::filesystem::path& p)
|
|
||||||
: _path(p)
|
|
||||||
{
|
|
||||||
Av::InputFormatContext input(_path);
|
|
||||||
|
|
||||||
if (!input.findStreamInfo())
|
|
||||||
throw std::runtime_error("Cannot find stream info in file: " + p.string());
|
|
||||||
|
|
||||||
// Calculate estimated duration
|
|
||||||
if (input.getDurationSecs())
|
|
||||||
_duration = boost::posix_time::seconds(input.getDurationSecs() + 1);
|
|
||||||
|
|
||||||
// Get input streams
|
|
||||||
std::vector<Av::Stream> avStreams = input.getStreams();
|
|
||||||
|
|
||||||
std::list<enum AVMediaType> avMediaTypes; // List of encountered streams
|
|
||||||
for (std::size_t avStreamId = 0; avStreamId < avStreams.size(); ++avStreamId)
|
|
||||||
{
|
|
||||||
Av::Stream& avStream(avStreams[avStreamId]);
|
|
||||||
Stream::Type type;
|
|
||||||
|
|
||||||
if (getStreamType(avStream.getCodecContext().getType(), type))
|
|
||||||
{
|
|
||||||
// Reject Video stream hat are in fact cover arts
|
|
||||||
if (avStream.hasAttachedPic())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
avMediaTypes.push_back(avStream.getCodecContext().getType());
|
|
||||||
|
|
||||||
LMS_LOG(MOD_TRANSCODE, SEV_DEBUG) << "Stream idx " << avStreamId << ", type = " << type << ", bitrate = " << avStream.getCodecContext().getBitRate() << ", codec desc = " << avStream.getCodecContext().getCodecDesc();
|
|
||||||
|
|
||||||
_streams.push_back( Stream(avStreamId,
|
|
||||||
type,
|
|
||||||
avStream.getCodecContext().getBitRate(),
|
|
||||||
avStream.getMetadata().get("language"), // TODO define somewhere else?
|
|
||||||
avStream.getCodecContext().getCodecDesc()
|
|
||||||
));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
avMediaTypes.unique();
|
|
||||||
// Scan for best streams
|
|
||||||
for (enum AVMediaType type : avMediaTypes)
|
|
||||||
{
|
|
||||||
Av::Stream::Idx index;
|
|
||||||
|
|
||||||
if (input.getBestStreamIdx(type, index))
|
|
||||||
{
|
|
||||||
Stream::Type streamType;
|
|
||||||
if (getStreamType(type, streamType))
|
|
||||||
_bestStreams.insert(std::make_pair( streamType, index) );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
LMS_LOG(MOD_TRANSCODE, SEV_WARNING) << "Cannot find best stream for type " << type;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<Stream>
|
|
||||||
InputMediaFile::getStreams(Stream::Type type) const
|
|
||||||
{
|
|
||||||
std::vector<Stream> res;
|
|
||||||
for (const Stream& stream : _streams)
|
|
||||||
{
|
|
||||||
if (stream.getType() == type)
|
|
||||||
res.push_back(stream);
|
|
||||||
}
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
const Stream&
|
|
||||||
InputMediaFile::getStream(Stream::Id index) const
|
|
||||||
{
|
|
||||||
for (const Stream& stream : _streams)
|
|
||||||
{
|
|
||||||
if (stream.getId() == index)
|
|
||||||
return stream;
|
|
||||||
}
|
|
||||||
LMS_LOG(MOD_TRANSCODE, SEV_CRIT) << "Cannot find stream index " << index << " in stream map!";
|
|
||||||
throw std::runtime_error("InputMediaFile::getStream, cannot find stream idx");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Transcode
|
|
||||||
|
|
||||||
@@ -1,72 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TRANSCODE_INPUT_MEDIA_FILE
|
|
||||||
#define TRANSCODE_INPUT_MEDIA_FILE
|
|
||||||
|
|
||||||
#include <map>
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
|
||||||
|
|
||||||
#include "cover/CoverArt.hpp"
|
|
||||||
|
|
||||||
#include "Stream.hpp"
|
|
||||||
|
|
||||||
|
|
||||||
namespace Transcode
|
|
||||||
{
|
|
||||||
|
|
||||||
class InputMediaFile
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum StreamType
|
|
||||||
{
|
|
||||||
StreamAudio,
|
|
||||||
StreamVideo,
|
|
||||||
StreamSubtitle,
|
|
||||||
};
|
|
||||||
|
|
||||||
InputMediaFile(const boost::filesystem::path& p);
|
|
||||||
|
|
||||||
// Accessors
|
|
||||||
boost::filesystem::path getPath(void) const {return _path;}
|
|
||||||
boost::posix_time::time_duration getDuration(void) const {return _duration;}
|
|
||||||
|
|
||||||
// Stream handling
|
|
||||||
const Stream& getStream(Stream::Id id) const;
|
|
||||||
std::vector<Stream> getStreams(Stream::Type type) const;
|
|
||||||
const std::map<Stream::Type, Stream::Id>& getBestStreams(void) const {return _bestStreams;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
boost::filesystem::path _path;
|
|
||||||
boost::posix_time::time_duration _duration;
|
|
||||||
|
|
||||||
std::vector<Stream> _streams;
|
|
||||||
std::map<Stream::Type, Stream::Id> _bestStreams;
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Transcode
|
|
||||||
|
|
||||||
#endif // TRANSCODE_INPUT_MEDIA_FILE
|
|
||||||
|
|
||||||
@@ -1,87 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
#include "logger/Logger.hpp"
|
|
||||||
|
|
||||||
#include "av/InputFormatContext.hpp"
|
|
||||||
|
|
||||||
#include "Parameters.hpp"
|
|
||||||
|
|
||||||
namespace Transcode
|
|
||||||
{
|
|
||||||
|
|
||||||
Parameters::Parameters(const InputMediaFile& inputMediaFile,
|
|
||||||
const Format& outputFormat)
|
|
||||||
:
|
|
||||||
_mediaFile(inputMediaFile),
|
|
||||||
_outputFormat(outputFormat)
|
|
||||||
{
|
|
||||||
// By default, select the best stream indexes
|
|
||||||
_inputStreams = _mediaFile.getBestStreams();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t
|
|
||||||
Parameters::setBitrate(Stream::Type type, std::size_t bitrate)
|
|
||||||
{
|
|
||||||
// Limit the output bitrate to the input bitrate
|
|
||||||
if (_inputStreams.find(type) != _inputStreams.end())
|
|
||||||
{
|
|
||||||
const Transcode::Stream& stream = _mediaFile.getStream( _inputStreams[type] );
|
|
||||||
|
|
||||||
LMS_LOG(MOD_TRANSCODE, SEV_DEBUG) << "Stream bitrate = " << stream.getBitrate();
|
|
||||||
|
|
||||||
if (bitrate > stream.getBitrate())
|
|
||||||
{
|
|
||||||
LMS_LOG(MOD_TRANSCODE, SEV_INFO) << "Setting bitrate for stream idx " << _inputStreams[type] << " to input bitrate (" << stream.getBitrate() << ")";
|
|
||||||
_outputBitrate[type] = stream.getBitrate();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LMS_LOG(MOD_TRANSCODE, SEV_DEBUG) << "Setting bitrate for stream idx " << _inputStreams[type] << " to " << bitrate;
|
|
||||||
_outputBitrate[type] = bitrate;
|
|
||||||
}
|
|
||||||
return _outputBitrate[type];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LMS_LOG(MOD_TRANSCODE, SEV_DEBUG) << "Cannot find stream type " << type;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::size_t
|
|
||||||
Parameters::getOutputBitrate(Stream::Type type) const
|
|
||||||
{
|
|
||||||
std::map<Stream::Type, std::size_t>::const_iterator it = _outputBitrate.find(type);
|
|
||||||
|
|
||||||
if (it != _outputBitrate.end())
|
|
||||||
{
|
|
||||||
return it->second;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
LMS_LOG(MOD_TRANSCODE, SEV_DEBUG) << "output bitrate not set for type " << type;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} // namespace Transcode
|
|
||||||
|
|
||||||
@@ -1,77 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TRANSCODE_PARAMETERS_HPP
|
|
||||||
#define TRANSCODE_PARAMETERS_HPP
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
#include <boost/filesystem.hpp>
|
|
||||||
#include <boost/date_time/posix_time/posix_time.hpp>
|
|
||||||
|
|
||||||
#include "Format.hpp"
|
|
||||||
|
|
||||||
#include "InputMediaFile.hpp"
|
|
||||||
|
|
||||||
namespace Transcode
|
|
||||||
{
|
|
||||||
|
|
||||||
|
|
||||||
class Parameters {
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
Parameters(const InputMediaFile& InputFile, const Format& outputFormat);
|
|
||||||
|
|
||||||
// Modifiers
|
|
||||||
void setOffset(boost::posix_time::time_duration offset) { _offset = offset; } // Set input offset
|
|
||||||
void setOutputFormat(const Format& format) { _outputFormat = format; }
|
|
||||||
std::size_t setBitrate(Stream::Type type, std::size_t bitrate);
|
|
||||||
|
|
||||||
// Manually select an input stream to output
|
|
||||||
// There can be only one stream per each type (video, audio, subtitle)
|
|
||||||
typedef std::map<Stream::Type, Stream::Id> StreamMap;
|
|
||||||
void selectInputStream(Stream::Type type, Stream::Id id) { _inputStreams[type] = id; }
|
|
||||||
const StreamMap& getInputStreams(void) const {return _inputStreams;}
|
|
||||||
|
|
||||||
//Accessors
|
|
||||||
boost::posix_time::time_duration getOffset(void) const {return _offset;}
|
|
||||||
const Format& getOutputFormat(void) const { return _outputFormat; }
|
|
||||||
std::size_t getOutputBitrate(Stream::Type type) const;
|
|
||||||
const InputMediaFile& getInputMediaFile(void) const { return _mediaFile;}
|
|
||||||
InputMediaFile& getInputMediaFile(void) { return _mediaFile;}
|
|
||||||
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
InputMediaFile _mediaFile;
|
|
||||||
|
|
||||||
boost::posix_time::time_duration _offset; // start input offset
|
|
||||||
|
|
||||||
Format _outputFormat; // OGA, OGV, etc.
|
|
||||||
std::map<Stream::Type, std::size_t> _outputBitrate;
|
|
||||||
|
|
||||||
StreamMap _inputStreams;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace Transcode
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2013 Emeric Poupon
|
|
||||||
*
|
|
||||||
* This file is part of LMS.
|
|
||||||
*
|
|
||||||
* LMS is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* LMS 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 General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifndef TRANSCODE_STREAM_HPP
|
|
||||||
#define TRANSCODE_STREAM_HPP
|
|
||||||
|
|
||||||
#include <string>
|
|
||||||
|
|
||||||
namespace Transcode
|
|
||||||
{
|
|
||||||
|
|
||||||
class Stream
|
|
||||||
{
|
|
||||||
|
|
||||||
public:
|
|
||||||
|
|
||||||
enum Type
|
|
||||||
{
|
|
||||||
Audio,
|
|
||||||
Video,
|
|
||||||
Subtitle,
|
|
||||||
};
|
|
||||||
|
|
||||||
typedef std::size_t Id;
|
|
||||||
|
|
||||||
Stream(Id id, Type type, std::size_t bitrate, const std::string& lang, const std::string& desc)
|
|
||||||
: _id(id), _type(type), _bitrate(bitrate), _language(lang), _desc(desc) {}
|
|
||||||
|
|
||||||
// Accessors
|
|
||||||
Id getId() const { return _id;}
|
|
||||||
Type getType() const { return _type;}
|
|
||||||
std::size_t getBitrate() const { return _bitrate;}
|
|
||||||
const std::string& getLanguage() const { return _language;}
|
|
||||||
const std::string& getDesc() const { return _desc;}
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
Id _id;
|
|
||||||
Type _type;
|
|
||||||
std::size_t _bitrate;
|
|
||||||
std::string _language;
|
|
||||||
std::string _desc;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace Transcode
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
@@ -36,7 +36,9 @@
|
|||||||
#include "auth/LmsAuth.hpp"
|
#include "auth/LmsAuth.hpp"
|
||||||
#include "audio/desktop/DesktopAudio.hpp"
|
#include "audio/desktop/DesktopAudio.hpp"
|
||||||
#include "audio/mobile/MobileAudio.hpp"
|
#include "audio/mobile/MobileAudio.hpp"
|
||||||
|
#if HAVE_VIDEO
|
||||||
#include "video/VideoWidget.hpp"
|
#include "video/VideoWidget.hpp"
|
||||||
|
#endif
|
||||||
#include "common/LineEdit.hpp"
|
#include "common/LineEdit.hpp"
|
||||||
|
|
||||||
#include "LmsApplication.hpp"
|
#include "LmsApplication.hpp"
|
||||||
@@ -196,10 +198,13 @@ LmsApplication::handleAuthEvent(void)
|
|||||||
else
|
else
|
||||||
audio = new Desktop::Audio();
|
audio = new Desktop::Audio();
|
||||||
|
|
||||||
VideoWidget *videoWidget = new VideoWidget();
|
|
||||||
|
|
||||||
leftMenu->addItem("Audio", audio);
|
leftMenu->addItem("Audio", audio);
|
||||||
|
|
||||||
|
#if defined HAVE_VIDEO
|
||||||
|
VideoWidget *videoWidget = new VideoWidget();
|
||||||
leftMenu->addItem("Video", videoWidget);
|
leftMenu->addItem("Video", videoWidget);
|
||||||
|
#endif
|
||||||
|
|
||||||
leftMenu->addItem("Settings", new Settings::Settings());
|
leftMenu->addItem("Settings", new Settings::Settings());
|
||||||
|
|
||||||
// Setup a Right-aligned menu.
|
// Setup a Right-aligned menu.
|
||||||
|
|||||||
@@ -172,85 +172,92 @@ AudioMediaPlayer::AudioMediaPlayer(Wt::WContainerWidget *parent)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioMediaPlayer::loadPlayer(void)
|
AudioMediaPlayer::loadPlayer(boost::filesystem::path filePath, Av::TranscodeParameters& parameters)
|
||||||
{
|
{
|
||||||
|
_currentFile = filePath;
|
||||||
|
_currentParameters = parameters;
|
||||||
|
|
||||||
_mediaPlayer->clearSources();
|
_mediaPlayer->clearSources();
|
||||||
|
|
||||||
if (_mediaResource)
|
if (_mediaResource)
|
||||||
delete _mediaResource;
|
delete _mediaResource;
|
||||||
|
|
||||||
assert( _currentParameters );
|
_mediaResource = new AvConvTranscodeStreamResource( filePath, parameters, this );
|
||||||
_mediaResource = new AvConvTranscodeStreamResource( *_currentParameters, this );
|
|
||||||
|
|
||||||
_mediaPlayer->addSource( getEncoding(), Wt::WLink(_mediaResource));
|
_mediaPlayer->addSource( getEncoding(), Wt::WLink(_mediaResource));
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
AudioMediaPlayer::load(Database::Track::id_type trackId)
|
|
||||||
{
|
|
||||||
std::size_t bitrate = 0;
|
|
||||||
boost::filesystem::path trackPath;
|
|
||||||
|
|
||||||
{
|
|
||||||
Wt::Dbo::Transaction transaction(DboSession());
|
|
||||||
|
|
||||||
Database::Track::pointer track = Database::Track::getById(DboSession(), trackId);
|
|
||||||
|
|
||||||
bitrate = CurrentUser()->getAudioBitrate();
|
|
||||||
trackPath = track->getPath();
|
|
||||||
_mediaTitle->setText ( Wt::WString::fromUTF8(track->getName()) );
|
|
||||||
_mediaArtistRelease->setText ( Wt::WString::fromUTF8(track->getArtist()->getName()) + " - " + Wt::WString::fromUTF8(track->getRelease()->getName()) );
|
|
||||||
_mediaCover->setImageLink( Wt::WLink (LmsApplication::instance()->getCoverResource()->getTrackUrl(trackId, 72)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Transcode::Format::Encoding encoding;
|
|
||||||
switch (_encoding)
|
|
||||||
{
|
|
||||||
case Wt::WMediaPlayer::MP3: encoding = Transcode::Format::MP3; break;
|
|
||||||
case Wt::WMediaPlayer::FLA: encoding = Transcode::Format::FLA; break;
|
|
||||||
case Wt::WMediaPlayer::OGA: encoding = Transcode::Format::OGA; break;
|
|
||||||
case Wt::WMediaPlayer::WEBMA: encoding = Transcode::Format::WEBMA; break;
|
|
||||||
default:
|
|
||||||
encoding = Transcode::Format::MP3;
|
|
||||||
}
|
|
||||||
|
|
||||||
_timeSlider->setDisabled(false);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
Transcode::Parameters parameters(trackPath, Transcode::Format::get(encoding));
|
|
||||||
parameters.setBitrate(Transcode::Stream::Audio, bitrate);
|
|
||||||
|
|
||||||
_currentParameters = std::make_shared<Transcode::Parameters>( parameters );
|
|
||||||
}
|
|
||||||
catch(std::exception &e)
|
|
||||||
{
|
|
||||||
LMS_LOG(MOD_UI, SEV_ERROR) << "Cannot load input file '" << trackPath << "'";
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
loadPlayer();
|
|
||||||
|
|
||||||
_timeSlider->setRange(0, _currentParameters->getInputMediaFile().getDuration().total_seconds() );
|
|
||||||
_timeSlider->setValue(0);
|
|
||||||
|
|
||||||
_duration->setText( boost::posix_time::to_simple_string( _currentParameters->getInputMediaFile().getDuration() ));
|
|
||||||
|
|
||||||
// Auto play
|
// Auto play
|
||||||
_mediaPlayer->play();
|
_mediaPlayer->play();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
AudioMediaPlayer::load(Database::Track::id_type trackId)
|
||||||
|
{
|
||||||
|
Av::TranscodeParameters parameters;
|
||||||
|
|
||||||
|
boost::filesystem::path path;
|
||||||
|
|
||||||
|
boost::posix_time::time_duration duration;
|
||||||
|
|
||||||
|
{
|
||||||
|
Wt::Dbo::Transaction transaction(DboSession());
|
||||||
|
|
||||||
|
Database::Track::pointer track = Database::Track::getById(DboSession(), trackId);
|
||||||
|
|
||||||
|
path = track->getPath();
|
||||||
|
parameters.setBitrate(Av::Stream::Type::Audio, CurrentUser()->getAudioBitrate() );
|
||||||
|
|
||||||
|
duration = track->getDuration();
|
||||||
|
|
||||||
|
_mediaTitle->setText ( Wt::WString::fromUTF8(track->getName()) );
|
||||||
|
_mediaArtistRelease->setText ( Wt::WString::fromUTF8(track->getArtist()->getName()) + " - " + Wt::WString::fromUTF8(track->getRelease()->getName()) );
|
||||||
|
_mediaCover->setImageLink( Wt::WLink (LmsApplication::instance()->getCoverResource()->getTrackUrl(trackId, 72)));
|
||||||
|
}
|
||||||
|
|
||||||
|
Av::MediaFile mediaFile(path);
|
||||||
|
|
||||||
|
if (!mediaFile.open())
|
||||||
|
{
|
||||||
|
// No longer exist ? TODO next?
|
||||||
|
LMS_LOG(MOD_UI, SEV_INFO) << "Cannot open file '" << path << "'";
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// It seems to be far better to manually map the streams
|
||||||
|
// otherwise, some files may have to be fully transcoded to be played by browser...
|
||||||
|
int audioBestStreamId = mediaFile.getBestStreamId(Av::Stream::Type::Audio);
|
||||||
|
if (audioBestStreamId != -1)
|
||||||
|
parameters.addStream(audioBestStreamId);
|
||||||
|
|
||||||
|
Av::Encoding encoding;
|
||||||
|
switch (_encoding)
|
||||||
|
{
|
||||||
|
case Wt::WMediaPlayer::MP3: encoding = Av::Encoding::MP3; break;
|
||||||
|
case Wt::WMediaPlayer::FLA: encoding = Av::Encoding::FLA; break;
|
||||||
|
case Wt::WMediaPlayer::OGA: encoding = Av::Encoding::OGA; break;
|
||||||
|
case Wt::WMediaPlayer::WEBMA: encoding = Av::Encoding::WEBMA; break;
|
||||||
|
default:
|
||||||
|
encoding = Av::Encoding::MP3;
|
||||||
|
}
|
||||||
|
parameters.setEncoding(encoding);
|
||||||
|
|
||||||
|
_timeSlider->setDisabled(false);
|
||||||
|
_timeSlider->setRange(0, duration.total_seconds() );
|
||||||
|
_timeSlider->setValue(0);
|
||||||
|
|
||||||
|
_duration->setText( boost::posix_time::to_simple_string( duration ));
|
||||||
|
|
||||||
|
loadPlayer(path, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioMediaPlayer::handlePlayOffset(int offsetSecs)
|
AudioMediaPlayer::handlePlayOffset(int offsetSecs)
|
||||||
{
|
{
|
||||||
if (!_currentParameters)
|
Av::TranscodeParameters parameters = _currentParameters;
|
||||||
return;
|
|
||||||
|
|
||||||
_currentParameters->setOffset( boost::posix_time::seconds(offsetSecs) );
|
parameters.setOffset( boost::posix_time::seconds(offsetSecs) );
|
||||||
|
|
||||||
loadPlayer();
|
loadPlayer(_currentFile, parameters);
|
||||||
|
|
||||||
_mediaPlayer->play();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -262,10 +269,7 @@ AudioMediaPlayer::handleTrackEnded(void)
|
|||||||
void
|
void
|
||||||
AudioMediaPlayer::handleTimeUpdated(void)
|
AudioMediaPlayer::handleTimeUpdated(void)
|
||||||
{
|
{
|
||||||
if (!_currentParameters)
|
boost::posix_time::time_duration currentTime ( boost::posix_time::seconds( _mediaPlayer->currentTime() + _currentParameters.getOffset().total_seconds()));
|
||||||
return;
|
|
||||||
|
|
||||||
boost::posix_time::time_duration currentTime ( boost::posix_time::seconds( _mediaPlayer->currentTime() + _currentParameters->getOffset().total_seconds()));
|
|
||||||
|
|
||||||
_timeSlider->setValue( currentTime.total_seconds() );
|
_timeSlider->setValue( currentTime.total_seconds() );
|
||||||
_curTime->setText( boost::posix_time::to_simple_string( currentTime) );
|
_curTime->setText( boost::posix_time::to_simple_string( currentTime) );
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
#include "database/Types.hpp"
|
#include "database/Types.hpp"
|
||||||
|
|
||||||
#include "transcode/Parameters.hpp"
|
#include "av/AvTranscoder.hpp"
|
||||||
#include "resource/AvConvTranscodeStreamResource.hpp"
|
#include "resource/AvConvTranscodeStreamResource.hpp"
|
||||||
#include "resource/CoverResource.hpp"
|
#include "resource/CoverResource.hpp"
|
||||||
|
|
||||||
@@ -70,7 +70,7 @@ class AudioMediaPlayer : public Wt::WContainerWidget
|
|||||||
|
|
||||||
void handleVolumeSliderMoved(int value);
|
void handleVolumeSliderMoved(int value);
|
||||||
|
|
||||||
void loadPlayer(void);
|
void loadPlayer(boost::filesystem::path filePath, Av::TranscodeParameters& parameters);
|
||||||
|
|
||||||
// Signals
|
// Signals
|
||||||
Wt::Signal<void> _playbackEnded;
|
Wt::Signal<void> _playbackEnded;
|
||||||
@@ -90,7 +90,6 @@ class AudioMediaPlayer : public Wt::WContainerWidget
|
|||||||
Wt::WText* _mediaArtistRelease;
|
Wt::WText* _mediaArtistRelease;
|
||||||
|
|
||||||
// Controls
|
// Controls
|
||||||
std::shared_ptr<Transcode::Parameters> _currentParameters;
|
|
||||||
Wt::WPushButton* _playBtn;
|
Wt::WPushButton* _playBtn;
|
||||||
Wt::WPushButton* _pauseBtn;
|
Wt::WPushButton* _pauseBtn;
|
||||||
Wt::WSlider* _timeSlider;
|
Wt::WSlider* _timeSlider;
|
||||||
@@ -98,6 +97,10 @@ class AudioMediaPlayer : public Wt::WContainerWidget
|
|||||||
Wt::WText* _curTime;
|
Wt::WText* _curTime;
|
||||||
Wt::WText* _duration;
|
Wt::WText* _duration;
|
||||||
|
|
||||||
|
// Transcode
|
||||||
|
boost::filesystem::path _currentFile;
|
||||||
|
Av::TranscodeParameters _currentParameters;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace Desktop
|
} // namespace Desktop
|
||||||
|
|||||||
@@ -164,21 +164,23 @@ Audio::Audio(Wt::WContainerWidget *parent)
|
|||||||
|
|
||||||
if (track)
|
if (track)
|
||||||
{
|
{
|
||||||
|
Av::TranscodeParameters parameters;
|
||||||
|
|
||||||
// Determine the output format using the encoding of the player
|
// Determine the output format using the encoding of the player
|
||||||
Transcode::Format::Encoding encoding;
|
Av::Encoding encoding;
|
||||||
switch(mediaPlayer->getEncoding())
|
switch(mediaPlayer->getEncoding())
|
||||||
{
|
{
|
||||||
case Wt::WMediaPlayer::MP3: encoding = Transcode::Format::MP3; break;
|
case Wt::WMediaPlayer::MP3: encoding = Av::Encoding::MP3; break;
|
||||||
case Wt::WMediaPlayer::FLA: encoding = Transcode::Format::FLA; break;
|
case Wt::WMediaPlayer::FLA: encoding = Av::Encoding::FLA; break;
|
||||||
case Wt::WMediaPlayer::OGA: encoding = Transcode::Format::OGA; break;
|
case Wt::WMediaPlayer::OGA: encoding = Av::Encoding::OGA; break;
|
||||||
case Wt::WMediaPlayer::WEBMA: encoding = Transcode::Format::WEBMA; break;
|
case Wt::WMediaPlayer::WEBMA: encoding = Av::Encoding::WEBMA; break;
|
||||||
default:
|
default:
|
||||||
encoding = Transcode::Format::MP3;
|
encoding = Av::Encoding::MP3;
|
||||||
}
|
}
|
||||||
// TODO compute parameters using user s profile
|
parameters.setEncoding(encoding);
|
||||||
Transcode::InputMediaFile inputFile(track->getPath());
|
|
||||||
Transcode::Parameters parameters(inputFile, Transcode::Format::get(encoding));
|
// TODO compute parameters using user's profile
|
||||||
parameters.setBitrate(Transcode::Stream::Audio, 96000);
|
parameters.setBitrate(Av::Stream::Type::Audio, 96000);
|
||||||
|
|
||||||
mediaPlayer->play(track.id(), parameters);
|
mediaPlayer->play(track.id(), parameters);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -80,17 +80,9 @@ _encoding(encoding)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
AudioMediaPlayer::play(Database::Track::id_type trackId, const Transcode::Parameters& parameters)
|
AudioMediaPlayer::play(Database::Track::id_type trackId, Av::TranscodeParameters parameters)
|
||||||
{
|
{
|
||||||
// FIXME memleak here
|
boost::filesystem::path path;
|
||||||
AvConvTranscodeStreamResource *resource = new AvConvTranscodeStreamResource( parameters, this );
|
|
||||||
|
|
||||||
_player->clearSources();
|
|
||||||
_player->addSource( _encoding, Wt::WLink(resource));
|
|
||||||
|
|
||||||
_player->play();
|
|
||||||
|
|
||||||
_cover->setImageLink( Wt::WLink (LmsApplication::instance()->getCoverResource()->getTrackUrl(trackId, 48)));
|
|
||||||
|
|
||||||
{
|
{
|
||||||
Wt::Dbo::Transaction transaction(DboSession());
|
Wt::Dbo::Transaction transaction(DboSession());
|
||||||
@@ -99,7 +91,19 @@ AudioMediaPlayer::play(Database::Track::id_type trackId, const Transcode::Parame
|
|||||||
|
|
||||||
_track->setText( Wt::WString::fromUTF8(track->getName() ));
|
_track->setText( Wt::WString::fromUTF8(track->getName() ));
|
||||||
_artistRelease->setText( Wt::WString::fromUTF8(track->getArtist()->getName()) );
|
_artistRelease->setText( Wt::WString::fromUTF8(track->getArtist()->getName()) );
|
||||||
|
path = track->getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// FIXME memleak here
|
||||||
|
AvConvTranscodeStreamResource *resource = new AvConvTranscodeStreamResource( path, parameters, this );
|
||||||
|
|
||||||
|
_player->clearSources();
|
||||||
|
_player->addSource( _encoding, Wt::WLink(resource));
|
||||||
|
|
||||||
|
_player->play();
|
||||||
|
|
||||||
|
_cover->setImageLink( Wt::WLink (LmsApplication::instance()->getCoverResource()->getTrackUrl(trackId, 48)));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace UserInterface
|
} // namespace UserInterface
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
#include <Wt/WImage>
|
#include <Wt/WImage>
|
||||||
|
|
||||||
#include "database/DatabaseHandler.hpp"
|
#include "database/DatabaseHandler.hpp"
|
||||||
#include "transcode/Parameters.hpp"
|
#include "av/AvTranscoder.hpp"
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
namespace Mobile {
|
namespace Mobile {
|
||||||
@@ -38,7 +38,7 @@ class AudioMediaPlayer : public Wt::WContainerWidget
|
|||||||
|
|
||||||
AudioMediaPlayer(Wt::WMediaPlayer::Encoding encoding, Wt::WContainerWidget *parent = 0);
|
AudioMediaPlayer(Wt::WMediaPlayer::Encoding encoding, Wt::WContainerWidget *parent = 0);
|
||||||
|
|
||||||
void play(Database::Track::id_type trackId, const Transcode::Parameters& parameters);
|
void play(Database::Track::id_type trackId, Av::TranscodeParameters parameters);
|
||||||
|
|
||||||
Wt::WMediaPlayer::Encoding getEncoding() const { return _encoding; }
|
Wt::WMediaPlayer::Encoding getEncoding() const { return _encoding; }
|
||||||
|
|
||||||
|
|||||||
@@ -27,9 +27,10 @@
|
|||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|
||||||
AvConvTranscodeStreamResource::AvConvTranscodeStreamResource(const Transcode::Parameters& parameters, Wt::WObject *parent)
|
AvConvTranscodeStreamResource::AvConvTranscodeStreamResource(boost::filesystem::path p, Av::TranscodeParameters parameters, Wt::WObject *parent)
|
||||||
: Wt::WResource(parent),
|
: Wt::WResource(parent),
|
||||||
_parameters( parameters )
|
_filePath(p),
|
||||||
|
_parameters( parameters )
|
||||||
{
|
{
|
||||||
LMS_LOG(MOD_UI, SEV_DEBUG) << "CONSTRUCTING RESOURCE";
|
LMS_LOG(MOD_UI, SEV_DEBUG) << "CONSTRUCTING RESOURCE";
|
||||||
}
|
}
|
||||||
@@ -49,17 +50,23 @@ AvConvTranscodeStreamResource::handleRequest(const Wt::Http::Request& request,
|
|||||||
|
|
||||||
LMS_LOG(MOD_UI, SEV_DEBUG) << "Handling new request. Continuation = " << continuation;
|
LMS_LOG(MOD_UI, SEV_DEBUG) << "Handling new request. Continuation = " << continuation;
|
||||||
|
|
||||||
std::shared_ptr<Transcode::AvConvTranscoder> transcoder;
|
std::shared_ptr<Av::Transcoder> transcoder;
|
||||||
if (continuation)
|
if (continuation)
|
||||||
transcoder = boost::any_cast<std::shared_ptr<Transcode::AvConvTranscoder> >(continuation->data());
|
transcoder = boost::any_cast<std::shared_ptr<Av::Transcoder> >(continuation->data());
|
||||||
|
|
||||||
if (!transcoder)
|
if (!transcoder)
|
||||||
{
|
{
|
||||||
LMS_LOG(MOD_UI, SEV_DEBUG) << "Launching transcoder";
|
LMS_LOG(MOD_UI, SEV_DEBUG) << "Launching transcoder";
|
||||||
transcoder = std::make_shared<Transcode::AvConvTranscoder>( _parameters);
|
transcoder = std::make_shared<Av::Transcoder>( _filePath, _parameters);
|
||||||
|
|
||||||
LMS_LOG(MOD_UI, SEV_DEBUG) << "Mime type set to '" << _parameters.getOutputFormat().getMimeType() << "'";
|
LMS_LOG(MOD_UI, SEV_DEBUG) << "Mime type set to '" << Av::encoding_to_mimetype(_parameters.getEncoding());
|
||||||
response.setMimeType(_parameters.getOutputFormat().getMimeType());
|
response.setMimeType( Av::encoding_to_mimetype(_parameters.getEncoding()) );
|
||||||
|
|
||||||
|
if (!transcoder->start())
|
||||||
|
{
|
||||||
|
LMS_LOG(MOD_UI, SEV_ERROR) << "Cannot start transcoder";
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!transcoder->isComplete())
|
if (!transcoder->isComplete())
|
||||||
@@ -72,7 +79,7 @@ AvConvTranscodeStreamResource::handleRequest(const Wt::Http::Request& request,
|
|||||||
// Give the client all the output data
|
// Give the client all the output data
|
||||||
response.out().write(reinterpret_cast<char*>(&data[0]), data.size());
|
response.out().write(reinterpret_cast<char*>(&data[0]), data.size());
|
||||||
|
|
||||||
LMS_LOG(MOD_UI, SEV_DEBUG) << "Written " << data.size() << " bytes! complete = " << std::boolalpha << transcoder->isComplete() << ", produced bytes = " << transcoder->getOutputBytes();
|
LMS_LOG(MOD_UI, SEV_DEBUG) << "Written " << data.size() << " bytes! complete = " << std::boolalpha << transcoder->isComplete();
|
||||||
|
|
||||||
if (!response.out())
|
if (!response.out())
|
||||||
LMS_LOG(MOD_UI, SEV_ERROR) << "Write failed!";
|
LMS_LOG(MOD_UI, SEV_ERROR) << "Write failed!";
|
||||||
|
|||||||
@@ -25,23 +25,22 @@
|
|||||||
|
|
||||||
#include <Wt/WResource>
|
#include <Wt/WResource>
|
||||||
|
|
||||||
#include "transcode/AvConvTranscoder.hpp"
|
#include "av/AvTranscoder.hpp"
|
||||||
#include "transcode/Parameters.hpp"
|
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|
||||||
class AvConvTranscodeStreamResource : public Wt::WResource
|
class AvConvTranscodeStreamResource : public Wt::WResource
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
AvConvTranscodeStreamResource(const Transcode::Parameters& parameters, Wt::WObject *parent = 0);
|
AvConvTranscodeStreamResource(boost::filesystem::path p, Av::TranscodeParameters parameters, Wt::WObject *parent = 0);
|
||||||
~AvConvTranscodeStreamResource();
|
~AvConvTranscodeStreamResource();
|
||||||
|
|
||||||
void handleRequest(const Wt::Http::Request& request,
|
void handleRequest(const Wt::Http::Request& request,
|
||||||
Wt::Http::Response& response);
|
Wt::Http::Response& response);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Transcode::Parameters _parameters;
|
boost::filesystem::path _filePath;
|
||||||
std::shared_ptr<Transcode::AvConvTranscoder> _transcoder;
|
Av::TranscodeParameters _parameters;
|
||||||
|
|
||||||
static const std::size_t _bufferSize = 8192*16;
|
static const std::size_t _bufferSize = 8192*16;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -29,25 +29,25 @@
|
|||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
|
|
||||||
Wt::WMediaPlayer::Encoding
|
Wt::WMediaPlayer::Encoding
|
||||||
convert(Transcode::Format format)
|
AvEncoding_to_WtEncoding(Av::Encoding encoding)
|
||||||
{
|
{
|
||||||
switch( format.getEncoding() )
|
switch( encoding )
|
||||||
{
|
{
|
||||||
case Transcode::Format::OGA: return Wt::WMediaPlayer::OGA;
|
case Av::Encoding::OGA: return Wt::WMediaPlayer::OGA;
|
||||||
case Transcode::Format::OGV: return Wt::WMediaPlayer::OGV;
|
case Av::Encoding::OGV: return Wt::WMediaPlayer::OGV;
|
||||||
case Transcode::Format::MP3: return Wt::WMediaPlayer::MP3;
|
case Av::Encoding::MP3: return Wt::WMediaPlayer::MP3;
|
||||||
case Transcode::Format::WEBMA: return Wt::WMediaPlayer::WEBMA;
|
case Av::Encoding::WEBMA: return Wt::WMediaPlayer::WEBMA;
|
||||||
case Transcode::Format::WEBMV: return Wt::WMediaPlayer::WEBMV;
|
case Av::Encoding::WEBMV: return Wt::WMediaPlayer::WEBMV;
|
||||||
case Transcode::Format::FLA: return Wt::WMediaPlayer::FLA;
|
case Av::Encoding::FLA: return Wt::WMediaPlayer::FLA;
|
||||||
case Transcode::Format::FLV: return Wt::WMediaPlayer::FLV;
|
case Av::Encoding::FLV: return Wt::WMediaPlayer::FLV;
|
||||||
case Transcode::Format::M4A: return Wt::WMediaPlayer::M4A;
|
case Av::Encoding::M4A: return Wt::WMediaPlayer::M4A;
|
||||||
case Transcode::Format::M4V: return Wt::WMediaPlayer::M4V;
|
case Av::Encoding::M4V: return Wt::WMediaPlayer::M4V;
|
||||||
}
|
}
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
VideoMediaPlayerWidget::VideoMediaPlayerWidget( const Transcode::Parameters& parameters, Wt::WContainerWidget *parent)
|
VideoMediaPlayerWidget::VideoMediaPlayerWidget( Av::TranscodeParameters parameters, Wt::WContainerWidget *parent)
|
||||||
: Wt::WContainerWidget(parent),
|
: Wt::WContainerWidget(parent),
|
||||||
_mediaResource(nullptr),
|
_mediaResource(nullptr),
|
||||||
_currentParameters(parameters),
|
_currentParameters(parameters),
|
||||||
@@ -106,7 +106,7 @@ VideoMediaPlayerWidget::VideoMediaPlayerWidget( const Transcode::Parameters& par
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
VideoMediaPlayerWidget::load(const Transcode::Parameters& parameters)
|
VideoMediaPlayerWidget::load(Av::TranscodeParameters parameters)
|
||||||
{
|
{
|
||||||
_mediaPlayer->clearSources();
|
_mediaPlayer->clearSources();
|
||||||
|
|
||||||
@@ -116,15 +116,15 @@ VideoMediaPlayerWidget::load(const Transcode::Parameters& parameters)
|
|||||||
if (_mediaResource)
|
if (_mediaResource)
|
||||||
delete _mediaResource;
|
delete _mediaResource;
|
||||||
|
|
||||||
_mediaResource = new AvConvTranscodeStreamResource( parameters, this );
|
// TODO _mediaResource = new AvConvTranscodeStreamResource( parameters, this );
|
||||||
_mediaInternalLink.setResource( _mediaResource );
|
_mediaInternalLink.setResource( _mediaResource );
|
||||||
|
|
||||||
_mediaPlayer->addSource( convert(parameters.getOutputFormat()), _mediaInternalLink );
|
_mediaPlayer->addSource( AvEncoding_to_WtEncoding(parameters.getEncoding()), _mediaInternalLink );
|
||||||
|
|
||||||
_timeSlider->setRange(0, parameters.getInputMediaFile().getDuration().total_seconds() );
|
_timeSlider->setRange(0, 0/* TODO parameters.getInputMediaFile().getDuration().total_seconds()*/ );
|
||||||
_timeSlider->setValue( parameters.getOffset().total_seconds() );
|
_timeSlider->setValue( parameters.getOffset().total_seconds() );
|
||||||
|
|
||||||
_duration->setText( boost::posix_time::to_simple_string( parameters.getInputMediaFile().getDuration() ));
|
// TODO _duration->setText( boost::posix_time::to_simple_string( parameters.getInputMediaFile().getDuration() ));
|
||||||
|
|
||||||
_mediaPlayer->play();
|
_mediaPlayer->play();
|
||||||
}
|
}
|
||||||
@@ -151,6 +151,7 @@ VideoMediaPlayerWidget::handleTimeUpdated(void)
|
|||||||
{
|
{
|
||||||
std::cout << "Time updated to " << _mediaPlayer->currentTime() << std::endl;
|
std::cout << "Time updated to " << _mediaPlayer->currentTime() << std::endl;
|
||||||
|
|
||||||
|
/* TODO
|
||||||
if (_mediaPlayer->currentTime() > 0 && _mediaPlayer->currentTime() < _currentParameters.getInputMediaFile().getDuration().total_seconds())
|
if (_mediaPlayer->currentTime() > 0 && _mediaPlayer->currentTime() < _currentParameters.getInputMediaFile().getDuration().total_seconds())
|
||||||
{
|
{
|
||||||
boost::posix_time::time_duration currentTime ( boost::posix_time::seconds( _mediaPlayer->currentTime() + _currentParameters.getOffset().total_seconds()));
|
boost::posix_time::time_duration currentTime ( boost::posix_time::seconds( _mediaPlayer->currentTime() + _currentParameters.getOffset().total_seconds()));
|
||||||
@@ -158,6 +159,7 @@ VideoMediaPlayerWidget::handleTimeUpdated(void)
|
|||||||
_timeSlider->setValue( currentTime.total_seconds() );
|
_timeSlider->setValue( currentTime.total_seconds() );
|
||||||
_curTime->setText( boost::posix_time::to_simple_string( currentTime) );
|
_curTime->setText( boost::posix_time::to_simple_string( currentTime) );
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -176,12 +178,12 @@ void
|
|||||||
VideoMediaPlayerWidget::handleParametersEdit(void)
|
VideoMediaPlayerWidget::handleParametersEdit(void)
|
||||||
{
|
{
|
||||||
|
|
||||||
_dialog = new VideoParametersDialog("Parameters");
|
// _dialog = new VideoParametersDialog("Parameters");
|
||||||
_dialog->load(_currentParameters);
|
//TODO _dialog->load(_currentParameters);
|
||||||
|
|
||||||
_dialog->show();
|
// _dialog->show();
|
||||||
|
|
||||||
_dialog->finished().connect(this, &VideoMediaPlayerWidget::handleParametersDone);
|
// _dialog->finished().connect(this, &VideoMediaPlayerWidget::handleParametersDone);
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@@ -191,7 +193,7 @@ VideoMediaPlayerWidget::handleParametersDone(Wt::WDialog::DialogCode code)
|
|||||||
|
|
||||||
if (code == Wt::WDialog::Accepted)
|
if (code == Wt::WDialog::Accepted)
|
||||||
{
|
{
|
||||||
_dialog->save( _currentParameters );
|
// TODO _dialog->save( _currentParameters );
|
||||||
|
|
||||||
// TODO SYNC current offset with player?
|
// TODO SYNC current offset with player?
|
||||||
// HACK use slider current value
|
// HACK use slider current value
|
||||||
|
|||||||
@@ -28,7 +28,7 @@
|
|||||||
|
|
||||||
#include "VideoParametersDialog.hpp"
|
#include "VideoParametersDialog.hpp"
|
||||||
|
|
||||||
#include "transcode/Parameters.hpp"
|
#include "av/AvTranscoder.hpp"
|
||||||
#include "resource/AvConvTranscodeStreamResource.hpp"
|
#include "resource/AvConvTranscodeStreamResource.hpp"
|
||||||
|
|
||||||
namespace UserInterface {
|
namespace UserInterface {
|
||||||
@@ -37,18 +37,16 @@ class VideoMediaPlayerWidget : public Wt::WContainerWidget
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
VideoMediaPlayerWidget( const Transcode::Parameters& parameters, Wt::WContainerWidget *parent = 0);
|
VideoMediaPlayerWidget( Av::TranscodeParameters parameters, Wt::WContainerWidget *parent = 0);
|
||||||
|
|
||||||
|
|
||||||
Wt::Signal<void>& close() { return _close; };
|
Wt::Signal<void>& close() { return _close; };
|
||||||
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
// Signals
|
// Signals
|
||||||
Wt::Signal<void> _close;
|
Wt::Signal<void> _close;
|
||||||
|
|
||||||
void load(const Transcode::Parameters& parameters);
|
void load(Av::TranscodeParameters parameters);
|
||||||
|
|
||||||
// Player controls
|
// Player controls
|
||||||
void handlePlayOffset(int offsetSecs);
|
void handlePlayOffset(int offsetSecs);
|
||||||
@@ -68,7 +66,7 @@ class VideoMediaPlayerWidget : public Wt::WContainerWidget
|
|||||||
Wt::WLink _mediaInternalLink;
|
Wt::WLink _mediaInternalLink;
|
||||||
|
|
||||||
// Controls
|
// Controls
|
||||||
Transcode::Parameters _currentParameters;
|
Av::TranscodeParameters _currentParameters;
|
||||||
Wt::WPushButton* _playBtn;
|
Wt::WPushButton* _playBtn;
|
||||||
Wt::WPushButton* _pauseBtn;
|
Wt::WPushButton* _pauseBtn;
|
||||||
Wt::WSlider* _timeSlider;
|
Wt::WSlider* _timeSlider;
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ VideoParametersDialog::VideoParametersDialog(const Wt::WString &windowTitle, Wt:
|
|||||||
|
|
||||||
_outputFormatModel = new Wt::WStringListModel(_outputFormat);
|
_outputFormatModel = new Wt::WStringListModel(_outputFormat);
|
||||||
|
|
||||||
std::vector<Format> formats = Format::get( Format::Video );
|
std::vector<Format> formats ; // TODO Format::get( Format::Video );
|
||||||
|
|
||||||
for(std::size_t idFormat = 0; idFormat < formats.size(); ++idFormat)
|
for(std::size_t idFormat = 0; idFormat < formats.size(); ++idFormat)
|
||||||
{
|
{
|
||||||
@@ -154,7 +154,7 @@ VideoParametersDialog::load(const Transcode::Parameters& parameters)
|
|||||||
Wt::WComboBox* combo = _streamSelection[streamType].first;
|
Wt::WComboBox* combo = _streamSelection[streamType].first;
|
||||||
Wt::WStringListModel* model = _streamSelection[streamType].second;
|
Wt::WStringListModel* model = _streamSelection[streamType].second;
|
||||||
|
|
||||||
addStreams(model, parameters.getInputMediaFile().getStreams( streamType ) );
|
// TODO addStreams(model, parameters.getInputMediaFile().getStreams( streamType ) );
|
||||||
|
|
||||||
selectStream(model, streamMap[streamType], combo);
|
selectStream(model, streamMap[streamType], combo);
|
||||||
}
|
}
|
||||||
@@ -168,7 +168,7 @@ VideoParametersDialog::save(Transcode::Parameters& parameters)
|
|||||||
|
|
||||||
// Get encoder used
|
// Get encoder used
|
||||||
Format::Encoding encoding = boost::any_cast<Format::Encoding>( _outputFormatModel->data(_outputFormatModel->index(_outputFormat->currentIndex(), 0), Wt::UserRole));
|
Format::Encoding encoding = boost::any_cast<Format::Encoding>( _outputFormatModel->data(_outputFormatModel->index(_outputFormat->currentIndex(), 0), Wt::UserRole));
|
||||||
parameters.setOutputFormat( Format::get(encoding) );
|
// TODO parameters.setOutputFormat( Format::get(encoding) );
|
||||||
|
|
||||||
// Get stream selected, if any
|
// Get stream selected, if any
|
||||||
BOOST_FOREACH(Stream::Type streamType, streamTypes)
|
BOOST_FOREACH(Stream::Type streamType, streamTypes)
|
||||||
|
|||||||
@@ -17,8 +17,7 @@
|
|||||||
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
* along with LMS. If not, see <http://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#ifndef VIDEO_PARAMETER_DIALOG
|
#pragma once
|
||||||
#define VIDEO_PARAMETER_DIALOG
|
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
@@ -66,5 +65,3 @@ class VideoParametersDialog : public Wt::WDialog
|
|||||||
|
|
||||||
} // namespace UserInterface
|
} // namespace UserInterface
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|||||||
@@ -52,6 +52,7 @@ VideoWidget::playVideo(boost::filesystem::path p)
|
|||||||
LMS_LOG(MOD_UI, SEV_DEBUG) << "Want to play video " << p << "'";
|
LMS_LOG(MOD_UI, SEV_DEBUG) << "Want to play video " << p << "'";
|
||||||
try {
|
try {
|
||||||
|
|
||||||
|
#if 0
|
||||||
std::size_t audioBitrate = 0;
|
std::size_t audioBitrate = 0;
|
||||||
std::size_t videoBitrate = 0;
|
std::size_t videoBitrate = 0;
|
||||||
|
|
||||||
@@ -89,6 +90,7 @@ VideoWidget::playVideo(boost::filesystem::path p)
|
|||||||
}));
|
}));
|
||||||
|
|
||||||
_videoDbWidget->setHidden(true);
|
_videoDbWidget->setHidden(true);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
catch( std::exception& e) {
|
catch( std::exception& e) {
|
||||||
LMS_LOG(MOD_UI, SEV_ERROR) << "Caught exception while loading '" << p << "': " << e.what();
|
LMS_LOG(MOD_UI, SEV_ERROR) << "Caught exception while loading '" << p << "': " << e.what();
|
||||||
|
|||||||
Reference in New Issue
Block a user