HLS/DASH stream track selector support in index URLs, fixed source matching when multi-select or type-select is used, handle user agent exceptions in Output::selectDefaultTracks(), added Util::codecString to stream.h library, removed duplicate/wrong code from DASH/HLS outputs

This commit is contained in:
Thulinma 2019-04-24 14:22:07 +02:00
parent bd34bafc03
commit b8415d09c6
8 changed files with 237 additions and 162 deletions

View file

@ -163,12 +163,18 @@ namespace h265{
return res;
}
void skipProfileTierLevel(Utils::bitstream &bs, unsigned int maxSubLayersMinus1){
bs.skip(8);
bs.skip(32); // general_profile_flags
bs.skip(4);
bs.skip(44); // reserverd_zero
bs.skip(8);
void profileTierLevel(Utils::bitstream &bs, unsigned int maxSubLayersMinus1, metaInfo &res){
res.general_profile_space = bs.get(2);
res.general_tier_flag = bs.get(1);
res.general_profile_idc = bs.get(5);
res.general_profile_compatflags = bs.get(32);
res.constraint_flags[0] = bs.get(8);
res.constraint_flags[1] = bs.get(8);
res.constraint_flags[2] = bs.get(8);
res.constraint_flags[3] = bs.get(8);
res.constraint_flags[4] = bs.get(8);
res.constraint_flags[5] = bs.get(8);
res.general_level_idc = bs.get(8);
std::deque<bool> profilePresent;
std::deque<bool> levelPresent;
for (size_t i = 0; i < maxSubLayersMinus1; i++){
@ -220,7 +226,7 @@ namespace h265{
if (maxSubLayersMinus1){
for (int i = maxSubLayersMinus1; i < 8; i++){
r << std::string(indent + 1, ' ') << "reserver_zero_2_bits[" << i << "]: " << bs.get(2)
r << std::string(indent + 1, ' ') << "reserved_zero_2_bits[" << i << "]: " << bs.get(2)
<< std::endl;
}
}
@ -521,7 +527,7 @@ namespace h265{
bs.skip(4);
unsigned int maxSubLayersMinus1 = bs.get(3);
bs.skip(1);
skipProfileTierLevel(bs, maxSubLayersMinus1);
profileTierLevel(bs, maxSubLayersMinus1, res);
bs.getUExpGolomb();
uint64_t chromaFormatIdc = bs.getUExpGolomb();
bool separateColorPlane = false;

View file

@ -22,6 +22,12 @@ namespace h265{
uint64_t width;
uint64_t height;
double fps;
uint8_t general_profile_space;
bool general_tier_flag;
uint8_t general_profile_idc;
uint32_t general_profile_compatflags;
uint8_t constraint_flags[6];
uint8_t general_level_idc;
};
class initData{

View file

@ -10,6 +10,8 @@
#include "shared_memory.h"
#include "socket.h"
#include "triggers.h" //LTS
#include "h265.h"
#include "mp4_generic.h"
#include <semaphore.h>
#include <stdlib.h>
#include <sys/stat.h>
@ -37,6 +39,76 @@ static void replace(std::string &str, const std::string &from, const std::string
}
}
std::string Util::codecString(const std::string & codec, const std::string & initData){
if (codec == "H264"){
std::stringstream r;
MP4::AVCC avccBox;
avccBox.setPayload(initData);
r << "avc1.";
r << std::hex << std::setw(2) << std::setfill('0') << (int)initData[1] << std::dec;
r << std::hex << std::setw(2) << std::setfill('0') << (int)initData[2] << std::dec;
r << std::hex << std::setw(2) << std::setfill('0') << (int)initData[3] << std::dec;
return r.str();
}
if (codec == "HEVC"){
h265::initData init(initData);
h265::metaInfo mInfo = init.getMeta();
std::stringstream r;
r << "hev1.";
switch (mInfo.general_profile_space){
case 0: break;
case 1: r << 'A'; break;
case 2: r << 'B'; break;
case 3: r << 'C'; break;
}
r << (unsigned long)mInfo.general_profile_idc << '.';
uint32_t mappedFlags = 0;
if (mInfo.general_profile_compatflags & 0x00000001ul){mappedFlags += 0x80000000ul;}
if (mInfo.general_profile_compatflags & 0x00000002ul){mappedFlags += 0x40000000ul;}
if (mInfo.general_profile_compatflags & 0x00000004ul){mappedFlags += 0x20000000ul;}
if (mInfo.general_profile_compatflags & 0x00000008ul){mappedFlags += 0x10000000ul;}
if (mInfo.general_profile_compatflags & 0x00000010ul){mappedFlags += 0x08000000ul;}
if (mInfo.general_profile_compatflags & 0x00000020ul){mappedFlags += 0x04000000ul;}
if (mInfo.general_profile_compatflags & 0x00000040ul){mappedFlags += 0x02000000ul;}
if (mInfo.general_profile_compatflags & 0x00000080ul){mappedFlags += 0x01000000ul;}
if (mInfo.general_profile_compatflags & 0x00000100ul){mappedFlags += 0x00800000ul;}
if (mInfo.general_profile_compatflags & 0x00000200ul){mappedFlags += 0x00400000ul;}
if (mInfo.general_profile_compatflags & 0x00000400ul){mappedFlags += 0x00200000ul;}
if (mInfo.general_profile_compatflags & 0x00000800ul){mappedFlags += 0x00100000ul;}
if (mInfo.general_profile_compatflags & 0x00001000ul){mappedFlags += 0x00080000ul;}
if (mInfo.general_profile_compatflags & 0x00002000ul){mappedFlags += 0x00040000ul;}
if (mInfo.general_profile_compatflags & 0x00004000ul){mappedFlags += 0x00020000ul;}
if (mInfo.general_profile_compatflags & 0x00008000ul){mappedFlags += 0x00010000ul;}
if (mInfo.general_profile_compatflags & 0x00010000ul){mappedFlags += 0x00008000ul;}
if (mInfo.general_profile_compatflags & 0x00020000ul){mappedFlags += 0x00004000ul;}
if (mInfo.general_profile_compatflags & 0x00040000ul){mappedFlags += 0x00002000ul;}
if (mInfo.general_profile_compatflags & 0x00080000ul){mappedFlags += 0x00001000ul;}
if (mInfo.general_profile_compatflags & 0x00100000ul){mappedFlags += 0x00000800ul;}
if (mInfo.general_profile_compatflags & 0x00200000ul){mappedFlags += 0x00000400ul;}
if (mInfo.general_profile_compatflags & 0x00400000ul){mappedFlags += 0x00000200ul;}
if (mInfo.general_profile_compatflags & 0x00800000ul){mappedFlags += 0x00000100ul;}
if (mInfo.general_profile_compatflags & 0x01000000ul){mappedFlags += 0x00000080ul;}
if (mInfo.general_profile_compatflags & 0x02000000ul){mappedFlags += 0x00000040ul;}
if (mInfo.general_profile_compatflags & 0x04000000ul){mappedFlags += 0x00000020ul;}
if (mInfo.general_profile_compatflags & 0x08000000ul){mappedFlags += 0x00000010ul;}
if (mInfo.general_profile_compatflags & 0x10000000ul){mappedFlags += 0x00000008ul;}
if (mInfo.general_profile_compatflags & 0x20000000ul){mappedFlags += 0x00000004ul;}
if (mInfo.general_profile_compatflags & 0x40000000ul){mappedFlags += 0x00000002ul;}
if (mInfo.general_profile_compatflags & 0x80000000ul){mappedFlags += 0x00000001ul;}
r << std::hex << (unsigned long)mappedFlags << std::dec << '.';
if (mInfo.general_tier_flag){r << 'H';}else{r << 'L';}
r << (unsigned long)mInfo.general_level_idc;
if (mInfo.constraint_flags[0]){
r << '.' << std::hex << (unsigned long)mInfo.constraint_flags[0] << std::dec;
}
return r.str();
}
if (codec == "AAC"){return "mp4a.40.2";}
if (codec == "MP3"){return "mp4a.40.34";}
if (codec == "AC3"){return "ec-3";}
return "";
}
/// Replaces all stream-related variables in the given 'str' with their values.
void Util::streamVariables(std::string &str, const std::string &streamname,
const std::string &source){
@ -493,6 +565,29 @@ uint8_t Util::getStreamStatus(const std::string &streamname){
return streamStatus.mapped[0];
}
/// Checks if a given user agent is allowed according to the given exception.
bool Util::checkException(const JSON::Value & ex, const std::string & useragent){
//No user agent? Always allow everything.
if (!useragent.size()){return true;}
if (!ex.isArray() || !ex.size()){return true;}
bool ret = true;
jsonForEachConst(ex, e){
if (!e->isArray() || !e->size()){continue;}
bool setTo = ((*e)[0u].asStringRef() == "whitelist");
if (e->size() == 1){
ret = setTo;
continue;
}
if (!(*e)[1].isArray()){continue;}
jsonForEachConst((*e)[1u], i){
if (useragent.find(i->asStringRef()) != std::string::npos){
ret = setTo;
}
}
}
return ret;
}
Util::DTSCShmReader::DTSCShmReader(const std::string &pageName){
rPage.init(pageName, 0, false, false);
if (rPage){rAcc = Util::RelAccX(rPage.mapped);}

View file

@ -20,6 +20,8 @@ namespace Util {
JSON::Value getInputBySource(const std::string & filename, bool isProvider = false);
DTSC::Meta getStreamMeta(const std::string & streamname);
uint8_t getStreamStatus(const std::string & streamname);
bool checkException(const JSON::Value & ex, const std::string & useragent);
std::string codecString(const std::string & codec, const std::string & initData = "");
class DTSCShmReader{
public: