mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
Refactor code to keep sample function order
This commit is contained in:
parent
7b5fa0e391
commit
6f2b78f16a
10 changed files with 987 additions and 593 deletions
File diff suppressed because it is too large
Load diff
|
@ -33,6 +33,7 @@
|
||||||
#include <srs_app_hourglass.hpp>
|
#include <srs_app_hourglass.hpp>
|
||||||
#include <srs_app_sdp.hpp>
|
#include <srs_app_sdp.hpp>
|
||||||
#include <srs_app_reload.hpp>
|
#include <srs_app_reload.hpp>
|
||||||
|
#include <srs_kernel_rtp.hpp>
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
@ -54,6 +55,8 @@ class ISrsUdpSender;
|
||||||
class SrsRtpQueue;
|
class SrsRtpQueue;
|
||||||
class SrsRtpH264Demuxer;
|
class SrsRtpH264Demuxer;
|
||||||
class SrsRtpOpusDemuxer;
|
class SrsRtpOpusDemuxer;
|
||||||
|
class SrsRtpPacket2;
|
||||||
|
class ISrsCodec;
|
||||||
|
|
||||||
const uint8_t kSR = 200;
|
const uint8_t kSR = 200;
|
||||||
const uint8_t kRR = 201;
|
const uint8_t kRR = 201;
|
||||||
|
@ -248,7 +251,7 @@ private:
|
||||||
srs_error_t package_stap_a(SrsSource* source, SrsSharedPtrMessage* msg, SrsRtcPackets& packets);
|
srs_error_t package_stap_a(SrsSource* source, SrsSharedPtrMessage* msg, SrsRtcPackets& packets);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsRtcPublisher : virtual public ISrsHourGlass
|
class SrsRtcPublisher : virtual public ISrsHourGlass, virtual public ISrsRtpPacketDecodeHandler
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
SrsHourGlass* report_timer;
|
SrsHourGlass* report_timer;
|
||||||
|
@ -258,7 +261,6 @@ private:
|
||||||
uint32_t audio_ssrc;
|
uint32_t audio_ssrc;
|
||||||
private:
|
private:
|
||||||
SrsRtpH264Demuxer* rtp_h264_demuxer;
|
SrsRtpH264Demuxer* rtp_h264_demuxer;
|
||||||
SrsRtpOpusDemuxer* rtp_opus_demuxer;
|
|
||||||
SrsRtpQueue* rtp_video_queue;
|
SrsRtpQueue* rtp_video_queue;
|
||||||
SrsRtpQueue* rtp_audio_queue;
|
SrsRtpQueue* rtp_audio_queue;
|
||||||
private:
|
private:
|
||||||
|
@ -283,11 +285,14 @@ private:
|
||||||
srs_error_t send_rtcp_fb_pli(uint32_t ssrc);
|
srs_error_t send_rtcp_fb_pli(uint32_t ssrc);
|
||||||
public:
|
public:
|
||||||
srs_error_t on_rtp(char* buf, int nb_buf);
|
srs_error_t on_rtp(char* buf, int nb_buf);
|
||||||
|
virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsCodec** ppayload);
|
||||||
private:
|
private:
|
||||||
srs_error_t on_audio(SrsRtpSharedPacket* pkt);
|
srs_error_t on_audio(SrsRtpPacket2* pkt);
|
||||||
srs_error_t collect_audio_frame();
|
srs_error_t collect_audio_frames();
|
||||||
srs_error_t on_video(SrsRtpSharedPacket* pkt);
|
srs_error_t do_collect_audio_frame(SrsRtpPacket2* packet);
|
||||||
srs_error_t collect_video_frame();
|
srs_error_t on_video(SrsRtpPacket2* pkt);
|
||||||
|
srs_error_t collect_video_frames();
|
||||||
|
srs_error_t do_collect_video_frame(std::vector<SrsRtpPacket2*>& packets);
|
||||||
public:
|
public:
|
||||||
void request_keyframe();
|
void request_keyframe();
|
||||||
// interface ISrsHourGlass
|
// interface ISrsHourGlass
|
||||||
|
@ -334,25 +339,18 @@ public:
|
||||||
SrsRtcSession(SrsRtcServer* s, SrsRequest* r, const std::string& un, int context_id);
|
SrsRtcSession(SrsRtcServer* s, SrsRequest* r, const std::string& un, int context_id);
|
||||||
virtual ~SrsRtcSession();
|
virtual ~SrsRtcSession();
|
||||||
public:
|
public:
|
||||||
SrsSdp* get_local_sdp() { return &local_sdp; }
|
SrsSdp* get_local_sdp();
|
||||||
void set_local_sdp(const SrsSdp& sdp);
|
void set_local_sdp(const SrsSdp& sdp);
|
||||||
|
SrsSdp* get_remote_sdp();
|
||||||
SrsSdp* get_remote_sdp() { return &remote_sdp; }
|
void set_remote_sdp(const SrsSdp& sdp);
|
||||||
void set_remote_sdp(const SrsSdp& sdp) { remote_sdp = sdp; }
|
SrsRtcSessionStateType get_session_state();
|
||||||
|
void set_session_state(SrsRtcSessionStateType state);
|
||||||
SrsRtcSessionStateType get_session_state() { return session_state; }
|
std::string id() const;
|
||||||
void set_session_state(SrsRtcSessionStateType state) { session_state = state; }
|
std::string get_peer_id() const;
|
||||||
|
void set_peer_id(const std::string& id);
|
||||||
std::string id() const { return peer_id + "_" + username; }
|
void set_encrypt(bool v);
|
||||||
|
|
||||||
std::string get_peer_id() const { return peer_id; }
|
|
||||||
void set_peer_id(const std::string& id) { peer_id = id; }
|
|
||||||
|
|
||||||
void set_encrypt(bool v) { encrypt = v; }
|
|
||||||
|
|
||||||
void switch_to_context();
|
void switch_to_context();
|
||||||
int context_id() { return cid; }
|
int context_id();
|
||||||
|
|
||||||
public:
|
public:
|
||||||
srs_error_t initialize();
|
srs_error_t initialize();
|
||||||
// The peer address may change, we can identify that by STUN messages.
|
// The peer address may change, we can identify that by STUN messages.
|
||||||
|
@ -361,7 +359,6 @@ public:
|
||||||
srs_error_t on_rtcp(char* data, int nb_data);
|
srs_error_t on_rtcp(char* data, int nb_data);
|
||||||
srs_error_t on_rtp(char* data, int nb_data);
|
srs_error_t on_rtp(char* data, int nb_data);
|
||||||
public:
|
public:
|
||||||
srs_error_t send_client_hello();
|
|
||||||
srs_error_t on_connection_established();
|
srs_error_t on_connection_established();
|
||||||
srs_error_t start_play();
|
srs_error_t start_play();
|
||||||
srs_error_t start_publish();
|
srs_error_t start_publish();
|
||||||
|
|
|
@ -141,8 +141,8 @@ SrsRtpRingBuffer::SrsRtpRingBuffer(size_t capacity)
|
||||||
capacity_ = capacity;
|
capacity_ = capacity;
|
||||||
initialized_ = false;
|
initialized_ = false;
|
||||||
|
|
||||||
queue_ = new SrsRtpSharedPacket*[capacity_];
|
queue_ = new SrsRtpPacket2*[capacity_];
|
||||||
memset(queue_, 0, sizeof(SrsRtpSharedPacket*) * capacity);
|
memset(queue_, 0, sizeof(SrsRtpPacket2*) * capacity);
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsRtpRingBuffer::~SrsRtpRingBuffer()
|
SrsRtpRingBuffer::~SrsRtpRingBuffer()
|
||||||
|
@ -150,9 +150,9 @@ SrsRtpRingBuffer::~SrsRtpRingBuffer()
|
||||||
srs_freepa(queue_);
|
srs_freepa(queue_);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsRtpRingBuffer::set(uint16_t at, SrsRtpSharedPacket* pkt)
|
void SrsRtpRingBuffer::set(uint16_t at, SrsRtpPacket2* pkt)
|
||||||
{
|
{
|
||||||
SrsRtpSharedPacket* p = queue_[at % capacity_];
|
SrsRtpPacket2* p = queue_[at % capacity_];
|
||||||
|
|
||||||
if (p) {
|
if (p) {
|
||||||
srs_freep(p);
|
srs_freep(p);
|
||||||
|
@ -161,9 +161,11 @@ void SrsRtpRingBuffer::set(uint16_t at, SrsRtpSharedPacket* pkt)
|
||||||
queue_[at % capacity_] = pkt;
|
queue_[at % capacity_] = pkt;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsRtpRingBuffer::remove(uint16_t at)
|
void SrsRtpRingBuffer::reset(uint16_t low, uint16_t high)
|
||||||
{
|
{
|
||||||
set(at, NULL);
|
for (uint16_t s = low; s != high; ++s) {
|
||||||
|
queue_[s % capacity_] = NULL;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint16_t SrsRtpRingBuffer::next_start_of_frame()
|
uint16_t SrsRtpRingBuffer::next_start_of_frame()
|
||||||
|
@ -173,8 +175,8 @@ uint16_t SrsRtpRingBuffer::next_start_of_frame()
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint16_t s = low_ + 1 ; s != high_; ++s) {
|
for (uint16_t s = low_ + 1 ; s != high_; ++s) {
|
||||||
SrsRtpSharedPacket*& pkt = queue_[s % capacity_];
|
SrsRtpPacket2*& pkt = queue_[s % capacity_];
|
||||||
if (pkt && pkt->rtp_payload_header->is_first_packet_of_frame) {
|
if (pkt && pkt->is_first_packet_of_frame) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -189,8 +191,8 @@ uint16_t SrsRtpRingBuffer::next_keyframe()
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint16_t s = low_ + 1 ; s != high_; ++s) {
|
for (uint16_t s = low_ + 1 ; s != high_; ++s) {
|
||||||
SrsRtpSharedPacket*& pkt = queue_[s % capacity_];
|
SrsRtpPacket2*& pkt = queue_[s % capacity_];
|
||||||
if (pkt && pkt->rtp_payload_header->is_key_frame && pkt->rtp_payload_header->is_first_packet_of_frame) {
|
if (pkt && pkt->is_key_frame && pkt->is_first_packet_of_frame) {
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -269,7 +271,7 @@ SrsRtpQueue::~SrsRtpQueue()
|
||||||
srs_freep(nack_);
|
srs_freep(nack_);
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsRtpQueue::consume(SrsRtpSharedPacket* pkt)
|
srs_error_t SrsRtpQueue::consume(SrsRtpPacket2* pkt)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
@ -337,8 +339,8 @@ srs_error_t SrsRtpQueue::consume(SrsRtpSharedPacket* pkt)
|
||||||
queue_->advance_to(next + 1);
|
queue_->advance_to(next + 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO: FIXME: Change to ptr of ptr.
|
// Save packet at the position seq.
|
||||||
queue_->set(seq, pkt->copy());
|
queue_->set(seq, pkt);
|
||||||
|
|
||||||
// Collect packets to frame when:
|
// Collect packets to frame when:
|
||||||
// 1. Marker bit means the last packet of frame received.
|
// 1. Marker bit means the last packet of frame received.
|
||||||
|
@ -351,7 +353,7 @@ srs_error_t SrsRtpQueue::consume(SrsRtpSharedPacket* pkt)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsRtpQueue::collect_frames(std::vector<std::vector<SrsRtpSharedPacket*> >& frames)
|
void SrsRtpQueue::collect_frames(std::vector<std::vector<SrsRtpPacket2*> >& frames)
|
||||||
{
|
{
|
||||||
frames.swap(frames_);
|
frames.swap(frames_);
|
||||||
}
|
}
|
||||||
|
@ -446,33 +448,39 @@ void SrsRtpQueue::insert_into_nack_list(uint16_t seq_start, uint16_t seq_end)
|
||||||
|
|
||||||
void SrsRtpQueue::collect_packet()
|
void SrsRtpQueue::collect_packet()
|
||||||
{
|
{
|
||||||
vector<SrsRtpSharedPacket*> frame;
|
while (queue_->low() != queue_->high()) {
|
||||||
|
vector<SrsRtpPacket2*> frame;
|
||||||
for (uint16_t s = queue_->low(); s != queue_->high(); ++s) {
|
for (uint16_t s = queue_->low(); s != queue_->high(); ++s) {
|
||||||
SrsRtpSharedPacket* pkt = queue_->at(s);
|
SrsRtpPacket2* pkt = queue_->at(s);
|
||||||
|
|
||||||
|
// In NACK, never collect frame.
|
||||||
if (nack_->find(s) != NULL) {
|
if (nack_->find(s) != NULL) {
|
||||||
srs_verbose("seq=%u, found in nack list when collect frame", s);
|
srs_verbose("seq=%u, found in nack list when collect frame", s);
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
// We must collect frame from first packet to last packet.
|
// Ignore when the first packet not the start.
|
||||||
if (s == queue_->low() && pkt->rtp_payload_size() != 0 && !pkt->rtp_payload_header->is_first_packet_of_frame) {
|
if (s == queue_->low() && pkt->nn_original_payload && !pkt->is_first_packet_of_frame) {
|
||||||
break;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
frame.push_back(pkt->copy());
|
// OK, collect packet to frame.
|
||||||
|
frame.push_back(pkt);
|
||||||
|
|
||||||
|
// Not the last packet, continue to process next one.
|
||||||
if (pkt->rtp_header.get_marker() || one_packet_per_frame_) {
|
if (pkt->rtp_header.get_marker() || one_packet_per_frame_) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Done, we got the last packet of frame.
|
||||||
nn_collected_frames++;
|
nn_collected_frames++;
|
||||||
frames_.push_back(frame);
|
frames_.push_back(frame);
|
||||||
frame.clear();
|
|
||||||
|
// Reset the range of packets to NULL in buffer.
|
||||||
|
queue_->reset(queue_->low(), s);
|
||||||
|
|
||||||
srs_verbose("head seq=%u, update to %u because collect one full farme", queue_->low(), s + 1);
|
srs_verbose("head seq=%u, update to %u because collect one full farme", queue_->low(), s + 1);
|
||||||
queue_->advance_to(s + 1);
|
queue_->advance_to(s + 1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// remove the tmp buffer
|
|
||||||
for (size_t i = 0; i < frame.size(); ++i) {
|
|
||||||
srs_freep(frame[i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -30,7 +30,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
class SrsRtpSharedPacket;
|
class SrsRtpPacket2;
|
||||||
class SrsRtpQueue;
|
class SrsRtpQueue;
|
||||||
|
|
||||||
struct SrsNackOption
|
struct SrsNackOption
|
||||||
|
@ -119,7 +119,7 @@ private:
|
||||||
// Capacity of the ring-buffer.
|
// Capacity of the ring-buffer.
|
||||||
uint16_t capacity_;
|
uint16_t capacity_;
|
||||||
// Ring bufer.
|
// Ring bufer.
|
||||||
SrsRtpSharedPacket** queue_;
|
SrsRtpPacket2** queue_;
|
||||||
// Increase one when uint16 flip back, for get_extended_highest_sequence.
|
// Increase one when uint16 flip back, for get_extended_highest_sequence.
|
||||||
uint64_t nn_seq_flip_backs;
|
uint64_t nn_seq_flip_backs;
|
||||||
// Whether initialized, because we use uint16 so we can't use -1.
|
// Whether initialized, because we use uint16 so we can't use -1.
|
||||||
|
@ -132,12 +132,17 @@ public:
|
||||||
SrsRtpRingBuffer(size_t capacity);
|
SrsRtpRingBuffer(size_t capacity);
|
||||||
virtual ~SrsRtpRingBuffer();
|
virtual ~SrsRtpRingBuffer();
|
||||||
public:
|
public:
|
||||||
|
// Move the position of buffer.
|
||||||
uint16_t low() { return low_; }
|
uint16_t low() { return low_; }
|
||||||
uint16_t high() { return high_; }
|
uint16_t high() { return high_; }
|
||||||
void advance_to(uint16_t seq) { low_ = seq; }
|
void advance_to(uint16_t seq) { low_ = seq; }
|
||||||
void set(uint16_t at, SrsRtpSharedPacket* pkt);
|
// Free the packet at position.
|
||||||
void remove(uint16_t at);
|
void set(uint16_t at, SrsRtpPacket2* pkt);
|
||||||
bool overflow() { return low_ + capacity_ < high_; }
|
void remove(uint16_t at) { set(at, NULL); }
|
||||||
|
// Directly reset range [low, high] to NULL.
|
||||||
|
void reset(uint16_t low, uint16_t high);
|
||||||
|
// Whether queue overflow or heavy(too many packets and need clear).
|
||||||
|
bool overflow() { return high_ - low_ < capacity_; }
|
||||||
bool is_heavy() { return high_ - low_ >= capacity_ / 2; }
|
bool is_heavy() { return high_ - low_ >= capacity_ / 2; }
|
||||||
// Get the next start packet of frame.
|
// Get the next start packet of frame.
|
||||||
// @remark If not found, return the low_, which should never be the "next" one,
|
// @remark If not found, return the low_, which should never be the "next" one,
|
||||||
|
@ -151,7 +156,7 @@ public:
|
||||||
// Update the sequence, got the nack range by [low, high].
|
// Update the sequence, got the nack range by [low, high].
|
||||||
void update(uint16_t seq, bool startup, uint16_t& nack_low, uint16_t& nack_high);
|
void update(uint16_t seq, bool startup, uint16_t& nack_low, uint16_t& nack_high);
|
||||||
// Get the packet by seq.
|
// Get the packet by seq.
|
||||||
SrsRtpSharedPacket* at(uint16_t seq) { return queue_[seq % capacity_]; }
|
SrsRtpPacket2* at(uint16_t seq) { return queue_[seq % capacity_]; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsRtpQueue
|
class SrsRtpQueue
|
||||||
|
@ -170,14 +175,14 @@ private:
|
||||||
uint64_t num_of_packet_received_;
|
uint64_t num_of_packet_received_;
|
||||||
uint64_t number_of_packet_lossed_;
|
uint64_t number_of_packet_lossed_;
|
||||||
private:
|
private:
|
||||||
std::vector<std::vector<SrsRtpSharedPacket*> > frames_;
|
std::vector<std::vector<SrsRtpPacket2*> > frames_;
|
||||||
bool request_key_frame_;
|
bool request_key_frame_;
|
||||||
public:
|
public:
|
||||||
SrsRtpQueue(size_t capacity = 1024, bool one_packet_per_frame = false);
|
SrsRtpQueue(size_t capacity = 1024, bool one_packet_per_frame = false);
|
||||||
virtual ~SrsRtpQueue();
|
virtual ~SrsRtpQueue();
|
||||||
public:
|
public:
|
||||||
srs_error_t consume(SrsRtpSharedPacket* pkt);
|
srs_error_t consume(SrsRtpPacket2* pkt);
|
||||||
void collect_frames(std::vector<std::vector<SrsRtpSharedPacket*> >& frames);
|
void collect_frames(std::vector<std::vector<SrsRtpPacket2*> >& frames);
|
||||||
bool should_request_key_frame();
|
bool should_request_key_frame();
|
||||||
void notify_drop_seq(uint16_t seq);
|
void notify_drop_seq(uint16_t seq);
|
||||||
void notify_nack_list_full();
|
void notify_nack_list_full();
|
||||||
|
|
|
@ -58,11 +58,26 @@ SrsBuffer::~SrsBuffer()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char* SrsBuffer::data()
|
||||||
|
{
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
char* SrsBuffer::head()
|
||||||
|
{
|
||||||
|
return p;
|
||||||
|
}
|
||||||
|
|
||||||
int SrsBuffer::size()
|
int SrsBuffer::size()
|
||||||
{
|
{
|
||||||
return nb_bytes;
|
return nb_bytes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SrsBuffer::set_size(int v)
|
||||||
|
{
|
||||||
|
nb_bytes = v;
|
||||||
|
}
|
||||||
|
|
||||||
int SrsBuffer::pos()
|
int SrsBuffer::pos()
|
||||||
{
|
{
|
||||||
return (int)(p - bytes);
|
return (int)(p - bytes);
|
||||||
|
|
|
@ -105,62 +105,62 @@ public:
|
||||||
// Create buffer with data b and size nn.
|
// Create buffer with data b and size nn.
|
||||||
// @remark User must free the data b.
|
// @remark User must free the data b.
|
||||||
SrsBuffer(char* b, int nn);
|
SrsBuffer(char* b, int nn);
|
||||||
virtual ~SrsBuffer();
|
~SrsBuffer();
|
||||||
public:
|
public:
|
||||||
// Get the data and head of buffer.
|
// Get the data and head of buffer.
|
||||||
// current-bytes = head() = data() + pos()
|
// current-bytes = head() = data() + pos()
|
||||||
inline char* data() { return bytes; }
|
char* data();
|
||||||
inline char* head() { return p; }
|
char* head();
|
||||||
// Get the total size of buffer.
|
// Get the total size of buffer.
|
||||||
// left-bytes = size() - pos()
|
// left-bytes = size() - pos()
|
||||||
virtual int size();
|
int size();
|
||||||
void set_size(int v) { nb_bytes = v; }
|
void set_size(int v);
|
||||||
// Get the current buffer position.
|
// Get the current buffer position.
|
||||||
virtual int pos();
|
int pos();
|
||||||
// Left bytes in buffer, total size() minus the current pos().
|
// Left bytes in buffer, total size() minus the current pos().
|
||||||
virtual int left();
|
int left();
|
||||||
// Whether buffer is empty.
|
// Whether buffer is empty.
|
||||||
virtual bool empty();
|
bool empty();
|
||||||
// Whether buffer is able to supply required size of bytes.
|
// Whether buffer is able to supply required size of bytes.
|
||||||
// @remark User should check buffer by require then do read/write.
|
// @remark User should check buffer by require then do read/write.
|
||||||
// @remark Assert the required_size is not negative.
|
// @remark Assert the required_size is not negative.
|
||||||
virtual bool require(int required_size);
|
bool require(int required_size);
|
||||||
public:
|
public:
|
||||||
// Skip some size.
|
// Skip some size.
|
||||||
// @param size can be any value. positive to forward; nagetive to backward.
|
// @param size can be any value. positive to forward; nagetive to backward.
|
||||||
// @remark to skip(pos()) to reset buffer.
|
// @remark to skip(pos()) to reset buffer.
|
||||||
// @remark assert initialized, the data() not NULL.
|
// @remark assert initialized, the data() not NULL.
|
||||||
virtual void skip(int size);
|
void skip(int size);
|
||||||
public:
|
public:
|
||||||
// Read 1bytes char from buffer.
|
// Read 1bytes char from buffer.
|
||||||
virtual int8_t read_1bytes();
|
int8_t read_1bytes();
|
||||||
// Read 2bytes int from buffer.
|
// Read 2bytes int from buffer.
|
||||||
virtual int16_t read_2bytes();
|
int16_t read_2bytes();
|
||||||
// Read 3bytes int from buffer.
|
// Read 3bytes int from buffer.
|
||||||
virtual int32_t read_3bytes();
|
int32_t read_3bytes();
|
||||||
// Read 4bytes int from buffer.
|
// Read 4bytes int from buffer.
|
||||||
virtual int32_t read_4bytes();
|
int32_t read_4bytes();
|
||||||
// Read 8bytes int from buffer.
|
// Read 8bytes int from buffer.
|
||||||
virtual int64_t read_8bytes();
|
int64_t read_8bytes();
|
||||||
// Read string from buffer, length specifies by param len.
|
// Read string from buffer, length specifies by param len.
|
||||||
virtual std::string read_string(int len);
|
std::string read_string(int len);
|
||||||
// Read bytes from buffer, length specifies by param len.
|
// Read bytes from buffer, length specifies by param len.
|
||||||
virtual void read_bytes(char* data, int size);
|
void read_bytes(char* data, int size);
|
||||||
public:
|
public:
|
||||||
// Write 1bytes char to buffer.
|
// Write 1bytes char to buffer.
|
||||||
virtual void write_1bytes(int8_t value);
|
void write_1bytes(int8_t value);
|
||||||
// Write 2bytes int to buffer.
|
// Write 2bytes int to buffer.
|
||||||
virtual void write_2bytes(int16_t value);
|
void write_2bytes(int16_t value);
|
||||||
// Write 4bytes int to buffer.
|
// Write 4bytes int to buffer.
|
||||||
virtual void write_4bytes(int32_t value);
|
void write_4bytes(int32_t value);
|
||||||
// Write 3bytes int to buffer.
|
// Write 3bytes int to buffer.
|
||||||
virtual void write_3bytes(int32_t value);
|
void write_3bytes(int32_t value);
|
||||||
// Write 8bytes int to buffer.
|
// Write 8bytes int to buffer.
|
||||||
virtual void write_8bytes(int64_t value);
|
void write_8bytes(int64_t value);
|
||||||
// Write string to buffer
|
// Write string to buffer
|
||||||
virtual void write_string(std::string value);
|
void write_string(std::string value);
|
||||||
// Write bytes to buffer
|
// Write bytes to buffer
|
||||||
virtual void write_bytes(char* data, int size);
|
void write_bytes(char* data, int size);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -175,10 +175,10 @@ private:
|
||||||
SrsBuffer* stream;
|
SrsBuffer* stream;
|
||||||
public:
|
public:
|
||||||
SrsBitBuffer(SrsBuffer* b);
|
SrsBitBuffer(SrsBuffer* b);
|
||||||
virtual ~SrsBitBuffer();
|
~SrsBitBuffer();
|
||||||
public:
|
public:
|
||||||
virtual bool empty();
|
bool empty();
|
||||||
virtual int8_t read_bit();
|
int8_t read_bit();
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -388,6 +388,36 @@ void SrsSharedPtrMessage::set_extra_payloads(SrsSample* payloads, int nn_payload
|
||||||
memcpy((void*)ptr->extra_payloads, payloads, nn_payloads * sizeof(SrsSample));
|
memcpy((void*)ptr->extra_payloads, payloads, nn_payloads * sizeof(SrsSample));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SrsSharedPtrMessage::nn_extra_payloads()
|
||||||
|
{
|
||||||
|
return ptr->nn_extra_payloads;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsSample* SrsSharedPtrMessage::extra_payloads()
|
||||||
|
{
|
||||||
|
return ptr->extra_payloads;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsSharedPtrMessage::set_max_extra_payload(int v)
|
||||||
|
{
|
||||||
|
ptr->nn_max_extra_payloads = v;
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsSharedPtrMessage::nn_max_extra_payloads()
|
||||||
|
{
|
||||||
|
return ptr->nn_max_extra_payloads;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool SrsSharedPtrMessage::has_idr()
|
||||||
|
{
|
||||||
|
return ptr->has_idr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void SrsSharedPtrMessage::set_has_idr(bool v)
|
||||||
|
{
|
||||||
|
ptr->has_idr = v;
|
||||||
|
}
|
||||||
|
|
||||||
void SrsSharedPtrMessage::set_samples(SrsSample* samples, int nn_samples)
|
void SrsSharedPtrMessage::set_samples(SrsSample* samples, int nn_samples)
|
||||||
{
|
{
|
||||||
srs_assert(nn_samples);
|
srs_assert(nn_samples);
|
||||||
|
@ -398,6 +428,16 @@ void SrsSharedPtrMessage::set_samples(SrsSample* samples, int nn_samples)
|
||||||
ptr->samples = new SrsSample[nn_samples];
|
ptr->samples = new SrsSample[nn_samples];
|
||||||
memcpy((void*)ptr->samples, samples, nn_samples * sizeof(SrsSample));
|
memcpy((void*)ptr->samples, samples, nn_samples * sizeof(SrsSample));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int SrsSharedPtrMessage::nn_samples()
|
||||||
|
{
|
||||||
|
return ptr->nn_samples;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsSample* SrsSharedPtrMessage::samples()
|
||||||
|
{
|
||||||
|
return ptr->samples;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
SrsFlvTransmuxer::SrsFlvTransmuxer()
|
SrsFlvTransmuxer::SrsFlvTransmuxer()
|
||||||
|
|
|
@ -367,18 +367,18 @@ public:
|
||||||
// Set extra samples, for example, when we transcode an AAC audio packet to OPUS,
|
// Set extra samples, for example, when we transcode an AAC audio packet to OPUS,
|
||||||
// we may get more than one OPUS packets, we set these OPUS packets in extra payloads.
|
// we may get more than one OPUS packets, we set these OPUS packets in extra payloads.
|
||||||
void set_extra_payloads(SrsSample* payloads, int nn_payloads);
|
void set_extra_payloads(SrsSample* payloads, int nn_payloads);
|
||||||
int nn_extra_payloads() { return ptr->nn_extra_payloads; }
|
int nn_extra_payloads();
|
||||||
SrsSample* extra_payloads() { return ptr->extra_payloads; }
|
SrsSample* extra_payloads();
|
||||||
// The max extra payload size.
|
// The max extra payload size.
|
||||||
void set_max_extra_payload(int v) { ptr->nn_max_extra_payloads = v; }
|
void set_max_extra_payload(int v);
|
||||||
int nn_max_extra_payloads() { return ptr->nn_max_extra_payloads; }
|
int nn_max_extra_payloads();
|
||||||
// Whether samples has idr.
|
// Whether samples has idr.
|
||||||
bool has_idr() { return ptr->has_idr; }
|
bool has_idr();
|
||||||
void set_has_idr(bool v) { ptr->has_idr = v; }
|
void set_has_idr(bool v);
|
||||||
// Set samples, each sample points to the address of payload.
|
// Set samples, each sample points to the address of payload.
|
||||||
void set_samples(SrsSample* samples, int nn_samples);
|
void set_samples(SrsSample* samples, int nn_samples);
|
||||||
int nn_samples() { return ptr->nn_samples; }
|
int nn_samples();
|
||||||
SrsSample* samples() { return ptr->samples; }
|
SrsSample* samples();
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -61,11 +61,11 @@ SrsRtpHeader::~SrsRtpHeader()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsRtpHeader::decode(SrsBuffer* stream)
|
srs_error_t SrsRtpHeader::decode(SrsBuffer* buf)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
if (stream->size() < kRtpHeaderFixedSize) {
|
if (buf->size() < kRtpHeaderFixedSize) {
|
||||||
return srs_error_new(ERROR_RTC_RTP_MUXER, "rtp payload incorrect");
|
return srs_error_new(ERROR_RTC_RTP_MUXER, "rtp payload incorrect");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -84,60 +84,58 @@ srs_error_t SrsRtpHeader::decode(SrsBuffer* stream)
|
||||||
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
||||||
*/
|
*/
|
||||||
|
|
||||||
uint8_t first = stream->read_1bytes();
|
uint8_t first = buf->read_1bytes();
|
||||||
padding = (first & 0x20);
|
padding = (first & 0x20);
|
||||||
extension = (first & 0x10);
|
extension = (first & 0x10);
|
||||||
cc = (first & 0x0F);
|
cc = (first & 0x0F);
|
||||||
|
|
||||||
uint8_t second = stream->read_1bytes();
|
uint8_t second = buf->read_1bytes();
|
||||||
marker = (second & 0x80);
|
marker = (second & 0x80);
|
||||||
payload_type = (second & 0x7F);
|
payload_type = (second & 0x7F);
|
||||||
|
|
||||||
sequence = stream->read_2bytes();
|
sequence = buf->read_2bytes();
|
||||||
timestamp = stream->read_4bytes();
|
timestamp = buf->read_4bytes();
|
||||||
ssrc = stream->read_4bytes();
|
ssrc = buf->read_4bytes();
|
||||||
|
|
||||||
if ((size_t)stream->size() < header_size()) {
|
if (!buf->require(nb_bytes())) {
|
||||||
return srs_error_new(ERROR_RTC_RTP_MUXER, "rtp payload incorrect");
|
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d+ bytes", nb_bytes());
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint8_t i = 0; i < cc; ++i) {
|
for (uint8_t i = 0; i < cc; ++i) {
|
||||||
csrc[i] = stream->read_4bytes();
|
csrc[i] = buf->read_4bytes();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (extension) {
|
if (extension) {
|
||||||
// TODO:
|
uint16_t profile_id = buf->read_2bytes();
|
||||||
uint16_t profile_id = stream->read_2bytes();
|
extension_length = buf->read_2bytes();
|
||||||
extension_length = stream->read_2bytes();
|
|
||||||
// @see: https://tools.ietf.org/html/rfc3550#section-5.3.1
|
|
||||||
stream->skip(extension_length * 4);
|
|
||||||
|
|
||||||
srs_verbose("extension, profile_id=%u, length=%u", profile_id, extension_length);
|
// TODO: FIXME: Read extensions.
|
||||||
|
// @see: https://tools.ietf.org/html/rfc3550#section-5.3.1
|
||||||
|
buf->skip(extension_length * 4);
|
||||||
|
|
||||||
// @see: https://tools.ietf.org/html/rfc5285#section-4.2
|
// @see: https://tools.ietf.org/html/rfc5285#section-4.2
|
||||||
if (profile_id == 0xBEDE) {
|
if (profile_id == 0xBEDE) {
|
||||||
|
// TODO: FIXME: Implements it.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (padding) {
|
if (padding) {
|
||||||
padding_length = *(reinterpret_cast<uint8_t*>(stream->data() + stream->size() - 1));
|
padding_length = *(reinterpret_cast<uint8_t*>(buf->data() + buf->size() - 1));
|
||||||
if (padding_length > (stream->size() - stream->pos())) {
|
if (!buf->require(padding_length)) {
|
||||||
return srs_error_new(ERROR_RTC_RTP_MUXER, "rtp payload incorrect");
|
return srs_error_new(ERROR_RTC_RTP_MUXER, "padding requires %d bytes", padding_length);
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_verbose("offset=%d, padding_length=%u", stream->size(), padding_length);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
srs_error_t SrsRtpHeader::encode(SrsBuffer* stream)
|
srs_error_t SrsRtpHeader::encode(SrsBuffer* buf)
|
||||||
{
|
{
|
||||||
srs_error_t err = srs_success;
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
// Encode the RTP fix header, 12bytes.
|
// Encode the RTP fix header, 12bytes.
|
||||||
// @see https://tools.ietf.org/html/rfc1889#section-5.1
|
// @see https://tools.ietf.org/html/rfc1889#section-5.1
|
||||||
char* op = stream->head();
|
char* op = buf->head();
|
||||||
char* p = op;
|
char* p = op;
|
||||||
|
|
||||||
// The version, padding, extension and cc, total 1 byte.
|
// The version, padding, extension and cc, total 1 byte.
|
||||||
|
@ -190,24 +188,42 @@ srs_error_t SrsRtpHeader::encode(SrsBuffer* stream)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Consume the data.
|
// Consume the data.
|
||||||
stream->skip(p - op);
|
buf->skip(p - op);
|
||||||
|
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t SrsRtpHeader::header_size()
|
int SrsRtpHeader::nb_bytes()
|
||||||
{
|
{
|
||||||
return kRtpHeaderFixedSize + cc * 4 + (extension ? (extension_length + 1) * 4 : 0);
|
return kRtpHeaderFixedSize + cc * 4 + (extension ? (extension_length + 1) * 4 : 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ISrsRtpPacketDecodeHandler::ISrsRtpPacketDecodeHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
ISrsRtpPacketDecodeHandler::~ISrsRtpPacketDecodeHandler()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
SrsRtpPacket2::SrsRtpPacket2()
|
SrsRtpPacket2::SrsRtpPacket2()
|
||||||
{
|
{
|
||||||
payload = NULL;
|
|
||||||
padding = 0;
|
padding = 0;
|
||||||
|
payload = NULL;
|
||||||
|
decode_handler = NULL;
|
||||||
|
|
||||||
|
is_first_packet_of_frame = false;
|
||||||
|
is_last_packet_of_frame = false;
|
||||||
|
is_key_frame = false;
|
||||||
|
nalu_type = SrsAvcNaluTypeReserved;
|
||||||
|
|
||||||
cache_raw = new SrsRtpRawPayload();
|
cache_raw = new SrsRtpRawPayload();
|
||||||
cache_fua = new SrsRtpFUAPayload2();
|
cache_fua = new SrsRtpFUAPayload2();
|
||||||
cache_payload = 0;
|
cache_payload = 0;
|
||||||
|
|
||||||
|
original_bytes = NULL;
|
||||||
|
nn_original_bytes = 0;
|
||||||
|
nn_original_payload = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsRtpPacket2::~SrsRtpPacket2()
|
SrsRtpPacket2::~SrsRtpPacket2()
|
||||||
|
@ -220,6 +236,8 @@ SrsRtpPacket2::~SrsRtpPacket2()
|
||||||
srs_freep(payload);
|
srs_freep(payload);
|
||||||
srs_freep(cache_raw);
|
srs_freep(cache_raw);
|
||||||
srs_freep(cache_fua);
|
srs_freep(cache_fua);
|
||||||
|
|
||||||
|
srs_freepa(original_bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsRtpPacket2::set_padding(int size)
|
void SrsRtpPacket2::set_padding(int size)
|
||||||
|
@ -270,7 +288,7 @@ SrsRtpFUAPayload2* SrsRtpPacket2::reuse_fua()
|
||||||
int SrsRtpPacket2::nb_bytes()
|
int SrsRtpPacket2::nb_bytes()
|
||||||
{
|
{
|
||||||
if (!cache_payload) {
|
if (!cache_payload) {
|
||||||
cache_payload = rtp_header.header_size() + (payload? payload->nb_bytes():0) + padding;
|
cache_payload = rtp_header.nb_bytes() + (payload? payload->nb_bytes():0) + padding;
|
||||||
}
|
}
|
||||||
return cache_payload;
|
return cache_payload;
|
||||||
}
|
}
|
||||||
|
@ -284,7 +302,7 @@ srs_error_t SrsRtpPacket2::encode(SrsBuffer* buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (payload && (err = payload->encode(buf)) != srs_success) {
|
if (payload && (err = payload->encode(buf)) != srs_success) {
|
||||||
return srs_error_wrap(err, "encode payload");
|
return srs_error_wrap(err, "rtp payload");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (padding > 0) {
|
if (padding > 0) {
|
||||||
|
@ -298,6 +316,44 @@ srs_error_t SrsRtpPacket2::encode(SrsBuffer* buf)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srs_error_t SrsRtpPacket2::decode(SrsBuffer* buf)
|
||||||
|
{
|
||||||
|
srs_error_t err = srs_success;
|
||||||
|
|
||||||
|
if ((err = rtp_header.decode(buf)) != srs_success) {
|
||||||
|
return srs_error_wrap(err, "rtp header");
|
||||||
|
}
|
||||||
|
|
||||||
|
// We must skip the padding bytes before parsing payload.
|
||||||
|
padding = rtp_header.get_padding_length();
|
||||||
|
if (!buf->require(padding)) {
|
||||||
|
return srs_error_wrap(err, "requires padding %d bytes", padding);
|
||||||
|
}
|
||||||
|
buf->set_size(buf->size() - padding);
|
||||||
|
|
||||||
|
// Try to parse the NALU type for video decoder.
|
||||||
|
if (!buf->empty()) {
|
||||||
|
nalu_type = SrsAvcNaluType((uint8_t)(buf->head()[0] & 0x3f));
|
||||||
|
}
|
||||||
|
|
||||||
|
// If user set the decode handler, call it to set the payload.
|
||||||
|
if (decode_handler) {
|
||||||
|
decode_handler->on_before_decode_payload(this, buf, &payload);
|
||||||
|
nn_original_payload = buf->left();
|
||||||
|
}
|
||||||
|
|
||||||
|
// By default, we always use the RAW payload.
|
||||||
|
if (!payload) {
|
||||||
|
payload = reuse_raw();
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((err = payload->decode(buf)) != srs_success) {
|
||||||
|
return srs_error_wrap(err, "rtp payload");
|
||||||
|
}
|
||||||
|
|
||||||
|
return err;
|
||||||
|
}
|
||||||
|
|
||||||
SrsRtpRawPayload::SrsRtpRawPayload()
|
SrsRtpRawPayload::SrsRtpRawPayload()
|
||||||
{
|
{
|
||||||
payload = NULL;
|
payload = NULL;
|
||||||
|
@ -328,6 +384,18 @@ srs_error_t SrsRtpRawPayload::encode(SrsBuffer* buf)
|
||||||
return srs_success;
|
return srs_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srs_error_t SrsRtpRawPayload::decode(SrsBuffer* buf)
|
||||||
|
{
|
||||||
|
if (buf->empty()) {
|
||||||
|
return srs_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
payload = buf->head();
|
||||||
|
nn_payload = buf->left();
|
||||||
|
|
||||||
|
return srs_success;
|
||||||
|
}
|
||||||
|
|
||||||
SrsRtpRawNALUs::SrsRtpRawNALUs()
|
SrsRtpRawNALUs::SrsRtpRawNALUs()
|
||||||
{
|
{
|
||||||
cursor = 0;
|
cursor = 0;
|
||||||
|
@ -336,14 +404,12 @@ SrsRtpRawNALUs::SrsRtpRawNALUs()
|
||||||
|
|
||||||
SrsRtpRawNALUs::~SrsRtpRawNALUs()
|
SrsRtpRawNALUs::~SrsRtpRawNALUs()
|
||||||
{
|
{
|
||||||
if (true) {
|
|
||||||
int nn_nalus = (int)nalus.size();
|
int nn_nalus = (int)nalus.size();
|
||||||
for (int i = 0; i < nn_nalus; i++) {
|
for (int i = 0; i < nn_nalus; i++) {
|
||||||
SrsSample* p = nalus[i];
|
SrsSample* p = nalus[i];
|
||||||
srs_freep(p);
|
srs_freep(p);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void SrsRtpRawNALUs::push_back(SrsSample* sample)
|
void SrsRtpRawNALUs::push_back(SrsSample* sample)
|
||||||
{
|
{
|
||||||
|
@ -436,6 +502,22 @@ srs_error_t SrsRtpRawNALUs::encode(SrsBuffer* buf)
|
||||||
return srs_success;
|
return srs_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srs_error_t SrsRtpRawNALUs::decode(SrsBuffer* buf)
|
||||||
|
{
|
||||||
|
if (buf->empty()) {
|
||||||
|
return srs_success;
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsSample* sample = new SrsSample();
|
||||||
|
sample->bytes = buf->head();
|
||||||
|
sample->size = buf->left();
|
||||||
|
buf->skip(sample->size);
|
||||||
|
|
||||||
|
nalus.push_back(sample);
|
||||||
|
|
||||||
|
return srs_success;
|
||||||
|
}
|
||||||
|
|
||||||
SrsRtpSTAPPayload::SrsRtpSTAPPayload()
|
SrsRtpSTAPPayload::SrsRtpSTAPPayload()
|
||||||
{
|
{
|
||||||
nri = (SrsAvcNaluType)0;
|
nri = (SrsAvcNaluType)0;
|
||||||
|
@ -491,6 +573,39 @@ srs_error_t SrsRtpSTAPPayload::encode(SrsBuffer* buf)
|
||||||
return srs_success;
|
return srs_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srs_error_t SrsRtpSTAPPayload::decode(SrsBuffer* buf)
|
||||||
|
{
|
||||||
|
if (!buf->require(1)) {
|
||||||
|
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
// STAP header, RTP payload format for aggregation packets
|
||||||
|
// @see https://tools.ietf.org/html/rfc6184#section-5.7
|
||||||
|
uint8_t v = buf->read_1bytes();
|
||||||
|
nri = SrsAvcNaluType(v & kNalTypeMask);
|
||||||
|
|
||||||
|
// NALUs.
|
||||||
|
while (!buf->empty()) {
|
||||||
|
if (!buf->require(2)) {
|
||||||
|
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
int size = buf->read_2bytes();
|
||||||
|
if (!buf->require(size)) {
|
||||||
|
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", size);
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsSample* sample = new SrsSample();
|
||||||
|
sample->bytes = buf->head();
|
||||||
|
sample->size = size;
|
||||||
|
buf->skip(size);
|
||||||
|
|
||||||
|
nalus.push_back(sample);
|
||||||
|
}
|
||||||
|
|
||||||
|
return srs_success;
|
||||||
|
}
|
||||||
|
|
||||||
SrsRtpFUAPayload::SrsRtpFUAPayload()
|
SrsRtpFUAPayload::SrsRtpFUAPayload()
|
||||||
{
|
{
|
||||||
start = end = false;
|
start = end = false;
|
||||||
|
@ -555,6 +670,36 @@ srs_error_t SrsRtpFUAPayload::encode(SrsBuffer* buf)
|
||||||
return srs_success;
|
return srs_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srs_error_t SrsRtpFUAPayload::decode(SrsBuffer* buf)
|
||||||
|
{
|
||||||
|
if (!buf->require(2)) {
|
||||||
|
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FU indicator, @see https://tools.ietf.org/html/rfc6184#section-5.8
|
||||||
|
uint8_t v = buf->read_1bytes();
|
||||||
|
nri = SrsAvcNaluType(v & kNalTypeMask);
|
||||||
|
|
||||||
|
// FU header, @see https://tools.ietf.org/html/rfc6184#section-5.8
|
||||||
|
v = buf->read_1bytes();
|
||||||
|
start = v & kStart;
|
||||||
|
end = v & kEnd;
|
||||||
|
nalu_type = SrsAvcNaluType(v & 0x3f);
|
||||||
|
|
||||||
|
if (!buf->require(1)) {
|
||||||
|
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SrsSample* sample = new SrsSample();
|
||||||
|
sample->bytes = buf->head();
|
||||||
|
sample->size = buf->left();
|
||||||
|
buf->skip(sample->size);
|
||||||
|
|
||||||
|
nalus.push_back(sample);
|
||||||
|
|
||||||
|
return srs_success;
|
||||||
|
}
|
||||||
|
|
||||||
SrsRtpFUAPayload2::SrsRtpFUAPayload2()
|
SrsRtpFUAPayload2::SrsRtpFUAPayload2()
|
||||||
{
|
{
|
||||||
start = end = false;
|
start = end = false;
|
||||||
|
@ -606,6 +751,33 @@ srs_error_t SrsRtpFUAPayload2::encode(SrsBuffer* buf)
|
||||||
return srs_success;
|
return srs_success;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
srs_error_t SrsRtpFUAPayload2::decode(SrsBuffer* buf)
|
||||||
|
{
|
||||||
|
if (!buf->require(2)) {
|
||||||
|
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 2);
|
||||||
|
}
|
||||||
|
|
||||||
|
// FU indicator, @see https://tools.ietf.org/html/rfc6184#section-5.8
|
||||||
|
uint8_t v = buf->read_1bytes();
|
||||||
|
nri = SrsAvcNaluType(v & (~kNalTypeMask));
|
||||||
|
|
||||||
|
// FU header, @see https://tools.ietf.org/html/rfc6184#section-5.8
|
||||||
|
v = buf->read_1bytes();
|
||||||
|
start = v & kStart;
|
||||||
|
end = v & kEnd;
|
||||||
|
nalu_type = SrsAvcNaluType(v & 0x3f);
|
||||||
|
|
||||||
|
if (!buf->require(1)) {
|
||||||
|
return srs_error_new(ERROR_RTC_RTP_MUXER, "requires %d bytes", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
payload = buf->head();
|
||||||
|
size = buf->left();
|
||||||
|
buf->skip(size);
|
||||||
|
|
||||||
|
return srs_success;
|
||||||
|
}
|
||||||
|
|
||||||
SrsRtpPayloadHeader::SrsRtpPayloadHeader()
|
SrsRtpPayloadHeader::SrsRtpPayloadHeader()
|
||||||
{
|
{
|
||||||
is_first_packet_of_frame = false;
|
is_first_packet_of_frame = false;
|
||||||
|
@ -721,7 +893,7 @@ srs_error_t SrsRtpSharedPacket::create(SrsRtpHeader* rtp_h, SrsRtpPayloadHeader*
|
||||||
this->rtp_payload_header = rtp_ph;
|
this->rtp_payload_header = rtp_ph;
|
||||||
|
|
||||||
// TODO: rtp header padding.
|
// TODO: rtp header padding.
|
||||||
size_t buffer_size = rtp_header.header_size() + s;
|
int buffer_size = rtp_header.nb_bytes() + s;
|
||||||
|
|
||||||
char* buffer = new char[buffer_size];
|
char* buffer = new char[buffer_size];
|
||||||
SrsBuffer stream(buffer, buffer_size);
|
SrsBuffer stream(buffer, buffer_size);
|
||||||
|
|
|
@ -31,6 +31,8 @@
|
||||||
|
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
|
class SrsRtpPacket2;
|
||||||
|
|
||||||
const int kRtpHeaderFixedSize = 12;
|
const int kRtpHeaderFixedSize = 12;
|
||||||
const uint8_t kRtpMarker = 0x80;
|
const uint8_t kRtpMarker = 0x80;
|
||||||
|
|
||||||
|
@ -72,10 +74,9 @@ public:
|
||||||
virtual ~SrsRtpHeader();
|
virtual ~SrsRtpHeader();
|
||||||
void reset();
|
void reset();
|
||||||
public:
|
public:
|
||||||
srs_error_t decode(SrsBuffer* stream);
|
virtual srs_error_t decode(SrsBuffer* buf);
|
||||||
srs_error_t encode(SrsBuffer* stream);
|
virtual srs_error_t encode(SrsBuffer* buf);
|
||||||
public:
|
virtual int nb_bytes();
|
||||||
size_t header_size();
|
|
||||||
public:
|
public:
|
||||||
inline void set_marker(bool v) { marker = v; }
|
inline void set_marker(bool v) { marker = v; }
|
||||||
bool get_marker() const { return marker; }
|
bool get_marker() const { return marker; }
|
||||||
|
@ -92,16 +93,48 @@ public:
|
||||||
uint8_t get_padding_length() const { return padding_length; }
|
uint8_t get_padding_length() const { return padding_length; }
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsRtpPacket2
|
class ISrsRtpPacketDecodeHandler
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
ISrsRtpPacketDecodeHandler();
|
||||||
|
virtual ~ISrsRtpPacketDecodeHandler();
|
||||||
|
public:
|
||||||
|
// We don't know the actual payload, so we depends on external handler.
|
||||||
|
virtual void on_before_decode_payload(SrsRtpPacket2* pkt, SrsBuffer* buf, ISrsCodec** ppayload) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SrsRtpPacket2
|
||||||
|
{
|
||||||
|
// RTP packet fields.
|
||||||
|
public:
|
||||||
|
// TODO: FIXME: Rename to header.
|
||||||
SrsRtpHeader rtp_header;
|
SrsRtpHeader rtp_header;
|
||||||
ISrsEncoder* payload;
|
ISrsCodec* payload;
|
||||||
|
// TODO: FIXME: Merge into rtp_header.
|
||||||
int padding;
|
int padding;
|
||||||
|
// Decoder helper.
|
||||||
|
public:
|
||||||
|
// Helper information for decoder.
|
||||||
|
bool is_first_packet_of_frame;
|
||||||
|
bool is_last_packet_of_frame;
|
||||||
|
bool is_key_frame;
|
||||||
|
// The first byte as nalu type, for video decoder only.
|
||||||
|
SrsAvcNaluType nalu_type;
|
||||||
|
// The original payload bytes length.
|
||||||
|
int nn_original_payload;
|
||||||
|
// Decoder helper.
|
||||||
private:
|
private:
|
||||||
|
// The original bytes for decoder only, we will free it.
|
||||||
|
char* original_bytes;
|
||||||
|
int nn_original_bytes;
|
||||||
|
// Fast cache for performance.
|
||||||
|
private:
|
||||||
|
// Cache frequently used payload for performance.
|
||||||
SrsRtpRawPayload* cache_raw;
|
SrsRtpRawPayload* cache_raw;
|
||||||
SrsRtpFUAPayload2* cache_fua;
|
SrsRtpFUAPayload2* cache_fua;
|
||||||
int cache_payload;
|
int cache_payload;
|
||||||
|
// The helper handler for decoder, use RAW payload if NULL.
|
||||||
|
ISrsRtpPacketDecodeHandler* decode_handler;
|
||||||
public:
|
public:
|
||||||
SrsRtpPacket2();
|
SrsRtpPacket2();
|
||||||
virtual ~SrsRtpPacket2();
|
virtual ~SrsRtpPacket2();
|
||||||
|
@ -116,14 +149,19 @@ public:
|
||||||
SrsRtpRawPayload* reuse_raw();
|
SrsRtpRawPayload* reuse_raw();
|
||||||
// Reuse the cached fua message as payload.
|
// Reuse the cached fua message as payload.
|
||||||
SrsRtpFUAPayload2* reuse_fua();
|
SrsRtpFUAPayload2* reuse_fua();
|
||||||
|
// Set the decode handler.
|
||||||
|
void set_decode_handler(ISrsRtpPacketDecodeHandler* h) { decode_handler = h; }
|
||||||
|
// Set the original bytes.
|
||||||
|
void set_original_bytes(char* buf, int nn_buf) { original_bytes = buf; nn_original_bytes = nn_buf; }
|
||||||
// interface ISrsEncoder
|
// interface ISrsEncoder
|
||||||
public:
|
public:
|
||||||
virtual int nb_bytes();
|
virtual int nb_bytes();
|
||||||
virtual srs_error_t encode(SrsBuffer* buf);
|
virtual srs_error_t encode(SrsBuffer* buf);
|
||||||
|
virtual srs_error_t decode(SrsBuffer* buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Single payload data.
|
// Single payload data.
|
||||||
class SrsRtpRawPayload : public ISrsEncoder
|
class SrsRtpRawPayload : public ISrsCodec
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// The RAW payload, directly point to the shared memory.
|
// The RAW payload, directly point to the shared memory.
|
||||||
|
@ -137,10 +175,11 @@ public:
|
||||||
public:
|
public:
|
||||||
virtual int nb_bytes();
|
virtual int nb_bytes();
|
||||||
virtual srs_error_t encode(SrsBuffer* buf);
|
virtual srs_error_t encode(SrsBuffer* buf);
|
||||||
|
virtual srs_error_t decode(SrsBuffer* buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
// Multiple NALUs, automatically insert 001 between NALUs.
|
// Multiple NALUs, automatically insert 001 between NALUs.
|
||||||
class SrsRtpRawNALUs : public ISrsEncoder
|
class SrsRtpRawNALUs : public ISrsCodec
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
// We will manage the samples, but the sample itself point to the shared memory.
|
// We will manage the samples, but the sample itself point to the shared memory.
|
||||||
|
@ -160,10 +199,11 @@ public:
|
||||||
public:
|
public:
|
||||||
virtual int nb_bytes();
|
virtual int nb_bytes();
|
||||||
virtual srs_error_t encode(SrsBuffer* buf);
|
virtual srs_error_t encode(SrsBuffer* buf);
|
||||||
|
virtual srs_error_t decode(SrsBuffer* buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
// STAP-A, for multiple NALUs.
|
// STAP-A, for multiple NALUs.
|
||||||
class SrsRtpSTAPPayload : public ISrsEncoder
|
class SrsRtpSTAPPayload : public ISrsCodec
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// The NRI in NALU type.
|
// The NRI in NALU type.
|
||||||
|
@ -178,11 +218,12 @@ public:
|
||||||
public:
|
public:
|
||||||
virtual int nb_bytes();
|
virtual int nb_bytes();
|
||||||
virtual srs_error_t encode(SrsBuffer* buf);
|
virtual srs_error_t encode(SrsBuffer* buf);
|
||||||
|
virtual srs_error_t decode(SrsBuffer* buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
// FU-A, for one NALU with multiple fragments.
|
// FU-A, for one NALU with multiple fragments.
|
||||||
// With more than one payload.
|
// With more than one payload.
|
||||||
class SrsRtpFUAPayload : public ISrsEncoder
|
class SrsRtpFUAPayload : public ISrsCodec
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// The NRI in NALU type.
|
// The NRI in NALU type.
|
||||||
|
@ -201,11 +242,12 @@ public:
|
||||||
public:
|
public:
|
||||||
virtual int nb_bytes();
|
virtual int nb_bytes();
|
||||||
virtual srs_error_t encode(SrsBuffer* buf);
|
virtual srs_error_t encode(SrsBuffer* buf);
|
||||||
|
virtual srs_error_t decode(SrsBuffer* buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
// FU-A, for one NALU with multiple fragments.
|
// FU-A, for one NALU with multiple fragments.
|
||||||
// With only one payload.
|
// With only one payload.
|
||||||
class SrsRtpFUAPayload2 : public ISrsEncoder
|
class SrsRtpFUAPayload2 : public ISrsCodec
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
// The NRI in NALU type.
|
// The NRI in NALU type.
|
||||||
|
@ -224,6 +266,7 @@ public:
|
||||||
public:
|
public:
|
||||||
virtual int nb_bytes();
|
virtual int nb_bytes();
|
||||||
virtual srs_error_t encode(SrsBuffer* buf);
|
virtual srs_error_t encode(SrsBuffer* buf);
|
||||||
|
virtual srs_error_t decode(SrsBuffer* buf);
|
||||||
};
|
};
|
||||||
|
|
||||||
class SrsRtpPayloadHeader
|
class SrsRtpPayloadHeader
|
||||||
|
@ -290,8 +333,8 @@ public:
|
||||||
srs_error_t decode(char* buf, int nb_buf);
|
srs_error_t decode(char* buf, int nb_buf);
|
||||||
SrsRtpSharedPacket* copy();
|
SrsRtpSharedPacket* copy();
|
||||||
public:
|
public:
|
||||||
char* rtp_payload() { return payload + rtp_header.header_size(); }
|
char* rtp_payload() { return payload + rtp_header.nb_bytes(); }
|
||||||
int rtp_payload_size() { return size - rtp_header.header_size() - rtp_header.get_padding_length(); }
|
int rtp_payload_size() { return size - rtp_header.nb_bytes() - rtp_header.get_padding_length(); }
|
||||||
// Interface to modify rtp header
|
// Interface to modify rtp header
|
||||||
public:
|
public:
|
||||||
srs_error_t modify_rtp_header_marker(bool marker);
|
srs_error_t modify_rtp_header_marker(bool marker);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue