1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-24 06:54:22 +00:00
srs/trunk/src/app/srs_app_rtp.cpp

380 lines
10 KiB
C++
Raw Normal View History

2020-03-08 11:20:46 +00:00
/**
* The MIT License (MIT)
*
* Copyright (c) 2013-2020 Winlin
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
* IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <srs_app_rtp.hpp>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <unistd.h>
#include <algorithm>
#include <sstream>
using namespace std;
#include <srs_kernel_buffer.hpp>
#include <srs_kernel_error.hpp>
#include <srs_kernel_codec.hpp>
#include <srs_kernel_flv.hpp>
#include <srs_app_config.hpp>
#include <srs_app_source.hpp>
#include <srs_core_autofree.hpp>
#include <srs_app_pithy_print.hpp>
#include <srs_kernel_utility.hpp>
#include <srs_kernel_codec.hpp>
#include <srs_kernel_file.hpp>
#include <srs_app_utility.hpp>
#include <srs_app_http_hooks.hpp>
#include <srs_protocol_format.hpp>
#include <openssl/rand.h>
SrsRtpMuxer::SrsRtpMuxer()
{
2020-03-08 16:40:30 +00:00
sequence = 0;
2020-03-08 11:20:46 +00:00
}
SrsRtpMuxer::~SrsRtpMuxer()
{
}
2020-03-10 16:04:12 +00:00
srs_error_t SrsRtpMuxer::frame_to_packet(SrsSharedPtrMessage* shared_frame, SrsFormat* format)
{
srs_error_t err = srs_success;
if (format->is_avc_sequence_header()) {
sps.assign(format->vcodec->sequenceParameterSetNALUnit.data(), format->vcodec->sequenceParameterSetNALUnit.size());
pps.assign(format->vcodec->pictureParameterSetNALUnit.data(), format->vcodec->pictureParameterSetNALUnit.size());
2020-03-10 11:47:49 +00:00
}
2020-03-11 11:21:44 +00:00
vector<SrsSample> rtp_packet_vec;
2020-03-10 16:04:12 +00:00
for (int i = 0; i < format->video->nb_samples; ++i) {
SrsSample sample = format->video->samples[i];
2020-03-10 16:04:12 +00:00
uint8_t header = sample.bytes[0];
2020-03-11 11:21:44 +00:00
uint8_t nal_type = header & kNalTypeMask;
2020-03-10 16:04:12 +00:00
if (nal_type == 0x06) {
2020-03-10 11:47:49 +00:00
srs_trace("ignore SEI");
continue;
}
2020-03-10 16:04:12 +00:00
if (sample.size <= max_payload_size) {
2020-03-11 11:21:44 +00:00
packet_single_nalu(shared_frame, format, &sample, rtp_packet_vec);
2020-03-10 16:04:12 +00:00
} else {
2020-03-11 11:21:44 +00:00
packet_fu_a(shared_frame, format, &sample, rtp_packet_vec);
2020-03-10 11:47:49 +00:00
}
#if 0
2020-03-10 16:04:12 +00:00
srs_trace("nal size=%d, nal=%s", sample.size, dump_string_hex(sample.bytes, sample.size, sample.size).c_str());
for (int i = 0; i < shared_frame->nb_rtp_fragments; ++i) {
srs_trace("rtp=%s", dump_string_hex(shared_frame->rtp_fragments[i].bytes, shared_frame->rtp_fragments[i].size, kRtpPacketSize).c_str());
}
#endif
2020-03-10 16:04:12 +00:00
}
2020-03-11 11:21:44 +00:00
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());
2020-03-10 16:04:12 +00:00
return err;
}
2020-03-10 11:47:49 +00:00
2020-03-11 11:21:44 +00:00
srs_error_t SrsRtpMuxer::packet_fu_a(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, vector<SrsSample>& rtp_packet_vec)
2020-03-10 16:04:12 +00:00
{
srs_error_t err = srs_success;
2020-03-10 16:04:12 +00:00
char* p = sample->bytes + 1;
int nb_left = sample->size - 1;
uint8_t header = sample->bytes[0];
uint8_t nal_type = header & kNalTypeMask;
2020-03-10 16:04:12 +00:00
if (nal_type == kIdr) {
packet_stap_a(sps, pps, shared_frame, rtp_packet_vec);
}
2020-03-10 16:04:12 +00:00
int num_of_packet = (sample->size - 1 + max_payload_size) / max_payload_size;
int avg_packet_size = sample->size / num_of_packet;
for (int i = 0; i < num_of_packet; ++i) {
char* buf = new char[kRtpPacketSize];
2020-03-11 11:21:44 +00:00
SrsBuffer* stream = new SrsBuffer(buf, kRtpPacketSize);
2020-03-10 16:04:12 +00:00
SrsAutoFree(SrsBuffer, stream);
int packet_size = min(nb_left, max_payload_size);
// v=2,p=0,x=0,cc=0
stream->write_1bytes(0x80);
// marker payloadtype
2020-03-11 11:21:44 +00:00
if (i == num_of_packet - 1) {
stream->write_1bytes(kMarker | kH264PayloadType);
} else {
stream->write_1bytes(kH264PayloadType);
}
// sequence
2020-03-10 16:04:12 +00:00
stream->write_2bytes(sequence++);
// timestamp
stream->write_4bytes(int32_t(shared_frame->timestamp * 90));
// ssrc
stream->write_4bytes(int32_t(kVideoSSRC));
// fu-indicate
2020-03-11 11:21:44 +00:00
uint8_t fu_indicate = kFuA;
fu_indicate |= (header & (~kNalTypeMask));
2020-03-10 16:04:12 +00:00
stream->write_1bytes(fu_indicate);
2020-03-11 11:21:44 +00:00
uint8_t fu_header = nal_type;
2020-03-10 16:04:12 +00:00
if (i == 0)
fu_header |= kStart;
if (i == num_of_packet - 1)
fu_header |= kEnd;
stream->write_1bytes(fu_header);
stream->write_bytes(p, packet_size);
p += packet_size;
2020-03-11 11:21:44 +00:00
nb_left -= packet_size;
2020-03-10 16:04:12 +00:00
SrsSample rtp_packet;
rtp_packet.bytes = stream->data();
rtp_packet.size = stream->pos();
rtp_packet_vec.push_back(rtp_packet);
}
}
2020-03-09 16:45:40 +00:00
2020-03-11 11:21:44 +00:00
srs_error_t SrsRtpMuxer::packet_single_nalu(SrsSharedPtrMessage* shared_frame, SrsFormat* format, SrsSample* sample, vector<SrsSample>& rtp_packet_vec)
2020-03-10 16:04:12 +00:00
{
srs_error_t err = srs_success;
2020-03-09 16:45:40 +00:00
2020-03-10 16:04:12 +00:00
uint8_t header = sample->bytes[0];
uint8_t nal_type = header & kNalTypeMask;
char* buf = new char[kRtpPacketSize];
2020-03-11 11:21:44 +00:00
SrsBuffer* stream = new SrsBuffer(buf, kRtpPacketSize);
2020-03-10 16:04:12 +00:00
SrsAutoFree(SrsBuffer, stream);
if (nal_type == kIdr) {
packet_stap_a(sps, pps, shared_frame, rtp_packet_vec);
2020-03-08 11:20:46 +00:00
}
2020-03-10 16:04:12 +00:00
// v=2,p=0,x=0,cc=0
stream->write_1bytes(0x80);
// marker payloadtype
stream->write_1bytes(kMarker | kH264PayloadType);
// sequenct
stream->write_2bytes(sequence++);
// timestamp
stream->write_4bytes(int32_t(shared_frame->timestamp * 90));
// ssrc
stream->write_4bytes(int32_t(kVideoSSRC));
stream->write_bytes(sample->bytes, sample->size);
SrsSample rtp_packet;
rtp_packet.bytes = stream->data();
rtp_packet.size = stream->pos();
2020-03-11 11:21:44 +00:00
rtp_packet_vec.push_back(rtp_packet);
2020-03-10 16:04:12 +00:00
return err;
}
srs_error_t SrsRtpMuxer::packet_stap_a(const string &sps, const string& pps, SrsSharedPtrMessage* shared_frame, vector<SrsSample>& rtp_packet_vec)
{
srs_error_t err = srs_success;
uint8_t header = sps[0];
uint8_t nal_type = header & kNalTypeMask;
char* buf = new char[kRtpPacketSize];
2020-03-11 11:21:44 +00:00
SrsBuffer* stream = new SrsBuffer(buf, kRtpPacketSize);
2020-03-10 16:04:12 +00:00
SrsAutoFree(SrsBuffer, stream);
// v=2,p=0,x=0,cc=0
stream->write_1bytes(0x80);
// marker payloadtype
stream->write_1bytes(kMarker | kH264PayloadType);
// sequenct
stream->write_2bytes(sequence++);
// timestamp
stream->write_4bytes(int32_t(shared_frame->timestamp * 90));
// ssrc
stream->write_4bytes(int32_t(kVideoSSRC));
// stap-a header
uint8_t stap_a_header = kStapA;
stap_a_header |= (nal_type & (~kNalTypeMask));
stream->write_1bytes(stap_a_header);
stream->write_2bytes(sps.size());
stream->write_bytes((char*)sps.data(), sps.size());
stream->write_2bytes(pps.size());
stream->write_bytes((char*)pps.data(), pps.size());
SrsSample rtp_packet;
rtp_packet.bytes = stream->data();
rtp_packet.size = stream->pos();
rtp_packet_vec.push_back(rtp_packet);
2020-03-08 11:20:46 +00:00
return err;
}
SrsRtp::SrsRtp()
{
req = NULL;
hub = NULL;
enabled = false;
disposable = false;
last_update_time = 0;
}
SrsRtp::~SrsRtp()
{
}
void SrsRtp::dispose()
{
if (enabled) {
on_unpublish();
}
}
srs_error_t SrsRtp::cycle()
{
srs_error_t err = srs_success;
return err;
}
srs_error_t SrsRtp::initialize(SrsOriginHub* h, SrsRequest* r)
{
srs_error_t err = srs_success;
hub = h;
req = r;
2020-03-08 16:40:30 +00:00
rtp_h264_muxer = new SrsRtpMuxer();
2020-03-08 11:20:46 +00:00
return err;
}
srs_error_t SrsRtp::on_publish()
{
srs_error_t err = srs_success;
// update the hls time, for hls_dispose.
last_update_time = srs_get_system_time();
// support multiple publish.
if (enabled) {
return err;
}
// if enabled, open the muxer.
enabled = true;
// ok, the hls can be dispose, or need to be dispose.
disposable = true;
return err;
}
void SrsRtp::on_unpublish()
{
srs_error_t err = srs_success;
// support multiple unpublish.
if (!enabled) {
return;
}
enabled = false;
}
srs_error_t SrsRtp::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format)
{
srs_error_t err = srs_success;
if (!enabled) {
return err;
}
// Ignore if no format->acodec, it means the codec is not parsed, or unknown codec.
// @issue https://github.com/ossrs/srs/issues/1506#issuecomment-562079474
if (!format->acodec) {
return err;
}
// update the hls time, for hls_dispose.
last_update_time = srs_get_system_time();
SrsSharedPtrMessage* audio = shared_audio->copy();
SrsAutoFree(SrsSharedPtrMessage, audio);
// ts support audio codec: aac/mp3
SrsAudioCodecId acodec = format->acodec->id;
if (acodec != SrsAudioCodecIdAAC && acodec != SrsAudioCodecIdMP3) {
return err;
}
// ignore sequence header
srs_assert(format->audio);
2020-03-08 16:40:30 +00:00
// TODO: rtc no support aac
return err;
2020-03-08 11:20:46 +00:00
}
srs_error_t SrsRtp::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format)
{
srs_error_t err = srs_success;
if (!enabled) {
return err;
}
// Ignore if no format->vcodec, it means the codec is not parsed, or unknown codec.
// @issue https://github.com/ossrs/srs/issues/1506#issuecomment-562079474
if (!format->vcodec) {
return err;
}
// update the hls time, for hls_dispose.
last_update_time = srs_get_system_time();
SrsSharedPtrMessage* video = shared_video->copy();
SrsAutoFree(SrsSharedPtrMessage, video);
// ignore info frame,
// @see https://github.com/ossrs/srs/issues/288#issuecomment-69863909
srs_assert(format->video);
2020-03-08 16:40:30 +00:00
return rtp_h264_muxer->frame_to_packet(video, format);
2020-03-08 11:20:46 +00:00
}