support pure audio hls. change to 0.9.24

pull/133/head
winlin 11 years ago
parent b708f588fc
commit e0fb1029c9

@ -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…
Cancel
Save