refine hls, extract ts cache for ts cache audio and flush once
正在显示
2 个修改的文件
包含
277 行增加
和
198 行删除
| @@ -856,13 +856,8 @@ int SrsM3u8Muxer::create_dir() | @@ -856,13 +856,8 @@ int SrsM3u8Muxer::create_dir() | ||
| 856 | return ret; | 856 | return ret; |
| 857 | } | 857 | } |
| 858 | 858 | ||
| 859 | -SrsHls::SrsHls() | 859 | +SrsTSCache::SrsTSCache() |
| 860 | { | 860 | { |
| 861 | - hls_enabled = false; | ||
| 862 | - | ||
| 863 | - codec = new SrsCodec(); | ||
| 864 | - sample = new SrsCodecSample(); | ||
| 865 | - jitter = new SrsRtmpJitter(); | ||
| 866 | aac_jitter = new SrsHlsAacJitter(); | 861 | aac_jitter = new SrsHlsAacJitter(); |
| 867 | 862 | ||
| 868 | ab = new SrsCodecBuffer(); | 863 | ab = new SrsCodecBuffer(); |
| @@ -870,15 +865,10 @@ SrsHls::SrsHls() | @@ -870,15 +865,10 @@ SrsHls::SrsHls() | ||
| 870 | 865 | ||
| 871 | af = new SrsMpegtsFrame(); | 866 | af = new SrsMpegtsFrame(); |
| 872 | vf = new SrsMpegtsFrame(); | 867 | vf = new SrsMpegtsFrame(); |
| 873 | - | ||
| 874 | - muxer = new SrsM3u8Muxer(); | ||
| 875 | } | 868 | } |
| 876 | 869 | ||
| 877 | -SrsHls::~SrsHls() | 870 | +SrsTSCache::~SrsTSCache() |
| 878 | { | 871 | { |
| 879 | - srs_freep(codec); | ||
| 880 | - srs_freep(sample); | ||
| 881 | - srs_freep(jitter); | ||
| 882 | srs_freep(aac_jitter); | 872 | srs_freep(aac_jitter); |
| 883 | 873 | ||
| 884 | ab->free(); | 874 | ab->free(); |
| @@ -889,8 +879,237 @@ SrsHls::~SrsHls() | @@ -889,8 +879,237 @@ SrsHls::~SrsHls() | ||
| 889 | 879 | ||
| 890 | srs_freep(af); | 880 | srs_freep(af); |
| 891 | srs_freep(vf); | 881 | srs_freep(vf); |
| 882 | +} | ||
| 883 | + | ||
| 884 | +int SrsTSCache::write_audio(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t pts, SrsCodecSample* sample) | ||
| 885 | +{ | ||
| 886 | + int ret = ERROR_SUCCESS; | ||
| 887 | + | ||
| 888 | + // start buffer, set the af | ||
| 889 | + if (ab->size == 0) { | ||
| 890 | + pts = aac_jitter->on_buffer_start(pts, sample->sound_rate); | ||
| 891 | + | ||
| 892 | + af->dts = af->pts = audio_buffer_start_pts = pts; | ||
| 893 | + af->pid = TS_AUDIO_PID; | ||
| 894 | + af->sid = TS_AUDIO_AAC; | ||
| 895 | + } else { | ||
| 896 | + aac_jitter->on_buffer_continue(); | ||
| 897 | + } | ||
| 898 | + | ||
| 899 | + // write audio to cache. | ||
| 900 | + if ((ret = cache_audio(codec, sample)) != ERROR_SUCCESS) { | ||
| 901 | + return ret; | ||
| 902 | + } | ||
| 903 | + | ||
| 904 | + // flush if buffer exceed max size. | ||
| 905 | + if (ab->size > SRS_HLS_AUDIO_CACHE_SIZE) { | ||
| 906 | + if ((ret = muxer->flush_audio(af, ab)) != ERROR_SUCCESS) { | ||
| 907 | + return ret; | ||
| 908 | + } | ||
| 909 | + } | ||
| 910 | + // TODO: config it. | ||
| 911 | + // in ms, audio delay to flush the audios. | ||
| 912 | + int64_t audio_delay = SRS_CONF_DEFAULT_AAC_DELAY; | ||
| 913 | + // flush if audio delay exceed | ||
| 914 | + if (pts - audio_buffer_start_pts > audio_delay * 90) { | ||
| 915 | + if ((ret = muxer->flush_audio(af, ab)) != ERROR_SUCCESS) { | ||
| 916 | + return ret; | ||
| 917 | + } | ||
| 918 | + } | ||
| 919 | + | ||
| 920 | + return ret; | ||
| 921 | +} | ||
| 922 | + | ||
| 923 | +int SrsTSCache::write_video(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t dts, SrsCodecSample* sample) | ||
| 924 | +{ | ||
| 925 | + int ret = ERROR_SUCCESS; | ||
| 926 | + | ||
| 927 | + // write video to cache. | ||
| 928 | + if ((ret = cache_video(codec, sample)) != ERROR_SUCCESS) { | ||
| 929 | + return ret; | ||
| 930 | + } | ||
| 931 | + | ||
| 932 | + vf->dts = dts; | ||
| 933 | + vf->pts = vf->dts + sample->cts * 90; | ||
| 934 | + vf->pid = TS_VIDEO_PID; | ||
| 935 | + vf->sid = TS_VIDEO_AVC; | ||
| 936 | + vf->key = sample->frame_type == SrsCodecVideoAVCFrameKeyFrame; | ||
| 937 | + | ||
| 938 | + // flush video when got one | ||
| 939 | + if ((ret = muxer->flush_video(af, ab, vf, vb)) != ERROR_SUCCESS) { | ||
| 940 | + srs_error("m3u8 muxer flush video failed. ret=%d", ret); | ||
| 941 | + return ret; | ||
| 942 | + } | ||
| 943 | + | ||
| 944 | + return ret; | ||
| 945 | +} | ||
| 946 | + | ||
| 947 | +int SrsTSCache::flush_audio(SrsM3u8Muxer* muxer) | ||
| 948 | +{ | ||
| 949 | + int ret = ERROR_SUCCESS; | ||
| 950 | + | ||
| 951 | + if ((ret = muxer->flush_audio(af, ab)) != ERROR_SUCCESS) { | ||
| 952 | + srs_error("m3u8 muxer flush audio failed. ret=%d", ret); | ||
| 953 | + return ret; | ||
| 954 | + } | ||
| 955 | + | ||
| 956 | + return ret; | ||
| 957 | +} | ||
| 958 | + | ||
| 959 | +int SrsTSCache::cache_audio(SrsCodec* codec, SrsCodecSample* sample) | ||
| 960 | +{ | ||
| 961 | + int ret = ERROR_SUCCESS; | ||
| 962 | + | ||
| 963 | + for (int i = 0; i < sample->nb_buffers; i++) { | ||
| 964 | + SrsCodecBuffer* buf = &sample->buffers[i]; | ||
| 965 | + int32_t size = buf->size; | ||
| 966 | + | ||
| 967 | + if (!buf->bytes || size <= 0 || size > 0x1fff) { | ||
| 968 | + ret = ERROR_HLS_AAC_FRAME_LENGTH; | ||
| 969 | + srs_error("invalid aac frame length=%d, ret=%d", size, ret); | ||
| 970 | + return ret; | ||
| 971 | + } | ||
| 972 | + | ||
| 973 | + // the frame length is the AAC raw data plus the adts header size. | ||
| 974 | + int32_t frame_length = size + 7; | ||
| 975 | + | ||
| 976 | + // AAC-ADTS | ||
| 977 | + // 6.2 Audio Data Transport Stream, ADTS | ||
| 978 | + // in aac-iso-13818-7.pdf, page 26. | ||
| 979 | + // fixed 7bytes header | ||
| 980 | + static u_int8_t adts_header[7] = {0xff, 0xf1, 0x00, 0x00, 0x00, 0x0f, 0xfc}; | ||
| 981 | + /* | ||
| 982 | + // adts_fixed_header | ||
| 983 | + // 2B, 16bits | ||
| 984 | + int16_t syncword; //12bits, '1111 1111 1111' | ||
| 985 | + int8_t ID; //1bit, '0' | ||
| 986 | + int8_t layer; //2bits, '00' | ||
| 987 | + int8_t protection_absent; //1bit, can be '1' | ||
| 988 | + // 12bits | ||
| 989 | + int8_t profile; //2bit, 7.1 Profiles, page 40 | ||
| 990 | + TSAacSampleFrequency sampling_frequency_index; //4bits, Table 35, page 46 | ||
| 991 | + int8_t private_bit; //1bit, can be '0' | ||
| 992 | + int8_t channel_configuration; //3bits, Table 8 | ||
| 993 | + int8_t original_or_copy; //1bit, can be '0' | ||
| 994 | + int8_t home; //1bit, can be '0' | ||
| 995 | + | ||
| 996 | + // adts_variable_header | ||
| 997 | + // 28bits | ||
| 998 | + int8_t copyright_identification_bit; //1bit, can be '0' | ||
| 999 | + int8_t copyright_identification_start; //1bit, can be '0' | ||
| 1000 | + int16_t frame_length; //13bits | ||
| 1001 | + int16_t adts_buffer_fullness; //11bits, 7FF signals that the bitstream is a variable rate bitstream. | ||
| 1002 | + int8_t number_of_raw_data_blocks_in_frame; //2bits, 0 indicating 1 raw_data_block() | ||
| 1003 | + */ | ||
| 1004 | + // profile, 2bits | ||
| 1005 | + adts_header[2] = (codec->aac_profile << 6) & 0xc0; | ||
| 1006 | + // sampling_frequency_index 4bits | ||
| 1007 | + adts_header[2] |= (codec->aac_sample_rate << 2) & 0x3c; | ||
| 1008 | + // channel_configuration 3bits | ||
| 1009 | + adts_header[2] |= (codec->aac_channels >> 2) & 0x01; | ||
| 1010 | + adts_header[3] = (codec->aac_channels << 6) & 0xc0; | ||
| 1011 | + // frame_length 13bits | ||
| 1012 | + adts_header[3] |= (frame_length >> 11) & 0x03; | ||
| 1013 | + adts_header[4] = (frame_length >> 3) & 0xff; | ||
| 1014 | + adts_header[5] = ((frame_length << 5) & 0xe0); | ||
| 1015 | + // adts_buffer_fullness; //11bits | ||
| 1016 | + adts_header[5] |= 0x1f; | ||
| 1017 | + | ||
| 1018 | + // copy to audio buffer | ||
| 1019 | + ab->append(adts_header, sizeof(adts_header)); | ||
| 1020 | + ab->append(buf->bytes, buf->size); | ||
| 1021 | + } | ||
| 1022 | + | ||
| 1023 | + return ret; | ||
| 1024 | +} | ||
| 1025 | + | ||
| 1026 | +int SrsTSCache::cache_video(SrsCodec* codec, SrsCodecSample* sample) | ||
| 1027 | +{ | ||
| 1028 | + int ret = ERROR_SUCCESS; | ||
| 1029 | + | ||
| 1030 | + static u_int8_t aud_nal[] = { 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0 }; | ||
| 1031 | + vb->append(aud_nal, sizeof(aud_nal)); | ||
| 1032 | + | ||
| 1033 | + bool sps_pps_sent = false; | ||
| 1034 | + for (int i = 0; i < sample->nb_buffers; i++) { | ||
| 1035 | + SrsCodecBuffer* buf = &sample->buffers[i]; | ||
| 1036 | + int32_t size = buf->size; | ||
| 1037 | + | ||
| 1038 | + if (!buf->bytes || size <= 0) { | ||
| 1039 | + ret = ERROR_HLS_AVC_SAMPLE_SIZE; | ||
| 1040 | + srs_error("invalid avc sample length=%d, ret=%d", size, ret); | ||
| 1041 | + return ret; | ||
| 1042 | + } | ||
| 1043 | + | ||
| 1044 | + // 5bits, 7.3.1 NAL unit syntax, | ||
| 1045 | + // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. | ||
| 1046 | + u_int8_t nal_unit_type; | ||
| 1047 | + nal_unit_type = *buf->bytes; | ||
| 1048 | + nal_unit_type &= 0x1f; | ||
| 1049 | + | ||
| 1050 | + // Table 7-1 – NAL unit type codes, page 61 | ||
| 1051 | + // 1: Coded slice | ||
| 1052 | + if (nal_unit_type == 1) { | ||
| 1053 | + sps_pps_sent = false; | ||
| 1054 | + } | ||
| 1055 | + // 5: Coded slice of an IDR picture. | ||
| 1056 | + // insert sps/pps before IDR or key frame is ok. | ||
| 1057 | + if (nal_unit_type == 5 && !sps_pps_sent) { | ||
| 1058 | + //if (vf->key && !sps_pps_sent) { | ||
| 1059 | + sps_pps_sent = true; | ||
| 1060 | + | ||
| 1061 | + // ngx_rtmp_hls_append_sps_pps | ||
| 1062 | + if (codec->sequenceParameterSetLength > 0) { | ||
| 1063 | + // AnnexB prefix | ||
| 1064 | + vb->append(aud_nal, 4); | ||
| 1065 | + // sps | ||
| 1066 | + vb->append(codec->sequenceParameterSetNALUnit, codec->sequenceParameterSetLength); | ||
| 1067 | + } | ||
| 1068 | + if (codec->pictureParameterSetLength > 0) { | ||
| 1069 | + // AnnexB prefix | ||
| 1070 | + vb->append(aud_nal, 4); | ||
| 1071 | + // pps | ||
| 1072 | + vb->append(codec->pictureParameterSetNALUnit, codec->pictureParameterSetLength); | ||
| 1073 | + } | ||
| 1074 | + } | ||
| 1075 | + | ||
| 1076 | + // sample start prefix, '00 00 00 01' or '00 00 01' | ||
| 1077 | + u_int8_t* p = aud_nal + 1; | ||
| 1078 | + u_int8_t* end = p + 3; | ||
| 1079 | + | ||
| 1080 | + // first AnnexB prefix is long (4 bytes) | ||
| 1081 | + if (i == 0) { | ||
| 1082 | + p = aud_nal; | ||
| 1083 | + } | ||
| 1084 | + vb->append(p, end - p); | ||
| 1085 | + | ||
| 1086 | + // sample data | ||
| 1087 | + vb->append(buf->bytes, buf->size); | ||
| 1088 | + } | ||
| 1089 | + | ||
| 1090 | + return ret; | ||
| 1091 | +} | ||
| 1092 | + | ||
| 1093 | +SrsHls::SrsHls() | ||
| 1094 | +{ | ||
| 1095 | + hls_enabled = false; | ||
| 1096 | + | ||
| 1097 | + codec = new SrsCodec(); | ||
| 1098 | + sample = new SrsCodecSample(); | ||
| 1099 | + jitter = new SrsRtmpJitter(); | ||
| 1100 | + | ||
| 1101 | + muxer = new SrsM3u8Muxer(); | ||
| 1102 | + ts_cache = new SrsTSCache(); | ||
| 1103 | +} | ||
| 1104 | + | ||
| 1105 | +SrsHls::~SrsHls() | ||
| 1106 | +{ | ||
| 1107 | + srs_freep(codec); | ||
| 1108 | + srs_freep(sample); | ||
| 1109 | + srs_freep(jitter); | ||
| 892 | 1110 | ||
| 893 | srs_freep(muxer); | 1111 | srs_freep(muxer); |
| 1112 | + srs_freep(ts_cache); | ||
| 894 | } | 1113 | } |
| 895 | 1114 | ||
| 896 | int SrsHls::on_publish(SrsRequest* req) | 1115 | int SrsHls::on_publish(SrsRequest* req) |
| @@ -953,7 +1172,7 @@ void SrsHls::on_unpublish() | @@ -953,7 +1172,7 @@ void SrsHls::on_unpublish() | ||
| 953 | int ret = ERROR_SUCCESS; | 1172 | int ret = ERROR_SUCCESS; |
| 954 | 1173 | ||
| 955 | // close muxer when unpublish. | 1174 | // close muxer when unpublish. |
| 956 | - ret = muxer->flush_audio(af, ab); | 1175 | + ret = ts_cache->flush_audio(muxer); |
| 957 | ret += muxer->segment_close(); | 1176 | ret += muxer->segment_close(); |
| 958 | if (ret != ERROR_SUCCESS) { | 1177 | if (ret != ERROR_SUCCESS) { |
| 959 | srs_error("ignore m3u8 muxer flush/close audio failed. ret=%d", ret); | 1178 | srs_error("ignore m3u8 muxer flush/close audio failed. ret=%d", ret); |
| @@ -1028,6 +1247,7 @@ int SrsHls::on_audio(SrsSharedPtrMessage* audio) | @@ -1028,6 +1247,7 @@ int SrsHls::on_audio(SrsSharedPtrMessage* audio) | ||
| 1028 | 1247 | ||
| 1029 | sample->clear(); | 1248 | sample->clear(); |
| 1030 | if ((ret = codec->audio_aac_demux(audio->payload, audio->size, sample)) != ERROR_SUCCESS) { | 1249 | if ((ret = codec->audio_aac_demux(audio->payload, audio->size, sample)) != ERROR_SUCCESS) { |
| 1250 | + srs_error("codec demux audio failed. ret=%d", ret); | ||
| 1031 | return ret; | 1251 | return ret; |
| 1032 | } | 1252 | } |
| 1033 | 1253 | ||
| @@ -1042,44 +1262,18 @@ int SrsHls::on_audio(SrsSharedPtrMessage* audio) | @@ -1042,44 +1262,18 @@ int SrsHls::on_audio(SrsSharedPtrMessage* audio) | ||
| 1042 | 1262 | ||
| 1043 | int64_t corrected_time = 0; | 1263 | int64_t corrected_time = 0; |
| 1044 | if ((ret = jitter->correct(audio, 0, 0, &corrected_time)) != ERROR_SUCCESS) { | 1264 | if ((ret = jitter->correct(audio, 0, 0, &corrected_time)) != ERROR_SUCCESS) { |
| 1265 | + srs_error("rtmp jitter correct audio failed. ret=%d", ret); | ||
| 1045 | return ret; | 1266 | return ret; |
| 1046 | } | 1267 | } |
| 1047 | 1268 | ||
| 1048 | // the pts calc from rtmp/flv header. | 1269 | // the pts calc from rtmp/flv header. |
| 1049 | int64_t pts = corrected_time * 90; | 1270 | int64_t pts = corrected_time * 90; |
| 1050 | 1271 | ||
| 1051 | - // start buffer, set the af | ||
| 1052 | - if (ab->size == 0) { | ||
| 1053 | - pts = aac_jitter->on_buffer_start(pts, sample->sound_rate); | ||
| 1054 | - | ||
| 1055 | - af->dts = af->pts = audio_buffer_start_pts = pts; | ||
| 1056 | - af->pid = TS_AUDIO_PID; | ||
| 1057 | - af->sid = TS_AUDIO_AAC; | ||
| 1058 | - } else { | ||
| 1059 | - aac_jitter->on_buffer_continue(); | ||
| 1060 | - } | ||
| 1061 | - | ||
| 1062 | - // write audio to cache. | ||
| 1063 | - if ((ret = cache_audio()) != ERROR_SUCCESS) { | 1272 | + if ((ret = ts_cache->write_audio(codec, muxer, pts, sample)) != ERROR_SUCCESS) { |
| 1273 | + srs_error("ts cache write audio failed. ret=%d", ret); | ||
| 1064 | return ret; | 1274 | return ret; |
| 1065 | } | 1275 | } |
| 1066 | 1276 | ||
| 1067 | - // flush if buffer exceed max size. | ||
| 1068 | - if (ab->size > SRS_HLS_AUDIO_CACHE_SIZE) { | ||
| 1069 | - if ((ret = muxer->flush_audio(af, ab)) != ERROR_SUCCESS) { | ||
| 1070 | - return ret; | ||
| 1071 | - } | ||
| 1072 | - } | ||
| 1073 | - // TODO: config it. | ||
| 1074 | - // in ms, audio delay to flush the audios. | ||
| 1075 | - int64_t audio_delay = SRS_CONF_DEFAULT_AAC_DELAY; | ||
| 1076 | - // flush if audio delay exceed | ||
| 1077 | - if (pts - audio_buffer_start_pts > audio_delay * 90) { | ||
| 1078 | - if ((ret = muxer->flush_audio(af, ab)) != ERROR_SUCCESS) { | ||
| 1079 | - return ret; | ||
| 1080 | - } | ||
| 1081 | - } | ||
| 1082 | - | ||
| 1083 | return ret; | 1277 | return ret; |
| 1084 | } | 1278 | } |
| 1085 | 1279 | ||
| @@ -1096,6 +1290,7 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) | @@ -1096,6 +1290,7 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) | ||
| 1096 | 1290 | ||
| 1097 | sample->clear(); | 1291 | sample->clear(); |
| 1098 | if ((ret = codec->video_avc_demux(video->payload, video->size, sample)) != ERROR_SUCCESS) { | 1292 | if ((ret = codec->video_avc_demux(video->payload, video->size, sample)) != ERROR_SUCCESS) { |
| 1293 | + srs_error("codec demux video failed. ret=%d", ret); | ||
| 1099 | return ret; | 1294 | return ret; |
| 1100 | } | 1295 | } |
| 1101 | 1296 | ||
| @@ -1104,166 +1299,23 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) | @@ -1104,166 +1299,23 @@ int SrsHls::on_video(SrsSharedPtrMessage* video) | ||
| 1104 | } | 1299 | } |
| 1105 | 1300 | ||
| 1106 | // ignore sequence header | 1301 | // ignore sequence header |
| 1107 | - if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame && sample->avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) { | 1302 | + if (sample->frame_type == SrsCodecVideoAVCFrameKeyFrame |
| 1303 | + && sample->avc_packet_type == SrsCodecVideoAVCTypeSequenceHeader) { | ||
| 1108 | return ret; | 1304 | return ret; |
| 1109 | } | 1305 | } |
| 1110 | 1306 | ||
| 1111 | int64_t corrected_time = 0; | 1307 | int64_t corrected_time = 0; |
| 1112 | if ((ret = jitter->correct(video, 0, 0, &corrected_time)) != ERROR_SUCCESS) { | 1308 | if ((ret = jitter->correct(video, 0, 0, &corrected_time)) != ERROR_SUCCESS) { |
| 1309 | + srs_error("rtmp jitter correct video failed. ret=%d", ret); | ||
| 1113 | return ret; | 1310 | return ret; |
| 1114 | } | 1311 | } |
| 1115 | 1312 | ||
| 1116 | - // write video to cache. | ||
| 1117 | - if ((ret = cache_video()) != ERROR_SUCCESS) { | 1313 | + int64_t dts = corrected_time * 90; |
| 1314 | + if ((ret = ts_cache->write_video(codec, muxer, dts, sample)) != ERROR_SUCCESS) { | ||
| 1315 | + srs_error("ts cache write video failed. ret=%d", ret); | ||
| 1118 | return ret; | 1316 | return ret; |
| 1119 | } | 1317 | } |
| 1120 | 1318 | ||
| 1121 | - vf->dts = corrected_time * 90; | ||
| 1122 | - vf->pts = vf->dts + sample->cts * 90; | ||
| 1123 | - vf->pid = TS_VIDEO_PID; | ||
| 1124 | - vf->sid = TS_VIDEO_AVC; | ||
| 1125 | - vf->key = sample->frame_type == SrsCodecVideoAVCFrameKeyFrame; | ||
| 1126 | - | ||
| 1127 | - // flush video when got one | ||
| 1128 | - if ((ret = muxer->flush_video(af, ab, vf, vb)) != ERROR_SUCCESS) { | ||
| 1129 | - srs_error("m3u8 muxer flush video failed. ret=%d", ret); | ||
| 1130 | - return ret; | ||
| 1131 | - } | ||
| 1132 | - | ||
| 1133 | - return ret; | ||
| 1134 | -} | ||
| 1135 | - | ||
| 1136 | -int SrsHls::cache_audio() | ||
| 1137 | -{ | ||
| 1138 | - int ret = ERROR_SUCCESS; | ||
| 1139 | - | ||
| 1140 | - for (int i = 0; i < sample->nb_buffers; i++) { | ||
| 1141 | - SrsCodecBuffer* buf = &sample->buffers[i]; | ||
| 1142 | - int32_t size = buf->size; | ||
| 1143 | - | ||
| 1144 | - if (!buf->bytes || size <= 0 || size > 0x1fff) { | ||
| 1145 | - ret = ERROR_HLS_AAC_FRAME_LENGTH; | ||
| 1146 | - srs_error("invalid aac frame length=%d, ret=%d", size, ret); | ||
| 1147 | - return ret; | ||
| 1148 | - } | ||
| 1149 | - | ||
| 1150 | - // the frame length is the AAC raw data plus the adts header size. | ||
| 1151 | - int32_t frame_length = size + 7; | ||
| 1152 | - | ||
| 1153 | - // AAC-ADTS | ||
| 1154 | - // 6.2 Audio Data Transport Stream, ADTS | ||
| 1155 | - // in aac-iso-13818-7.pdf, page 26. | ||
| 1156 | - // fixed 7bytes header | ||
| 1157 | - static u_int8_t adts_header[7] = {0xff, 0xf1, 0x00, 0x00, 0x00, 0x0f, 0xfc}; | ||
| 1158 | - /* | ||
| 1159 | - // adts_fixed_header | ||
| 1160 | - // 2B, 16bits | ||
| 1161 | - int16_t syncword; //12bits, '1111 1111 1111' | ||
| 1162 | - int8_t ID; //1bit, '0' | ||
| 1163 | - int8_t layer; //2bits, '00' | ||
| 1164 | - int8_t protection_absent; //1bit, can be '1' | ||
| 1165 | - // 12bits | ||
| 1166 | - int8_t profile; //2bit, 7.1 Profiles, page 40 | ||
| 1167 | - TSAacSampleFrequency sampling_frequency_index; //4bits, Table 35, page 46 | ||
| 1168 | - int8_t private_bit; //1bit, can be '0' | ||
| 1169 | - int8_t channel_configuration; //3bits, Table 8 | ||
| 1170 | - int8_t original_or_copy; //1bit, can be '0' | ||
| 1171 | - int8_t home; //1bit, can be '0' | ||
| 1172 | - | ||
| 1173 | - // adts_variable_header | ||
| 1174 | - // 28bits | ||
| 1175 | - int8_t copyright_identification_bit; //1bit, can be '0' | ||
| 1176 | - int8_t copyright_identification_start; //1bit, can be '0' | ||
| 1177 | - int16_t frame_length; //13bits | ||
| 1178 | - int16_t adts_buffer_fullness; //11bits, 7FF signals that the bitstream is a variable rate bitstream. | ||
| 1179 | - int8_t number_of_raw_data_blocks_in_frame; //2bits, 0 indicating 1 raw_data_block() | ||
| 1180 | - */ | ||
| 1181 | - // profile, 2bits | ||
| 1182 | - adts_header[2] = (codec->aac_profile << 6) & 0xc0; | ||
| 1183 | - // sampling_frequency_index 4bits | ||
| 1184 | - adts_header[2] |= (codec->aac_sample_rate << 2) & 0x3c; | ||
| 1185 | - // channel_configuration 3bits | ||
| 1186 | - adts_header[2] |= (codec->aac_channels >> 2) & 0x01; | ||
| 1187 | - adts_header[3] = (codec->aac_channels << 6) & 0xc0; | ||
| 1188 | - // frame_length 13bits | ||
| 1189 | - adts_header[3] |= (frame_length >> 11) & 0x03; | ||
| 1190 | - adts_header[4] = (frame_length >> 3) & 0xff; | ||
| 1191 | - adts_header[5] = ((frame_length << 5) & 0xe0); | ||
| 1192 | - // adts_buffer_fullness; //11bits | ||
| 1193 | - adts_header[5] |= 0x1f; | ||
| 1194 | - | ||
| 1195 | - // copy to audio buffer | ||
| 1196 | - ab->append(adts_header, sizeof(adts_header)); | ||
| 1197 | - ab->append(buf->bytes, buf->size); | ||
| 1198 | - } | ||
| 1199 | - | ||
| 1200 | - return ret; | ||
| 1201 | -} | ||
| 1202 | - | ||
| 1203 | -int SrsHls::cache_video() | ||
| 1204 | -{ | ||
| 1205 | - int ret = ERROR_SUCCESS; | ||
| 1206 | - | ||
| 1207 | - static u_int8_t aud_nal[] = { 0x00, 0x00, 0x00, 0x01, 0x09, 0xf0 }; | ||
| 1208 | - vb->append(aud_nal, sizeof(aud_nal)); | ||
| 1209 | - | ||
| 1210 | - bool sps_pps_sent = false; | ||
| 1211 | - for (int i = 0; i < sample->nb_buffers; i++) { | ||
| 1212 | - SrsCodecBuffer* buf = &sample->buffers[i]; | ||
| 1213 | - int32_t size = buf->size; | ||
| 1214 | - | ||
| 1215 | - if (!buf->bytes || size <= 0) { | ||
| 1216 | - ret = ERROR_HLS_AVC_SAMPLE_SIZE; | ||
| 1217 | - srs_error("invalid avc sample length=%d, ret=%d", size, ret); | ||
| 1218 | - return ret; | ||
| 1219 | - } | ||
| 1220 | - | ||
| 1221 | - // 5bits, 7.3.1 NAL unit syntax, | ||
| 1222 | - // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. | ||
| 1223 | - u_int8_t nal_unit_type; | ||
| 1224 | - nal_unit_type = *buf->bytes; | ||
| 1225 | - nal_unit_type &= 0x1f; | ||
| 1226 | - | ||
| 1227 | - // Table 7-1 – NAL unit type codes, page 61 | ||
| 1228 | - // 1: Coded slice | ||
| 1229 | - if (nal_unit_type == 1) { | ||
| 1230 | - sps_pps_sent = false; | ||
| 1231 | - } | ||
| 1232 | - // 5: Coded slice of an IDR picture. | ||
| 1233 | - // insert sps/pps before IDR or key frame is ok. | ||
| 1234 | - if (nal_unit_type == 5 && !sps_pps_sent) { | ||
| 1235 | - //if (vf->key && !sps_pps_sent) { | ||
| 1236 | - sps_pps_sent = true; | ||
| 1237 | - | ||
| 1238 | - // ngx_rtmp_hls_append_sps_pps | ||
| 1239 | - if (codec->sequenceParameterSetLength > 0) { | ||
| 1240 | - // AnnexB prefix | ||
| 1241 | - vb->append(aud_nal, 4); | ||
| 1242 | - // sps | ||
| 1243 | - vb->append(codec->sequenceParameterSetNALUnit, codec->sequenceParameterSetLength); | ||
| 1244 | - } | ||
| 1245 | - if (codec->pictureParameterSetLength > 0) { | ||
| 1246 | - // AnnexB prefix | ||
| 1247 | - vb->append(aud_nal, 4); | ||
| 1248 | - // pps | ||
| 1249 | - vb->append(codec->pictureParameterSetNALUnit, codec->pictureParameterSetLength); | ||
| 1250 | - } | ||
| 1251 | - } | ||
| 1252 | - | ||
| 1253 | - // sample start prefix, '00 00 00 01' or '00 00 01' | ||
| 1254 | - u_int8_t* p = aud_nal + 1; | ||
| 1255 | - u_int8_t* end = p + 3; | ||
| 1256 | - | ||
| 1257 | - // first AnnexB prefix is long (4 bytes) | ||
| 1258 | - if (i == 0) { | ||
| 1259 | - p = aud_nal; | ||
| 1260 | - } | ||
| 1261 | - vb->append(p, end - p); | ||
| 1262 | - | ||
| 1263 | - // sample data | ||
| 1264 | - vb->append(buf->bytes, buf->size); | ||
| 1265 | - } | ||
| 1266 | - | ||
| 1267 | return ret; | 1319 | return ret; |
| 1268 | } | 1320 | } |
| 1269 | 1321 |
| @@ -160,25 +160,55 @@ private: | @@ -160,25 +160,55 @@ private: | ||
| 160 | }; | 160 | }; |
| 161 | 161 | ||
| 162 | /** | 162 | /** |
| 163 | -* write m3u8 hls. | 163 | +* ts need to cache some audio then flush |
| 164 | */ | 164 | */ |
| 165 | -class SrsHls | 165 | +class SrsTSCache |
| 166 | { | 166 | { |
| 167 | private: | 167 | private: |
| 168 | - SrsM3u8Muxer* muxer; | ||
| 169 | // current frame and buffer | 168 | // current frame and buffer |
| 170 | SrsMpegtsFrame* af; | 169 | SrsMpegtsFrame* af; |
| 171 | SrsCodecBuffer* ab; | 170 | SrsCodecBuffer* ab; |
| 172 | SrsMpegtsFrame* vf; | 171 | SrsMpegtsFrame* vf; |
| 173 | SrsCodecBuffer* vb; | 172 | SrsCodecBuffer* vb; |
| 173 | +private: | ||
| 174 | // the audio cache buffer start pts, to flush audio if full. | 174 | // the audio cache buffer start pts, to flush audio if full. |
| 175 | int64_t audio_buffer_start_pts; | 175 | int64_t audio_buffer_start_pts; |
| 176 | + // time jitter for aac | ||
| 177 | + SrsHlsAacJitter* aac_jitter; | ||
| 178 | +public: | ||
| 179 | + SrsTSCache(); | ||
| 180 | + virtual ~SrsTSCache(); | ||
| 181 | +public: | ||
| 182 | + /** | ||
| 183 | + * write audio to cache, if need to flush, flush to muxer. | ||
| 184 | + */ | ||
| 185 | + virtual int write_audio(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t pts, SrsCodecSample* sample); | ||
| 186 | + /** | ||
| 187 | + * write video to muxer. | ||
| 188 | + */ | ||
| 189 | + virtual int write_video(SrsCodec* codec, SrsM3u8Muxer* muxer, int64_t dts, SrsCodecSample* sample); | ||
| 190 | + /** | ||
| 191 | + * flush audio in cache to muxer. | ||
| 192 | + */ | ||
| 193 | + virtual int flush_audio(SrsM3u8Muxer* muxer); | ||
| 194 | +private: | ||
| 195 | + virtual int cache_audio(SrsCodec* codec, SrsCodecSample* sample); | ||
| 196 | + virtual int cache_video(SrsCodec* codec, SrsCodecSample* sample); | ||
| 197 | +}; | ||
| 198 | + | ||
| 199 | +/** | ||
| 200 | +* write m3u8 hls. | ||
| 201 | +*/ | ||
| 202 | +class SrsHls | ||
| 203 | +{ | ||
| 204 | +private: | ||
| 205 | + SrsM3u8Muxer* muxer; | ||
| 206 | + SrsTSCache* ts_cache; | ||
| 176 | private: | 207 | private: |
| 177 | bool hls_enabled; | 208 | bool hls_enabled; |
| 178 | SrsCodec* codec; | 209 | SrsCodec* codec; |
| 179 | SrsCodecSample* sample; | 210 | SrsCodecSample* sample; |
| 180 | SrsRtmpJitter* jitter; | 211 | SrsRtmpJitter* jitter; |
| 181 | - SrsHlsAacJitter* aac_jitter; | ||
| 182 | public: | 212 | public: |
| 183 | SrsHls(); | 213 | SrsHls(); |
| 184 | virtual ~SrsHls(); | 214 | virtual ~SrsHls(); |
| @@ -188,9 +218,6 @@ public: | @@ -188,9 +218,6 @@ public: | ||
| 188 | virtual int on_meta_data(SrsOnMetaDataPacket* metadata); | 218 | virtual int on_meta_data(SrsOnMetaDataPacket* metadata); |
| 189 | virtual int on_audio(SrsSharedPtrMessage* audio); | 219 | virtual int on_audio(SrsSharedPtrMessage* audio); |
| 190 | virtual int on_video(SrsSharedPtrMessage* video); | 220 | virtual int on_video(SrsSharedPtrMessage* video); |
| 191 | -private: | ||
| 192 | - virtual int cache_audio(); | ||
| 193 | - virtual int cache_video(); | ||
| 194 | }; | 221 | }; |
| 195 | 222 | ||
| 196 | #endif | 223 | #endif |
-
请 注册 或 登录 后发表评论