summaryrefslogtreecommitdiff
path: root/hlsPlayer.cpp
diff options
context:
space:
mode:
authorchriszero <zerov83@gmail.com>2015-01-28 21:17:18 +0100
committerchriszero <zerov83@gmail.com>2015-01-28 21:17:18 +0100
commit87eb8a9e931606da4197391b6e3a09376b1383c2 (patch)
tree9427c28a2d7e9e44d4d77dc7fe53ff91f5152e23 /hlsPlayer.cpp
parent1da4dbe662e75be47e046472137c6bd72daa7b4d (diff)
downloadvdr-plugin-plex-87eb8a9e931606da4197391b6e3a09376b1383c2.tar.gz
vdr-plugin-plex-87eb8a9e931606da4197391b6e3a09376b1383c2.tar.bz2
- Counting played time correctly
- Implemented switching audiostreams - Removed some compile warnings
Diffstat (limited to 'hlsPlayer.cpp')
-rw-r--r--hlsPlayer.cpp134
1 files changed, 114 insertions, 20 deletions
diff --git a/hlsPlayer.cpp b/hlsPlayer.cpp
index 3f90750..9245efb 100644
--- a/hlsPlayer.cpp
+++ b/hlsPlayer.cpp
@@ -1,5 +1,6 @@
#include "hlsPlayer.h"
+#include <sys/time.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>
#include <Poco/Exception.h>
@@ -8,6 +9,9 @@
#include <pcrecpp.h>
#include "Plexservice.h"
+#include "XmlObject.h"
+#include "Media.h"
+#include "Stream.h"
static cMutex hlsMutex;
@@ -18,7 +22,7 @@ cHlsSegmentLoader::cHlsSegmentLoader(std::string startm3u8)
m_newList = false;
m_bufferFilled = false;
m_lastLoadedSegment = 0;
- m_segmentsToBuffer = 3;
+ m_segmentsToBuffer = 2;
m_pBuffer = new uchar[8192];
// Initialize members
@@ -54,9 +58,9 @@ void cHlsSegmentLoader::Action(void)
if(!LoadLists()) return;
int estSize = EstimateSegmentSize();
- m_ringBufferSize = MEGABYTE(estSize*3);
+ m_ringBufferSize = MEGABYTE(estSize*m_segmentsToBuffer);
- isyslog("[plex]%s Create Ringbuffer %d MB", __FUNCTION__, estSize*3);
+ isyslog("[plex]%s Create Ringbuffer %d MB", __FUNCTION__, estSize*m_segmentsToBuffer);
m_pRingbuffer = new cRingBufferLinear(m_ringBufferSize, 2*TS_SIZE);
@@ -128,9 +132,9 @@ bool cHlsSegmentLoader::LoadIndexList(void)
m_segmentUriPart = path.substr(0, path.find_last_of("/")+1);
}
if(m_indexParser.TargetDuration > 3) {
- m_segmentsToBuffer = 1;
- } else {
m_segmentsToBuffer = 2;
+ } else {
+ m_segmentsToBuffer = 3;
}
}
return res;
@@ -174,7 +178,11 @@ int cHlsSegmentLoader::EstimateSegmentSize()
int len = m_indexParser.TargetDuration;
double estSize = (bandw) * len;
- estSize = max(estSize, 1.0); // default
+ estSize = max(estSize, 1.0);
+ // default
+ if(estSize <= 1) {
+ estSize = 32;
+ }
return ceil(estSize);
}
@@ -322,8 +330,11 @@ cHlsPlayer::cHlsPlayer(std::string startm3u8, plexclient::Video* Video)
m_pSegmentLoader = new cHlsSegmentLoader(startm3u8);
m_pVideo = Video;
m_timeOffset = 0;
+ m_jumpOffset = 0;
+ m_tTimeSum = 0;
m_doJump = false;
m_isBuffering = false;
+ AudioIndexOffset = 1000; // Just a magic number
}
cHlsPlayer::~cHlsPlayer()
@@ -332,6 +343,21 @@ cHlsPlayer::~cHlsPlayer()
m_pSegmentLoader = NULL;
}
+void cHlsPlayer::SetAudioAndSubtitleTracks(void)
+{
+ //DeviceClrAvailableTracks();
+ DeviceSetAvailableTrack(ttDolby, 0, 0, "Current");
+ if(m_pVideo->m_Media.m_vStreams.size() > 0) {
+ std::vector<plexclient::Stream> streams = m_pVideo->m_Media.m_vStreams;
+ for(std::vector<plexclient::Stream>::iterator it = streams.begin(); it != streams.end(); ++it) {
+ plexclient::Stream *pStream = &(*it);
+ if(pStream->m_eStreamType == plexclient::sAUDIO) {
+ DeviceSetAvailableTrack(ttDolby, pStream->m_iIndex, pStream->m_iIndex + AudioIndexOffset, pStream->m_sLanguage.c_str(), pStream->m_sCodec.c_str());
+ }
+ }
+ }
+}
+
void cHlsPlayer::Action(void)
{
@@ -344,12 +370,21 @@ void cHlsPlayer::Action(void)
DeviceFreeze();
m_doJump = false;
+ m_bFirstPlay = true;
std::string uri = plexclient::Plexservice::GetUniversalTranscodeUrl(m_pVideo, m_jumpOffset);
m_pSegmentLoader->LoadM3u8(uri);
+ m_timeOffset = m_jumpOffset;
DeviceClear();
DevicePlay();
+ playMode = pmPlay;
} else if(m_pSegmentLoader && m_pSegmentLoader->BufferFilled()) {
DoPlay();
+ if(m_bFirstPlay) {
+ SetAudioAndSubtitleTracks();
+ ResetPlayedSeconds();
+ m_bFirstPlay = false;
+ }
+ CountPlayedSeconds();
} else {
// Pause
cCondWait::SleepMs(3);
@@ -359,6 +394,7 @@ void cHlsPlayer::Action(void)
bool cHlsPlayer::DoPlay(void)
{
+ bool res = false;
cPoller Poller;
if(DevicePoll(Poller, 10)) {
hlsMutex.Lock();
@@ -372,6 +408,7 @@ bool cHlsPlayer::DoPlay(void)
if(bytesAvaliable >= TS_SIZE) {
int playedBytes = PlayTs(toPlay, TS_SIZE, false);
m_pSegmentLoader->m_pRingbuffer->Del(playedBytes);
+ res = true;
} else {
// Pause & Buffer
break;
@@ -379,7 +416,7 @@ bool cHlsPlayer::DoPlay(void)
}
hlsMutex.Unlock();
}
- return true;
+ return res;
}
void cHlsPlayer::Activate(bool On)
@@ -391,12 +428,10 @@ void cHlsPlayer::Activate(bool On)
}
}
-bool cHlsPlayer::GetIndex(int& Current, int& Total, bool SnapToIFrame)
+bool cHlsPlayer::GetIndex(int& Current, int& Total, bool SnapToIFrame __attribute__((unused)))
{
- long stc = DeviceGetSTC();
- Total = m_pVideo->m_pMedia->m_lDuration / 1000 * 25;//FramesPerSecond(); // milliseconds
- Current = stc / (100 * 1000) * FramesPerSecond(); // 100ns per Tick
- Current += m_timeOffset; // apply offset
+ Total = m_pVideo->m_Media.m_lDuration / 1000 * FramesPerSecond(); // milliseconds
+ Current = GetPlayedSeconds() * FramesPerSecond();
return true;
}
@@ -446,18 +481,12 @@ void cHlsPlayer::Stop(void)
double cHlsPlayer::FramesPerSecond(void)
{
- return m_pVideo->m_pMedia->m_VideoFrameRate ? m_pVideo->m_pMedia->m_VideoFrameRate : DEFAULTFRAMESPERSECOND;
+ return m_pVideo->m_Media.m_VideoFrameRate ? m_pVideo->m_Media.m_VideoFrameRate : DEFAULTFRAMESPERSECOND;
}
void cHlsPlayer::JumpRelative(int seconds)
{
- long stc = DeviceGetSTC();
- if(stc > 0) {
- int current = stc / (100 * 1000);
- JumpTo(current + seconds);
- } else {
- JumpTo(m_jumpOffset + seconds);
- }
+ JumpTo(GetPlayedSeconds() + seconds);
}
void cHlsPlayer::JumpTo(int seconds)
@@ -468,3 +497,68 @@ void cHlsPlayer::JumpTo(int seconds)
m_jumpOffset = seconds;
m_doJump = true;
}
+
+void cHlsPlayer::SetAudioTrack(eTrackType Type __attribute__((unused)), const tTrackId* TrackId)
+{
+ dsyslog("[plex]%s %d %s", __FUNCTION__, TrackId->id, TrackId->language);
+ // Check if stream availiable
+ int streamId = 0;
+ if(m_pVideo->m_Media.m_vStreams.size() > 0) {
+ std::vector<plexclient::Stream> streams = m_pVideo->m_Media.m_vStreams;
+ for(std::vector<plexclient::Stream>::iterator it = streams.begin(); it != streams.end(); ++it) {
+ plexclient::Stream *pStream = &(*it);
+ if(pStream->m_eStreamType == plexclient::sAUDIO && pStream->m_iIndex + AudioIndexOffset == TrackId->id) {
+ streamId = pStream->m_iID;
+ break;
+ }
+ }
+ }
+ // Then do the request
+ if(streamId > 0) {
+ Poco::Net::HTTPClientSession session(m_pVideo->m_pServer->GetIpAdress(), m_pVideo->m_pServer->GetPort());
+
+ std::string uri = "/library/parts/" + std::string(itoa(m_pVideo->m_Media.m_iPartId)) + "?audioStreamID=" + std::string(itoa(streamId));
+ Poco::Net::HTTPRequest req(Poco::Net::HTTPRequest::HTTP_PUT, uri);
+ session.sendRequest(req);
+
+ Poco::Net::HTTPResponse resp;
+ session.receiveResponse(resp);
+
+ if(resp.getStatus() == 200) {
+ DeviceSetCurrentAudioTrack(eTrackType(ttDolby + 0)); // hacky
+ DeviceSetAvailableTrack(ttDolby, 0, 0, TrackId->language);
+ JumpRelative(0); // Reload Stream to get new Audio
+ dsyslog("[plex]: Set AudioStream: %d\n", TrackId->id);
+ }
+ }
+}
+
+unsigned long long cHlsPlayer::MsNow(void)
+{
+ static timeval tv;
+ gettimeofday(&tv, 0);
+ return tv.tv_sec * 1000 + tv.tv_usec / 1000;
+}
+
+int cHlsPlayer::GetPlayedSeconds(void)
+{
+ return m_timeOffset + (m_tTimeSum / 1000);
+}
+
+void cHlsPlayer::CountPlayedSeconds(void)
+{
+ if (playMode == pmPlay) {
+ unsigned long long tTmp = MsNow();
+ m_tTimeSum += (tTmp - m_tLastTime);
+ m_tLastTime = tTmp;
+ }
+ else {
+ m_tLastTime = MsNow();
+ }
+}
+
+void cHlsPlayer::ResetPlayedSeconds(void)
+{
+ m_tTimeSum = 0;
+ m_tLastTime = MsNow();
+}