Skip to content

Commit

Permalink
For #299, refine the codec to format-frame-sample chain.
Browse files Browse the repository at this point in the history
  • Loading branch information
winlinvip committed Feb 12, 2017
1 parent c4a510b commit d7458c4
Show file tree
Hide file tree
Showing 18 changed files with 972 additions and 1,132 deletions.
314 changes: 122 additions & 192 deletions trunk/src/app/srs_app_hls.cpp

Large diffs are not rendered by default.

87 changes: 30 additions & 57 deletions trunk/src/app/srs_app_hls.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ class SrsFormat;
class SrsSharedPtrMessage;
class SrsAmf0Object;
class SrsRtmpJitter;
class SrsTSMuxer;
class SrsTsMuxer;
class SrsRequest;
class SrsPithyPrint;
class SrsSource;
Expand All @@ -53,41 +53,6 @@ class SrsHlsSegment;
class SrsTsCache;
class SrsTsContext;

/**
* write to file and cache.
*/
class SrsHlsCacheWriter : public SrsFileWriter
{
private:
SrsFileWriter impl;
std::string data;
bool should_write_cache;
bool should_write_file;
public:
SrsHlsCacheWriter(bool write_cache, bool write_file);
virtual ~SrsHlsCacheWriter();
public:
/**
* open file writer, can open then close then open...
*/
virtual int open(std::string file);
virtual void close();
public:
virtual bool is_open();
virtual int64_t tellg();
public:
/**
* write to file.
* @param pnwrite the output nb_write, NULL to ignore.
*/
virtual int write(void* buf, size_t count, ssize_t* pnwrite);
public:
/**
* get the string cache.
*/
virtual std::string cache();
};

/**
* the wrapper of m3u8 segment from specification:
*
Expand All @@ -106,14 +71,14 @@ class SrsHlsSegment
// ts full file to write.
std::string full_path;
// the muxer to write ts.
SrsHlsCacheWriter* writer;
SrsTSMuxer* muxer;
SrsFileWriter* writer;
SrsTsMuxer* muxer;
// current segment start dts for m3u8
int64_t segment_start_dts;
// whether current segement is sequence header.
bool is_sequence_header;
public:
SrsHlsSegment(SrsTsContext* c, bool write_cache, bool write_file, SrsCodecAudio ac, SrsCodecVideo vc);
SrsHlsSegment(SrsTsContext* c, SrsCodecAudio ac, SrsCodecVideo vc);
virtual ~SrsHlsSegment();
public:
/**
Expand Down Expand Up @@ -200,10 +165,6 @@ class SrsHlsMuxer
int max_td;
std::string m3u8;
std::string m3u8_url;
private:
// TODO: FIXME: remove it.
bool should_write_cache;
bool should_write_file;
private:
/**
* m3u8 segments.
Expand Down Expand Up @@ -303,42 +264,54 @@ class SrsHlsMuxer
* so we must gather audio frame together, and recalc the timestamp @see SrsTsAacJitter,
* we use a aac jitter to correct the audio pts.
*/
class SrsHlsCache
class SrsHlsController
{
private:
SrsTsCache* cache;
// The HLS muxer to reap ts and m3u8.
// The TS is cached to SrsTsCache then flush to ts segment.
SrsHlsMuxer* muxer;
// The TS cache
SrsTsCache* ts;
public:
SrsHlsCache();
virtual ~SrsHlsCache();
SrsHlsController();
virtual ~SrsHlsController();
public:
virtual int initialize();
virtual void dispose();
virtual int update_acodec(SrsCodecAudio ac);
virtual int sequence_no();
virtual std::string ts_url();
virtual double duration();
virtual int deviation();
public:
/**
* when publish or unpublish stream.
*/
virtual int on_publish(SrsHlsMuxer* muxer, SrsRequest* req, int64_t segment_start_dts);
virtual int on_unpublish(SrsHlsMuxer* muxer);
virtual int on_publish(SrsRequest* req, int64_t segment_start_dts);
virtual int on_unpublish();
/**
* 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 int on_sequence_header(SrsHlsMuxer* muxer);
virtual int on_sequence_header();
/**
* write audio to cache, if need to flush, flush to muxer.
*/
virtual int write_audio(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t pts, SrsCodecSample* sample);
virtual int write_audio(SrsAudioFrame* frame, int64_t pts);
/**
* write video to muxer.
*/
virtual int write_video(SrsAvcAacCodec* codec, SrsHlsMuxer* muxer, int64_t dts, SrsCodecSample* sample);
virtual int write_video(SrsVideoFrame* frame, int64_t dts);
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(std::string log_desc, SrsHlsMuxer* muxer, int64_t segment_start_dts);
virtual int reap_segment(std::string log_desc, int64_t segment_start_dts);
};

