Skip to content

Commit

Permalink
H265: Support HEVC over HLS.(#465)
Browse files Browse the repository at this point in the history
  • Loading branch information
chundonglinlin committed Jan 1, 2023
1 parent c46ef81 commit 94b2c9c
Show file tree
Hide file tree
Showing 4 changed files with 54 additions and 26 deletions.
52 changes: 38 additions & 14 deletions trunk/src/app/srs_app_hls.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -203,6 +203,7 @@ SrsHlsMuxer::SrsHlsMuxer()
context = new SrsTsContext();
segments = new SrsFragmentWindow();
latest_acodec_ = SrsAudioCodecIdForbidden;
latest_vcodec_ = SrsVideoCodecIdForbidden;

memset(key, 0, 16);
memset(iv, 0, 16);
Expand Down Expand Up @@ -282,6 +283,24 @@ void SrsHlsMuxer::set_latest_acodec(SrsAudioCodecId v)
latest_acodec_ = v;
}

SrsVideoCodecId SrsHlsMuxer::latest_vcodec()
{
// If current context writer exists, we query from it.
if (current && current->tscw) return current->tscw->vcodec();

// Get the configured or updated config.
return latest_vcodec_;
}

void SrsHlsMuxer::set_latest_vcodec(SrsVideoCodecId v)
{
// Refresh the codec in context writer for current segment.
if (current && current->tscw) current->tscw->set_vcodec(v);

// Refresh the codec for future segments.
latest_vcodec_ = v;
}

srs_error_t SrsHlsMuxer::initialize()
{
return srs_success;
Expand Down Expand Up @@ -399,13 +418,17 @@ 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 == "h265") {
default_vcodec = SrsVideoCodecIdHEVC;
} else if (default_vcodec_str == "vn") {
default_vcodec = SrsVideoCodecIdDisabled;
} else {
srs_warn("hls: use h264 for other codec=%s", default_vcodec_str.c_str());
}
}

// Now that we know the latest video codec in stream, use it.
if (latest_vcodec_ != SrsVideoCodecIdForbidden) default_vcodec = latest_vcodec_;

// new segment.
current = new SrsHlsSegment(context, default_acodec, default_vcodec, writer);
current->sequence_no = _sequence_no++;
Expand Down Expand Up @@ -546,7 +569,7 @@ bool SrsHlsMuxer::is_segment_absolutely_overflow()

bool SrsHlsMuxer::pure_audio()
{
return current && current->tscw && current->tscw->video_codec() == SrsVideoCodecIdDisabled;
return current && current->tscw && current->tscw->vcodec() == SrsVideoCodecIdDisabled;
}

srs_error_t SrsHlsMuxer::flush_audio(SrsTsMessageCache* cache)
Expand Down Expand Up @@ -576,7 +599,7 @@ srs_error_t SrsHlsMuxer::flush_audio(SrsTsMessageCache* cache)
return err;
}

