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
29 changes: 29 additions & 0 deletions trunk/conf/hevc.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# the config for srs to delivery hls
# @see https://github.com/ossrs/srs/wiki/v1_CN_SampleHLS
# @see full.conf for detail config.

listen 1935;
max_connections 1000;
daemon off;
srs_log_tank console;
http_server {
enabled on;
listen 8080;
dir ./objs/nginx/html;
}
vhost __defaultVhost__ {
http_remux {
enabled on;
mount [vhost]/[app]/[stream].flv;
}

hls {
enabled on;
hls_vcodec hevc;
hls_fragment 10;
hls_window 60;
hls_path ./objs/nginx/html;
hls_m3u8_file [app]/[stream].m3u8;
hls_ts_file [app]/[stream]-[seq].ts;
}
}
3 changes: 2 additions & 1 deletion trunk/src/app/srs_app_dvr.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -880,7 +880,8 @@ srs_error_t SrsDvrSegmentPlan::update_duration(SrsSharedPtrMessage* msg)

char* payload = msg->payload;
int size = msg->size;
bool is_key_frame = SrsFlvVideo::h264(payload, size) && SrsFlvVideo::keyframe(payload, size) && !SrsFlvVideo::sh(payload, size);
bool is_key_frame = (SrsFlvVideo::h264(payload, size) || SrsFlvVideo::hevc(payload, size)) &&
SrsFlvVideo::keyframe(payload, size) && !SrsFlvVideo::sh(payload, size);
if (!is_key_frame) {
return err;
}
Expand Down
4 changes: 3 additions & 1 deletion trunk/src/app/srs_app_hls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -382,6 +382,8 @@ srs_error_t SrsHlsMuxer::segment_open()
std::string default_vcodec_str = _srs_config->get_hls_vcodec(req->vhost);
if (default_vcodec_str == "h264") {
default_vcodec = SrsVideoCodecIdAVC;
} else if (default_vcodec_str == "hevc") {
default_vcodec = SrsVideoCodecIdHEVC;
} else if (default_vcodec_str == "vn") {
default_vcodec = SrsVideoCodecIdDisabled;
} else {
Expand Down Expand Up @@ -1322,7 +1324,7 @@ srs_error_t SrsHls::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* forma
}

