177 lines
4.6 KiB
C++
177 lines
4.6 KiB
C++
#include "MediaRequestHandler.hpp"
|
|
|
|
#include "database/AudioTypes.hpp"
|
|
|
|
namespace Remote {
|
|
namespace Server {
|
|
|
|
MediaRequestHandler::MediaRequestHandler(Database::Handler& db)
|
|
: _db(db)
|
|
{}
|
|
|
|
bool
|
|
MediaRequestHandler::process(const MediaRequest& request, MediaResponse& response)
|
|
{
|
|
|
|
bool res = false;
|
|
|
|
switch (request.type())
|
|
{
|
|
case MediaRequest::TypeMediaPrepare:
|
|
if (request.has_prepare())
|
|
{
|
|
if (request.prepare().has_audio())
|
|
res = processAudioPrepare(request.prepare().audio(), response);
|
|
else if (request.prepare().has_video())
|
|
;// TODO;
|
|
else
|
|
std::cerr << "Bad MediaRequest::TypeMediaPrepare!" << std::endl;
|
|
|
|
}
|
|
else
|
|
std::cerr << "Bad MediaRequest::TypeMediaPrepare!" << std::endl;
|
|
break;
|
|
|
|
case MediaRequest::TypeMediaGetPart:
|
|
if (request.has_get_part())
|
|
res = processGetPart(request.get_part(), response);
|
|
else
|
|
std::cerr << "Bad MediaRequest::TypeMediaGet!" << std::endl;
|
|
break;
|
|
|
|
case MediaRequest::TypeMediaTerminate:
|
|
if (request.has_terminate())
|
|
res = processTerminate(request.terminate(), response);
|
|
else
|
|
std::cerr << "Bad MediaRequest::TypeMediaTerminate!" << std::endl;
|
|
break;
|
|
|
|
default:
|
|
std::cerr << "Unhandled MediaRequest type = " << request.type() << std::endl;
|
|
}
|
|
|
|
return res;
|
|
}
|
|
|
|
bool
|
|
MediaRequestHandler::processAudioPrepare(const MediaRequest::Prepare::Audio& request, MediaResponse& response)
|
|
{
|
|
// TODO, get user default values
|
|
Transcode::Format::Encoding format = Transcode::Format::OGA;
|
|
std::size_t bitrate = 128000;
|
|
|
|
if (request.has_codec_type())
|
|
{
|
|
switch( request.codec_type())
|
|
{
|
|
case AudioCodecType::CodecTypeOGA:
|
|
format = Transcode::Format::OGA;
|
|
break;
|
|
default:
|
|
std::cerr << "Unhandled codec type = " << request.codec_type() << std::endl;
|
|
return false;
|
|
}
|
|
}
|
|
if (request.has_bitrate())
|
|
bitrate = request.bitrate();
|
|
|
|
if (_transcoder)
|
|
{
|
|
response.mutable_error()->set_error(true);
|
|
response.mutable_error()->set_message("Transcode already in progress");
|
|
response.set_type(MediaResponse::TypeError);
|
|
return true;
|
|
}
|
|
|
|
Wt::Dbo::Transaction transaction( _db.getSession());
|
|
|
|
Database::Track::pointer track = Database::Track::getById( _db.getSession(), request.track_id() );
|
|
|
|
if (!track)
|
|
{
|
|
response.mutable_error()->set_error(true);
|
|
response.mutable_error()->set_message("Cannot find requested track!");
|
|
response.set_type(MediaResponse::TypeError);
|
|
return true;
|
|
}
|
|
|
|
try
|
|
{
|
|
Transcode::InputMediaFile inputFile(track->getPath());
|
|
Transcode::Parameters parameters(inputFile, Transcode::Format::get( format ), bitrate);
|
|
|
|
_transcoder = std::make_shared<Transcode::AvConvTranscoder>( parameters );
|
|
|
|
response.mutable_error()->set_error(false);
|
|
response.mutable_error()->set_message("");
|
|
response.set_type(MediaResponse::TypeError);
|
|
}
|
|
catch(std::exception& e)
|
|
{
|
|
std::cerr << "Caught exception: " << e.what() << std::endl;
|
|
response.mutable_error()->set_error(true);
|
|
response.mutable_error()->set_message("exception: " + std::string(e.what()));
|
|
response.set_type(MediaResponse::TypeError);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool
|
|
MediaRequestHandler::processGetPart(const MediaRequest::GetPart& request, MediaResponse& response)
|
|
{
|
|
std::size_t dataSize = request.requested_data_size();
|
|
if (dataSize > _maxPartSize)
|
|
dataSize = _maxPartSize;
|
|
|
|
if (!_transcoder)
|
|
{
|
|
response.mutable_error()->set_error(true);
|
|
response.mutable_error()->set_message("No transcoder set!");
|
|
response.set_type(MediaResponse::TypeError);
|
|
return true;
|
|
}
|
|
|
|
while (!_transcoder->isComplete() && _transcoder->getOutputData().size() < dataSize)
|
|
_transcoder->process();
|
|
|
|
std::cout << "MediaRequestHandler::processGetPart, isComplete = " << std::boolalpha << _transcoder->isComplete() << ", size = " << _transcoder->getOutputData().size() << std::endl;
|
|
|
|
Transcode::AvConvTranscoder::data_type::iterator itEnd;
|
|
if (_transcoder->getOutputData().size() > dataSize)
|
|
itEnd = _transcoder->getOutputData().begin() + dataSize;
|
|
else
|
|
itEnd = _transcoder->getOutputData().end();
|
|
|
|
response.set_type(MediaResponse::TypePart);
|
|
std::copy(_transcoder->getOutputData().begin(), itEnd, std::back_inserter(*response.mutable_part()->mutable_data()));
|
|
|
|
// Consume sent bytes
|
|
_transcoder->getOutputData().erase(_transcoder->getOutputData().begin(), itEnd);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
bool
|
|
MediaRequestHandler::processTerminate(const MediaRequest::Terminate& /*request*/, MediaResponse& response)
|
|
{
|
|
std::cout << "MediaRequestHandler: resetting transcoder" << std::endl;
|
|
_transcoder.reset();
|
|
|
|
assert(!_transcoder);
|
|
|
|
response.mutable_error()->set_error(false);
|
|
response.mutable_error()->set_message("");
|
|
response.set_type(MediaResponse::TypeError);
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
|
|
} // namespace Remote
|
|
} // namespace Server
|
|
|
|
|