srs_error_t SrsHlsMuxer::flush_video(SrsTsMessageCache* cache, SrsVideoFrame* frame)
srs_error_t SrsHlsMuxer::flush_video(SrsTsMessageCache* cache)
{
srs_error_t err = srs_success;

Expand All @@ -595,12 +618,6 @@ srs_error_t SrsHlsMuxer::flush_video(SrsTsMessageCache* cache, SrsVideoFrame* fr
// update the duration of segment.
current->append(cache->video->dts / 90);

// The video codec might change during streaming. Note that the frame might be NULL, when reap segment.
if (frame && frame->vcodec()) {
SrsTsContextWriter* tscw = current->tscw;
tscw->update_video_codec(frame->vcodec()->id);
}

if ((err = current->tscw->write_video(cache->video)) != srs_success) {
return srs_error_wrap(err, "hls: write video");
}
Expand Down Expand Up @@ -1039,7 +1056,14 @@ srs_error_t SrsHlsController::write_audio(SrsAudioFrame* frame, int64_t pts)
srs_error_t SrsHlsController::write_video(SrsVideoFrame* frame, int64_t dts)
{
srs_error_t err = srs_success;


// Refresh the codec ASAP.
if (muxer->latest_vcodec() != frame->vcodec()->id) {
srs_trace("HLS: Switch video codec %d(%s) to %d(%s)", muxer->latest_acodec(), srs_video_codec_id2str(muxer->latest_vcodec()).c_str(),
frame->vcodec()->id, srs_video_codec_id2str(frame->vcodec()->id).c_str());
muxer->set_latest_vcodec(frame->vcodec()->id);
}

// write video to cache.
if ((err = tsmc->cache_video(frame, dts)) != srs_success) {
return srs_error_wrap(err, "hls: cache video");
Expand All @@ -1059,7 +1083,7 @@ srs_error_t SrsHlsController::write_video(SrsVideoFrame* frame, int64_t dts)
}

// flush video when got one
if ((err = muxer->flush_video(tsmc, frame)) != srs_success) {
if ((err = muxer->flush_video(tsmc)) != srs_success) {
return srs_error_wrap(err, "hls: flush video");
}

Expand Down Expand Up @@ -1091,7 +1115,7 @@ srs_error_t SrsHlsController::reap_segment()
}

// segment open, flush video first.
if ((err = muxer->flush_video(tsmc, NULL)) != srs_success) {
if ((err = muxer->flush_video(tsmc)) != srs_success) {
return srs_error_wrap(err, "hls: flush video");
}

Expand Down Expand Up @@ -1351,9 +1375,9 @@ srs_error_t SrsHls::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* forma
if (format->video->frame_type == SrsVideoAvcFrameTypeVideoInfoFrame) {
return err;
}

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

Expand Down
6 changes: 5 additions & 1 deletion trunk/src/app/srs_app_hls.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,8 @@ class SrsHlsMuxer
private:
// Latest audio codec, parsed from stream.
SrsAudioCodecId latest_acodec_;
// Latest audio codec, parsed from stream.
SrsVideoCodecId latest_vcodec_;
public:
SrsHlsMuxer();
virtual ~SrsHlsMuxer();
Expand All @@ -172,6 +174,8 @@ class SrsHlsMuxer
public:
SrsAudioCodecId latest_acodec();
void set_latest_acodec(SrsAudioCodecId v);
SrsVideoCodecId latest_vcodec();
void set_latest_vcodec(SrsVideoCodecId v);
public:
// Initialize the hls muxer.
virtual srs_error_t initialize();
Expand Down Expand Up @@ -199,7 +203,7 @@ class SrsHlsMuxer
// Whether current hls muxer is pure audio mode.
virtual bool pure_audio();
virtual srs_error_t flush_audio(SrsTsMessageCache* cache);
virtual srs_error_t flush_video(SrsTsMessageCache* cache, SrsVideoFrame* frame);
virtual srs_error_t flush_video(SrsTsMessageCache* cache);
// Close segment(ts).
virtual srs_error_t segment_close();
private:
Expand Down
16 changes: 8 additions & 8 deletions trunk/src/kernel/srs_kernel_ts.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2678,7 +2678,7 @@ SrsTsContextWriter::SrsTsContextWriter(ISrsStreamWriter* w, SrsTsContext* c, Srs
context = c;

acodec_ = ac;
vcodec = vc;
vcodec_ = vc;
}

SrsTsContextWriter::~SrsTsContextWriter()
Expand All @@ -2692,7 +2692,7 @@ srs_error_t SrsTsContextWriter::write_audio(SrsTsMessage* audio)
srs_info("hls: write audio pts=%" PRId64 ", dts=%" PRId64 ", size=%d",
audio->pts, audio->dts, audio->PES_packet_length);

if ((err = context->encode(writer, audio, vcodec, acodec_)) != srs_success) {
if ((err = context->encode(writer, audio, vcodec_, acodec_)) != srs_success) {
return srs_error_wrap(err, "ts: write audio");
}
srs_info("hls encode audio ok");
Expand All @@ -2707,22 +2707,22 @@ srs_error_t SrsTsContextWriter::write_video(SrsTsMessage* video)
srs_info("hls: write video pts=%" PRId64 ", dts=%" PRId64 ", size=%d",
video->pts, video->dts, video->PES_packet_length);

if ((err = context->encode(writer, video, vcodec, acodec_)) != srs_success) {
if ((err = context->encode(writer, video, vcodec_, acodec_)) != srs_success) {
return srs_error_wrap(err, "ts: write video");
}
srs_info("hls encode video ok");

return err;
}

SrsVideoCodecId SrsTsContextWriter::video_codec()
SrsVideoCodecId SrsTsContextWriter::vcodec()
{
return vcodec;
return vcodec_;
}

void SrsTsContextWriter::update_video_codec(SrsVideoCodecId v)
void SrsTsContextWriter::set_vcodec(SrsVideoCodecId v)
{
vcodec = v;
vcodec_ = v;
}

SrsAudioCodecId SrsTsContextWriter::acodec()
Expand Down Expand Up @@ -3293,7 +3293,7 @@ srs_error_t SrsTsTransmuxer::write_video(int64_t timestamp, char* data, int size
}

// The video codec might change during streaming.
tscw->update_video_codec(format->vcodec->id);
tscw->set_vcodec(format->vcodec->id);

// ignore sequence header
if (format->video->frame_type == SrsVideoAvcFrameTypeKeyFrame && format->video->avc_packet_type == SrsVideoAvcFrameTraitSequenceHeader) {
Expand Down
6 changes: 3 additions & 3 deletions trunk/src/kernel/srs_kernel_ts.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -1259,7 +1259,7 @@ class SrsTsContextWriter
private:
// User must config the codec in right way.
// @see https://github.com/ossrs/srs/issues/301
SrsVideoCodecId vcodec;
SrsVideoCodecId vcodec_;
SrsAudioCodecId acodec_;
private:
SrsTsContext* context;
Expand All @@ -1275,8 +1275,8 @@ class SrsTsContextWriter
virtual srs_error_t write_video(SrsTsMessage* video);
public:
// Get or update the video codec of ts muxer.
virtual SrsVideoCodecId video_codec();
virtual void update_video_codec(SrsVideoCodecId v);
virtual SrsVideoCodecId vcodec();
virtual void set_vcodec(SrsVideoCodecId v);
public:
// Get and set the audio codec.
SrsAudioCodecId acodec();
Expand Down

0 comments on commit 94b2c9c

Please sign in to comment.