/**
Expand All @@ -348,8 +321,7 @@ class SrsHlsCache
class SrsHls
{
private:
SrsHlsMuxer* muxer;
SrsHlsCache* cache;
SrsHlsController* controller;
private:
SrsRequest* req;
bool enabled;
Expand Down Expand Up @@ -400,13 +372,14 @@ class SrsHls
* mux the audio packets to ts.
* @param shared_audio, directly ptr, copy it if need to save it.
*/
virtual int on_audio(SrsSharedPtrMessage* shared_audio);
virtual int on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* format);
/**
* 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.
*/
virtual int on_video(SrsSharedPtrMessage* shared_video, bool is_sps_pps);
// TODO: FIXME: Remove param is_sps_pps.
virtual int on_video(SrsSharedPtrMessage* shared_video, SrsFormat* format);
private:
virtual void hls_show_mux_log();
};
Expand Down
69 changes: 0 additions & 69 deletions trunk/src/app/srs_app_http_stream.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -653,75 +653,6 @@ bool SrsLiveEntry::is_mp3()
return _is_mp3;
}

SrsHlsM3u8Stream::SrsHlsM3u8Stream()
{
}

SrsHlsM3u8Stream::~SrsHlsM3u8Stream()
{
}

void SrsHlsM3u8Stream::set_m3u8(std::string v)
{
m3u8 = v;
}

int SrsHlsM3u8Stream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
{
int ret = ERROR_SUCCESS;

std::string data = m3u8;

w->header()->set_content_length((int)data.length());
w->header()->set_content_type("application/x-mpegURL;charset=utf-8");

if ((ret = w->write((char*)data.data(), (int)data.length())) != ERROR_SUCCESS) {
if (!srs_is_client_gracefully_close(ret)) {
srs_error("send m3u8 failed. ret=%d", ret);
}
return ret;
}

return ret;
}

SrsHlsTsStream::SrsHlsTsStream()
{
}

SrsHlsTsStream::~SrsHlsTsStream()
{
}

void SrsHlsTsStream::set_ts(std::string v)
{
ts = v;
}

int SrsHlsTsStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
{
int ret = ERROR_SUCCESS;

std::string data = ts;

w->header()->set_content_length((int)data.length());
w->header()->set_content_type("video/MP2T");

if ((ret = w->write((char*)data.data(), (int)data.length())) != ERROR_SUCCESS) {
if (!srs_is_client_gracefully_close(ret)) {
srs_error("send ts failed. ret=%d", ret);
}
return ret;
}

return ret;
}

SrsHlsEntry::SrsHlsEntry()
{
tmpl = NULL;
}

SrsHttpStreamServer::SrsHttpStreamServer(SrsServer* svr)
{
server = svr;
Expand Down
52 changes: 0 additions & 52 deletions trunk/src/app/srs_app_http_stream.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -262,58 +262,6 @@ struct SrsLiveEntry
bool is_aac();
};

/**
* the m3u8 stream handler.
*/
class SrsHlsM3u8Stream : public ISrsHttpHandler
{
private:
std::string m3u8;
public:
SrsHlsM3u8Stream();
virtual ~SrsHlsM3u8Stream();
public:
virtual void set_m3u8(std::string v);
public:
virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
};

/**
* the ts stream handler.
*/
class SrsHlsTsStream : public ISrsHttpHandler
{
private:
std::string ts;
public:
SrsHlsTsStream();
virtual ~SrsHlsTsStream();
public:
virtual void set_ts(std::string v);
public:
virtual int serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r);
};

/**
* the srs hls entry.
*/
// TODO: FIXME: use hte hls template and entry.
struct SrsHlsEntry
{
// for template, the mount contains variables.
// for concrete stream, the mount is url to access.
std::string mount;

// the template to create the entry
SrsHlsEntry* tmpl;

// key: the m3u8/ts file path.
// value: the http handler.
std::map<std::string, ISrsHttpHandler*> streams;

SrsHlsEntry();
};

