Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v4.x support hevc(h.265) RTMP streaming #1721

Closed
wants to merge 17 commits into from
Prev Previous commit
Next Next commit
tmp commit 2
  • Loading branch information
maguoliang committed Apr 23, 2020
commit 0cb1e04e173d4e0bebb8d1908a6312f5fa084d0e
2 changes: 1 addition & 1 deletion trunk/src/app/srs_app_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2237,7 +2237,7 @@ srs_error_t SrsSource::on_video(SrsCommonMessage* shared_video)
}
last_packet_time = shared_video->header.timestamp;

if (shared_video->header.stream_id == SrsCodecVideoH264) {
if (shared_video->header.stream_id == SrsVideoCodecIdAVC) {
// drop any unknown header video.
// @see https://github.com/ossrs/srs/issues/421
if (!SrsFlvVideo::acceptable(shared_video->payload, shared_video->size)) {
Expand Down
29 changes: 20 additions & 9 deletions trunk/src/kernel/srs_kernel_codec.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -124,20 +124,24 @@ bool SrsFlvVideo::keyframe(char* data, int size)
bool SrsFlvVideo::sh(char* data, int size)
{
// sequence header only for h264
if (!h264(data, size)) {
if (!h264(data, size) && !hevc(data, size)) {
return false;
}

// 2bytes required.
if (size < 2) {
return false;
}
char frame_type = data[0];
frame_type = (frame_type >> 4) & 0x0F;

char avc_packet_type = data[1];


if (hevc(data, size)) {
return avc_packet_type == SrsVideoAvcFrameTraitSequenceHeader;
}

return frame_type == SrsVideoAvcFrameTypeKeyFrame
&& avc_packet_type == SrsVideoAvcFrameTraitSequenceHeader;
}
Expand All @@ -155,22 +159,29 @@ bool SrsFlvVideo::h264(char* data, int size)
return codec_id == SrsVideoCodecIdAVC;
}

bool SrsFlvVideo::acceptable_hevc(char* data, int size)
bool SrsFlvVideo::hevc(char* data, int size)
{
// 1bytes required.
if (size < 1) {
return false;
}

char frame_type = data[0];
char codec_id = frame_type & 0x0f;
frame_type = (frame_type >> 4) & 0x0f;
char codec_id = data[0];
codec_id = codec_id & 0x0F;

if (frame_type < 1 || frame_type > 5) {
return codec_id == SrsVideoCodecIdHEVC;
}


bool SrsFlvVideo::acceptable_hevc(char* data, int size)
{
// 1bytes required.
if (size < 2) {
return false;
}

if (codec_id < 2 || codec_id > 7) {
int nal_unit_type = (*data & 0x7E)>>1;
if (nal_unit_type > 40 || (nal_unit_type > 21 && nal_unit_type < 32)) {
return false;
}

Expand Down
71 changes: 52 additions & 19 deletions trunk/src/kernel/srs_kernel_ts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ using namespace std;
#define TS_PMT_NUMBER 1
#define TS_PMT_PID 0x1001
#define TS_VIDEO_AVC_PID 0x100
#define TS_VIDEO_HEVC_PID 0x110
#define TS_AUDIO_AAC_PID 0x101
#define TS_AUDIO_MP3_PID 0x102

Expand Down Expand Up @@ -300,6 +301,10 @@ srs_error_t SrsTsContext::encode(ISrsStreamWriter* writer, SrsTsMessage* msg, Sr
case SrsVideoCodecIdAVC:
vs = SrsTsStreamVideoH264;
video_pid = TS_VIDEO_AVC_PID;
break;
case SrsVideoCodecIdHEVC:
vs = SrsTsStreamVideoHEVC;
video_pid = TS_VIDEO_HEVC_PID;
break;
case SrsVideoCodecIdDisabled:
vs = SrsTsStreamReserved;
Expand All @@ -312,7 +317,6 @@ srs_error_t SrsTsContext::encode(ISrsStreamWriter* writer, SrsTsMessage* msg, Sr
case SrsVideoCodecIdOn2VP6:
case SrsVideoCodecIdOn2VP6WithAlphaChannel:
case SrsVideoCodecIdScreenVideoVersion2:
case SrsVideoCodecIdHEVC:
case SrsVideoCodecIdAV1:
vs = SrsTsStreamReserved;
break;
Expand Down Expand Up @@ -2964,24 +2968,53 @@ srs_error_t SrsTsMessageCache::do_cache_avc(SrsVideoFrame* frame)
if (!sample->bytes || size <= 0) {
return srs_error_new(ERROR_HLS_AVC_SAMPLE_SIZE, "ts: invalid avc sample length=%d", size);
}

// 5bits, 7.3.1 NAL unit syntax,
// ISO_IEC_14496-10-AVC-2012.pdf, page 83.
SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(sample->bytes[0] & 0x1f);

// Insert sps/pps before IDR when there is no sps/pps in samples.
// The sps/pps is parsed from sequence header(generally the first flv packet).
if (nal_unit_type == SrsAvcNaluTypeIDR && !frame->has_sps_pps && !is_sps_pps_appended) {
if (!codec->sequenceParameterSetNALUnit.empty()) {
srs_avc_insert_aud(video->payload, aud_inserted);
video->payload->append(&codec->sequenceParameterSetNALUnit[0], (int)codec->sequenceParameterSetNALUnit.size());
}
if (!codec->pictureParameterSetNALUnit.empty()) {
srs_avc_insert_aud(video->payload, aud_inserted);
video->payload->append(&codec->pictureParameterSetNALUnit[0], (int)codec->pictureParameterSetNALUnit.size());
}
is_sps_pps_appended = true;
}


if (frame->vcodec()->id == 7)
{
// 5bits, 7.3.1 NAL unit syntax,
// ISO_IEC_14496-10-AVC-2012.pdf, page 83.
SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(sample->bytes[0] & 0x1f);

// Insert sps/pps before IDR when there is no sps/pps in samples.
// The sps/pps is parsed from sequence header(generally the first flv packet).
if (nal_unit_type == SrsAvcNaluTypeIDR && !frame->has_sps_pps && !is_sps_pps_appended) {
if (!codec->sequenceParameterSetNALUnit.empty()) {
srs_avc_insert_aud(video->payload, aud_inserted);
video->payload->append(&codec->sequenceParameterSetNALUnit[0], (int)codec->sequenceParameterSetNALUnit.size());
}
if (!codec->pictureParameterSetNALUnit.empty()) {
srs_avc_insert_aud(video->payload, aud_inserted);
video->payload->append(&codec->pictureParameterSetNALUnit[0], (int)codec->pictureParameterSetNALUnit.size());
}
is_sps_pps_appended = true;
}
}
else if (frame->vcodec()->id == 12)
{
SrsAvcNaluType nal_unit_type = (SrsAvcNaluType)(sample->bytes[0] & 0x7e);

// Insert sps/pps before IDR when there is no sps/pps in samples.
// The sps/pps is parsed from sequence header(generally the first flv packet).
if (nal_unit_type >= 16 && nal_unit_type <= 21 && !sample->has_sps_pps && !is_sps_pps_appended) {
if (frame->vcodec()->videoParameterSetNALUnit.size() > 0) {
srs_avc_insert_aud(video->payload, aud_inserted);
video->payload->append(
frame->vcodec()->videoParameterSetNALUnit.c_str(), frame->vcodec()->videoParameterSetNALUnit.size());
}
if (frame->vcodec()->sequenceParameterSetNALUnit().size() > 0) {
srs_avc_insert_aud(video->payload, aud_inserted);
video->payload->append(
frame->vcodec()->sequenceParameterSetNALUnit.c_str(), frame->vcodec()->sequenceParameterSetNALUnit.size());
}
if (frame->vcodec()->pictureParameterSetNALUnit().size() > 0) {
srs_avc_insert_aud(video->payload, aud_inserted);
video->payload->append(
frame->vcodec()->pictureParameterSetNALUnit.c_str(), frame->vcodec()->pictureParameterSetNALUnit.size());
}
is_sps_pps_appended = true;
}
}

// Insert the NALU to video in annexb.
srs_avc_insert_aud(video->payload, aud_inserted);
Expand Down