Commit 561df979 authored by François Grisez's avatar François Grisez
Browse files

Implementation of H265NaluPacker and H265NaluUnpacker classes.

parent c1ce97c0
......@@ -314,13 +314,13 @@ MS2_PUBLIC struct _MSEventQueue * ms_factory_get_event_queue(MSFactory *obj);
MS2_PUBLIC void ms_factory_set_event_queue(MSFactory *obj,struct _MSEventQueue *q);
MS2_PUBLIC int ms_factory_get_payload_max_size(MSFactory *factory);
MS2_PUBLIC int ms_factory_get_payload_max_size(const MSFactory *factory);
MS2_PUBLIC void ms_factory_set_payload_max_size(MSFactory *obj, int size);
MS2_PUBLIC void ms_factory_set_mtu(MSFactory *obj, int mtu);
MS2_PUBLIC int ms_factory_get_mtu(MSFactory *obj);
MS2_PUBLIC int ms_factory_get_mtu(const MSFactory *obj);
/**
* Set the name of the echo canceller filter to use.
......
......@@ -306,6 +306,7 @@ if(ENABLE_VIDEO)
utils/h264utils.cpp
utils/h265-utils.cpp
voip/h264-nal-packer.cpp
voip/h265-nal-packer.cpp
voip/h264-nal-unpacker.cpp
voip/h265-nal-unpacker.cpp
voip/nal-packer.cpp
......
......@@ -76,7 +76,7 @@ static void ms_fmt_descriptor_destroy(MSFmtDescriptor *obj);
#define DEFAULT_MAX_PAYLOAD_SIZE 1440
int ms_factory_get_payload_max_size(MSFactory *factory){
int ms_factory_get_payload_max_size(const MSFactory *factory) {
return factory->max_payload_size;
}
......@@ -100,7 +100,7 @@ void ms_factory_set_mtu(MSFactory *obj, int mtu){
}
}
int ms_factory_get_mtu(MSFactory *obj){
int ms_factory_get_mtu(const MSFactory *obj) {
return obj->mtu;
}
......
......@@ -50,10 +50,14 @@ void H265NaluHeader::parse(const uint8_t *header) {
_layerId = header2 & 0x3f;
header2 >>= 6;
_type = header2 & 0x3f;
header2 >>= 6;
_fBit = (header2 != 0);
}
mblk_t *H265NaluHeader::forge() const {
uint16_t header = _type;
uint16_t header = _fBit ? 1 : 0;
header <<= 1;
header |= _type;
header <<= 6;
header |= _layerId;
header <<= 3;
......
......@@ -45,6 +45,9 @@ public:
H265NaluHeader() = default;
H265NaluHeader(const uint8_t *header) {parse(header);}
void setFBit(bool val) {_fBit = val;}
bool getFBit() const {return _fBit;}
void setType(H265NaluType type) {_type = type;}
H265NaluType getType() const {return _type;}
......@@ -57,7 +60,10 @@ public:
void parse(const uint8_t *header);
mblk_t *forge() const;
static const size_t length = 2;
private:
bool _fBit = false;
H265NaluType _type;
uint8_t _layerId = 0;
uint8_t _tid = 0;
......@@ -83,6 +89,8 @@ public:
void parse(const uint8_t *header);
mblk_t *forge() const;
static const size_t length = 1;
private:
Position _pos = Position::Start;
H265NaluType _type;
......
......@@ -69,8 +69,8 @@ public:
NonInterleavedMode
};
H264NalPacker(): NalPacker(new H264NaluSpliter(), new H264NaluAggregator()) {}
H264NalPacker(MSFactory *factory): NalPacker(new H264NaluSpliter(), new H264NaluAggregator(), factory) {}
H264NalPacker(): NalPacker(new H264NaluAggregator(), new H264NaluSpliter()) {}
H264NalPacker(MSFactory *factory): NalPacker(new H264NaluAggregator(), new H264NaluSpliter(), factory) {}
};
} // namespace mediastreamer
/*
Mediastream*er2 library - modular sound and video processing and streaming
Copyright (C) 2006 Simon MORLAT (simon.morlat@linphone.org)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include <algorithm>
#include <cstring>
#include "h265-nal-packer.h"
using namespace std;
namespace mediastreamer {
H265NalPacker::NaluAggregator::~NaluAggregator() {
if (_ap) freemsg(_ap);
}
mblk_t *H265NalPacker::NaluAggregator::feed(mblk_t *nalu) {
H265NaluHeader header(nalu->b_rptr);
if (_ap == nullptr) {
placeFirstNalu(nalu);
} else {
if (H265NaluHeader::length + _size + 2 + msgdsize(nalu) > _maxSize) {
mblk_t *m = completeAggregation();
placeFirstNalu(nalu);
return m;
} else {
aggregate(nalu);
}
}
return nullptr;
}
void H265NalPacker::NaluAggregator::reset() {
if (_ap) freemsg(_ap);
}
mblk_t *H265NalPacker::NaluAggregator::completeAggregation() {
mblk_t *m;
if (_ap == nullptr) return nullptr;
if (_apHeader.getType() != H265NaluType::Ap) {
m = _ap;
} else {
m = _apHeader.forge();
concatb(m, _ap);
msgpullup(m, -1);
}
_ap = nullptr;
return m;
}
void H265NalPacker::NaluAggregator::placeFirstNalu(mblk_t *nalu) {
H265NaluHeader header(nalu->b_rptr);
_ap = nalu;
_apHeader = header;
_size = msgdsize(nalu);
}
void H265NalPacker::NaluAggregator::aggregate(mblk_t *nalu) {
H265NaluHeader header(nalu->b_rptr);
_apHeader.setFBit(_apHeader.getFBit() || header.getFBit());
_apHeader.setType(H265NaluType::Ap);
_apHeader.setLayerId(min(_apHeader.getLayerId(), header.getLayerId()));
_apHeader.setTid(min(_apHeader.getTid(), header.getTid()));
mblk_t *size = allocb(2, 0);
uint16_t *sizePtr = reinterpret_cast<uint16_t *>(size->b_wptr);
*sizePtr = htons(msgdsize(nalu));
size->b_wptr += 2;
_size += (msgdsize(size) + msgdsize(nalu)); // warning: this line must remain before 'concatb()' invocations.
concatb(_ap, size);
concatb(_ap, nalu);
}
void H265NalPacker::NaluSpliter::feed(mblk_t *nalu) {
if (msgdsize(nalu) <= _maxSize) return;
H265NaluHeader naluHeader(nalu->b_rptr);
H265FuHeader fuHeader;
fuHeader.setType(naluHeader.getType());
naluHeader.setType(H265NaluType::Fu);
while (msgdsize(nalu) > _maxSize) {
ms_queue_put(&_q, makeFu(naluHeader, fuHeader, nalu->b_rptr, _maxSize));
fuHeader.setPosition(H265FuHeader::Position::Middle);
nalu->b_rptr += _maxSize;
}
fuHeader.setPosition(H265FuHeader::Position::End);
ms_queue_put(&_q, makeFu(naluHeader, fuHeader, nalu->b_rptr, msgdsize(nalu)));
freemsg(nalu);
}
mblk_t *H265NalPacker::NaluSpliter::makeFu(const H265NaluHeader &naluHeader, const H265FuHeader &fuHeader, const uint8_t *payload, size_t length) {
mblk_t *naluHeaderBuf = naluHeader.forge();
mblk_t *fuHeaderBuf = fuHeader.forge();
mblk_t *payloadBuf = allocb(length, 0);
memcpy(payloadBuf->b_wptr, payload, length);
payloadBuf->b_wptr += length;
mblk_t *fu = naluHeaderBuf;
concatb(fu, fuHeaderBuf);
concatb(fu, payloadBuf);
msgpullup(fu, -1);
return fu;
}
}
/*
Mediastream*er2 library - modular sound and video processing and streaming
Copyright (C) 2006 Simon MORLAT (simon.morlat@linphone.org)
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#pragma once
#include "h265-utils.h"
#include "nal-packer.h"
namespace mediastreamer {
class H265NalPacker: NalPacker {
private:
class NaluAggregator: public NaluAggregatorInterface {
public:
~NaluAggregator();
size_t getMaxSize() const override {return _maxSize;}
void setMaxSize(size_t maxSize) override {_maxSize = maxSize;}
mblk_t *feed(mblk_t *nalu) override;
bool isAggregating() const override {return _ap != nullptr;}
void reset() override;
mblk_t *completeAggregation() override;
private:
void placeFirstNalu(mblk_t *nalu);
void aggregate(mblk_t *nalu);
size_t _maxSize = MS_DEFAULT_MAX_PAYLOAD_SIZE;
size_t _size = 0;
H265NaluHeader _apHeader;
mblk_t *_ap = nullptr;
};
class NaluSpliter: public NaluSpliterInterface {
public:
NaluSpliter() {ms_queue_init(&_q);}
~NaluSpliter() {ms_queue_flush(&_q);}
size_t getMaxSize() const override {return _maxSize;}
void setMaxSize(size_t maxSize) override {_maxSize = maxSize;}
void feed(mblk_t *nalu) override;
MSQueue *getPackets() override {return &_q;}
private:
mblk_t *makeFu(const H265NaluHeader &naluHeader, const H265FuHeader &fuHeader, const uint8_t *payload, size_t length);
size_t _maxSize = MS_DEFAULT_MAX_PAYLOAD_SIZE;
MSQueue _q;
};
H265NalPacker(const MSFactory *factory): NalPacker(new NaluAggregator, new NaluSpliter(), factory) {}
};
}
......@@ -21,7 +21,7 @@
namespace mediastreamer {
NalPacker::NalPacker(NaluSpliterInterface *naluSpliter, NaluAggregatorInterface *naluAggregator, MSFactory *factory): _naluSpliter(naluSpliter), _naluAggregator(naluAggregator) {
NalPacker::NalPacker(NaluAggregatorInterface *naluAggregator, NaluSpliterInterface *naluSpliter, const MSFactory *factory) {
setMaxPayloadSize(ms_factory_get_payload_max_size(factory));
}
......
......@@ -56,9 +56,6 @@ public:
virtual MSQueue *getPackets() = 0;
};
NalPacker(NaluSpliterInterface *naluSpliter, NaluAggregatorInterface *naluAggregator): _naluSpliter(naluSpliter), _naluAggregator(naluAggregator) {}
NalPacker(NaluSpliterInterface *naluSpliter, NaluAggregatorInterface *naluAggregator, MSFactory *factory);
void setPacketizationMode(PacketizationMode packMode) {_packMode = packMode;}
PacketizationMode getPacketizationMode() const {return _packMode;}
......@@ -73,6 +70,9 @@ public:
void pack(MSQueue *naluq, MSQueue *rtpq, uint32_t ts);
protected:
NalPacker(NaluAggregatorInterface *naluAggregator, NaluSpliterInterface *naluSpliter): _naluSpliter(naluSpliter), _naluAggregator(naluAggregator) {}
NalPacker(NaluAggregatorInterface *naluAggregator, NaluSpliterInterface *naluSpliter, const MSFactory *factory);
void packInSingleNalUnitMode(MSQueue *naluq, MSQueue *rtpq, uint32_t ts);
void packInNonInterleavedMode(MSQueue *naluq, MSQueue *rtpq, uint32_t ts);
void fragNaluAndSend(MSQueue *rtpq, uint32_t ts, mblk_t *nalu, bool_t marker);
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment