mirror of
https://github.com/ossrs/srs.git
synced 2025-03-09 15:49:59 +00:00
support pure audio hls. change to 0.9.24
This commit is contained in:
parent
b708f588fc
commit
e0fb1029c9
3 changed files with 81 additions and 39 deletions
|
@ -44,7 +44,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
#include <srs_app_pithy_print.hpp>
|
#include <srs_app_pithy_print.hpp>
|
||||||
|
|
||||||
// max PES packets size to flush the video.
|
// max PES packets size to flush the video.
|
||||||
#define SRS_HLS_AUDIO_CACHE_SIZE 512 * 1024
|
#define SRS_HLS_AUDIO_CACHE_SIZE 1024 * 1024
|
||||||
|
|
||||||
// @see: NGX_RTMP_HLS_DELAY,
|
// @see: NGX_RTMP_HLS_DELAY,
|
||||||
// 63000: 700ms, ts_tbn=90000
|
// 63000: 700ms, ts_tbn=90000
|
||||||
|
@ -481,12 +481,20 @@ SrsHlsSegment::~SrsHlsSegment()
|
||||||
srs_freep(muxer);
|
srs_freep(muxer);
|
||||||
}
|
}
|
||||||
|
|
||||||
double SrsHlsSegment::update_duration(int64_t current_frame_dts)
|
void SrsHlsSegment::update_duration(int64_t current_frame_dts)
|
||||||
{
|
{
|
||||||
|
// we use video/audio to update segment duration,
|
||||||
|
// so when reap segment, some previous audio frame will
|
||||||
|
// update the segment duration, which is nagetive,
|
||||||
|
// just ignore it.
|
||||||
|
if (current_frame_dts < segment_start_dts) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
duration = (current_frame_dts - segment_start_dts) / 90000.0;
|
duration = (current_frame_dts - segment_start_dts) / 90000.0;
|
||||||
srs_assert(duration >= 0);
|
srs_assert(duration >= 0);
|
||||||
|
|
||||||
return duration;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsHlsAacJitter::SrsHlsAacJitter()
|
SrsHlsAacJitter::SrsHlsAacJitter()
|
||||||
|
@ -503,7 +511,6 @@ SrsHlsMuxer::SrsHlsMuxer()
|
||||||
hls_fragment = hls_window = 0;
|
hls_fragment = hls_window = 0;
|
||||||
file_index = 0;
|
file_index = 0;
|
||||||
current = NULL;
|
current = NULL;
|
||||||
video_count = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsHlsMuxer::~SrsHlsMuxer()
|
SrsHlsMuxer::~SrsHlsMuxer()
|
||||||
|
@ -542,9 +549,6 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// reset video count for new publish session.
|
|
||||||
video_count = 0;
|
|
||||||
|
|
||||||
// TODO: create all parents dirs.
|
// TODO: create all parents dirs.
|
||||||
// create dir for app.
|
// create dir for app.
|
||||||
if ((ret = create_dir()) != ERROR_SUCCESS) {
|
if ((ret = create_dir()) != ERROR_SUCCESS) {
|
||||||
|
@ -605,6 +609,9 @@ int SrsHlsMuxer::flush_audio(SrsMpegtsFrame* af, SrsCodecBuffer* ab)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// update the duration of segment.
|
||||||
|
current->update_duration(af->pts);
|
||||||
|
|
||||||
if ((ret = current->muxer->write_audio(af, ab)) != ERROR_SUCCESS) {
|
if ((ret = current->muxer->write_audio(af, ab)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
@ -635,6 +642,9 @@ int SrsHlsMuxer::flush_video(
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// write success, clear and free the buffer
|
||||||
|
vb->free();
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -860,6 +870,8 @@ SrsHlsCache::SrsHlsCache()
|
||||||
|
|
||||||
af = new SrsMpegtsFrame();
|
af = new SrsMpegtsFrame();
|
||||||
vf = new SrsMpegtsFrame();
|
vf = new SrsMpegtsFrame();
|
||||||
|
|
||||||
|
video_count = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
SrsHlsCache::~SrsHlsCache()
|
SrsHlsCache::~SrsHlsCache()
|
||||||
|
@ -890,6 +902,9 @@ int SrsHlsCache::on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment
|
||||||
// get the hls path config
|
// get the hls path config
|
||||||
std::string hls_path = _srs_config->get_hls_path(vhost);
|
std::string hls_path = _srs_config->get_hls_path(vhost);
|
||||||
|
|
||||||
|
// reset video count for new publish session.
|
||||||
|
video_count = 0;
|
||||||
|
|
||||||
// open muxer
|
// open muxer
|
||||||
if ((ret = muxer->update_config(app, stream, hls_path, hls_fragment, hls_window)) != ERROR_SUCCESS) {
|
if ((ret = muxer->update_config(app, stream, hls_path, hls_fragment, hls_window)) != ERROR_SUCCESS) {
|
||||||
srs_error("m3u8 muxer update config failed. ret=%d", ret);
|
srs_error("m3u8 muxer update config failed. ret=%d", ret);
|
||||||
|
@ -956,13 +971,25 @@ int SrsHlsCache::write_audio(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t pts, S
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// for pure audio
|
||||||
|
// start new segment when duration overflow.
|
||||||
|
if (video_count == 0 && muxer->is_segment_overflow()) {
|
||||||
|
srs_trace("pure audio segment reap");
|
||||||
|
if ((ret = reap_segment(muxer, af->pts)) != ERROR_SUCCESS) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
int SrsHlsCache::write_video(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t dts, SrsCodecSample* sample)
|
int SrsHlsCache::write_video(
|
||||||
|
SrsCodec* codec, SrsHlsMuxer* muxer, int64_t dts, SrsCodecSample* sample)
|
||||||
{
|
{
|
||||||
int ret = ERROR_SUCCESS;
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
video_count++;
|
||||||
|
|
||||||
// write video to cache.
|
// write video to cache.
|
||||||
if ((ret = cache_video(codec, sample)) != ERROR_SUCCESS) {
|
if ((ret = cache_video(codec, sample)) != ERROR_SUCCESS) {
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -974,26 +1001,11 @@ int SrsHlsCache::write_video(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t dts, S
|
||||||
vf->sid = TS_VIDEO_AVC;
|
vf->sid = TS_VIDEO_AVC;
|
||||||
vf->key = sample->frame_type == SrsCodecVideoAVCFrameKeyFrame;
|
vf->key = sample->frame_type == SrsCodecVideoAVCFrameKeyFrame;
|
||||||
|
|
||||||
// reopen the muxer for a gop
|
// new segment when:
|
||||||
// close current segment, open a new segment,
|
// 1. base on gop.
|
||||||
// then write the key frame to the new segment.
|
// 2. some gops duration overflow.
|
||||||
if (vf->key && muxer->is_segment_overflow()) {
|
if (vf->key && muxer->is_segment_overflow()) {
|
||||||
if ((ret = muxer->segment_close()) != ERROR_SUCCESS) {
|
if ((ret = reap_segment(muxer, vf->dts)) != ERROR_SUCCESS) {
|
||||||
srs_error("m3u8 muxer close segment failed. ret=%d", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((ret = muxer->segment_open(vf->dts)) != ERROR_SUCCESS) {
|
|
||||||
srs_error("m3u8 muxer open segment failed. ret=%d", ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: flush audio before or after segment?
|
|
||||||
// segment open, flush the audio.
|
|
||||||
// @see: ngx_rtmp_hls_open_fragment
|
|
||||||
/* start fragment with audio to make iPhone happy */
|
|
||||||
if ((ret = muxer->flush_audio(af, ab)) != ERROR_SUCCESS) {
|
|
||||||
srs_error("m3u8 muxer flush audio failed. ret=%d", ret);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1004,8 +1016,31 @@ int SrsHlsCache::write_video(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t dts, S
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
// write success, clear and free the buffer
|
return ret;
|
||||||
vb->free();
|
}
|
||||||
|
|
||||||
|
int SrsHlsCache::reap_segment(SrsHlsMuxer* muxer, int64_t segment_start_dts)
|
||||||
|
{
|
||||||
|
int ret = ERROR_SUCCESS;
|
||||||
|
|
||||||
|
if ((ret = muxer->segment_close()) != ERROR_SUCCESS) {
|
||||||
|
srs_error("m3u8 muxer close segment failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ret = muxer->segment_open(segment_start_dts)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("m3u8 muxer open segment failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: flush audio before or after segment?
|
||||||
|
// segment open, flush the audio.
|
||||||
|
// @see: ngx_rtmp_hls_open_fragment
|
||||||
|
/* start fragment with audio to make iPhone happy */
|
||||||
|
if ((ret = muxer->flush_audio(af, ab)) != ERROR_SUCCESS) {
|
||||||
|
srs_error("m3u8 muxer flush audio failed. ret=%d", ret);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
|
@ -124,7 +124,7 @@ public:
|
||||||
* update the segment duration.
|
* update the segment duration.
|
||||||
* @current_frame_dts the dts of frame, in tbn of ts.
|
* @current_frame_dts the dts of frame, in tbn of ts.
|
||||||
*/
|
*/
|
||||||
virtual double update_duration(int64_t current_frame_dts);
|
virtual void update_duration(int64_t current_frame_dts);
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -147,14 +147,6 @@ private:
|
||||||
private:
|
private:
|
||||||
int file_index;
|
int file_index;
|
||||||
std::string m3u8;
|
std::string m3u8;
|
||||||
private:
|
|
||||||
/**
|
|
||||||
* for pure audio HLS application,
|
|
||||||
* the video count used to count the video,
|
|
||||||
* if zero and audio buffer overflow, reap the ts,
|
|
||||||
* just like we got a keyframe.
|
|
||||||
*/
|
|
||||||
u_int32_t video_count;
|
|
||||||
private:
|
private:
|
||||||
/**
|
/**
|
||||||
* m3u8 segments.
|
* m3u8 segments.
|
||||||
|
@ -219,6 +211,14 @@ private:
|
||||||
int64_t audio_buffer_start_pts;
|
int64_t audio_buffer_start_pts;
|
||||||
// time jitter for aac
|
// time jitter for aac
|
||||||
SrsHlsAacJitter* aac_jitter;
|
SrsHlsAacJitter* aac_jitter;
|
||||||
|
private:
|
||||||
|
/**
|
||||||
|
* for pure audio HLS application,
|
||||||
|
* the video count used to count the video,
|
||||||
|
* if zero and audio buffer overflow, reap the ts,
|
||||||
|
* just like we got a keyframe.
|
||||||
|
*/
|
||||||
|
u_int32_t video_count;
|
||||||
public:
|
public:
|
||||||
SrsHlsCache();
|
SrsHlsCache();
|
||||||
virtual ~SrsHlsCache();
|
virtual ~SrsHlsCache();
|
||||||
|
@ -237,6 +237,13 @@ public:
|
||||||
*/
|
*/
|
||||||
virtual int write_video(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t dts, SrsCodecSample* sample);
|
virtual int write_video(SrsCodec* codec, SrsHlsMuxer* muxer, int64_t dts, SrsCodecSample* sample);
|
||||||
private:
|
private:
|
||||||
|
/**
|
||||||
|
* 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 int reap_segment(SrsHlsMuxer* muxer, int64_t segment_start_dts);
|
||||||
virtual int cache_audio(SrsCodec* codec, SrsCodecSample* sample);
|
virtual int cache_audio(SrsCodec* codec, SrsCodecSample* sample);
|
||||||
virtual int cache_video(SrsCodec* codec, SrsCodecSample* sample);
|
virtual int cache_video(SrsCodec* codec, SrsCodecSample* sample);
|
||||||
};
|
};
|
||||||
|
|
|
@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||||
// current release version
|
// current release version
|
||||||
#define VERSION_MAJOR "0"
|
#define VERSION_MAJOR "0"
|
||||||
#define VERSION_MINOR "9"
|
#define VERSION_MINOR "9"
|
||||||
#define VERSION_REVISION "23"
|
#define VERSION_REVISION "24"
|
||||||
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
|
#define RTMP_SIG_SRS_VERSION VERSION_MAJOR"."VERSION_MINOR"."VERSION_REVISION
|
||||||
// server info.
|
// server info.
|
||||||
#define RTMP_SIG_SRS_KEY "srs"
|
#define RTMP_SIG_SRS_KEY "srs"
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue