Skip to content

Commit

Permalink
Support for UHD HDR10 and HDR10+ (#70)
Browse files Browse the repository at this point in the history
  • Loading branch information
jcdr428 authored and lighterowl committed Dec 26, 2019
1 parent 46b15eb commit cadb85a
Show file tree
Hide file tree
Showing 20 changed files with 316 additions and 98 deletions.
1 change: 1 addition & 0 deletions tsMuxer/abstractStreamReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ class AbstractStreamReader: public BaseAbstractStreamReader {
virtual int readPacket(AVPacket& avPacket) = 0;
virtual int flushPacket(AVPacket& avPacket) = 0;
virtual int getTSDescriptor(uint8_t* dstBuff) {return 0;}
virtual int getStreamHDR() const { return 0; }
virtual void writePESExtension(PESPacket* pesPacket, const AVPacket& avPacket) {}
virtual void setStreamIndex(int index) {m_streamIndex = index;}
int getStreamIndex() const { return m_streamIndex; }
Expand Down
18 changes: 14 additions & 4 deletions tsMuxer/blurayHelper.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "iso_writer.h"
#include "psgStreamReader.h"
#include "tsPacket.h"
#include "hevc.h"

using namespace std;

Expand Down Expand Up @@ -165,22 +166,29 @@ bool BlurayHelper::writeBluRayFiles(bool usedBlackPL, int mplsNum, int blankNum,
delete file;
return false;
}

uint8_t* emptyCommand;
if (m_dt == DT_BLURAY) {
bdMovieObjectData[5] = bdIndexData[5] = '2';
fileSize = 0x78;
}
else if (m_dt == UHD_BLURAY) {
bdMovieObjectData[5] = bdIndexData[5] = '3';
fileSize = 0x78;
fileSize = 0x9C; // add 36 bytes for HDR data extension
bdIndexData[15] = 0x78; // start address of HDR data extension
emptyCommand = bdIndexData + 0x78;
memcpy(emptyCommand, "\x00\x00\x00\x20\x00\x00\x00\x18\x00\x00\x00\x01"
"\x00\x03\x00\x01\x00\x00\x00\x18\x00\x00\x00\x0C"
"\x00\x00\x00\x08\x51\x00\x00\x00\x00\x00\x00\x00", 36); // HDR data extension
bdIndexData[0x96] = (uint8_t)HDR10_metadata[0]; // HDR flags

}
else {
bdMovieObjectData[5] = bdIndexData[5] = '1';
bdIndexData[15] = 0x78;
}
bdIndexData[0x2c] = stereoMode ? 0x60 : 0; // set initial_output_mode_preference and SS_content_exist_flag

uint8_t* emptyCommand = bdMovieObjectData + 78;
emptyCommand = bdMovieObjectData + 78;
if (usedBlackPL) {
memcpy(emptyCommand, "\x42\x82\x00\x00", 4);
uint32_t blackPlNum = my_htonl(blankNum);
Expand Down Expand Up @@ -274,7 +282,9 @@ bool BlurayHelper::createCLPIFile(TSMuxer* muxer, int clpiNum, bool doLog)
clpiParser.TS_recording_rate = MAX_SUBMUXER_RATE / 8;
else
clpiParser.TS_recording_rate = MAX_MAIN_MUXER_RATE / 8;

// max rate is 109 mbps for UHD BD 66/100 GB Default TR
if (m_dt == UHD_BLURAY)
clpiParser.TS_recording_rate = (clpiParser.TS_recording_rate * 109) / 48;
//clpiParser.TS_recording_rate = 188.0 / (maxRates[i] / 27000000.0);
clpiParser.number_of_source_packets = packetCount[i];
clpiParser.presentation_start_time = firstPts[i] / 2;
Expand Down
13 changes: 6 additions & 7 deletions tsMuxer/h264StreamReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
#include "math.h"
#include "vodCoreException.h"
#include "tsPacket.h"
#include <algorithm>

using namespace std;

Expand Down Expand Up @@ -490,9 +489,9 @@ void H264StreamReader::updateStreamFps(void* nalUnit, uint8_t* buff, uint8_t* ne
delete [] tmpBuffer;
}

void H264StreamReader::updateHDRParam(SPSUnit* sps)
void H264StreamReader::updateHRDParam(SPSUnit* sps)
{
// correct HDR parameters here (this function is call for every SPS nal unit)
// correct HRD parameters here (this function is called for every SPS nal unit)
if (!m_needSeiCorrection)
return;

Expand All @@ -501,7 +500,7 @@ void H264StreamReader::updateHDRParam(SPSUnit* sps)
//}
if (!sps->vui_parameters_present_flag)
sps->setFps(m_fps);
sps->insertHdrParameters();
sps->insertHrdParameters();
}

// All the remaining checks of the stream, executed at start
Expand Down Expand Up @@ -982,7 +981,7 @@ int H264StreamReader::processSEI(uint8_t* buff)
return 0;
}

int H264StreamReader::getNalHdrLen(uint8_t* nal)
int H264StreamReader::getNalHrdLen(uint8_t* nal)
{
if (m_bufEnd-nal >= 3) {
if (nal[0] == 0 && nal[1] == 0)
Expand Down Expand Up @@ -1241,7 +1240,7 @@ int H264StreamReader::detectPrimaryPicType(SliceUnit& firstSlice, uint8_t* buff)
m_nextFrameIdr = slice.isIDR();
return 0; // next frame found
}
m_pict_type = std::max(m_pict_type, sliceTypeToPictType(slice.slice_type));
m_pict_type = (std::max)(m_pict_type, sliceTypeToPictType(slice.slice_type));
break;
/*
case nuDelimiter:
Expand Down Expand Up @@ -1359,7 +1358,7 @@ int H264StreamReader::processSPS(uint8_t* buff)
updateFPS(sps, buff, nextNal, oldSpsLen);
nextNal = NALUnit::findNALWithStartCode(buff, m_bufEnd, true);
oldSpsLen = nextNal - buff;
updateHDRParam(sps);
updateHRDParam(sps);
if (sps->nalHrdParams.isPresent)
updatedSPSList.insert(sps->seq_parameter_set_id);

Expand Down
5 changes: 3 additions & 2 deletions tsMuxer/h264StreamReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class H264StreamReader: public MPEGStreamReader {
int getFrameDepth() override { return m_frameDepth; }
int getStreamWidth() const override;
int getStreamHeight() const override;
int getStreamHDR() const override { return 0; }
bool getInterlaced() override;
bool isIFrame() override { return m_lastIFrame; }
//virtual bool isIFrame() { return m_lastSliceIDR; }
Expand Down Expand Up @@ -125,9 +126,9 @@ class H264StreamReader: public MPEGStreamReader {
int sliceTypeToPictType(int slice_type);
uint8_t* writeNalPrefix(uint8_t* curPos);
bool findPPSForward(uint8_t* buff);
void updateHDRParam(SPSUnit* sps);
void updateHRDParam(SPSUnit* sps);
int processSEI(uint8_t* buff);
int getNalHdrLen(uint8_t* nal);
int getNalHrdLen(uint8_t* nal);
int writeSEIMessage(uint8_t* dstBuffer, uint8_t* dstEnd, SEIUnit& sei, uint8_t payloadType);

uint8_t* m_nextFrameAddr;
Expand Down
71 changes: 69 additions & 2 deletions tsMuxer/hevc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -697,11 +697,13 @@ int HevcSpsUnit::deserialize()
int PicHeightInCtbsY = ceilDiv(pic_height_in_luma_samples, CtbSizeY);
int PicSizeInCtbsY = PicWidthInCtbsY * PicHeightInCtbsY;
PicSizeInCtbsY_bits = 0;
while (PicSizeInCtbsY) {
int count1bits = 0;
while (PicSizeInCtbsY) {
count1bits += PicSizeInCtbsY & 1;
PicSizeInCtbsY_bits++;
PicSizeInCtbsY >>= 1;
}

if (count1bits == 1) PicSizeInCtbsY_bits -= 1; // in case PicSizeInCtbsY is power of 2

bool scaling_list_enabled_flag = m_reader.getBit();
if( scaling_list_enabled_flag )
Expand Down Expand Up @@ -807,6 +809,71 @@ int HevcPpsUnit::deserialize()
}
}

// ----------------------- HevcSeiUnit ------------------------
HevcSeiUnit::HevcSeiUnit():
isHDR10(false), isHDR10plus(false), isDV(false) {}

int HevcSeiUnit::deserialize()
{
int rez = HevcUnit::deserialize();
if (rez)
return rez;
try
{
do {
int payloadType = 0;
int payloadSize = 0;
int nbyte = 0xFF;
while (nbyte == 0xFF) {
nbyte = m_reader.getBits(8);
payloadType += nbyte;
}
nbyte = 0xFF;
while (nbyte == 0xFF) {
nbyte = m_reader.getBits(8);
payloadSize += nbyte;
}
if (payloadType == 137 && !isHDR10) { // mastering_display_colour_volume
HDR10_metadata[1] = m_reader.getBits(32); // display_primaries Green
HDR10_metadata[2] = m_reader.getBits(32); // display_primaries Red
HDR10_metadata[3] = m_reader.getBits(32); // display_primaries Blue
HDR10_metadata[4] = m_reader.getBits(32); // White Point
HDR10_metadata[5] = ((m_reader.getBits(32) / 10000) << 16) + m_reader.getBits(32); // max & min display_mastering_luminance
}
else if (payloadType == 144 && !isHDR10) { // content_light_level_info
isHDR10 = true;
*HDR10_metadata |= 2; // HDR10 flag
int maxCLL = m_reader.getBits(32); // maxCLL, maxFALL
if (maxCLL != 0) HDR10_metadata[6] = maxCLL;
}
else if (payloadType == 4 && !isHDR10plus) { // HDR10Plus Metadata
m_reader.skipBits(8); // country_code
m_reader.skipBits(32); // terminal_provider
int application_identifier = m_reader.getBits(8);
int application_version = m_reader.getBits(8);
int num_windows = m_reader.getBits(2);
m_reader.skipBits(6);
if (application_identifier == 4 && application_version == 1 && num_windows == 1)
{
isHDR10plus = true;
*HDR10_metadata |= 16; // HDR10plus flag
}
payloadSize -= 8;
for (int i = 0; i < payloadSize; i++)
m_reader.skipBits(8);
}
else for (int i = 0; i < payloadSize; i++)
m_reader.skipBits(8);
} while (m_reader.showBits(8) != 0x80);

return 0;
}
catch (VodCoreException & e)
{
return NOT_ENOUGHT_BUFFER;
}
}

// ----------------------- HevcSliceHeader() -------------------------------------

HevcSliceHeader::HevcSliceHeader():
Expand Down
13 changes: 13 additions & 0 deletions tsMuxer/hevc.h
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@

#include "nalUnits.h"

extern int HDR10_metadata[7];

enum HevcSliceTypes
{
HEVC_BFRAME_SLICE = 0,
Expand Down Expand Up @@ -39,6 +41,7 @@ enum HEVCUnitType {
NAL_FD_NUT = 38,
NAL_SEI_PREFIX = 39,
NAL_SEI_SUFFIX = 40,
NAL_DV = 62,
};

struct HevcUnit
Expand Down Expand Up @@ -169,6 +172,16 @@ struct HevcPpsUnit: public HevcUnit
int num_extra_slice_header_bits;
};

struct HevcSeiUnit: public HevcUnit
{
HevcSeiUnit();
int deserialize() override;
public:
bool isHDR10;
bool isHDR10plus;
bool isDV;
};

struct HevcSliceHeader: public HevcUnit
{
HevcSliceHeader();
Expand Down
31 changes: 31 additions & 0 deletions tsMuxer/hevcStreamReader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@
#include "nalUnits.h"
#include <fs/systemlog.h>
#include "vodCoreException.h"
#include "hevc.h"

using namespace std;

static const int MAX_SLICE_HEADER = 64;
int HDR10_metadata[7] = { 1,0,0,0,0,0,0 };

HEVCStreamReader::HEVCStreamReader():
MPEGStreamReader(),
m_vps(0),
m_sps(0),
m_pps(0),
m_sei(0),
m_firstFrame(true),
m_frameNum(0),
m_fullPicOrder(0),
Expand All @@ -32,6 +35,7 @@ HEVCStreamReader::~HEVCStreamReader()
delete m_vps;
delete m_sps;
delete m_pps;
delete m_sei;
}


Expand Down Expand Up @@ -74,6 +78,24 @@ CheckStreamRez HEVCStreamReader::checkStream(uint8_t* buffer, int len)
return rez;
break;
}
case NAL_SEI_PREFIX: {
uint8_t* nextNal = NALUnit::findNALWithStartCode(nal, end, true);
if (!m_sei)
m_sei = new HevcSeiUnit();
m_sei->decodeBuffer(nal, nextNal);
if (m_sei->deserialize() != 0)
return rez;
break;
}
case NAL_DV: {
if (!m_sei)
m_sei = new HevcSeiUnit();
if (nal[1] == 1 && !m_sei->isDV) {
m_sei->isDV = true;
*HDR10_metadata |= 4; // Dolby Vision flag
}
break;
}
}
}

Expand All @@ -88,6 +110,10 @@ CheckStreamRez HEVCStreamReader::checkStream(uint8_t* buffer, int len)

int HEVCStreamReader::getTSDescriptor(uint8_t* dstBuff)
{
if (m_firstFrame) {
checkStream(m_buffer, m_bufEnd - m_buffer);
}

*dstBuff++ = 0x05; // registreation descriptor tag
*dstBuff++ = 4;
memcpy(dstBuff, "HEVC", 4);
Expand Down Expand Up @@ -128,6 +154,11 @@ int HEVCStreamReader::getStreamHeight() const
return m_sps ? m_sps->pic_height_in_luma_samples : 0;
}

int HEVCStreamReader::getStreamHDR() const
{
return m_sei->isDV ? 4 : (m_sei->isHDR10plus ? 16 : (m_sei->isHDR10 ? 2 : 1));
}

double HEVCStreamReader::getStreamFPS(void * curNalUnit)
{
HevcVpsUnit* vps = (HevcVpsUnit*) curNalUnit;
Expand Down
3 changes: 3 additions & 0 deletions tsMuxer/hevcStreamReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ class HEVCStreamReader: public MPEGStreamReader
double getStreamFPS(void * curNalUnit) override;
int getStreamWidth() const override;
int getStreamHeight() const override;
int getStreamHDR() const override;
bool getInterlaced() override {return false;}
bool isIFrame() override {return m_lastIFrame;}

Expand All @@ -41,6 +42,7 @@ class HEVCStreamReader: public MPEGStreamReader
HevcVpsUnit* m_vps;
HevcSpsUnit* m_sps;
HevcPpsUnit* m_pps;
HevcSeiUnit* m_sei;
bool m_firstFrame;

int m_frameNum;
Expand All @@ -55,6 +57,7 @@ class HEVCStreamReader: public MPEGStreamReader
MemoryBlock m_vpsBuffer;
MemoryBlock m_spsBuffer;
MemoryBlock m_ppsBuffer;
MemoryBlock m_seiBuffer;
bool m_firstFileFrame;
int m_vpsCounter;
int m_vpsSizeDiff;
Expand Down
2 changes: 1 addition & 1 deletion tsMuxer/main.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -675,14 +675,14 @@ int main(int argc, char** argv)
throw runtime_error(string("Can't create output file ") + dstFile);
blurayHelper.setVolumeLabel(isoDiskLabel);
blurayHelper.createBluRayDirs();
blurayHelper.writeBluRayFiles(insertBlankPL, firstMplsOffset, blankNum, stereoMode);
dstFile = blurayHelper.m2tsFileName(firstM2tsOffset);
}
if (muxerManager.getTrackCnt() == 0)
THROW(ERR_COMMON, "No tracks selected");
muxerManager.doMux(dstFile, dt != DT_NONE ? &blurayHelper : 0);
if (dt != DT_NONE)
{
blurayHelper.writeBluRayFiles(insertBlankPL, firstMplsOffset, blankNum, stereoMode);
TSMuxer* mainMuxer = dynamic_cast<TSMuxer*> (muxerManager.getMainMuxer());
TSMuxer* subMuxer = dynamic_cast<TSMuxer*> (muxerManager.getSubMuxer());

Expand Down
2 changes: 0 additions & 2 deletions tsMuxer/metaDemuxer.cpp
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@

#include <iomanip>
#include <chrono>

#include <types/types.h>
#include <fs/textfile.h>
Expand Down
1 change: 1 addition & 0 deletions tsMuxer/mpeg2StreamReader.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ class MPEG2StreamReader: public MPEGStreamReader {

int getStreamWidth() const override {return m_sequence.width;}
int getStreamHeight()const override {return m_sequence.height;}
int getStreamHDR()const override { return 0; }
bool getInterlaced() override {return !m_sequence.progressive_sequence;}

protected:
Expand Down
Loading

0 comments on commit cadb85a

Please sign in to comment.