mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
h264 packet done, chrome play well
This commit is contained in:
parent
e831f3254a
commit
da72caf8b9
6 changed files with 169 additions and 297 deletions
|
@ -50,42 +50,6 @@ using namespace std;
|
|||
#include <srs_protocol_format.hpp>
|
||||
#include <openssl/rand.h>
|
||||
|
||||
static string dump_string_hex(const char* buf, const int nb_buf, const int& max_len);
|
||||
static string dump_string_hex(const std::string& str, const int& max_len = 128)
|
||||
{
|
||||
return dump_string_hex(str.c_str(), str.size(), max_len);
|
||||
}
|
||||
|
||||
static string dump_string_hex(const char* buf, const int nb_buf, const int& max_len = 128)
|
||||
{
|
||||
string ret;
|
||||
ret.reserve(max_len * 4);
|
||||
|
||||
char tmp_buf[1024*16];
|
||||
tmp_buf[0] = '\n';
|
||||
int len = 1;
|
||||
|
||||
for (int i = 0; i < nb_buf && i < max_len; ++i) {
|
||||
//int nb = snprintf(tmp_buf + len, sizeof(tmp_buf) - len - 2, "(%03d)%02X ", i, (uint8_t)buf[i]);
|
||||
int nb = snprintf(tmp_buf + len, sizeof(tmp_buf) - len - 2, "%02X ", (uint8_t)buf[i]);
|
||||
if (nb <= 0)
|
||||
break;
|
||||
|
||||
len += nb;
|
||||
|
||||
if (i % 48 == 47) {
|
||||
tmp_buf[len++] = '\n';
|
||||
ret.append(tmp_buf, len);
|
||||
len = 0;
|
||||
}
|
||||
}
|
||||
tmp_buf[len] = '\0';
|
||||
ret.append(tmp_buf, len);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
SrsRtpMuxer::SrsRtpMuxer()
|
||||
{
|
||||
sequence = 0;
|
||||
|
@ -95,182 +59,6 @@ SrsRtpMuxer::~SrsRtpMuxer()
|
|||
{
|
||||
}
|
||||
|
||||
#if 0
|
||||
srs_error_t SrsRtpMuxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, SrsFormat* format)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
int nb_samples = format->video->nb_samples;
|
||||
SrsSample* samples = format->video->samples;
|
||||
|
||||
SrsSample* rtp_fragment_samples = new SrsSample[2000];
|
||||
int rtp_fragment_samples_index = 0;
|
||||
|
||||
static int debug_fd = -1;
|
||||
static uint8_t start_code[4] = {0x00, 0x00, 0x00, 0x01};
|
||||
if (debug_fd < 0) {
|
||||
debug_fd = open("./raw.264", O_CREAT|O_TRUNC|O_RDWR, 0664);
|
||||
}
|
||||
|
||||
SrsSample sps_pps_samples[2];
|
||||
if (format->is_avc_sequence_header()) {
|
||||
sps_pps_samples[0].bytes = format->vcodec->sequenceParameterSetNALUnit.data();
|
||||
sps_pps_samples[0].size = format->vcodec->sequenceParameterSetNALUnit.size();
|
||||
sps_pps_samples[1].bytes = format->vcodec->pictureParameterSetNALUnit.data();
|
||||
sps_pps_samples[1].size = format->vcodec->pictureParameterSetNALUnit.size();
|
||||
|
||||
nb_samples = 2;
|
||||
samples = sps_pps_samples;
|
||||
|
||||
{
|
||||
char* buf = new char[1460];
|
||||
SrsBuffer* stream = new SrsBuffer(buf, 1460);
|
||||
SrsAutoFree(SrsBuffer, stream);
|
||||
// write rtp header first
|
||||
stream->write_1bytes(0x80);
|
||||
stream->write_1bytes(102);
|
||||
|
||||
stream->write_2bytes(sequence++);
|
||||
stream->write_4bytes((int32_t)shared_frame->timestamp * 90);
|
||||
stream->write_4bytes((int32_t)3233846889);
|
||||
|
||||
stream->write_1bytes(24/*STAP-A*/);
|
||||
// AUD
|
||||
stream->write_2bytes(2);
|
||||
stream->write_1bytes(0x09);
|
||||
stream->write_1bytes(0x10);
|
||||
|
||||
stream->write_2bytes(sps_pps_samples[0].size);
|
||||
stream->write_bytes(sps_pps_samples[0].bytes, sps_pps_samples[0].size);
|
||||
stream->write_2bytes(sps_pps_samples[1].size);
|
||||
stream->write_bytes(sps_pps_samples[1].bytes, sps_pps_samples[1].size);
|
||||
|
||||
if (debug_fd >= 0) {
|
||||
write(debug_fd, start_code, sizeof(start_code));
|
||||
write(debug_fd, sps_pps_samples[0].bytes, sps_pps_samples[0].size);
|
||||
write(debug_fd, start_code, sizeof(start_code));
|
||||
write(debug_fd, sps_pps_samples[1].bytes, sps_pps_samples[1].size);
|
||||
}
|
||||
|
||||
rtp_fragment_samples[rtp_fragment_samples_index].bytes = stream->data();
|
||||
rtp_fragment_samples[rtp_fragment_samples_index].size = stream->pos();
|
||||
|
||||
++rtp_fragment_samples_index;
|
||||
}
|
||||
shared_frame->set_rtp_fragments(rtp_fragment_samples, rtp_fragment_samples_index);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
for (int i = 0; i < nb_samples; ++i) {
|
||||
SrsSample sample = samples[i];
|
||||
|
||||
srs_trace("nal size=%d, dump=%s", sample.size, dump_string_hex(sample.bytes, sample.size, sample.size).c_str());
|
||||
|
||||
if ((sample.bytes[0] & 0x1F) == 0x06) {
|
||||
srs_trace("ignore SEI");
|
||||
continue;
|
||||
}
|
||||
|
||||
if (debug_fd >= 0) {
|
||||
write(debug_fd, start_code, sizeof(start_code));
|
||||
write(debug_fd, sample.bytes, sample.size);
|
||||
}
|
||||
|
||||
static int max_packet_size = 900;
|
||||
if (sample.size <= max_packet_size) {
|
||||
char* buf = new char[1460];
|
||||
SrsBuffer* stream = new SrsBuffer(buf, 1460);
|
||||
SrsAutoFree(SrsBuffer, stream);
|
||||
// write rtp header first
|
||||
stream->write_1bytes(0x80);
|
||||
if ((sample.bytes[0] & 0x1F) <= 5) {
|
||||
stream->write_1bytes((1 << 7) | 102);
|
||||
} else {
|
||||
stream->write_1bytes(102);
|
||||
}
|
||||
|
||||
stream->write_2bytes(sequence++);
|
||||
stream->write_4bytes((int32_t)shared_frame->timestamp * 90);
|
||||
stream->write_4bytes((int32_t)3233846889);
|
||||
|
||||
#if 0 // single nalu
|
||||
stream->write_bytes(sample.bytes, sample.size);
|
||||
#else
|
||||
stream->write_1bytes((sample.bytes[0] & 0xE0) | 24/*STAP-A*/);
|
||||
stream->write_2bytes(sample.size);
|
||||
stream->write_bytes(sample.bytes, sample.size);
|
||||
#endif
|
||||
|
||||
rtp_fragment_samples[rtp_fragment_samples_index].bytes = stream->data();
|
||||
rtp_fragment_samples[rtp_fragment_samples_index].size = stream->pos();
|
||||
|
||||
++rtp_fragment_samples_index;
|
||||
} else {
|
||||
int num_of_packet = (sample.size + max_packet_size) / max_packet_size;
|
||||
char* p = sample.bytes + 1;
|
||||
int left_bytes = sample.size - 1;
|
||||
for (int n = 0; n < num_of_packet; ++n) {
|
||||
char* buf = new char[1460];
|
||||
SrsBuffer* stream = new SrsBuffer(buf, 1460);
|
||||
SrsAutoFree(SrsBuffer, stream);
|
||||
// write rtp header first
|
||||
stream->write_1bytes(0x80);
|
||||
if ((sample.bytes[0] & 0x1F) <= 5) {
|
||||
stream->write_1bytes((1 << 7) | 102);
|
||||
} else {
|
||||
stream->write_1bytes(102);
|
||||
}
|
||||
|
||||
stream->write_2bytes(sequence++);
|
||||
stream->write_4bytes((int32_t)shared_frame->timestamp * 90);
|
||||
stream->write_4bytes((int32_t)3233846889);
|
||||
|
||||
stream->write_1bytes((sample.bytes[0] & 0xE0) | 28);
|
||||
if (n == 0) {
|
||||
stream->write_1bytes(0x80 | (sample.bytes[0] & 0x1F));
|
||||
} else if (n == num_of_packet - 1) {
|
||||
stream->write_1bytes(0x40 | (sample.bytes[0] & 0x1F));
|
||||
} else {
|
||||
stream->write_1bytes(0x00 | (sample.bytes[0] & 0x1F));
|
||||
}
|
||||
|
||||
int len = left_bytes > max_packet_size ? max_packet_size : left_bytes;
|
||||
stream->write_bytes(p, len);
|
||||
left_bytes -= len;
|
||||
p += len;
|
||||
|
||||
rtp_fragment_samples[rtp_fragment_samples_index].bytes = stream->data();
|
||||
rtp_fragment_samples[rtp_fragment_samples_index].size = stream->pos();
|
||||
|
||||
++rtp_fragment_samples_index;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
shared_frame->set_rtp_fragments(rtp_fragment_samples, rtp_fragment_samples_index);
|
||||
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
const int max_payload_size = 1200;
|
||||
const int kRtpPacketSize = 1500;
|
||||
|
||||
const uint8_t kMarker = 0x80;
|
||||
const uint8_t kH264PayloadType = 102;
|
||||
|
||||
const uint8_t kNalTypeMask = 0x1F;
|
||||
|
||||
const uint8_t kIdr = 5;
|
||||
const uint8_t kStapA = 24;
|
||||
const uint8_t kFua = 28;
|
||||
|
||||
const uint8_t kStart = 0x80;
|
||||
const uint8_t kEnd = 0x40;
|
||||
|
||||
const uint32_t kVideoSSRC = 3233846889;
|
||||
|
||||
srs_error_t SrsRtpMuxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, SrsFormat* format)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
@ -280,11 +68,13 @@ srs_error_t SrsRtpMuxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, SrsF
|
|||
pps.assign(format->vcodec->pictureParameterSetNALUnit.data(), format->vcodec->pictureParameterSetNALUnit.size());
|
||||
}
|
||||
|
||||
vector<SrsSample> rtp_packet_vec;
|
||||
|
||||
for (int i = 0; i < format->video->nb_samples; ++i) {
|
||||
SrsSample sample = format->video->samples[i];
|
||||
|
||||
uint8_t header = sample.bytes[0];
|
||||
uint8_t nal_type = header & 0x1F;
|
||||
uint8_t nal_type = header & kNalTypeMask;
|
||||
|
||||
if (nal_type == 0x06) {
|
||||
srs_trace("ignore SEI");
|
||||
|
@ -292,9 +82,9 @@ srs_error_t SrsRtpMuxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, SrsF
|
|||
}
|
||||
|
||||
if (sample.size <= max_payload_size) {
|
||||
packet_single_nalu(shared_frame, format, &sample);
|
||||
packet_single_nalu(shared_frame, format, &sample, rtp_packet_vec);
|
||||
} else {
|
||||
packet_fu_a(shared_frame, format, &sample);
|
||||
packet_fu_a(shared_frame, format, &sample, rtp_packet_vec);
|
||||
}
|
||||
|
||||
srs_trace("nal size=%d, nal=%s", sample.size, dump_string_hex(sample.bytes, sample.size, sample.size).c_str());
|
||||
|
@ -303,15 +93,20 @@ srs_error_t SrsRtpMuxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, SrsF
|
|||
}
|
||||
}
|
||||
|
||||
SrsSample* rtp_samples = new SrsSample[rtp_packet_vec.size()];
|
||||
for (int i = 0; i < rtp_packet_vec.size(); ++i) {
|
||||
rtp_samples[i] = rtp_packet_vec[i];
|
||||
}
|
||||
|
||||
shared_frame->set_rtp_fragments(rtp_samples, rtp_packet_vec.size());
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtpMuxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample)
|
||||
srs_error_t SrsRtpMuxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, vector<SrsSample>& rtp_packet_vec)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
vector<SrsSample> rtp_packet_vec;
|
||||
|
||||
char* p = sample->bytes + 1;
|
||||
int nb_left = sample->size - 1;
|
||||
uint8_t header = sample->bytes[0];
|
||||
|
@ -325,7 +120,7 @@ srs_error_t SrsRtpMuxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsForma
|
|||
int avg_packet_size = sample->size / num_of_packet;
|
||||
for (int i = 0; i < num_of_packet; ++i) {
|
||||
char* buf = new char[kRtpPacketSize];
|
||||
SrsBuffer* stream = new SrsBuffer(buf, 1460);
|
||||
SrsBuffer* stream = new SrsBuffer(buf, kRtpPacketSize);
|
||||
SrsAutoFree(SrsBuffer, stream);
|
||||
|
||||
int packet_size = min(nb_left, max_payload_size);
|
||||
|
@ -333,8 +128,13 @@ srs_error_t SrsRtpMuxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsForma
|
|||
// v=2,p=0,x=0,cc=0
|
||||
stream->write_1bytes(0x80);
|
||||
// marker payloadtype
|
||||
stream->write_1bytes(kMarker | kH264PayloadType);
|
||||
// sequenct
|
||||
if (i == num_of_packet - 1) {
|
||||
stream->write_1bytes(kMarker | kH264PayloadType);
|
||||
} else {
|
||||
stream->write_1bytes(kH264PayloadType);
|
||||
}
|
||||
// sequence
|
||||
srs_trace("sequence=%u", sequence);
|
||||
stream->write_2bytes(sequence++);
|
||||
// timestamp
|
||||
stream->write_4bytes(int32_t(shared_frame->timestamp * 90));
|
||||
|
@ -342,11 +142,11 @@ srs_error_t SrsRtpMuxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsForma
|
|||
stream->write_4bytes(int32_t(kVideoSSRC));
|
||||
|
||||
// fu-indicate
|
||||
uint8_t fu_indicate = kFua;
|
||||
fu_indicate |= (nal_type & (~kNalTypeMask));
|
||||
uint8_t fu_indicate = kFuA;
|
||||
fu_indicate |= (header & (~kNalTypeMask));
|
||||
stream->write_1bytes(fu_indicate);
|
||||
|
||||
uint8_t fu_header = nal_type & kNalTypeMask;
|
||||
uint8_t fu_header = nal_type;
|
||||
if (i == 0)
|
||||
fu_header |= kStart;
|
||||
if (i == num_of_packet - 1)
|
||||
|
@ -355,7 +155,7 @@ srs_error_t SrsRtpMuxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsForma
|
|||
|
||||
stream->write_bytes(p, packet_size);
|
||||
p += packet_size;
|
||||
nb_left -= max_payload_size;
|
||||
nb_left -= packet_size;
|
||||
|
||||
|
||||
SrsSample rtp_packet;
|
||||
|
@ -364,26 +164,17 @@ srs_error_t SrsRtpMuxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsForma
|
|||
|
||||
rtp_packet_vec.push_back(rtp_packet);
|
||||
}
|
||||
|
||||
SrsSample* rtp_samples = new SrsSample[rtp_packet_vec.size()];
|
||||
for (int i = 0; i < rtp_packet_vec.size(); ++i) {
|
||||
rtp_samples[i] = rtp_packet_vec[i];
|
||||
}
|
||||
|
||||
shared_frame->set_rtp_fragments(rtp_samples, rtp_packet_vec.size());
|
||||
}
|
||||
|
||||
srs_error_t SrsRtpMuxer::packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample)
|
||||
srs_error_t SrsRtpMuxer::packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, vector<SrsSample>& rtp_packet_vec)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
vector<SrsSample> rtp_packet_vec;
|
||||
|
||||
uint8_t header = sample->bytes[0];
|
||||
uint8_t nal_type = header & kNalTypeMask;
|
||||
|
||||
char* buf = new char[kRtpPacketSize];
|
||||
SrsBuffer* stream = new SrsBuffer(buf, 1460);
|
||||
SrsBuffer* stream = new SrsBuffer(buf, kRtpPacketSize);
|
||||
SrsAutoFree(SrsBuffer, stream);
|
||||
|
||||
if (nal_type == kIdr) {
|
||||
|
@ -395,6 +186,7 @@ srs_error_t SrsRtpMuxer::packet_single_nalu(SrsSharedPtrMessage* shared_frame, S
|
|||
// marker payloadtype
|
||||
stream->write_1bytes(kMarker | kH264PayloadType);
|
||||
// sequenct
|
||||
srs_trace("sequence=%u", sequence);
|
||||
stream->write_2bytes(sequence++);
|
||||
// timestamp
|
||||
stream->write_4bytes(int32_t(shared_frame->timestamp * 90));
|
||||
|
@ -407,12 +199,7 @@ srs_error_t SrsRtpMuxer::packet_single_nalu(SrsSharedPtrMessage* shared_frame, S
|
|||
rtp_packet.bytes = stream->data();
|
||||
rtp_packet.size = stream->pos();
|
||||
|
||||
SrsSample* rtp_samples = new SrsSample[rtp_packet_vec.size()];
|
||||
for (int i = 0; i < rtp_packet_vec.size(); ++i) {
|
||||
rtp_samples[i] = rtp_packet_vec[i];
|
||||
}
|
||||
|
||||
shared_frame->set_rtp_fragments(rtp_samples, rtp_packet_vec.size());
|
||||
rtp_packet_vec.push_back(rtp_packet);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
@ -425,7 +212,7 @@ srs_error_t SrsRtpMuxer::packet_stap_a(const string &sps, const string& pps, Srs
|
|||
uint8_t nal_type = header & kNalTypeMask;
|
||||
|
||||
char* buf = new char[kRtpPacketSize];
|
||||
SrsBuffer* stream = new SrsBuffer(buf, 1460);
|
||||
SrsBuffer* stream = new SrsBuffer(buf, kRtpPacketSize);
|
||||
SrsAutoFree(SrsBuffer, stream);
|
||||
|
||||
// v=2,p=0,x=0,cc=0
|
||||
|
@ -433,6 +220,7 @@ srs_error_t SrsRtpMuxer::packet_stap_a(const string &sps, const string& pps, Srs
|
|||
// marker payloadtype
|
||||
stream->write_1bytes(kMarker | kH264PayloadType);
|
||||
// sequenct
|
||||
srs_trace("sequence=%u", sequence);
|
||||
stream->write_2bytes(sequence++);
|
||||
// timestamp
|
||||
stream->write_4bytes(int32_t(shared_frame->timestamp * 90));
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue