Made the player work, first WIP version

This commit is contained in:
emeric
2018-03-21 22:26:57 +01:00
parent d87731c09e
commit 4683a9ef1e
21 changed files with 200 additions and 362 deletions
+99 -115
View File
@@ -41,15 +41,13 @@ TranscodeResource:: ~TranscodeResource()
}
std::string
TranscodeResource::getUrl(Database::Track::id_type trackId, Av::Encoding encoding, std::size_t offset, std::vector<std::size_t> streamIds) const
TranscodeResource::getUrl(Database::Track::id_type trackId, Av::Encoding encoding, boost::posix_time::time_duration offset, boost::optional<std::size_t> streamId) const
{
std::string res = url()+ "&trackid=" + std::to_string(trackId) + "&encoding=" + std::to_string(Av::encoding_to_int(encoding));
if (!streamIds.empty())
{
for (std::size_t streamId : streamIds)
res += "&stream=" + std::to_string(streamId);
}
res += "&offset=" + std::to_string(offset);
if (streamId)
res += "&stream=" + std::to_string(*streamId);
res += "&offset=" + std::to_string(offset.seconds());
return res;
}
@@ -57,121 +55,107 @@ void
TranscodeResource::handleRequest(const Wt::Http::Request& request,
Wt::Http::Response& response)
{
// Retrieve parameters
const std::string *trackIdStr = request.getParameter("trackid");
const std::string *offsetStr = request.getParameter("offset");
const std::string *encodingStr = request.getParameter("encoding");
std::vector<std::string> streams = request.getParameterValues ("stream");
std::shared_ptr<Av::Transcoder> transcoder;
LMS_LOG(UI, DEBUG) << "Handling new request...";
try
// First, see if this request is for a continuation
Wt::Http::ResponseContinuation *continuation = request.continuation();
if (continuation)
{
std::shared_ptr<Av::Transcoder> transcoder;
// First, see if this request is for a continuation
Wt::Http::ResponseContinuation *continuation = request.continuation();
if (continuation)
{
LMS_LOG(UI, DEBUG) << "Continuation! " << continuation ;
transcoder = boost::any_cast<std::shared_ptr<Av::Transcoder> >(continuation->data());
if (!transcoder)
{
LMS_LOG(UI, ERROR) << "No transcoder set -> abort!";
return;
}
}
else
{
LMS_LOG(UI, DEBUG) << "No continuation yet";
if (!trackIdStr
|| !offsetStr
|| !encodingStr)
{
LMS_LOG(UI, ERROR) << "Missing transcode parameter";
return;
}
Database::Track::id_type trackId = std::stol(*trackIdStr);
// transactions are not thread safe
{
Wt::WApplication::UpdateLock lock(LmsApplication::instance());
Wt::Dbo::Transaction transaction(_db.getSession());
Database::User::pointer user = _db.getCurrentUser();
Database::Track::pointer track = Database::Track::getById(_db.getSession(), trackId);
if (!track)
{
LMS_LOG(UI, ERROR) << "Missing track";
return;
}
if (!user)
{
LMS_LOG(UI, ERROR) << "Missing user";
return;
}
Av::TranscodeParameters parameters;
parameters.setOffset(boost::posix_time::seconds(std::stol(*offsetStr)));
parameters.setEncoding(Av::encoding_from_int(std::stol(*encodingStr)));
parameters.setBitrate(Av::Stream::Type::Audio, user->getAudioBitrate() );
for (std::string strStream: streams)
{
LMS_LOG(UI, DEBUG) << "Added stream " << std::stol(strStream);
parameters.addStream(std::stol(strStream));
}
LMS_LOG(UI, DEBUG) << "Offset set to " << parameters.getOffset();
transcoder = std::make_shared<Av::Transcoder>(track->getPath(), parameters);
}
std::string mimeType = Av::encoding_to_mimetype(transcoder->getParameters().getEncoding());
LMS_LOG(UI, DEBUG) << "Mime type set to '" << mimeType << "'";
response.setMimeType(mimeType);
if (!transcoder->start())
{
LMS_LOG(UI, ERROR) << "Cannot start transcoder";
return;
}
LMS_LOG(UI, DEBUG) << "Transcoder started";
}
if (!transcoder->isComplete())
{
std::vector<unsigned char> data;
data.reserve(_chunkSize);
transcoder->process(data, _chunkSize);
response.out().write(reinterpret_cast<char*>(&data[0]), data.size());
LMS_LOG(UI, DEBUG) << "Written " << data.size() << " bytes! complete = " << std::boolalpha << transcoder->isComplete();
if (!response.out())
{
LMS_LOG(UI, ERROR) << "Write failed!";
}
}
if (!transcoder->isComplete() && response.out()) {
continuation = response.createContinuation();
continuation->setData(transcoder);
}
else
LMS_LOG(UI, DEBUG) << "No more data!";
LMS_LOG(UI, DEBUG) << "Continuation! " << continuation ;
transcoder = boost::any_cast<std::shared_ptr<Av::Transcoder>>(continuation->data());
}
catch (std::invalid_argument& e)
else
{
LMS_LOG(UI, ERROR) << "Invalid argument: " << e.what();
Database::Track::id_type trackId;
Av::TranscodeParameters parameters;
LMS_LOG(UI, DEBUG) << "No continuation yet";
try
{
auto trackIdStr = request.getParameter("trackid");
if (!trackIdStr)
{
LMS_LOG(UI, ERROR) << "Missing trackid transcode parameter!";
return;
}
trackId = std::stol(*request.getParameter("trackid"));
auto offsetStr = request.getParameter("offset");
if (offsetStr)
parameters.offset = boost::posix_time::seconds(std::stol(*offsetStr));
auto encodingStr = request.getParameter("encoding");
if (encodingStr)
parameters.encoding = Av::encoding_from_int(std::stol(*encodingStr));
auto streamStr = request.getParameter("stream");
if (streamStr)
parameters.stream = std::stol(*streamStr);
}
catch (std::exception &e)
{
LMS_LOG(UI, ERROR) << "Exception while handling URL parameters: " << e.what();
return;
}
// transactions are not thread safe
{
Wt::WApplication::UpdateLock lock(LmsApplication::instance());
Wt::Dbo::Transaction transaction(_db.getSession());
Database::User::pointer user = _db.getCurrentUser();
Database::Track::pointer track = Database::Track::getById(_db.getSession(), trackId);
if (!track)
{
LMS_LOG(UI, ERROR) << "Missing track";
return;
}
parameters.bitrate = user->getAudioBitrate();
transcoder = std::make_shared<Av::Transcoder>(track->getPath(), parameters);
}
std::string mimeType = Av::encoding_to_mimetype(transcoder->getParameters().encoding);
LMS_LOG(UI, DEBUG) << "Mime type set to '" << mimeType << "'";
response.setMimeType(mimeType);
if (!transcoder->start())
{
LMS_LOG(UI, ERROR) << "Cannot start transcoder";
return;
}
LMS_LOG(UI, DEBUG) << "Transcoder started";
}
if (!transcoder->isComplete())
{
std::vector<unsigned char> data;
data.reserve(_chunkSize);
transcoder->process(data, _chunkSize);
response.out().write(reinterpret_cast<char*>(&data[0]), data.size());
LMS_LOG(UI, DEBUG) << "Written " << data.size() << " bytes! complete = " << std::boolalpha << transcoder->isComplete();
if (!response.out())
{
LMS_LOG(UI, ERROR) << "Write failed!";
}
}
if (!transcoder->isComplete() && response.out())
{
continuation = response.createContinuation();
continuation->setData(transcoder);
}
else
LMS_LOG(UI, DEBUG) << "No more data!";
}
} // namespace UserInterface