player: initial implementation
This commit is contained in:
parent
beca2400dd
commit
21f6a1fe9d
3 changed files with 152 additions and 1 deletions
|
@ -8,7 +8,7 @@ EXTRA_DIST=server.html server.html.h embed.js.h
|
|||
AM_CPPFLAGS = $(MIST_CFLAGS)
|
||||
LDADD = $(MIST_LIBS)
|
||||
SUBDIRS=converters analysers
|
||||
bin_PROGRAMS=MistBuffer MistController MistConnRAW MistConnRTMP MistConnHTTP MistConnHTTPProgressive MistConnHTTPDynamic
|
||||
bin_PROGRAMS=MistBuffer MistController MistConnRAW MistConnRTMP MistConnHTTP MistConnHTTPProgressive MistConnHTTPDynamic MistPlayer
|
||||
MistBuffer_SOURCES=buffer.cpp buffer_user.h buffer_user.cpp buffer_stream.h buffer_stream.cpp tinythread.cpp tinythread.h ../VERSION
|
||||
MistBuffer_LDADD=$(MIST_LIBS) -lpthread
|
||||
MistController_SOURCES=controller.cpp ../VERSION ./server.html.h
|
||||
|
@ -18,6 +18,8 @@ MistConnHTTP_SOURCES=conn_http.cpp tinythread.cpp tinythread.h ../VERSION ./embe
|
|||
MistConnHTTP_LDADD=$(MIST_LIBS) -lpthread
|
||||
MistConnHTTPProgressive_SOURCES=conn_http_progressive.cpp ../VERSION
|
||||
MistConnHTTPDynamic_SOURCES=conn_http_dynamic.cpp ../VERSION
|
||||
MistPlayer_SOURCES=player.h player.cpp
|
||||
MistPlayer_LDADD=$(MIST_LIBS)
|
||||
|
||||
lspSOURCES=$(lspdir)/jquery.js $(lspdir)/placeholder.js $(lspdir)/md5.js $(lspdir)/main.js $(lspdir)/functions.js
|
||||
lspDATA=$(lspdir)/header.html $(lspdir)/style.css $(lspdir)/footer.html
|
||||
|
|
124
src/player.cpp
Normal file
124
src/player.cpp
Normal file
|
@ -0,0 +1,124 @@
|
|||
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <mist/dtsc.h>
|
||||
#include "player.h"
|
||||
|
||||
namespace Player{
|
||||
///\todo Make getNowMS available in a library
|
||||
/// Gets the current system time in milliseconds.
|
||||
long long int getNowMS(){
|
||||
timeval t;
|
||||
gettimeofday(&t, 0);
|
||||
return t.tv_sec * 1000 + t.tv_usec/1000;
|
||||
}//getNowMS
|
||||
|
||||
File::File(std::string filename){
|
||||
stream = new DTSC::Stream(5);
|
||||
ring = NULL;// ring will be initialized when necessary
|
||||
fileSrc.open(filename.c_str(), std::ifstream::in | std::ifstream::binary);
|
||||
std::cout.setf(std::ios::unitbuf);//do not choke
|
||||
nextPacket();// initial read always returns nothing
|
||||
if (!nextPacket()){//parse metadata
|
||||
std::cout << stream->outHeader();
|
||||
} else {
|
||||
std::cerr << "Error: Expected metadata!" << std::endl;
|
||||
}
|
||||
};
|
||||
File::~File() {
|
||||
if (ring) {
|
||||
stream->dropRing(ring);
|
||||
ring = NULL;
|
||||
}
|
||||
delete stream;
|
||||
}
|
||||
// \returns True if there is a packet available for pull.
|
||||
bool File::nextPacket(){
|
||||
if (fileSrc.good()){
|
||||
if (stream->parsePacket(inBuffer)){
|
||||
return true;
|
||||
} else {
|
||||
char buffer[1024 * 10];
|
||||
fileSrc.read(buffer, sizeof(buffer));
|
||||
inBuffer.append(buffer, fileSrc.gcount());
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
void File::seek(int position){
|
||||
// XXX: implement seek.
|
||||
};
|
||||
std::string * File::getPacket(){
|
||||
if (ring->waiting){
|
||||
return NULL;
|
||||
}//still waiting for next buffer?
|
||||
if (ring->starved){
|
||||
//if corrupt data, warn and get new DTSC::Ring
|
||||
std::cerr << "Warning: User was send corrupt video data and send to the next keyframe!" << std::endl;
|
||||
stream->dropRing(ring);
|
||||
ring = stream->getRing();
|
||||
return NULL;
|
||||
}
|
||||
//switch to next buffer
|
||||
if (ring->b < 0){
|
||||
ring->waiting = true;
|
||||
return NULL;
|
||||
}//no next buffer? go in waiting mode.
|
||||
// get current packet
|
||||
std::string * packet = &stream->outPacket(ring->b);
|
||||
// make next request take a different packet
|
||||
ring->b--;
|
||||
return packet;
|
||||
}
|
||||
|
||||
/// Reads a command from stdin. Returns true if a command was read.
|
||||
bool File::readCommand() {
|
||||
// XXX: implement seek.
|
||||
return false;
|
||||
}
|
||||
|
||||
void File::Play() {
|
||||
long long now, timeDiff = 0, lastTime = 0;
|
||||
while (fileSrc.good()) {
|
||||
if (readCommand()) {
|
||||
continue;
|
||||
}
|
||||
now = getNowMS();
|
||||
if (now - timeDiff >= lastTime || lastTime - (now - timeDiff) > 5000) {
|
||||
if (nextPacket()) {
|
||||
std::string * packet;
|
||||
if (!ring){ring = stream->getRing();}//get ring after reading first non-metadata
|
||||
packet = getPacket();
|
||||
if (!packet){
|
||||
continue;
|
||||
}
|
||||
lastTime = stream->getTime();
|
||||
if (std::abs(now - timeDiff - lastTime) > 5000) {
|
||||
timeDiff = now - lastTime;
|
||||
}
|
||||
std::cout.write(packet->c_str(), packet->length());
|
||||
}
|
||||
} else {
|
||||
usleep(std::min(999LL, lastTime - (now - timeDiff)) * 1000);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
int main(int argc, char** argv){
|
||||
if (argc < 2){
|
||||
std::cerr << "Usage: " << argv[0] << " filename.dtsc" << std::endl;
|
||||
return 1;
|
||||
}
|
||||
std::string filename = argv[1];
|
||||
#if DEBUG >= 3
|
||||
std::cerr << "VoD " << filename << std::endl;
|
||||
#endif
|
||||
Player::File file(filename);
|
||||
file.Play();
|
||||
return 0;
|
||||
}
|
||||
|
25
src/player.h
Normal file
25
src/player.h
Normal file
|
@ -0,0 +1,25 @@
|
|||
/// \file player.h
|
||||
/// Provides functionality for playing files for Video on Demand
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "buffer_stream.h"
|
||||
|
||||
namespace Player{
|
||||
class File{
|
||||
private:
|
||||
std::ifstream fileSrc; ///<File handle of the input file.
|
||||
std::string inBuffer; ///<Buffer of unprocessed bytes read from input.
|
||||
DTSC::Stream * stream;
|
||||
DTSC::Ring * ring;
|
||||
bool nextPacket(); ///<Pulls the next packet into the queue.
|
||||
bool getPacketFromInput(); ///<Attempts to retrieve a packet from input.
|
||||
bool readCommand();
|
||||
public:
|
||||
File(std::string filename); ///<Attempts to open a DTSC file
|
||||
void Play();
|
||||
~File();
|
||||
void seek(int position);
|
||||
std::string * getPacket();
|
||||
};
|
||||
};
|
Loading…
Add table
Reference in a new issue