mirror of
https://github.com/ossrs/srs.git
synced 2025-02-15 04:42:04 +00:00
Merge branch '2.0release' into develop
This commit is contained in:
commit
a1ae48f4ac
4 changed files with 67 additions and 119 deletions
|
@ -1070,11 +1070,6 @@ int SrsHlsCache::write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t
|
||||||
// a. wait keyframe and got keyframe.
|
// a. wait keyframe and got keyframe.
|
||||||
// b. always reap when not wait keyframe.
|
// b. always reap when not wait keyframe.
|
||||||
if (!muxer->wait_keyframe() || sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) {
|
if (!muxer->wait_keyframe() || sample->frame_type == SrsCodecVideoAVCFrameKeyFrame) {
|
||||||
// when wait keyframe, there must exists idr frame in sample, or NonIDR(open gop) specified.
|
|
||||||
if (!sample->open_gop && !sample->has_idr && muxer->wait_keyframe()) {
|
|
||||||
srs_warn("hls: ts starts without IDR, first nalu=%d, idr=%d", sample->first_nalu_type, sample->has_idr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// reap the segment, which will also flush the video.
|
// reap the segment, which will also flush the video.
|
||||||
if ((ret = reap_segment("video", muxer, cache->video->dts)) != ERROR_SUCCESS) {
|
if ((ret = reap_segment("video", muxer, cache->video->dts)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1271,8 +1266,6 @@ void SrsHls::on_unpublish()
|
||||||
srs_error("ignore m3u8 muxer flush/close audio failed. ret=%d", ret);
|
srs_error("ignore m3u8 muxer flush/close audio failed. ret=%d", ret);
|
||||||
}
|
}
|
||||||
|
|
||||||
sample->reset();
|
|
||||||
|
|
||||||
hls_enabled = false;
|
hls_enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -324,20 +324,13 @@ SrsCodecSampleUnit::~SrsCodecSampleUnit()
|
||||||
|
|
||||||
SrsCodecSample::SrsCodecSample()
|
SrsCodecSample::SrsCodecSample()
|
||||||
{
|
{
|
||||||
reset();
|
clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsCodecSample::~SrsCodecSample()
|
SrsCodecSample::~SrsCodecSample()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
void SrsCodecSample::reset()
|
|
||||||
{
|
|
||||||
clear();
|
|
||||||
|
|
||||||
open_gop = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void SrsCodecSample::clear()
|
void SrsCodecSample::clear()
|
||||||
{
|
{
|
||||||
is_video = false;
|
is_video = false;
|
||||||
|
@ -346,7 +339,7 @@ void SrsCodecSample::clear()
|
||||||
cts = 0;
|
cts = 0;
|
||||||
frame_type = SrsCodecVideoAVCFrameReserved;
|
frame_type = SrsCodecVideoAVCFrameReserved;
|
||||||
avc_packet_type = SrsCodecVideoAVCTypeReserved;
|
avc_packet_type = SrsCodecVideoAVCTypeReserved;
|
||||||
has_aud = has_idr = false;
|
has_sps_pps = has_aud = has_idr = false;
|
||||||
first_nalu_type = SrsAvcNaluTypeReserved;
|
first_nalu_type = SrsAvcNaluTypeReserved;
|
||||||
|
|
||||||
acodec = SrsCodecAudioReserved1;
|
acodec = SrsCodecAudioReserved1;
|
||||||
|
@ -377,6 +370,8 @@ int SrsCodecSample::add_sample_unit(char* bytes, int size)
|
||||||
|
|
||||||
if (nal_unit_type == SrsAvcNaluTypeIDR) {
|
if (nal_unit_type == SrsAvcNaluTypeIDR) {
|
||||||
has_idr = true;
|
has_idr = true;
|
||||||
|
} else if (nal_unit_type == SrsAvcNaluTypeSPS || nal_unit_type == SrsAvcNaluTypePPS) {
|
||||||
|
has_sps_pps = true;
|
||||||
} else if (nal_unit_type == SrsAvcNaluTypeAccessUnitDelimiter) {
|
} else if (nal_unit_type == SrsAvcNaluTypeAccessUnitDelimiter) {
|
||||||
has_aud = true;
|
has_aud = true;
|
||||||
}
|
}
|
||||||
|
@ -773,11 +768,6 @@ int SrsAvcAacCodec::video_nalu_demux(SrsBuffer* stream, SrsCodecSample* sample)
|
||||||
srs_info("hls decode avc payload in annexb format.");
|
srs_info("hls decode avc payload in annexb format.");
|
||||||
}
|
}
|
||||||
|
|
||||||
// for keyframe, but not IDR, it's open gop.
|
|
||||||
if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame && !sample->has_idr) {
|
|
||||||
sample->open_gop = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -387,12 +387,10 @@ public:
|
||||||
bool has_idr;
|
bool has_idr;
|
||||||
// Whether exists AUD NALU.
|
// Whether exists AUD NALU.
|
||||||
bool has_aud;
|
bool has_aud;
|
||||||
|
// Whether exists SPS/PPS NALU.
|
||||||
|
bool has_sps_pps;
|
||||||
// The first nalu type.
|
// The first nalu type.
|
||||||
SrsAvcNaluType first_nalu_type;
|
SrsAvcNaluType first_nalu_type;
|
||||||
public:
|
|
||||||
// Whether stream is open gop, which means the keyframe is not IDR but NonIDR.
|
|
||||||
// @remark we will identify whether stream is open-gop util reset.
|
|
||||||
bool open_gop;
|
|
||||||
public:
|
public:
|
||||||
// audio specified
|
// audio specified
|
||||||
SrsCodecAudio acodec;
|
SrsCodecAudio acodec;
|
||||||
|
@ -405,8 +403,6 @@ public:
|
||||||
SrsCodecSample();
|
SrsCodecSample();
|
||||||
virtual ~SrsCodecSample();
|
virtual ~SrsCodecSample();
|
||||||
public:
|
public:
|
||||||
// Reset the sample, clear the sample-base and stream-base data.
|
|
||||||
void reset();
|
|
||||||
/**
|
/**
|
||||||
* clear all samples.
|
* clear all samples.
|
||||||
* the sample units never copy the bytes, it directly use the ptr,
|
* the sample units never copy the bytes, it directly use the ptr,
|
||||||
|
|
|
@ -2939,10 +2939,8 @@ int SrsTsCache::do_cache_aac(SrsAvcAacCodec* codec, SrsCodecSample* sample)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample)
|
void srs_avc_insert_aud(SrsSimpleBuffer* payload, bool& aud_inserted)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
|
||||||
|
|
||||||
// mux the samples in annexb format,
|
// mux the samples in annexb format,
|
||||||
// H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 324.
|
// H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 324.
|
||||||
/**
|
/**
|
||||||
|
@ -2989,84 +2987,56 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample)
|
||||||
static u_int8_t fresh_nalu_header[] = { 0x00, 0x00, 0x00, 0x01 };
|
static u_int8_t fresh_nalu_header[] = { 0x00, 0x00, 0x00, 0x01 };
|
||||||
static u_int8_t cont_nalu_header[] = { 0x00, 0x00, 0x01 };
|
static u_int8_t cont_nalu_header[] = { 0x00, 0x00, 0x01 };
|
||||||
|
|
||||||
// the aud(access unit delimiter) before each frame.
|
if (!aud_inserted) {
|
||||||
// 7.3.2.4 Access unit delimiter RBSP syntax
|
aud_inserted = true;
|
||||||
// H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 66.
|
payload->append((const char*)fresh_nalu_header, 4);
|
||||||
//
|
} else {
|
||||||
// primary_pic_type u(3), the first 3bits, primary_pic_type indicates that the slice_type values
|
payload->append((const char*)cont_nalu_header, 3);
|
||||||
// for all slices of the primary coded picture are members of the set listed in Table 7-5 for
|
|
||||||
// the given value of primary_pic_type.
|
|
||||||
// 0, slice_type 2, 7
|
|
||||||
// 1, slice_type 0, 2, 5, 7
|
|
||||||
// 2, slice_type 0, 1, 2, 5, 6, 7
|
|
||||||
// 3, slice_type 4, 9
|
|
||||||
// 4, slice_type 3, 4, 8, 9
|
|
||||||
// 5, slice_type 2, 4, 7, 9
|
|
||||||
// 6, slice_type 0, 2, 3, 4, 5, 7, 8, 9
|
|
||||||
// 7, slice_type 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
|
|
||||||
// 7.4.2.4 Access unit delimiter RBSP semantics
|
|
||||||
// H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 102.
|
|
||||||
//
|
|
||||||
// slice_type specifies the coding type of the slice according to Table 7-6.
|
|
||||||
// 0, P (P slice)
|
|
||||||
// 1, B (B slice)
|
|
||||||
// 2, I (I slice)
|
|
||||||
// 3, SP (SP slice)
|
|
||||||
// 4, SI (SI slice)
|
|
||||||
// 5, P (P slice)
|
|
||||||
// 6, B (B slice)
|
|
||||||
// 7, I (I slice)
|
|
||||||
// 8, SP (SP slice)
|
|
||||||
// 9, SI (SI slice)
|
|
||||||
// H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 105.
|
|
||||||
static u_int8_t aud_nalu_7[] = { 0x09, 0xf0};
|
|
||||||
|
|
||||||
// For NonIDR(open gop), we directly appends all frames.
|
|
||||||
if (sample->open_gop) {
|
|
||||||
for (int i = 0; i < sample->nb_sample_units; i++) {
|
|
||||||
SrsCodecSampleUnit* sample_unit = &sample->sample_units[i];
|
|
||||||
int32_t size = sample_unit->size;
|
|
||||||
|
|
||||||
if (!sample_unit->bytes || size <= 0) {
|
|
||||||
ret = ERROR_HLS_AVC_SAMPLE_SIZE;
|
|
||||||
srs_error("invalid avc sample length=%d, ret=%d", size, ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// insert nalu header before rbsp.
|
|
||||||
if (i == 0) {
|
|
||||||
video->payload->append((const char*)fresh_nalu_header, 4);
|
|
||||||
} else {
|
|
||||||
video->payload->append((const char*)cont_nalu_header, 3);
|
|
||||||
}
|
|
||||||
|
|
||||||
// sample data
|
|
||||||
video->payload->append(sample_unit->bytes, sample_unit->size);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
// always append a aud nalu for each frame.
|
// Whether aud inserted.
|
||||||
video->payload->append((const char*)fresh_nalu_header, 4);
|
bool aud_inserted = false;
|
||||||
video->payload->append((const char*)aud_nalu_7, 2);
|
|
||||||
|
|
||||||
// when ts message(samples) contains IDR, insert sps+pps.
|
// Insert a default AUD NALU when no AUD in samples.
|
||||||
if (sample->has_idr) {
|
if (!sample->has_aud) {
|
||||||
// fresh nalu header before sps.
|
// the aud(access unit delimiter) before each frame.
|
||||||
if (codec->sequenceParameterSetLength > 0) {
|
// 7.3.2.4 Access unit delimiter RBSP syntax
|
||||||
// AnnexB prefix, for sps always 4 bytes header
|
// H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 66.
|
||||||
video->payload->append((const char*)fresh_nalu_header, 4);
|
//
|
||||||
// sps
|
// primary_pic_type u(3), the first 3bits, primary_pic_type indicates that the slice_type values
|
||||||
video->payload->append(codec->sequenceParameterSetNALUnit, codec->sequenceParameterSetLength);
|
// for all slices of the primary coded picture are members of the set listed in Table 7-5 for
|
||||||
}
|
// the given value of primary_pic_type.
|
||||||
// cont nalu header before pps.
|
// 0, slice_type 2, 7
|
||||||
if (codec->pictureParameterSetLength > 0) {
|
// 1, slice_type 0, 2, 5, 7
|
||||||
// AnnexB prefix, for pps always 3 bytes header
|
// 2, slice_type 0, 1, 2, 5, 6, 7
|
||||||
video->payload->append((const char*)cont_nalu_header, 3);
|
// 3, slice_type 4, 9
|
||||||
// pps
|
// 4, slice_type 3, 4, 8, 9
|
||||||
video->payload->append(codec->pictureParameterSetNALUnit, codec->pictureParameterSetLength);
|
// 5, slice_type 2, 4, 7, 9
|
||||||
}
|
// 6, slice_type 0, 2, 3, 4, 5, 7, 8, 9
|
||||||
|
// 7, slice_type 0, 1, 2, 3, 4, 5, 6, 7, 8, 9
|
||||||
|
// 7.4.2.4 Access unit delimiter RBSP semantics
|
||||||
|
// H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 102.
|
||||||
|
//
|
||||||
|
// slice_type specifies the coding type of the slice according to Table 7-6.
|
||||||
|
// 0, P (P slice)
|
||||||
|
// 1, B (B slice)
|
||||||
|
// 2, I (I slice)
|
||||||
|
// 3, SP (SP slice)
|
||||||
|
// 4, SI (SI slice)
|
||||||
|
// 5, P (P slice)
|
||||||
|
// 6, B (B slice)
|
||||||
|
// 7, I (I slice)
|
||||||
|
// 8, SP (SP slice)
|
||||||
|
// 9, SI (SI slice)
|
||||||
|
// H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 105.
|
||||||
|
static u_int8_t default_aud_nalu[] = { 0x09, 0xf0};
|
||||||
|
srs_avc_insert_aud(video->payload, aud_inserted);
|
||||||
|
video->payload->append((const char*)default_aud_nalu, 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// all sample use cont nalu header, except the sps-pps before IDR frame.
|
// all sample use cont nalu header, except the sps-pps before IDR frame.
|
||||||
|
@ -3084,20 +3054,21 @@ int SrsTsCache::do_cache_avc(SrsAvcAacCodec* codec, SrsCodecSample* sample)
|
||||||
// H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 83.
|
// H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 83.
|
||||||
SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(sample_unit->bytes[0] & 0x1f);
|
SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(sample_unit->bytes[0] & 0x1f);
|
||||||
|
|
||||||
// ignore SPS/PPS/AUD
|
// Insert sps/pps before IDR when there is no sps/pps in samples.
|
||||||
switch (nal_unit_type) {
|
// The sps/pps is parsed from sequence header(generally the first flv packet).
|
||||||
case SrsAvcNaluTypeSPS:
|
if (nal_unit_type == SrsAvcNaluTypeIDR && !sample->has_sps_pps) {
|
||||||
case SrsAvcNaluTypePPS:
|
if (codec->sequenceParameterSetLength > 0) {
|
||||||
case SrsAvcNaluTypeAccessUnitDelimiter:
|
srs_avc_insert_aud(video->payload, aud_inserted);
|
||||||
continue;
|
video->payload->append(codec->sequenceParameterSetNALUnit, codec->sequenceParameterSetLength);
|
||||||
default:
|
}
|
||||||
break;
|
if (codec->pictureParameterSetLength > 0) {
|
||||||
|
srs_avc_insert_aud(video->payload, aud_inserted);
|
||||||
|
video->payload->append(codec->pictureParameterSetNALUnit, codec->pictureParameterSetLength);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// insert cont nalu header before frame.
|
// Insert the NALU to video in annexb.
|
||||||
video->payload->append((const char*)cont_nalu_header, 3);
|
srs_avc_insert_aud(video->payload, aud_inserted);
|
||||||
|
|
||||||
// sample data
|
|
||||||
video->payload->append(sample_unit->bytes, sample_unit->size);
|
video->payload->append(sample_unit->bytes, sample_unit->size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3144,8 +3115,6 @@ int SrsTsEncoder::initialize(SrsFileWriter* fw)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
sample->reset();
|
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue