From 78f34ad46fbd6c9d59f29dadec5ebf06b0049814 Mon Sep 17 00:00:00 2001 From: winlin Date: Sun, 15 Feb 2015 18:11:24 +0800 Subject: [PATCH] for #304, support config default acodec/vcodec. 2.0.118. --- README.md | 1 + trunk/conf/full.conf | 46 ++-- trunk/src/app/srs_app_config.cpp | 19 +- trunk/src/app/srs_app_config.hpp | 5 + trunk/src/app/srs_app_hls.cpp | 41 ++- trunk/src/app/srs_app_hls.hpp | 2 +- trunk/src/core/srs_core.hpp | 2 +- trunk/src/kernel/srs_kernel_codec.hpp | 5 +- trunk/src/kernel/srs_kernel_ts.cpp | 356 ++------------------------ trunk/src/kernel/srs_kernel_ts.hpp | 18 +- 10 files changed, 114 insertions(+), 381 deletions(-) diff --git a/README.md b/README.md index bada9943f6..557c00f76e 100755 --- a/README.md +++ b/README.md @@ -527,6 +527,7 @@ Supported operating systems and hardware: ### SRS 2.0 history +* v2.0, 2015-02-15, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), support config default acodec/vcodec. 2.0.118. * v2.0, 2015-02-15, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), rewrite hls/ts code, support h.264+mp3 for hls. 2.0.117. * v2.0, 2015-02-12, for [#304](https://github.com/winlinvip/simple-rtmp-server/issues/304), use stringstream to generate m3u8, add hls_td_ratio. 2.0.116. * v2.0, 2015-02-11, dev code ZhouGuowen for 2.0.115. diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 5b31bc022c..a00f939580 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -495,10 +495,19 @@ vhost with-hls.srs.com { # the default audio codec of hls. # when codec changed, write the PAT/PMT table, but maybe ok util next ts. # so user can set the default codec for mp3. - # the available audio codec: aac, mp3 + # the available audio codec: + # aac, mp3 # default: aac # TODO: FIXME: update wiki for it. hls_acodec aac; + # the default video codec of hls. + # when codec changed, write the PAT/PMT table, but maybe ok util next ts. + # so user can set the default codec for pure audio(without video) to vn. + # the available video codec: + # h264, vn + # default: h264 + # TODO: FIXME: update wiki for it. + hls_vcodec h264; } } # the vhost with hls disabled. @@ -713,9 +722,9 @@ vhost example.transcode.srs.com { filter_complex 'overlay=10:10'; } # video encoder name. can be: - # libx264: use h.264(libx264) video encoder. - # copy: donot encoder the video stream, copy it. - # vn: disable video output. + # libx264: use h.264(libx264) video encoder. + # copy: donot encoder the video stream, copy it. + # vn: disable video output. vcodec libx264; # video bitrate, in kbps vbitrate 1500; @@ -731,8 +740,8 @@ vhost example.transcode.srs.com { # high,main,baseline vprofile main; # x264 preset, @see x264 -help, can be: - # ultrafast,superfast,veryfast,faster,fast - # medium,slow,slower,veryslow,placebo + # ultrafast,superfast,veryfast,faster,fast + # medium,slow,slower,veryslow,placebo vpreset medium; # other x264 or ffmpeg video params vparams { @@ -745,14 +754,15 @@ vhost example.transcode.srs.com { refs 10; } # audio encoder name. can be: - # libaacplus: use aac(libaacplus) audio encoder. - # copy: donot encoder the audio stream, copy it. - # an: disable audio output. + # libaacplus: use aac(libaacplus) audio encoder. + # libfdk_aac: use aac(libfdk_aac) audio encoder. + # copy: donot encoder the audio stream, copy it. + # an: disable audio output. acodec libaacplus; # audio bitrate, in kbps. [16, 72] for libaacplus. abitrate 70; # audio sample rate. for flv/rtmp, it must be: - # 44100,22050,11025,5512 + # 44100,22050,11025,5512 asample_rate 44100; # audio channel, 1 for mono, 2 for stereo. achannels 2; @@ -762,17 +772,17 @@ vhost example.transcode.srs.com { profile:a aac_low; } # output format, can be: - # off, do not specifies the format, ffmpeg will guess it. - # flv, for flv or RTMP stream. - # other format, for example, mp4/aac whatever. + # off, do not specifies the format, ffmpeg will guess it. + # flv, for flv or RTMP stream. + # other format, for example, mp4/aac whatever. # default: flv oformat flv; # output stream. variables: - # [vhost] the input stream vhost. - # [port] the intput stream port. - # [app] the input stream app. - # [stream] the input stream name. - # [engine] the tanscode engine name. + # [vhost] the input stream vhost. + # [port] the intput stream port. + # [app] the input stream app. + # [stream] the input stream name. + # [engine] the tanscode engine name. output rtmp://127.0.0.1:[port]/[app]?vhost=[vhost]/[stream]_[engine]; } } diff --git a/trunk/src/app/srs_app_config.cpp b/trunk/src/app/srs_app_config.cpp index dcedbee283..a769bbf1d3 100644 --- a/trunk/src/app/srs_app_config.cpp +++ b/trunk/src/app/srs_app_config.cpp @@ -1480,7 +1480,7 @@ int SrsConfig::check_config() for (int j = 0; j < (int)conf->directives.size(); j++) { string m = conf->at(j)->name.c_str(); if (m != "enabled" && m != "hls_path" && m != "hls_fragment" && m != "hls_window" && m != "hls_on_error" - && m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio" && m != "hls_acodec" + && m != "hls_storage" && m != "hls_mount" && m != "hls_td_ratio" && m != "hls_acodec" && m != "hls_vcodec" ) { ret = ERROR_SYSTEM_CONFIG_INVALID; srs_error("unsupported vhost hls directive %s, ret=%d", m.c_str(), ret); @@ -3349,6 +3349,23 @@ string SrsConfig::get_hls_acodec(string vhost) return conf->arg0(); } +string SrsConfig::get_hls_vcodec(string vhost) +{ + SrsConfDirective* hls = get_hls(vhost); + + if (!hls) { + return SRS_CONF_DEFAULT_HLS_VCODEC; + } + + SrsConfDirective* conf = hls->get("hls_vcodec"); + + if (!conf) { + return SRS_CONF_DEFAULT_HLS_VCODEC; + } + + return conf->arg0(); +} + SrsConfDirective* SrsConfig::get_dvr(string vhost) { SrsConfDirective* conf = get_vhost(vhost); diff --git a/trunk/src/app/srs_app_config.hpp b/trunk/src/app/srs_app_config.hpp index 2787cb9c97..bb2cf8d582 100644 --- a/trunk/src/app/srs_app_config.hpp +++ b/trunk/src/app/srs_app_config.hpp @@ -56,6 +56,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. #define SRS_CONF_DEFAULT_HLS_STORAGE "disk" #define SRS_CONF_DEFAULT_HLS_MOUNT "[vhost]/[app]/[stream].m3u8" #define SRS_CONF_DEFAULT_HLS_ACODEC "aac" +#define SRS_CONF_DEFAULT_HLS_VCODEC "h264" #define SRS_CONF_DEFAULT_DVR_PATH "./objs/nginx/html" #define SRS_CONF_DEFAULT_DVR_PLAN_SESSION "session" #define SRS_CONF_DEFAULT_DVR_PLAN_SEGMENT "segment" @@ -927,6 +928,10 @@ class SrsConfig * get the HLS default audio codec. */ virtual std::string get_hls_acodec(std::string vhost); + /** + * get the HLS default video codec. + */ + virtual std::string get_hls_vcodec(std::string vhost); // dvr section private: /** diff --git a/trunk/src/app/srs_app_hls.cpp b/trunk/src/app/srs_app_hls.cpp index 16ca9da314..01590f2e0e 100644 --- a/trunk/src/app/srs_app_hls.cpp +++ b/trunk/src/app/srs_app_hls.cpp @@ -131,14 +131,14 @@ string SrsHlsCacheWriter::cache() return data; } -SrsHlsSegment::SrsHlsSegment(bool write_cache, bool write_file, SrsCodecAudio ac) +SrsHlsSegment::SrsHlsSegment(bool write_cache, bool write_file, SrsCodecAudio ac, SrsCodecVideo vc) { duration = 0; sequence_no = 0; segment_start_dts = 0; is_sequence_header = false; writer = new SrsHlsCacheWriter(write_cache, write_file); - muxer = new SrsTSMuxer(writer, ac); + muxer = new SrsTSMuxer(writer, ac, vc); } SrsHlsSegment::~SrsHlsSegment() @@ -246,19 +246,36 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts) // load the default acodec from config. SrsCodecAudio default_acodec = SrsCodecAudioAAC; - std::string default_acodec_str = _srs_config->get_hls_acodec(req->vhost); - if (default_acodec_str == "mp3") { - default_acodec = SrsCodecAudioMP3; - srs_info("hls: use default mp3 acodec"); - } else if (default_acodec_str == "aac") { - default_acodec = SrsCodecAudioAAC; - srs_info("hls: use default aac acodec"); - } else { - srs_warn("hls: use aac for other codec=%s", default_acodec_str.c_str()); + if (true) { + std::string default_acodec_str = _srs_config->get_hls_acodec(req->vhost); + if (default_acodec_str == "mp3") { + default_acodec = SrsCodecAudioMP3; + srs_info("hls: use default mp3 acodec"); + } else if (default_acodec_str == "aac") { + default_acodec = SrsCodecAudioAAC; + srs_info("hls: use default aac acodec"); + } else { + srs_warn("hls: use aac for other codec=%s", default_acodec_str.c_str()); + } + } + + // load the default vcodec from config. + SrsCodecVideo default_vcodec = SrsCodecVideoAVC; + if (true) { + std::string default_vcodec_str = _srs_config->get_hls_vcodec(req->vhost); + if (default_vcodec_str == "h264") { + default_vcodec = SrsCodecVideoAVC; + srs_info("hls: use default h264 vcodec"); + } else if (default_vcodec_str == "vn") { + default_vcodec = SrsCodecVideoDisabled; + srs_info("hls: use default vn vcodec for pure audio"); + } else { + srs_warn("hls: use h264 for other codec=%s", default_vcodec_str.c_str()); + } } // new segment. - current = new SrsHlsSegment(should_write_cache, should_write_file, default_acodec); + current = new SrsHlsSegment(should_write_cache, should_write_file, default_acodec, default_vcodec); current->sequence_no = _sequence_no++; current->segment_start_dts = segment_start_dts; diff --git a/trunk/src/app/srs_app_hls.hpp b/trunk/src/app/srs_app_hls.hpp index 3cb0407b9a..42cc427ca6 100644 --- a/trunk/src/app/srs_app_hls.hpp +++ b/trunk/src/app/srs_app_hls.hpp @@ -144,7 +144,7 @@ class SrsHlsSegment // whether current segement is sequence header. bool is_sequence_header; public: - SrsHlsSegment(bool write_cache, bool write_file, SrsCodecAudio ac); + SrsHlsSegment(bool write_cache, bool write_file, SrsCodecAudio ac, SrsCodecVideo vc); virtual ~SrsHlsSegment(); public: /** diff --git a/trunk/src/core/srs_core.hpp b/trunk/src/core/srs_core.hpp index 5865baf6c6..2ecc3cc4c6 100644 --- a/trunk/src/core/srs_core.hpp +++ b/trunk/src/core/srs_core.hpp @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // current release version #define VERSION_MAJOR 2 #define VERSION_MINOR 0 -#define VERSION_REVISION 117 +#define VERSION_REVISION 118 // server info. #define RTMP_SIG_SRS_KEY "SRS" diff --git a/trunk/src/kernel/srs_kernel_codec.hpp b/trunk/src/kernel/srs_kernel_codec.hpp index 00a8ed4e30..192bc82adf 100644 --- a/trunk/src/kernel/srs_kernel_codec.hpp +++ b/trunk/src/kernel/srs_kernel_codec.hpp @@ -98,7 +98,10 @@ enum SrsCodecVideo // set to the zero to reserved, for array map. SrsCodecVideoReserved = 0, SrsCodecVideoReserved1 = 1, - SrsCodecVideoReserved2 = 8, + SrsCodecVideoReserved2 = 9, + + // for user to disable video, for example, use pure audio hls. + SrsCodecVideoDisabled = 8, SrsCodecVideoSorensonH263 = 2, SrsCodecVideoScreenVideo = 3, diff --git a/trunk/src/kernel/srs_kernel_ts.cpp b/trunk/src/kernel/srs_kernel_ts.cpp index ed894e96b9..dbac10b12f 100644 --- a/trunk/src/kernel/srs_kernel_ts.cpp +++ b/trunk/src/kernel/srs_kernel_ts.cpp @@ -75,327 +75,6 @@ int aac_sample_rates[] = 7350, 0, 0, 0 }; -// @see: ngx_rtmp_mpegts_header -u_int8_t mpegts_header[] = { - /* TS */ - 0x47, 0x40, 0x00, 0x10, 0x00, - /* PSI */ - 0x00, 0xb0, 0x0d, 0x00, 0x01, 0xc1, 0x00, 0x00, - /* PAT */ - 0x00, 0x01, 0xf0, 0x01, - /* CRC */ - 0x2e, 0x70, 0x19, 0x05, - /* stuffing 167 bytes */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - - /* TS */ - 0x47, 0x50, 0x01, 0x10, 0x00, - /* PSI */ - 0x02, 0xb0, 0x17, 0x00, 0x01, 0xc1, 0x00, 0x00, - /* PMT */ - 0xe1, 0x00, - 0xf0, 0x00, - // must generate header with/without video, @see: - // https://github.com/winlinvip/simple-rtmp-server/issues/40 - 0x1b, 0xe1, 0x00, 0xf0, 0x00, /* h264, pid=0x100=256 */ -}; -u_int8_t mpegts_header_aac[] = { - 0x0f, 0xe1, 0x01, 0xf0, 0x00, /* aac, pid=0x101=257 */ - /* CRC */ - 0x2f, 0x44, 0xb9, 0x9b, /* crc for aac */ -}; -u_int8_t mpegts_header_mp3[] = { - 0x03, 0xe1, 0x01, 0xf0, 0x00, /* mp3 */ - /* CRC */ - 0x4e, 0x59, 0x3d, 0x1e, /* crc for mp3 */ -}; -u_int8_t mpegts_header_padding[] = { - /* stuffing 157 bytes */ - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, - 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff -}; - -// @see: ngx_rtmp_mpegts.c -// TODO: support full mpegts feature in future. -class SrsMpegtsWriter -{ -public: - static int write_header(SrsFileWriter* writer, SrsCodecAudio acodec) - { - int ret = ERROR_SUCCESS; - - if ((ret = writer->write(mpegts_header, sizeof(mpegts_header), NULL)) != ERROR_SUCCESS) { - ret = ERROR_HLS_WRITE_FAILED; - srs_error("write ts file header failed. ret=%d", ret); - return ret; - } - - if (acodec == SrsCodecAudioAAC) { - if ((ret = writer->write(mpegts_header_aac, sizeof(mpegts_header_aac), NULL)) != ERROR_SUCCESS) { - ret = ERROR_HLS_WRITE_FAILED; - srs_error("write ts file aac header failed. ret=%d", ret); - return ret; - } - } else { - if ((ret = writer->write(mpegts_header_mp3, sizeof(mpegts_header_mp3), NULL)) != ERROR_SUCCESS) { - ret = ERROR_HLS_WRITE_FAILED; - srs_error("write ts file mp3 header failed. ret=%d", ret); - return ret; - } - } - - if ((ret = writer->write(mpegts_header_padding, sizeof(mpegts_header_padding), NULL)) != ERROR_SUCCESS) { - ret = ERROR_HLS_WRITE_FAILED; - srs_error("write ts file padding header failed. ret=%d", ret); - return ret; - } - - return ret; - } - static int write_frame(SrsFileWriter* writer, SrsMpegtsFrame* frame, SrsSimpleBuffer* buffer) - { - int ret = ERROR_SUCCESS; - - if (!buffer->bytes() || buffer->length() <= 0) { - return ret; - } - - char* last = buffer->bytes() + buffer->length(); - char* pos = buffer->bytes(); - - bool first = true; - while (pos < last) { - static char packet[188]; - char* p = packet; - - frame->cc++; - - // sync_byte; //8bits - *p++ = 0x47; - // pid; //13bits - *p++ = (frame->pid >> 8) & 0x1f; - // payload_unit_start_indicator; //1bit - if (first) { - p[-1] |= 0x40; - } - *p++ = frame->pid; - - // transport_scrambling_control; //2bits - // adaption_field_control; //2bits, 0x01: PayloadOnly - // continuity_counter; //4bits - *p++ = 0x10 | (frame->cc & 0x0f); - - if (first) { - first = false; - if (frame->write_pcr) { - p[-1] |= 0x20; // Both Adaption and Payload - *p++ = 7; // size - *p++ = 0x50; // random access + PCR - // @see https://github.com/winlinvip/simple-rtmp-server/issues/311 - p = write_pcr(p, frame->dts); - } - - // PES header - // packet_start_code_prefix; //24bits, '00 00 01' - *p++ = 0x00; - *p++ = 0x00; - *p++ = 0x01; - //8bits - *p++ = frame->sid; - - // pts(33bits) need 5bytes. - u_int8_t header_size = 5; - u_int8_t flags = 0x80; // pts - - // dts(33bits) need 5bytes also - if (frame->dts != frame->pts) { - header_size += 5; - flags |= 0x40; // dts - } - - // 3bytes: flag fields from PES_packet_length to PES_header_data_length - int pes_size = (last - pos) + header_size + 3; - if (pes_size > 0xffff) { - /** - * when actual packet length > 0xffff(65535), - * which exceed the max u_int16_t packet length, - * use 0 packet length, the next unit start indicates the end of packet. - */ - pes_size = 0; - } - - // PES_packet_length; //16bits - *p++ = (pes_size >> 8); - *p++ = pes_size; - - // PES_scrambling_control; //2bits, '10' - // PES_priority; //1bit - // data_alignment_indicator; //1bit - // copyright; //1bit - // original_or_copy; //1bit - *p++ = 0x80; /* H222 */ - - // PTS_DTS_flags; //2bits - // ESCR_flag; //1bit - // ES_rate_flag; //1bit - // DSM_trick_mode_flag; //1bit - // additional_copy_info_flag; //1bit - // PES_CRC_flag; //1bit - // PES_extension_flag; //1bit - *p++ = flags; - - // PES_header_data_length; //8bits - *p++ = header_size; - - // pts; // 33bits - p = write_dts_pts(p, flags >> 6, frame->pts); - - // dts; // 33bits - if (frame->dts != frame->pts) { - p = write_dts_pts(p, 1, frame->dts); - } - } - - int body_size = sizeof(packet) - (p - packet); - int in_size = last - pos; - - if (body_size <= in_size) { - memcpy(p, pos, body_size); - pos += body_size; - } else { - p = fill_stuff(p, packet, body_size, in_size); - memcpy(p, pos, in_size); - pos = last; - } - - // write ts packet - if ((ret = writer->write(packet, sizeof(packet), NULL)) != ERROR_SUCCESS) { - if (!srs_is_client_gracefully_close(ret)) { - srs_error("write ts file failed. ret=%d", ret); - } - return ret; - } - } - - return ret; - } -private: - static char* fill_stuff(char* pes_body_end, char* packet, int body_size, int in_size) - { - char* p = pes_body_end; - - // insert the stuff bytes before PES body - int stuff_size = (body_size - in_size); - - // adaption_field_control; //2bits - if (packet[3] & 0x20) { - // has adaptation - // packet[4]: adaption_field_length - // packet[5]: adaption field data - // base: start of PES body - char* base = &packet[5] + packet[4]; - int len = p - base; - p = (char*)memmove(base + stuff_size, base, len) + len; - // increase the adaption field size. - packet[4] += stuff_size; - - return p; - } - - // create adaption field. - // adaption_field_control; //2bits - packet[3] |= 0x20; - // base: start of PES body - char* base = &packet[4]; - int len = p - base; - p = (char*)memmove(base + stuff_size, base, len) + len; - // adaption_field_length; //8bits - packet[4] = (stuff_size - 1); - if (stuff_size >= 2) { - // adaption field flags. - packet[5] = 0; - // adaption data. - if (stuff_size > 2) { - memset(&packet[6], 0xff, stuff_size - 2); - } - } - - return p; - } - static char* write_pcr(char* p, int64_t pcr) - { - // the pcr=dts-delay, where dts = frame->dts + delay - // and the pcr should never be negative - // @see https://github.com/winlinvip/simple-rtmp-server/issues/268 - srs_assert(pcr >= 0); - - int64_t v = pcr; - - *p++ = (char) (v >> 25); - *p++ = (char) (v >> 17); - *p++ = (char) (v >> 9); - *p++ = (char) (v >> 1); - *p++ = (char) (v << 7 | 0x7e); - *p++ = 0; - - return p; - } - static char* write_dts_pts(char* p, u_int8_t fb, int64_t pts) - { - int32_t val; - - val = fb << 4 | (((pts >> 30) & 0x07) << 1) | 1; - *p++ = val; - - val = (((pts >> 15) & 0x7fff) << 1) | 1; - *p++ = (val >> 8); - *p++ = val; - - val = (((pts) & 0x7fff) << 1) | 1; - *p++ = (val >> 8); - *p++ = val; - - return p; - } -}; - -SrsMpegtsFrame::SrsMpegtsFrame() -{ - pts = dts = 0; - pid = sid = cc = 0; - write_pcr = false; -} - string srs_ts_stream2string(SrsTsStream stream) { switch (stream) { @@ -600,6 +279,7 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo case SrsCodecVideoReserved: case SrsCodecVideoReserved1: case SrsCodecVideoReserved2: + case SrsCodecVideoDisabled: case SrsCodecVideoSorensonH263: case SrsCodecVideoScreenVideo: case SrsCodecVideoOn2VP6: @@ -645,9 +325,9 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo // encode the media frame to PES packets over TS. if (msg->is_audio()) { - return encode_pes(writer, msg, audio_pid, as); + return encode_pes(writer, msg, audio_pid, as, vs == SrsTsStreamReserved); } else { - return encode_pes(writer, msg, video_pid, vs); + return encode_pes(writer, msg, video_pid, vs, vs == SrsTsStreamReserved); } } @@ -711,7 +391,7 @@ int SrsTsContext::encode_pat_pmt(SrsFileWriter* writer, int16_t vpid, SrsTsStrea return ret; } -int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t pid, SrsTsStream sid) +int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t pid, SrsTsStream sid, bool pure_audio) { int ret = ERROR_SUCCESS; @@ -719,6 +399,11 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p return ret; } + if (sid != SrsTsStreamVideoH264 && sid != SrsTsStreamAudioMp3 && sid != SrsTsStreamAudioAAC) { + srs_info("ts: ignore the unknown stream, sid=%d", sid); + return ret; + } + SrsTsChannel* channel = get(pid); srs_assert(channel); @@ -729,9 +414,15 @@ int SrsTsContext::encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t p while (p < end) { SrsTsPacket* pkt = NULL; if (p == start) { + // for pure audio stream, always write pcr. + bool write_pcr = msg->write_pcr; + if (pure_audio && msg->is_audio()) { + write_pcr = true; + } + pkt = SrsTsPacket::create_pes_first(this, pid, msg->sid, channel->continuity_counter++, msg->discontinuity, - msg->write_pcr? msg->dts:-1, msg->dts, msg->pts, msg->payload->length() + write_pcr? msg->dts:-1, msg->dts, msg->pts, msg->payload->length() ); } else { pkt = SrsTsPacket::create_pes_continue(this, @@ -1030,9 +721,13 @@ SrsTsPacket* SrsTsPacket::create_pmt(SrsTsContext* context, int16_t pmt_number, pmt->current_next_indicator = 1; pmt->section_number = 0; pmt->last_section_number = 0; - pmt->PCR_PID = vpid; pmt->program_info_length = 0; - pmt->infos.push_back(new SrsTsPayloadPMTESInfo(vs, vpid)); + if (vs == SrsTsStreamVideoH264) { + pmt->PCR_PID = vpid; + pmt->infos.push_back(new SrsTsPayloadPMTESInfo(vs, vpid)); + } else { + pmt->PCR_PID = apid; + } pmt->infos.push_back(new SrsTsPayloadPMTESInfo(as, apid)); pmt->CRC_32 = 0; // calc in encode. return pkt; @@ -2916,14 +2611,13 @@ int SrsTsPayloadPMT::psi_encode(SrsStream* stream) return ret; } -SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w, SrsCodecAudio ac) +SrsTSMuxer::SrsTSMuxer(SrsFileWriter* w, SrsCodecAudio ac, SrsCodecVideo vc) { writer = w; context = NULL; acodec = ac; - // default to avc(h.264) - vcodec = SrsCodecVideoAVC; + vcodec = vc; } SrsTSMuxer::~SrsTSMuxer() @@ -3295,7 +2989,7 @@ int SrsTsEncoder::initialize(SrsFileWriter* fs) _fs = fs; srs_freep(muxer); - muxer = new SrsTSMuxer(fs, SrsCodecAudioAAC); + muxer = new SrsTSMuxer(fs, SrsCodecAudioAAC, SrsCodecVideoAVC); if ((ret = muxer->open("")) != ERROR_SUCCESS) { return ret; diff --git a/trunk/src/kernel/srs_kernel_ts.hpp b/trunk/src/kernel/srs_kernel_ts.hpp index 58e303b37c..30a71d5c87 100644 --- a/trunk/src/kernel/srs_kernel_ts.hpp +++ b/trunk/src/kernel/srs_kernel_ts.hpp @@ -51,20 +51,6 @@ class SrsTsPacket; // Transport Stream packets are 188 bytes in length. #define SRS_TS_PACKET_SIZE 188 -// @see: ngx_rtmp_SrsMpegtsFrame_t -class SrsMpegtsFrame -{ -public: - int64_t pts; - int64_t dts; - int pid; - int sid; - int cc; // continuity_counter - bool write_pcr; - - SrsMpegtsFrame(); -}; - /** * the pid of ts packet, * Table 2-3 - PID table, hls-mpeg-ts-iso13818-1.pdf, page 37 @@ -387,7 +373,7 @@ class SrsTsContext virtual int encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo vc, SrsCodecAudio ac); private: virtual int encode_pat_pmt(SrsFileWriter* writer, int16_t vpid, SrsTsStream vs, int16_t apid, SrsTsStream as); - virtual int encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t pid, SrsTsStream sid); + virtual int encode_pes(SrsFileWriter* writer, SrsTsMessage* msg, int16_t pid, SrsTsStream sid, bool pure_audio); }; /** @@ -1547,7 +1533,7 @@ class SrsTSMuxer SrsFileWriter* writer; std::string path; public: - SrsTSMuxer(SrsFileWriter* w, SrsCodecAudio ac); + SrsTSMuxer(SrsFileWriter* w, SrsCodecAudio ac, SrsCodecVideo vc); virtual ~SrsTSMuxer(); public: /**