1
0
Fork 0
mirror of https://github.com/ossrs/srs.git synced 2025-02-15 04:42:04 +00:00
srs/trunk/src/app/srs_app_hls.hpp

312 lines
9.7 KiB
C++
Raw Normal View History

//
// Copyright (c) 2013-2021 The SRS Authors
//
// SPDX-License-Identifier: MIT or MulanPSL-2.0
//
2013-11-23 11:15:11 +00:00
#ifndef SRS_APP_HLS_HPP
#define SRS_APP_HLS_HPP
2013-11-23 11:15:11 +00:00
#include <srs_core.hpp>
2013-11-24 09:15:37 +00:00
#include <string>
2013-11-26 08:06:58 +00:00
#include <vector>
2013-11-24 09:15:37 +00:00
#include <srs_kernel_codec.hpp>
#include <srs_kernel_file.hpp>
#include <srs_app_async_call.hpp>
#include <srs_app_fragment.hpp>
class SrsFormat;
class SrsSharedPtrMessage;
class SrsAmf0Object;
2013-11-26 08:06:58 +00:00
class SrsRtmpJitter;
class SrsTsContextWriter;
class SrsRequest;
2013-12-05 15:34:26 +00:00
class SrsPithyPrint;
2021-05-16 08:14:00 +00:00
class SrsLiveSource;
class SrsOriginHub;
class SrsFileWriter;
class SrsSimpleStream;
class SrsTsAacJitter;
class SrsTsMessageCache;
class SrsHlsSegment;
class SrsTsContext;
2019-04-28 01:08:05 +00:00
// The wrapper of m3u8 segment from specification:
//
// 3.3.2. EXTINF
// The EXTINF tag specifies the duration of a media segment.
class SrsHlsSegment : public SrsFragment
2013-12-02 06:24:09 +00:00
{
public:
2014-03-18 03:32:58 +00:00
// sequence number in m3u8.
int sequence_no;
// ts uri in m3u8.
std::string uri;
2019-04-28 01:08:05 +00:00
// The underlayer file writer.
SrsFileWriter* writer;
// The TS context writer to write TS to file.
SrsTsContextWriter* tscw;
2018-03-25 04:05:52 +00:00
// Will be saved in m3u8 file.
unsigned char iv[16];
// The full key path.
std::string keypath;
public:
SrsHlsSegment(SrsTsContext* c, SrsAudioCodecId ac, SrsVideoCodecId vc, SrsFileWriter* w);
virtual ~SrsHlsSegment();
2018-03-25 04:05:52 +00:00
public:
void config_cipher(unsigned char* key,unsigned char* iv);
// replace the placeholder
virtual srs_error_t rename();
2013-12-02 06:24:09 +00:00
};
2019-04-28 01:08:05 +00:00
// The hls async call: on_hls
class SrsDvrAsyncCallOnHls : public ISrsAsyncCallTask
{
private:
SrsContextId cid;
std::string path;
std::string ts_url;
std::string m3u8;
std::string m3u8_url;
int seq_no;
SrsRequest* req;
2019-04-14 23:53:29 +00:00
srs_utime_t duration;
public:
// TODO: FIXME: Use TBN 1000.
SrsDvrAsyncCallOnHls(SrsContextId c, SrsRequest* r, std::string p, std::string t, std::string m, std::string mu, int s, srs_utime_t d);
virtual ~SrsDvrAsyncCallOnHls();
public:
virtual srs_error_t call();
virtual std::string to_string();
};
2019-04-28 01:08:05 +00:00
// The hls async call: on_hls_notify
class SrsDvrAsyncCallOnHlsNotify : public ISrsAsyncCallTask
{
private:
SrsContextId cid;
std::string ts_url;
SrsRequest* req;
public:
SrsDvrAsyncCallOnHlsNotify(SrsContextId c, SrsRequest* r, std::string u);
virtual ~SrsDvrAsyncCallOnHlsNotify();
public:
virtual srs_error_t call();
virtual std::string to_string();
};
2019-04-28 01:08:05 +00:00
// Mux the HLS stream(m3u8 and ts files).
// Generally, the m3u8 muxer only provides methods to open/close segments,
// to flush video/audio, without any mechenisms.
//
// That is, user must use HlsCache, which will control the methods of muxer,
// and provides HLS mechenisms.
class SrsHlsMuxer
2013-11-23 12:16:47 +00:00
{
private:
SrsRequest* req;
2013-12-02 07:55:10 +00:00
private:
std::string hls_entry_prefix;
2014-03-18 03:32:58 +00:00
std::string hls_path;
std::string hls_ts_file;
bool hls_cleanup;
bool hls_wait_keyframe;
2015-03-30 06:08:17 +00:00
std::string m3u8_dir;
double hls_aof_ratio;
// TODO: FIXME: Use TBN 1000.
2019-04-16 00:14:12 +00:00
srs_utime_t hls_fragment;
2019-04-16 00:20:32 +00:00
srs_utime_t hls_window;
SrsAsyncCallWorker* async;
private:
2019-04-28 01:08:05 +00:00
// Whether use floor algorithm for timestamp.
bool hls_ts_floor;
2019-04-28 01:08:05 +00:00
// The deviation in piece to adjust the fragment to be more
// bigger or smaller.
int deviation_ts;
2019-04-28 01:08:05 +00:00
// The previous reap floor timestamp,
// used to detect the dup or jmp or ts.
2015-03-31 09:03:14 +00:00
int64_t accept_floor_ts;
int64_t previous_floor_ts;
2018-03-25 04:05:52 +00:00
private:
2019-04-28 01:08:05 +00:00
// Whether encrypted or not
2018-03-25 04:05:52 +00:00
bool hls_keys;
int hls_fragments_per_key;
2019-04-28 01:08:05 +00:00
// The key file name
2018-03-25 04:05:52 +00:00
std::string hls_key_file;
2019-04-28 01:08:05 +00:00
// The key file path
2018-03-25 04:05:52 +00:00
std::string hls_key_file_path;
2019-04-28 01:08:05 +00:00
// The key file url
2018-03-25 04:05:52 +00:00
std::string hls_key_url;
2019-04-28 01:08:05 +00:00
// The key and iv.
2018-03-25 04:05:52 +00:00
unsigned char key[16];
unsigned char iv[16];
2019-05-06 23:40:19 +00:00
// The underlayer file writer.
SrsFileWriter* writer;
2013-11-26 08:06:58 +00:00
private:
2014-05-04 02:45:13 +00:00
int _sequence_no;
2019-04-16 01:32:26 +00:00
srs_utime_t max_td;
2014-03-18 03:32:58 +00:00
std::string m3u8;
std::string m3u8_url;
2013-11-26 08:06:58 +00:00
private:
// The available cached segments in m3u8.
SrsFragmentWindow* segments;
// The current writing segment.
SrsHlsSegment* current;
2019-04-28 01:08:05 +00:00
// The ts context, to keep cc continous between ts.
SrsTsContext* context;
2013-12-02 07:55:10 +00:00
public:
SrsHlsMuxer();
virtual ~SrsHlsMuxer();
public:
virtual void dispose();
2014-05-04 02:45:13 +00:00
public:
virtual int sequence_no();
virtual std::string ts_url();
virtual srs_utime_t duration();
virtual int deviation();
2013-12-02 07:55:10 +00:00
public:
2019-04-28 01:08:05 +00:00
// Initialize the hls muxer.
2017-06-11 01:40:07 +00:00
virtual srs_error_t initialize();
// When publish or unpublish stream.
virtual srs_error_t on_publish(SrsRequest* req);
virtual srs_error_t on_unpublish();
2019-04-28 01:08:05 +00:00
// When publish, update the config for muxer.
virtual srs_error_t update_config(SrsRequest* r, std::string entry_prefix,
std::string path, std::string m3u8_file, std::string ts_file,
2019-04-16 00:20:32 +00:00
srs_utime_t fragment, srs_utime_t window, bool ts_floor, double aof_ratio,
bool cleanup, bool wait_keyframe, bool keys, int fragments_per_key,
std::string key_file, std::string key_file_path, std::string key_url);
2019-04-28 01:08:05 +00:00
// Open a new segment(a new ts file)
virtual srs_error_t segment_open();
virtual srs_error_t on_sequence_header();
2019-04-28 01:08:05 +00:00
// Whether segment overflow,
// that is whether the current segment duration>=(the segment in config)
virtual bool is_segment_overflow();
2019-04-28 01:08:05 +00:00
// Whether wait keyframe to reap the ts.
virtual bool wait_keyframe();
2019-04-28 01:08:05 +00:00
// Whether segment absolutely overflow, for pure audio to reap segment,
// that is whether the current segment duration>=2*(the segment in config)
virtual bool is_segment_absolutely_overflow();
public:
2019-04-28 01:08:05 +00:00
// 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);
2019-04-28 01:08:05 +00:00
// Close segment(ts).
virtual srs_error_t segment_close();
2013-12-02 07:55:10 +00:00
private:
virtual srs_error_t do_segment_close();
virtual srs_error_t write_hls_key();
virtual srs_error_t refresh_m3u8();
virtual srs_error_t _refresh_m3u8(std::string m3u8_file);
2013-12-02 07:55:10 +00:00
};
2019-04-28 01:08:05 +00:00
// The hls stream cache,
// use to cache hls stream and flush to hls muxer.
//
// When write stream to ts file:
// video frame will directly flush to M3u8Muxer,
// audio frame need to cache, because it's small and flv tbn problem.
//
// Whatever, the Hls cache used to cache video/audio,
// and flush video/audio to m3u8 muxer if needed.
//
// About the flv tbn problem:
// flv tbn is 1/1000, ts tbn is 1/90000,
// when timestamp convert to flv tbn, it will loose precise,
// so we must gather audio frame together, and recalc the timestamp @see SrsTsAacJitter,
// we use a aac jitter to correct the audio pts.
class SrsHlsController
2013-12-02 07:55:10 +00:00
{
private:
// The HLS muxer to reap ts and m3u8.
// The TS is cached to SrsTsMessageCache then flush to ts segment.
SrsHlsMuxer* muxer;
// The TS cache
SrsTsMessageCache* tsmc;
public:
SrsHlsController();
virtual ~SrsHlsController();
public:
2017-06-11 01:40:07 +00:00
virtual srs_error_t initialize();
virtual void dispose();
virtual int sequence_no();
virtual std::string ts_url();
virtual srs_utime_t duration();
virtual int deviation();
public:
2019-04-28 01:08:05 +00:00
// When publish or unpublish stream.
virtual srs_error_t on_publish(SrsRequest* req);
virtual srs_error_t on_unpublish();
2019-04-28 01:08:05 +00:00
// When get sequence header,
// must write a #EXT-X-DISCONTINUITY to m3u8.
// @see: hls-m3u8-draft-pantos-http-live-streaming-12.txt
// @see: 3.4.11. EXT-X-DISCONTINUITY
virtual srs_error_t on_sequence_header();
2019-04-28 01:08:05 +00:00
// write audio to cache, if need to flush, flush to muxer.
virtual srs_error_t write_audio(SrsAudioFrame* frame, int64_t pts);
2019-04-28 01:08:05 +00:00
// write video to muxer.
virtual srs_error_t write_video(SrsVideoFrame* frame, int64_t dts);
private:
2019-04-28 01:08:05 +00:00
// Reopen the muxer for a new hls segment,
// close current segment, open a new segment,
// then write the key frame to the new segment.
// so, user must reap_segment then flush_video to hls muxer.
virtual srs_error_t reap_segment();
};
2019-04-28 01:08:05 +00:00
// Transmux RTMP stream to HLS(m3u8 and ts).
// TODO: FIXME: add utest for hls.
class SrsHls
{
private:
SrsHlsController* controller;
2013-11-26 08:06:58 +00:00
private:
SrsRequest* req;
2017-02-11 13:14:28 +00:00
bool enabled;
bool disposable;
srs_utime_t last_update_time;
private:
// If the diff=dts-previous_audio_dts is about 23,
// that's the AAC samples is 1024, and we use the samples to calc the dts.
int64_t previous_audio_dts;
// The total aac samples.
uint64_t aac_samples;
// Whether directly turn FLV timestamp to TS DTS.
bool hls_dts_directly;
private:
SrsOriginHub* hub;
2014-03-18 03:32:58 +00:00
SrsRtmpJitter* jitter;
SrsPithyPrint* pprint;
2013-11-23 12:16:47 +00:00
public:
SrsHls();
2014-03-18 03:32:58 +00:00
virtual ~SrsHls();
public:
virtual void dispose();
2017-06-11 01:40:07 +00:00
virtual srs_error_t cycle();
public:
2019-04-28 01:08:05 +00:00
// Initialize the hls by handler and source.
2017-06-11 01:40:07 +00:00
virtual srs_error_t initialize(SrsOriginHub* h, SrsRequest* r);
2019-04-28 01:08:05 +00:00
// Publish stream event, continue to write the m3u8,
// for the muxer object not destroyed.
// @param fetch_sequence_header whether fetch sequence from source.
virtual srs_error_t on_publish();
2019-04-28 01:08:05 +00:00
// The unpublish event, only close the muxer, donot destroy the
// muxer, for when we continue to publish, the m3u8 will continue.
2014-03-18 03:32:58 +00:00
virtual void on_unpublish();
2019-04-28 01:08:05 +00:00
// Mux the audio packets to ts.
// @param shared_audio, directly ptr, copy it if need to save it.
virtual srs_error_t on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format);
2019-04-28 01:08:05 +00:00
// Mux the video packets to ts.
// @param shared_video, directly ptr, copy it if need to save it.
// @param is_sps_pps whether the video is h.264 sps/pps.
// TODO: FIXME: Remove param is_sps_pps.
virtual srs_error_t on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format);
2013-12-05 15:34:26 +00:00
private:
virtual void hls_show_mux_log();
2013-11-23 12:16:47 +00:00
};
2013-11-27 14:41:58 +00:00
#endif