srs_assert(format->vcodec);
if (format->vcodec->id != SrsVideoCodecIdAVC) {
if (format->vcodec->id != SrsVideoCodecIdAVC && format->vcodec->id != SrsVideoCodecIdHEVC) {
return err;
}

Expand Down
13 changes: 8 additions & 5 deletions trunk/src/app/srs_app_source.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -625,7 +625,8 @@ srs_error_t SrsGopCache::cache(SrsSharedPtrMessage* shared_msg)
// got video, update the video count if acceptable
if (msg->is_video()) {
// drop video when not h.264
if (!SrsFlvVideo::h264(msg->payload, msg->size)) {
if (!SrsFlvVideo::h264(msg->payload, msg->size) &&
!SrsFlvVideo::hevc(msg->payload, msg->size)) {
return err;
}

Expand Down Expand Up @@ -1043,13 +1044,15 @@ srs_error_t SrsOriginHub::on_video(SrsSharedPtrMessage* shared_video, bool is_se

// when got video stream info.
SrsStatistic* stat = SrsStatistic::instance();
if ((err = stat->on_video_info(req, SrsVideoCodecIdAVC, c->avc_profile, c->avc_level, c->width, c->height)) != srs_success) {
if ((err = stat->on_video_info(req, c->id, c->avc_profile, c->avc_level, c->hevc_profile, c->hevc_level, c->width, c->height)) != srs_success) {
return srs_error_wrap(err, "stat video");
}

srs_trace("%dB video sh, codec(%d, profile=%s, level=%s, %dx%d, %dkbps, %.1ffps, %.1fs)",
msg->size, c->id, srs_avc_profile2str(c->avc_profile).c_str(),
srs_avc_level2str(c->avc_level).c_str(), c->width, c->height,
msg->size, c->id,
c->id == SrsVideoCodecIdHEVC ? srs_hevc_profile2str(c->hevc_profile).c_str() : srs_avc_profile2str(c->avc_profile).c_str(),
c->id == SrsVideoCodecIdHEVC ? srs_hevc_level2str(c->hevc_level).c_str() : srs_avc_level2str(c->avc_level).c_str(),
c->width, c->height,
c->video_data_rate / 1000, c->frame_rate, c->duration);
}

Expand Down Expand Up @@ -2236,7 +2239,7 @@ srs_error_t SrsSource::on_video(SrsCommonMessage* shared_video)
}
}
last_packet_time = shared_video->header.timestamp;

// drop any unknown header video.
// @see https://github.com/ossrs/srs/issues/421
if (!SrsFlvVideo::acceptable(shared_video->payload, shared_video->size)) {
Expand Down
27 changes: 22 additions & 5 deletions trunk/src/app/srs_app_statistic.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,8 @@ SrsStatisticStream::SrsStatisticStream()
vcodec = SrsVideoCodecIdReserved;
avc_profile = SrsAvcProfileReserved;
avc_level = SrsAvcLevelReserved;
hevc_profile = SrsHEvcProfileReserved;
hevc_level = SrsHEvcLevelReserved;

has_audio = false;
acodec = SrsAudioCodecIdReserved1;
Expand Down Expand Up @@ -163,8 +165,14 @@ srs_error_t SrsStatisticStream::dumps(SrsJsonObject* obj)
obj->set("video", video);

video->set("codec", SrsJsonAny::str(srs_video_codec_id2str(vcodec).c_str()));
video->set("profile", SrsJsonAny::str(srs_avc_profile2str(avc_profile).c_str()));
video->set("level", SrsJsonAny::str(srs_avc_level2str(avc_level).c_str()));
if (vcodec == SrsVideoCodecIdHEVC) {
video->set("profile", SrsJsonAny::str(srs_hevc_profile2str(hevc_profile).c_str()));
video->set("level", SrsJsonAny::str(srs_hevc_level2str(hevc_level).c_str()));
}
else {
video->set("profile", SrsJsonAny::str(srs_avc_profile2str(avc_profile).c_str()));
video->set("level", SrsJsonAny::str(srs_avc_level2str(avc_level).c_str()));
}
video->set("width", SrsJsonAny::integer(width));
video->set("height", SrsJsonAny::integer(height));
}
Expand Down Expand Up @@ -326,7 +334,10 @@ SrsStatisticClient* SrsStatistic::find_client(int cid)
return NULL;
}

srs_error_t SrsStatistic::on_video_info(SrsRequest* req, SrsVideoCodecId vcodec, SrsAvcProfile avc_profile, SrsAvcLevel avc_level, int width, int height)
srs_error_t SrsStatistic::on_video_info(SrsRequest* req, SrsVideoCodecId vcodec,
SrsAvcProfile avc_profile, SrsAvcLevel avc_level,
SrsHEvcProfile hevc_profile, SrsHEvcLevel hevc_level,
int width, int height)
{
srs_error_t err = srs_success;

Expand All @@ -335,8 +346,14 @@ srs_error_t SrsStatistic::on_video_info(SrsRequest* req, SrsVideoCodecId vcodec,

stream->has_video = true;
stream->vcodec = vcodec;
stream->avc_profile = avc_profile;
stream->avc_level = avc_level;
if (vcodec == SrsVideoCodecIdHEVC) {
stream->hevc_profile = hevc_profile;
stream->hevc_level = hevc_level;
}
else {
stream->avc_profile = avc_profile;
stream->avc_level = avc_level;
}

stream->width = width;
stream->height = height;
Expand Down
8 changes: 6 additions & 2 deletions trunk/src/app/srs_app_statistic.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ struct SrsStatisticStream
SrsAvcProfile avc_profile;
// The level_idc, ISO_IEC_14496-10-AVC-2003.pdf, page 45.
SrsAvcLevel avc_level;
SrsHEvcProfile hevc_profile;
SrsHEvcLevel hevc_level;
// The width and height in codec info.
int width;
int height;
Expand Down Expand Up @@ -158,8 +160,10 @@ class SrsStatistic
virtual SrsStatisticClient* find_client(int cid);
public:
// When got video info for stream.
virtual srs_error_t on_video_info(SrsRequest* req, SrsVideoCodecId vcodec, SrsAvcProfile avc_profile,
SrsAvcLevel avc_level, int width, int height);
virtual srs_error_t on_video_info(SrsRequest* req, SrsVideoCodecId vcodec,
SrsAvcProfile avc_profile, SrsAvcLevel avc_level,
SrsHEvcProfile hevc_profile, SrsHEvcLevel hevc_level,
int width, int height);
// When got audio info for stream.
virtual srs_error_t on_audio_info(SrsRequest* req, SrsAudioCodecId acodec, SrsAudioSampleRate asample_rate,
SrsAudioChannels asound_type, SrsAacObjectType aac_object);
Expand Down
Loading