正在显示
6 个修改的文件
包含
223 行增加
和
27 行删除
@@ -228,6 +228,7 @@ Supported operating systems and hardware: | @@ -228,6 +228,7 @@ Supported operating systems and hardware: | ||
228 | * 2013-10-17, Created.<br/> | 228 | * 2013-10-17, Created.<br/> |
229 | 229 | ||
230 | ## History | 230 | ## History |
231 | +* v2.0, 2014-11-08, fix [#66](https://github.com/winlinvip/simple-rtmp-server/issues/66), srs-librtmp support write h264 raw packet. 2.0.9. | ||
231 | * v2.0, 2014-10-25, fix [#185](https://github.com/winlinvip/simple-rtmp-server/issues/185), AMF0 support 0x0B the date type codec. 2.0.7. | 232 | * v2.0, 2014-10-25, fix [#185](https://github.com/winlinvip/simple-rtmp-server/issues/185), AMF0 support 0x0B the date type codec. 2.0.7. |
232 | * v2.0, 2014-10-24, fix [#186](https://github.com/winlinvip/simple-rtmp-server/issues/186), hotfix for bug #186, drop connect args when not object. 2.0.6. | 233 | * v2.0, 2014-10-24, fix [#186](https://github.com/winlinvip/simple-rtmp-server/issues/186), hotfix for bug #186, drop connect args when not object. 2.0.6. |
233 | * v2.0, 2014-10-24, rename wiki/xxx to wiki/v1_CN_xxx. 2.0.3. | 234 | * v2.0, 2014-10-24, rename wiki/xxx to wiki/v1_CN_xxx. 2.0.3. |
不能预览此文件类型
@@ -19,6 +19,11 @@ amf3_spec_121207.pdf | @@ -19,6 +19,11 @@ amf3_spec_121207.pdf | ||
19 | H.264-AVC-ISO_IEC_14496-10.pdf | 19 | H.264-AVC-ISO_IEC_14496-10.pdf |
20 | avc标准,编码部分。 | 20 | avc标准,编码部分。 |
21 | 21 | ||
22 | +H.264-AVC-ISO_IEC_14496-10-2012.pdf | ||
23 | + avc标准,编码部分。 | ||
24 | + 上面的标准是2003年的,和下面的15是2010年的对不上。 | ||
25 | + http://www.itu.int/ITU-T/recommendations/rec.aspx?rec=11466 | ||
26 | + | ||
22 | H.264-AVC-ISO_IEC_14496-15.pdf | 27 | H.264-AVC-ISO_IEC_14496-15.pdf |
23 | avc标准,封装部分。 | 28 | avc标准,封装部分。 |
24 | 29 |
@@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | @@ -31,7 +31,7 @@ CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | ||
31 | // current release version | 31 | // current release version |
32 | #define VERSION_MAJOR 2 | 32 | #define VERSION_MAJOR 2 |
33 | #define VERSION_MINOR 0 | 33 | #define VERSION_MINOR 0 |
34 | -#define VERSION_REVISION 8 | 34 | +#define VERSION_REVISION 9 |
35 | // server info. | 35 | // server info. |
36 | #define RTMP_SIG_SRS_KEY "SRS" | 36 | #define RTMP_SIG_SRS_KEY "SRS" |
37 | #define RTMP_SIG_SRS_ROLE "origin/edge server" | 37 | #define RTMP_SIG_SRS_ROLE "origin/edge server" |
@@ -73,6 +73,9 @@ struct Context | @@ -73,6 +73,9 @@ struct Context | ||
73 | // for h264 raw stream, | 73 | // for h264 raw stream, |
74 | // see: https://github.com/winlinvip/simple-rtmp-server/issues/66#issuecomment-62240521 | 74 | // see: https://github.com/winlinvip/simple-rtmp-server/issues/66#issuecomment-62240521 |
75 | SrsStream raw_stream; | 75 | SrsStream raw_stream; |
76 | + // about SPS, @see: 7.3.2.1.1, H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 62 | ||
77 | + std::string h264_sps; | ||
78 | + std::string h264_pps; | ||
76 | 79 | ||
77 | Context() { | 80 | Context() { |
78 | rtmp = NULL; | 81 | rtmp = NULL; |
@@ -1000,13 +1003,15 @@ char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize) | @@ -1000,13 +1003,15 @@ char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize) | ||
1000 | return any->human_print(pdata, psize); | 1003 | return any->human_print(pdata, psize); |
1001 | } | 1004 | } |
1002 | 1005 | ||
1003 | - /*// 5bits, 7.3.1 NAL unit syntax, | ||
1004 | - // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. | ||
1005 | - // 7: SPS, 8: PPS, 5: I Frame, 1: P Frame | ||
1006 | - u_int8_t nal_unit_type = (char)frame[0] & 0x1f; | ||
1007 | - | ||
1008 | - // the RTMP packet header | ||
1009 | - | 1006 | +/** |
1007 | +* write h264 packet, with rtmp header. | ||
1008 | +* @param frame_type, SrsCodecVideoAVCFrameKeyFrame or SrsCodecVideoAVCFrameInterFrame. | ||
1009 | +* @param avc_packet_type, SrsCodecVideoAVCTypeSequenceHeader or SrsCodecVideoAVCTypeNALU. | ||
1010 | +*/ | ||
1011 | +int __srs_write_h264_packet(Context* context, | ||
1012 | + int8_t frame_type, int8_t avc_packet_type, | ||
1013 | + char* h264_raw_data, int h264_raw_size, u_int32_t dts, u_int32_t pts | ||
1014 | +) { | ||
1010 | // the timestamp in rtmp message header is dts. | 1015 | // the timestamp in rtmp message header is dts. |
1011 | u_int32_t timestamp = dts; | 1016 | u_int32_t timestamp = dts; |
1012 | 1017 | ||
@@ -1018,24 +1023,16 @@ char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize) | @@ -1018,24 +1023,16 @@ char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize) | ||
1018 | int size = h264_raw_size + 5; | 1023 | int size = h264_raw_size + 5; |
1019 | char* data = new char[size]; | 1024 | char* data = new char[size]; |
1020 | memcpy(data + 5, h264_raw_data, h264_raw_size); | 1025 | memcpy(data + 5, h264_raw_data, h264_raw_size); |
1026 | + char* p = data; | ||
1021 | 1027 | ||
1022 | - // Frame Type, Type of video frame. | ||
1023 | // @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78 | 1028 | // @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78 |
1024 | - int8_t frame_type = SrsCodecVideoAVCFrameInterFrame; | ||
1025 | - if (nal_unit_type != 1) { | ||
1026 | - frame_type = SrsCodecVideoAVCFrameKeyFrame; | ||
1027 | - } | 1029 | + // Frame Type, Type of video frame. |
1028 | // CodecID, Codec Identifier. | 1030 | // CodecID, Codec Identifier. |
1029 | - int8_t codec_id = SrsCodecVideoAVC; | ||
1030 | // set the rtmp header | 1031 | // set the rtmp header |
1031 | - *p++ = (frame_type << 4) | codec_id; | 1032 | + *p++ = (frame_type << 4) | SrsCodecVideoAVC; |
1032 | 1033 | ||
1033 | // AVCPacketType | 1034 | // AVCPacketType |
1034 | - if (nal_unit_type == 7 || nal_unit_type == 8) { | ||
1035 | - *p++ = SrsCodecVideoAVCTypeSequenceHeader; | ||
1036 | - } else { | ||
1037 | - *p++ = SrsCodecVideoAVCTypeNALU; | ||
1038 | - } | 1035 | + *p++ = avc_packet_type; |
1039 | 1036 | ||
1040 | // CompositionTime | 1037 | // CompositionTime |
1041 | // pts = dts + cts, or | 1038 | // pts = dts + cts, or |
@@ -1045,19 +1042,211 @@ char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize) | @@ -1045,19 +1042,211 @@ char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize) | ||
1045 | char* pp = (char*)&cts; | 1042 | char* pp = (char*)&cts; |
1046 | *p++ = pp[2]; | 1043 | *p++ = pp[2]; |
1047 | *p++ = pp[1]; | 1044 | *p++ = pp[1]; |
1048 | - *p++ = pp[0];*/ | 1045 | + *p++ = pp[0]; |
1049 | 1046 | ||
1050 | -int srs_write_h264_raw_frame(Context* context, char* frame, int frame_size, u_int32_t dts, u_int32_t pts) | 1047 | + return srs_write_packet(context, SRS_RTMP_TYPE_VIDEO, timestamp, data, size); |
1048 | +} | ||
1049 | + | ||
1050 | +/** | ||
1051 | +* write the h264 sps/pps in context over RTMP. | ||
1052 | +*/ | ||
1053 | +int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts) | ||
1051 | { | 1054 | { |
1052 | int ret = ERROR_SUCCESS; | 1055 | int ret = ERROR_SUCCESS; |
1056 | + | ||
1057 | + // when pps or sps not ready, ignore. | ||
1058 | + if (context->h264_pps.empty() || context->h264_sps.empty()) { | ||
1053 | return ret; | 1059 | return ret; |
1060 | + } | ||
1061 | + | ||
1062 | + // 5bytes sps/pps header: | ||
1063 | + // configurationVersion, AVCProfileIndication, profile_compatibility, | ||
1064 | + // AVCLevelIndication, lengthSizeMinusOne | ||
1065 | + // 3bytes size of sps: | ||
1066 | + // numOfSequenceParameterSets, sequenceParameterSetLength(2B) | ||
1067 | + // Nbytes of sps. | ||
1068 | + // sequenceParameterSetNALUnit | ||
1069 | + // 3bytes size of pps: | ||
1070 | + // numOfPictureParameterSets, pictureParameterSetLength | ||
1071 | + // Nbytes of pps: | ||
1072 | + // pictureParameterSetNALUnit | ||
1073 | + int nb_packet = 5 | ||
1074 | + + 3 + (int)context->h264_sps.length() | ||
1075 | + + 3 + (int)context->h264_pps.length(); | ||
1076 | + char* packet = new char[nb_packet]; | ||
1077 | + | ||
1078 | + // use stream to generate the h264 packet. | ||
1079 | + SrsStream stream; | ||
1080 | + if ((ret = stream.initialize(packet, nb_packet)) != ERROR_SUCCESS) { | ||
1081 | + return ret; | ||
1082 | + } | ||
1083 | + | ||
1084 | + // decode the SPS: | ||
1085 | + // @see: 7.3.2.1.1, H.264-AVC-ISO_IEC_14496-10-2012.pdf, page 62 | ||
1086 | + if (true) { | ||
1087 | + srs_assert((int)context->h264_sps.length() >= 4); | ||
1088 | + char* frame = (char*)context->h264_sps.data(); | ||
1089 | + | ||
1090 | + // @see: Annex A Profiles and levels, H.264-AVC-ISO_IEC_14496-10.pdf, page 205 | ||
1091 | + // Baseline profile profile_idc is 66(0x42). | ||
1092 | + // Baseline profile profile_idc is 77(0x4d). | ||
1093 | + // Extended profile profile_idc is 88(0x58). | ||
1094 | + u_int8_t profile_idc = frame[1]; | ||
1095 | + //u_int8_t constraint_set = frame[2]; | ||
1096 | + u_int8_t level_idc = frame[3]; | ||
1097 | + | ||
1098 | + // generate the sps/pps header | ||
1099 | + // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 | ||
1100 | + // configurationVersion | ||
1101 | + stream.write_1bytes(0x01); | ||
1102 | + // AVCProfileIndication | ||
1103 | + stream.write_1bytes(profile_idc); | ||
1104 | + // profile_compatibility | ||
1105 | + stream.write_1bytes(0x00); | ||
1106 | + // AVCLevelIndication | ||
1107 | + stream.write_1bytes(level_idc); | ||
1108 | + // lengthSizeMinusOne, or NAL_unit_length, always use 4bytes size, | ||
1109 | + // so we always set it to 0x03. | ||
1110 | + stream.write_1bytes(0x03); | ||
1111 | + } | ||
1112 | + | ||
1113 | + // sps | ||
1114 | + if (true) { | ||
1115 | + // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 | ||
1116 | + // numOfSequenceParameterSets, always 1 | ||
1117 | + stream.write_1bytes(0x01); | ||
1118 | + // sequenceParameterSetLength | ||
1119 | + stream.write_2bytes(context->h264_sps.length()); | ||
1120 | + // sequenceParameterSetNALUnit | ||
1121 | + stream.write_string(context->h264_sps); | ||
1122 | + } | ||
1123 | + | ||
1124 | + // pps | ||
1125 | + if (true) { | ||
1126 | + // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 | ||
1127 | + // numOfPictureParameterSets, always 1 | ||
1128 | + stream.write_1bytes(0x01); | ||
1129 | + // pictureParameterSetLength | ||
1130 | + stream.write_2bytes(context->h264_pps.length()); | ||
1131 | + // pictureParameterSetNALUnit | ||
1132 | + stream.write_string(context->h264_pps); | ||
1133 | + } | ||
1134 | + | ||
1135 | + // TODO: FIXME: for more profile. | ||
1136 | + // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 | ||
1137 | + // profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 144 | ||
1138 | + | ||
1139 | + // send out h264 packet. | ||
1140 | + int8_t frame_type = SrsCodecVideoAVCFrameKeyFrame; | ||
1141 | + int8_t avc_packet_type = SrsCodecVideoAVCTypeSequenceHeader; | ||
1142 | + return __srs_write_h264_packet( | ||
1143 | + context, frame_type, avc_packet_type, | ||
1144 | + packet, nb_packet, dts, pts | ||
1145 | + ); | ||
1054 | } | 1146 | } |
1055 | 1147 | ||
1056 | -int srs_write_h264_raw_frames(srs_rtmp_t rtmp, char* frames, int frames_size, u_int32_t dts, u_int32_t pts) | ||
1057 | -{ | 1148 | +/** |
1149 | +* write h264 IPB-frame. | ||
1150 | +*/ | ||
1151 | +int __srs_write_h264_ipb_frame(Context* context, | ||
1152 | + char* data, int size, u_int32_t dts, u_int32_t pts | ||
1153 | +) { | ||
1154 | + int ret = ERROR_SUCCESS; | ||
1155 | + | ||
1156 | + // 5bits, 7.3.1 NAL unit syntax, | ||
1157 | + // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. | ||
1158 | + // 7: SPS, 8: PPS, 5: I Frame, 1: P Frame | ||
1159 | + u_int8_t nal_unit_type = (char)data[0] & 0x1f; | ||
1160 | + | ||
1161 | + // 4bytes size of nalu: | ||
1162 | + // NALUnitLength | ||
1163 | + // Nbytes of nalu. | ||
1164 | + // NALUnit | ||
1165 | + int nb_packet = 4 + size; | ||
1166 | + char* packet = new char[nb_packet]; | ||
1167 | + | ||
1168 | + // use stream to generate the h264 packet. | ||
1169 | + SrsStream stream; | ||
1170 | + if ((ret = stream.initialize(packet, nb_packet)) != ERROR_SUCCESS) { | ||
1171 | + return ret; | ||
1172 | + } | ||
1173 | + | ||
1174 | + // 5.3.4.2.1 Syntax, H.264-AVC-ISO_IEC_14496-15.pdf, page 16 | ||
1175 | + // lengthSizeMinusOne, or NAL_unit_length, always use 4bytes size | ||
1176 | + u_int32_t NAL_unit_length = size; | ||
1177 | + | ||
1178 | + // mux the avc NALU in "ISO Base Media File Format" | ||
1179 | + // from H.264-AVC-ISO_IEC_14496-15.pdf, page 20 | ||
1180 | + // NALUnitLength | ||
1181 | + stream.write_4bytes(NAL_unit_length); | ||
1182 | + // NALUnit | ||
1183 | + stream.write_bytes(data, size); | ||
1184 | + | ||
1185 | + // send out h264 packet. | ||
1186 | + int8_t frame_type = SrsCodecVideoAVCFrameInterFrame; | ||
1187 | + if (nal_unit_type != 1) { | ||
1188 | + frame_type = SrsCodecVideoAVCFrameKeyFrame; | ||
1189 | + } | ||
1190 | + int8_t avc_packet_type = SrsCodecVideoAVCTypeNALU; | ||
1191 | + return __srs_write_h264_packet( | ||
1192 | + context, frame_type, avc_packet_type, | ||
1193 | + packet, nb_packet, dts, pts | ||
1194 | + ); | ||
1195 | + | ||
1196 | + return ret; | ||
1197 | +} | ||
1198 | + | ||
1199 | +/** | ||
1200 | +* write h264 raw frame, maybe sps/pps/IPB-frame. | ||
1201 | +*/ | ||
1202 | +int __srs_write_h264_raw_frame(Context* context, | ||
1203 | + char* frame, int frame_size, u_int32_t dts, u_int32_t pts | ||
1204 | +) { | ||
1205 | + int ret = ERROR_SUCCESS; | ||
1206 | + | ||
1207 | + // ignore invalid frame, | ||
1208 | + // atleast 1bytes for SPS to decode the type | ||
1209 | + if (frame_size < 1) { | ||
1210 | + return ret; | ||
1211 | + } | ||
1212 | + | ||
1213 | + // 5bits, 7.3.1 NAL unit syntax, | ||
1214 | + // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. | ||
1215 | + // 7: SPS, 8: PPS, 5: I Frame, 1: P Frame | ||
1216 | + u_int8_t nal_unit_type = (char)frame[0] & 0x1f; | ||
1217 | + | ||
1218 | + if (nal_unit_type == 7) { | ||
1219 | + // atleast 1bytes for SPS to decode the type, profile, constrain and level. | ||
1220 | + if (frame_size < 4) { | ||
1221 | + return ret; | ||
1222 | + } | ||
1223 | + | ||
1224 | + context->h264_sps = ""; | ||
1225 | + context->h264_sps.append(frame, frame_size); | ||
1226 | + | ||
1227 | + return __srs_write_h264_sps_pps(context, dts, pts); | ||
1228 | + } else if (nal_unit_type == 8) { | ||
1229 | + context->h264_pps = ""; | ||
1230 | + context->h264_pps.append(frame, frame_size); | ||
1231 | + | ||
1232 | + return __srs_write_h264_sps_pps(context, dts, pts); | ||
1233 | + } else { | ||
1234 | + return __srs_write_h264_ipb_frame(context, frame, frame_size, dts, pts); | ||
1235 | + } | ||
1236 | + | ||
1237 | + return ret; | ||
1238 | +} | ||
1239 | + | ||
1240 | +/** | ||
1241 | +* write h264 multiple frames, in annexb format. | ||
1242 | +*/ | ||
1243 | +int srs_write_h264_raw_frames(srs_rtmp_t rtmp, | ||
1244 | + char* frames, int frames_size, u_int32_t dts, u_int32_t pts | ||
1245 | +) { | ||
1058 | int ret = ERROR_SUCCESS; | 1246 | int ret = ERROR_SUCCESS; |
1059 | 1247 | ||
1060 | - srs_assert(frames_size > 1); | 1248 | + srs_assert(frames != NULL); |
1249 | + srs_assert(frames_size > 0); | ||
1061 | 1250 | ||
1062 | srs_assert(rtmp != NULL); | 1251 | srs_assert(rtmp != NULL); |
1063 | Context* context = (Context*)rtmp; | 1252 | Context* context = (Context*)rtmp; |
@@ -1088,7 +1277,7 @@ int srs_write_h264_raw_frames(srs_rtmp_t rtmp, char* frames, int frames_size, u_ | @@ -1088,7 +1277,7 @@ int srs_write_h264_raw_frames(srs_rtmp_t rtmp, char* frames, int frames_size, u_ | ||
1088 | 1277 | ||
1089 | // send out the frame. | 1278 | // send out the frame. |
1090 | char* frame = context->raw_stream.data() + start; | 1279 | char* frame = context->raw_stream.data() + start; |
1091 | - if ((ret = srs_write_h264_raw_frame(context, frame, size, dts, pts)) != ERROR_SUCCESS) { | 1280 | + if ((ret = __srs_write_h264_raw_frame(context, frame, size, dts, pts)) != ERROR_SUCCESS) { |
1092 | return ret; | 1281 | return ret; |
1093 | } | 1282 | } |
1094 | } | 1283 | } |
@@ -344,12 +344,13 @@ extern char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize); | @@ -344,12 +344,13 @@ extern char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize); | ||
344 | * for instance, frame = header(00 00 00 01) + payload(67 42 80 29 95 A0 14 01 6E 40) | 344 | * for instance, frame = header(00 00 00 01) + payload(67 42 80 29 95 A0 14 01 6E 40) |
345 | * about annexb, @see H.264-AVC-ISO_IEC_14496-10.pdf, page 211. | 345 | * about annexb, @see H.264-AVC-ISO_IEC_14496-10.pdf, page 211. |
346 | * @paam frames_size the size of h264 raw data. | 346 | * @paam frames_size the size of h264 raw data. |
347 | -* assert frames_size > 1, at least has 1 bytes header. | 347 | +* assert frames_size > 0, at least has 1 bytes header. |
348 | * @param dts the dts of h.264 raw data. | 348 | * @param dts the dts of h.264 raw data. |
349 | * @param pts the pts of h.264 raw data. | 349 | * @param pts the pts of h.264 raw data. |
350 | * | 350 | * |
351 | * @remark, user should free the frames. | 351 | * @remark, user should free the frames. |
352 | * @remark, the tbn of dts/pts is 1/1000 for RTMP, that is, in ms. | 352 | * @remark, the tbn of dts/pts is 1/1000 for RTMP, that is, in ms. |
353 | +* @remark, cts = pts - dts | ||
353 | * | 354 | * |
354 | * @return 0, success; otherswise, failed. | 355 | * @return 0, success; otherswise, failed. |
355 | */ | 356 | */ |
-
请 注册 或 登录 后发表评论