/**
* the http stream server instance,
* serve http stream, for example, flv/ts/mp3/aac live stream.
Expand Down
33 changes: 19 additions & 14 deletions trunk/src/app/srs_app_rtsp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ using namespace std;
#include <srs_app_pithy_print.hpp>
#include <srs_app_rtmp_conn.hpp>
#include <srs_protocol_utility.hpp>
#include <srs_protocol_format.hpp>

#ifdef SRS_AUTO_STREAM_CASTER

Expand Down Expand Up @@ -135,13 +136,13 @@ int SrsRtpConn::on_udp_packet(sockaddr_in* from, char* buf, int nb_buf)
SrsRtspAudioCache::SrsRtspAudioCache()
{
dts = 0;
audio_samples = NULL;
audio = NULL;
payload = NULL;
}

SrsRtspAudioCache::~SrsRtspAudioCache()
{
srs_freep(audio_samples);
srs_freep(audio);
srs_freep(payload);
}

Expand Down Expand Up @@ -456,10 +457,10 @@ int SrsRtspConn::on_rtp_audio(SrsRtpPacket* pkt, int64_t dts)

// cache current audio to kickoff.
acache->dts = dts;
acache->audio_samples = pkt->audio_samples;
acache->audio = pkt->audio;
acache->payload = pkt->payload;

pkt->audio_samples = NULL;
pkt->audio = NULL;
pkt->payload = NULL;

return ret;
Expand All @@ -474,11 +475,11 @@ int SrsRtspConn::kickoff_audio_cache(SrsRtpPacket* pkt, int64_t dts)
return ret;
}

if (dts - acache->dts > 0 && acache->audio_samples->nb_sample_units > 0) {
int64_t delta = (dts - acache->dts) / acache->audio_samples->nb_sample_units;
for (int i = 0; i < acache->audio_samples->nb_sample_units; i++) {
char* frame = acache->audio_samples->sample_units[i].bytes;
int nb_frame = acache->audio_samples->sample_units[i].size;
if (dts - acache->dts > 0 && acache->audio->nb_samples > 0) {
int64_t delta = (dts - acache->dts) / acache->audio->nb_samples;
for (int i = 0; i < acache->audio->nb_samples; i++) {
char* frame = acache->audio->samples[i].bytes;
int nb_frame = acache->audio->samples[i].size;
int64_t timestamp = (acache->dts + delta * i) / 90;
acodec->aac_packet_type = 1;
if ((ret = write_audio_raw_frame(frame, nb_frame, acodec, (uint32_t)timestamp)) != ERROR_SUCCESS) {
Expand All @@ -488,7 +489,7 @@ int SrsRtspConn::kickoff_audio_cache(SrsRtpPacket* pkt, int64_t dts)
}

acache->dts = 0;
srs_freep(acache->audio_samples);
srs_freep(acache->audio);
srs_freep(acache->payload);

return ret;
Expand All @@ -510,13 +511,17 @@ int SrsRtspConn::write_sequence_header()
if (true) {
std::string sh = aac_specific_config;

SrsAvcAacCodec dec;
if ((ret = dec.audio_aac_sequence_header_demux((char*)sh.c_str(), (int)sh.length())) != ERROR_SUCCESS) {
SrsFormat* format = new SrsFormat();
SrsAutoFree(SrsFormat, format);

if ((ret = format->on_aac_sequence_header((char*)sh.c_str(), (int)sh.length())) != ERROR_SUCCESS) {
return ret;
}

SrsAudioCodec* dec = format->acodec;

acodec->sound_format = SrsCodecAudioAAC;
acodec->sound_type = (dec.aac_channels == 2)? SrsCodecAudioSoundTypeStereo : SrsCodecAudioSoundTypeMono;
acodec->sound_type = (dec->aac_channels == 2)? SrsCodecAudioSoundTypeStereo : SrsCodecAudioSoundTypeMono;
acodec->sound_size = SrsCodecAudioSampleSize16bit;
acodec->aac_packet_type = 0;

Expand All @@ -526,7 +531,7 @@ int SrsRtspConn::write_sequence_header()
16000, 12000, 11025, 8000,
7350, 0, 0, 0
};
switch (aac_sample_rates[dec.aac_sample_rate]) {
switch (aac_sample_rates[dec->aac_sample_rate]) {
case 11025:
acodec->sound_rate = SrsCodecAudioSampleRate11025;
break;
Expand Down
Loading

0 comments on commit d7458c4

Please sign in to comment.