Added initial DTSCv2 support

This commit is contained in:
Erik Zandvliet 2013-04-25 10:52:37 +02:00
parent a7de3bf08f
commit 2c343b9db6
3 changed files with 147 additions and 9 deletions

View file

@ -7,6 +7,7 @@
#include <arpa/inet.h> //for htonl/ntohl
char DTSC::Magic_Header[] = "DTSC";
char DTSC::Magic_Packet[] = "DTPD";
char DTSC::Magic_Packet2[] = "DTP2";
/// Initializes a DTSC::Stream with only one packet buffer.
DTSC::Stream::Stream(){
@ -92,6 +93,49 @@ bool DTSC::Stream::parsePacket(std::string & buffer){
syncing = false;
return true;
}
if (memcmp(buffer.c_str(), DTSC::Magic_Packet2, 4) == 0){
len = ntohl(((uint32_t *)buffer.c_str())[1]);
if (buffer.length() < len + 20){
return false;
}
buffers.push_front(JSON::Value());
unsigned int i = 0;
long long int tmpTrackID = ntohl(((int*)(buffer.c_str() + 8))[0]);
long long int tmpTime = ntohl(((int*)(buffer.c_str() + 12))[0]);
tmpTime << 32;
tmpTime += ntohl(((int*)(buffer.c_str() + 16))[0]);
buffers.front() = JSON::fromDTMI((unsigned char*)buffer.c_str() + 20, len, i);
buffers.front()["time"] = tmpTime;
buffers.front()["trackid"] = tmpTrackID;
datapointertype = INVALID;
if (buffers.front().isMember("data")){
datapointer = &(buffers.front()["data"].strVal);
}else{
datapointer = 0;
}
if (buffers.front().isMember("datatype")){
std::string tmp = buffers.front()["datatype"].asString();
if (tmp == "video"){
datapointertype = VIDEO;
}
if (tmp == "audio"){
datapointertype = AUDIO;
}
if (tmp == "meta"){
datapointertype = META;
}
if (tmp == "pause_marker"){
datapointertype = PAUSEMARK;
}
}
buffer.erase(0, len + 20);
while (buffers.size() > buffercount){
buffers.pop_back();
}
advanceRings();
syncing = false;
return true;
}
#if DEBUG >= 2
if (!syncing){
std::cerr << "Error: Invalid DTMI data detected - re-syncing" << std::endl;
@ -99,11 +143,16 @@ bool DTSC::Stream::parsePacket(std::string & buffer){
}
#endif
size_t magic_search = buffer.find(Magic_Packet);
size_t magic_search2 = buffer.find(Magic_Packet2);
if (magic_search2 == std::string::npos){
if (magic_search == std::string::npos){
buffer.clear();
}else{
buffer.erase(0, magic_search);
}
}else{
buffer.erase(0, magic_search2);
}
}
return false;
}
@ -169,6 +218,49 @@ bool DTSC::Stream::parsePacket(Socket::Buffer & buffer){
syncing = false;
return true;
}
if (memcmp(header_bytes.c_str(), DTSC::Magic_Packet2, 4) == 0){
len = ntohl(((uint32_t *)header_bytes.c_str())[1]);
if ( !buffer.available(len + 20)){
return false;
}
buffers.push_front(JSON::Value());
unsigned int i = 0;
std::string wholepacket = buffer.remove(len + 20);
long long int tmpTrackID = ntohl(((int*)(wholepacket.c_str() + 8))[0]);
long long int tmpTime = ntohl(((int*)(wholepacket.c_str() + 12))[0]);
tmpTime << 32;
tmpTime += ntohl(((int*)(wholepacket.c_str() + 16))[0]);
buffers.front() = JSON::fromDTMI((unsigned char*)wholepacket.c_str() + 20, len, i);
buffers.front()["time"] = tmpTime;
buffers.front()["trackid"] = tmpTrackID;
datapointertype = INVALID;
if (buffers.front().isMember("data")){
datapointer = &(buffers.front()["data"].strVal);
}else{
datapointer = 0;
}
if (buffers.front().isMember("datatype")){
std::string tmp = buffers.front()["datatype"].asString();
if (tmp == "video"){
datapointertype = VIDEO;
}
if (tmp == "audio"){
datapointertype = AUDIO;
}
if (tmp == "meta"){
datapointertype = META;
}
if (tmp == "pause_marker"){
datapointertype = PAUSEMARK;
}
}
while (buffers.size() > buffercount){
buffers.pop_back();
}
advanceRings();
syncing = false;
return true;
}
#if DEBUG >= 2
if (!syncing){
std::cerr << "Error: Invalid DTMI data detected - syncing" << std::endl;
@ -648,8 +740,15 @@ void DTSC::File::seekNext(){
jsonbuffer = metadata;
return;
}
if (memcmp(buffer, DTSC::Magic_Packet, 4) != 0){
fprintf(stderr, "Invalid header - %.4s != %.4s\n", buffer, DTSC::Magic_Packet);
long long unsigned int version = 0;
if (memcmp(buffer, DTSC::Magic_Packet, 4) == 0){
version = 1;
}
if (memcmp(buffer, DTSC::Magic_Packet2, 4) == 0){
version = 2;
}
if (version == 0){
fprintf(stderr, "Invalid header - %.4s != %.4s\n", buffer, DTSC::Magic_Packet2);
strbuffer = "";
jsonbuffer.null();
return;
@ -661,7 +760,7 @@ void DTSC::File::seekNext(){
return;
}
uint32_t * ubuffer = (uint32_t *)buffer;
long packSize = ntohl(ubuffer[0]);
long packSize = ntohl(ubuffer[0]) + (version == 2 ? 12 : 0);
strbuffer.resize(packSize);
if (fread((void*)strbuffer.c_str(), packSize, 1, F) != 1){
fprintf(stderr, "Could not read packet\n");
@ -669,6 +768,9 @@ void DTSC::File::seekNext(){
jsonbuffer.null();
return;
}
if (version == 2){
strbuffer.erase(0,12);
}
jsonbuffer = JSON::fromDTMI(strbuffer);
if (jsonbuffer.isMember("keyframe")){
if (frames[currframe] != lastreadpos){

View file

@ -62,6 +62,7 @@ namespace DTSC {
extern char Magic_Header[]; ///< The magic bytes for a DTSC header
extern char Magic_Packet[]; ///< The magic bytes for a DTSC packet
extern char Magic_Packet2[]; ///< The magic bytes for a DTSC packet version 2
/// A simple wrapper class that will open a file and allow easy reading/writing of DTSC data from/to it.
class File{

View file

@ -475,18 +475,53 @@ void JSON::Value::netPrepare(){
return;
}
std::string packed = toPacked();
strVal.resize(packed.size() + 8);
//insert proper header for this type of data
int packID = -1;
long long unsigned int time = objVal["time"].asInt();
std::string dataType = objVal["datatype"].asString();
if (isMember("datatype")){
memcpy((void*)strVal.c_str(), "DTPD", 4);
if (isMember("trackid")){
packID = objVal["trackid"].asInt();
}else{
if (objVal["datatype"].asString() == "video"){
packID = 1;
}
if (objVal["datatype"].asString() == "audio"){
packID = 2;
}
if (objVal["datatype"].asString() == "meta"){
packID = 3;
}
if (packID == -1){
packID = 0;
}
}
removeMember("time");
removeMember("datatype");
packed = toPacked();
objVal["time"] = (long long int)time;
objVal["datatype"] = dataType;
strVal.resize(packed.size() + 20);
memcpy((void*)strVal.c_str(), "DTP2", 4);
}else{
strVal.resize(packed.size() + 8);
memcpy((void*)strVal.c_str(), "DTSC", 4);
}
//insert the packet length at bytes 4-7
unsigned int size = htonl(packed.size());
memcpy((void*)(strVal.c_str() + 4), (void*) &size, 4);
//copy the rest of the string
if (packID != -1){
packID = htonl((int)packID);
memcpy((void*)(strVal.c_str() + 8), (void*) &packID, 4);
int tmpHalf = htonl((int)(time >> 32));
memcpy((void*)(strVal.c_str() + 12), (void*) &tmpHalf, 4);
tmpHalf = htonl((int)(time & 0xFFFFFFFF));
memcpy((void*)(strVal.c_str() + 16), (void*) &tmpHalf, 4);
memcpy((void*)(strVal.c_str() + 20), packed.c_str(), packed.size());
}else{
memcpy((void*)(strVal.c_str() + 8), packed.c_str(), packed.size());
}
}
/// Packs any object-type JSON::Value to a std::string for transfer over the network, including proper DTMI header.