support pure video hls.

pull/499/head
winlin 10 years ago
commit 597993d414

@ -346,6 +346,7 @@ Remark:
* v3.0, 2015-03-15, fork srs2 and start srs3. 3.0.0 * v3.0, 2015-03-15, fork srs2 and start srs3. 3.0.0
### SRS 2.0 history ### SRS 2.0 history
* v2.0, 2015-05-29, fix [#409](https://github.com/simple-rtmp-server/srs/issues/409) support pure video hls. 2.0.172.
* v2.0, 2015-05-28, support [srs-dolphin][srs-dolphin], the multiple-process SRS. * v2.0, 2015-05-28, support [srs-dolphin][srs-dolphin], the multiple-process SRS.
* v2.0, 2015-05-24, fix [#404](https://github.com/simple-rtmp-server/srs/issues/404) register handler then start http thread. 2.0.167. * v2.0, 2015-05-24, fix [#404](https://github.com/simple-rtmp-server/srs/issues/404) register handler then start http thread. 2.0.167.
* v2.0, 2015-05-23, refine the thread, protocol, kbps code. 2.0.166 * v2.0, 2015-05-23, refine the thread, protocol, kbps code. 2.0.166
@ -735,7 +736,7 @@ The latency between encoder and player with realtime config(
[CN](https://github.com/simple-rtmp-server/srs/wiki/v2_CN_LowLatency), [CN](https://github.com/simple-rtmp-server/srs/wiki/v2_CN_LowLatency),
[EN](https://github.com/simple-rtmp-server/srs/wiki/v2_EN_LowLatency) [EN](https://github.com/simple-rtmp-server/srs/wiki/v2_EN_LowLatency)
): ):
|
| Update | SRS | VP6 | H.264 | VP6+MP3 | H.264+MP3 | | Update | SRS | VP6 | H.264 | VP6+MP3 | H.264+MP3 |
| ------------- | --------- | --------- | --------- | --------- | -------- | | ------------- | --------- | --------- | --------- | --------- | -------- |
@ -747,6 +748,32 @@ We use FMLE as encoder for benchmark. The latency of server is 0.1s+,
and the bottleneck is the encoder. For more information, read and the bottleneck is the encoder. For more information, read
[bug #257](https://github.com/simple-rtmp-server/srs/issues/257#issuecomment-66864413). [bug #257](https://github.com/simple-rtmp-server/srs/issues/257#issuecomment-66864413).
### HLS overhead
About the HLS overhead of SRS, we compare the overhead to FLV by remux the HLS to FLV by ffmpeg.
| Bitrate | Duration | FLV(KB) | HLS(KB) | Overhead |
| ------- | -------- | ------- | -------- | --------- |
| 275kbps | 600s | 11144 | 12756 | 14.46% |
| 260kbps | 1860s | 59344 | 68004 | 14.59% |
| 697kbps | 60s | 5116 | 5476 | 7.03% |
| 565kbps | 453s | 31316 | 33544 | 7.11% |
| 565kbps | 1813s | 125224 | 134140 | 7.12% |
| 861kbps | 497s | 52316 | 54924 | 4.98% |
| 857kbps | 1862s | 195008 | 204768 | 5.00% |
| 1301kbps | 505s | 80320 | 83676 | 4.17% |
| 1312kbps | 1915s | 306920 | 319680 | 4.15% |
| 2707kbps | 600s | 198356 | 204560 | 3.12% |
| 2814kbps | 1800s | 618456 | 637660 | 3.10% |
| 2828kbps | 60s | 20716 | 21356 | 3.08% |
| 2599kbps | 307s | 97580 | 100672 | 3.16% |
| 2640kbps | 1283s | 413880 | 426912 | 3.14% |
| 5254kbps | 71s | 45832 | 47056 | 2.67% |
| 5147kbps | 370s | 195040 | 200280 | 2.68% |
| 5158kbps | 1327s | 835664 | 858092 | 2.68% |
The HLS overhead is calc by: (HLS - FLV) / FLV * 100%
## Architecture ## Architecture
SRS always use the most simple architecture to support complex transaction. SRS always use the most simple architecture to support complex transaction.

@ -608,7 +608,7 @@ vhost with-hls.srs.com {
# when codec changed, write the PAT/PMT table, but maybe ok util next ts. # when codec changed, write the PAT/PMT table, but maybe ok util next ts.
# so user can set the default codec for mp3. # so user can set the default codec for mp3.
# the available audio codec: # the available audio codec:
# aac, mp3 # aac, mp3, an
# default: aac # default: aac
hls_acodec aac; hls_acodec aac;
# the default video codec of hls. # the default video codec of hls.

@ -420,6 +420,9 @@ int SrsHlsMuxer::segment_open(int64_t segment_start_dts)
} else if (default_acodec_str == "aac") { } else if (default_acodec_str == "aac") {
default_acodec = SrsCodecAudioAAC; default_acodec = SrsCodecAudioAAC;
srs_info("hls: use default aac acodec"); srs_info("hls: use default aac acodec");
} else if (default_acodec_str == "an") {
default_acodec = SrsCodecAudioDisabled;
srs_info("hls: use default an acodec for pure video");
} else { } else {
srs_warn("hls: use aac for other codec=%s", default_acodec_str.c_str()); srs_warn("hls: use aac for other codec=%s", default_acodec_str.c_str());
} }

@ -136,6 +136,9 @@ enum SrsCodecAudio
// set to the max value to reserved, for array map. // set to the max value to reserved, for array map.
SrsCodecAudioReserved1 = 16, SrsCodecAudioReserved1 = 16,
// for user to disable audio, for example, use pure video hls.
SrsCodecAudioDisabled = 17,
SrsCodecAudioLinearPCMPlatformEndian = 0, SrsCodecAudioLinearPCMPlatformEndian = 0,
SrsCodecAudioADPCM = 1, SrsCodecAudioADPCM = 1,
SrsCodecAudioMP3 = 2, SrsCodecAudioMP3 = 2,

@ -215,13 +215,13 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#define ERROR_HTTP_DVR_CREATE_REQUEST 3053 #define ERROR_HTTP_DVR_CREATE_REQUEST 3053
#define ERROR_HTTP_DVR_NO_TAEGET 3054 #define ERROR_HTTP_DVR_NO_TAEGET 3054
#define ERROR_ADTS_ID_NOT_AAC 3055 #define ERROR_ADTS_ID_NOT_AAC 3055
// HDS error code
#define ERROR_HDS_OPEN_F4M_FAILED 3056 #define ERROR_HDS_OPEN_F4M_FAILED 3056
#define ERROR_HDS_WRITE_F4M_FAILED 3057 #define ERROR_HDS_WRITE_F4M_FAILED 3057
#define ERROR_HDS_OPEN_BOOTSTRAP_FAILED 3058 #define ERROR_HDS_OPEN_BOOTSTRAP_FAILED 3058
#define ERROR_HDS_WRITE_BOOTSTRAP_FAILED 3059 #define ERROR_HDS_WRITE_BOOTSTRAP_FAILED 3059
#define ERROR_HDS_OPEN_FRAGMENT_FAILED 3060 #define ERROR_HDS_OPEN_FRAGMENT_FAILED 3060
#define ERROR_HDS_WRITE_FRAGMENT_FAILED 3061 #define ERROR_HDS_WRITE_FRAGMENT_FAILED 3061
#define ERROR_HLS_NO_STREAM 3062
/////////////////////////////////////////////////////// ///////////////////////////////////////////////////////
// HTTP/StreamCaster protocol error. // HTTP/StreamCaster protocol error.

@ -302,10 +302,12 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo
vs = SrsTsStreamVideoH264; vs = SrsTsStreamVideoH264;
video_pid = TS_VIDEO_AVC_PID; video_pid = TS_VIDEO_AVC_PID;
break; break;
case SrsCodecVideoDisabled:
vs = SrsTsStreamReserved;
break;
case SrsCodecVideoReserved: case SrsCodecVideoReserved:
case SrsCodecVideoReserved1: case SrsCodecVideoReserved1:
case SrsCodecVideoReserved2: case SrsCodecVideoReserved2:
case SrsCodecVideoDisabled:
case SrsCodecVideoSorensonH263: case SrsCodecVideoSorensonH263:
case SrsCodecVideoScreenVideo: case SrsCodecVideoScreenVideo:
case SrsCodecVideoOn2VP6: case SrsCodecVideoOn2VP6:
@ -323,6 +325,9 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo
as = SrsTsStreamAudioMp3; as = SrsTsStreamAudioMp3;
audio_pid = TS_AUDIO_MP3_PID; audio_pid = TS_AUDIO_MP3_PID;
break; break;
case SrsCodecAudioDisabled:
as = SrsTsStreamReserved;
break;
case SrsCodecAudioReserved1: case SrsCodecAudioReserved1:
case SrsCodecAudioLinearPCMPlatformEndian: case SrsCodecAudioLinearPCMPlatformEndian:
case SrsCodecAudioADPCM: case SrsCodecAudioADPCM:
@ -340,6 +345,12 @@ int SrsTsContext::encode(SrsFileWriter* writer, SrsTsMessage* msg, SrsCodecVideo
break; break;
} }
if (as == SrsTsStreamReserved && vs == SrsTsStreamReserved) {
ret = ERROR_HLS_NO_STREAM;
srs_error("hls: no video or audio stream, vcodec=%d, acodec=%d. ret=%d", vc, ac, ret);
return ret;
}
// when any codec changed, write PAT/PMT table. // when any codec changed, write PAT/PMT table.
if (vcodec != vc || acodec != ac) { if (vcodec != vc || acodec != ac) {
vcodec = vc; vcodec = vc;
@ -361,6 +372,12 @@ int SrsTsContext::encode_pat_pmt(SrsFileWriter* writer, int16_t vpid, SrsTsStrea
{ {
int ret = ERROR_SUCCESS; int ret = ERROR_SUCCESS;
if (vs != SrsTsStreamVideoH264 && as != SrsTsStreamAudioAAC && as != SrsTsStreamAudioMp3) {
ret = ERROR_HLS_NO_STREAM;
srs_error("hls: no pmt pcr pid, vs=%d, as=%d. ret=%d", vs, as, ret);
return ret;
}
int16_t pmt_number = TS_PMT_NUMBER; int16_t pmt_number = TS_PMT_NUMBER;
int16_t pmt_pid = TS_PMT_PID; int16_t pmt_pid = TS_PMT_PID;
if (true) { if (true) {
@ -754,15 +771,17 @@ SrsTsPacket* SrsTsPacket::create_pmt(SrsTsContext* context, int16_t pmt_number,
pmt->last_section_number = 0; pmt->last_section_number = 0;
pmt->program_info_length = 0; pmt->program_info_length = 0;
// use audio to carray pcr by default.
// for hls, there must be atleast one audio channel.
pmt->PCR_PID = apid;
pmt->infos.push_back(new SrsTsPayloadPMTESInfo(as, apid));
// if h.264 specified, use video to carry pcr. // if h.264 specified, use video to carry pcr.
if (vs == SrsTsStreamVideoH264) { if (vs == SrsTsStreamVideoH264) {
pmt->PCR_PID = vpid; pmt->PCR_PID = vpid;
pmt->infos.push_back(new SrsTsPayloadPMTESInfo(vs, vpid)); pmt->infos.push_back(new SrsTsPayloadPMTESInfo(vs, vpid));
} else if (as == SrsTsStreamAudioAAC || as == SrsTsStreamAudioMp3) {
// use audio to carray pcr by default.
// for hls, there must be atleast one audio channel.
pmt->PCR_PID = apid;
pmt->infos.push_back(new SrsTsPayloadPMTESInfo(as, apid));
} else {
srs_assert(false);
} }
pmt->CRC_32 = 0; // calc in encode. pmt->CRC_32 = 0; // calc in encode.

Loading…
Cancel
Save