正在显示
3 个修改的文件
包含
57 行增加
和
7 行删除
@@ -171,8 +171,13 @@ int main(int argc, char** argv) | @@ -171,8 +171,13 @@ int main(int argc, char** argv) | ||
171 | if (srs_write_packet(rtmp, type, timestamp, rtmp_data, rtmp_size) != 0) { | 171 | if (srs_write_packet(rtmp, type, timestamp, rtmp_data, rtmp_size) != 0) { |
172 | goto rtmp_destroy; | 172 | goto rtmp_destroy; |
173 | } | 173 | } |
174 | - srs_trace("sent packet: type=%s, time=%d, size=%d, fps=%d", | ||
175 | - srs_type2string(type), timestamp, rtmp_size, fps); | 174 | + |
175 | + // 5bits, 7.3.1 NAL unit syntax, | ||
176 | + // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. | ||
177 | + u_int8_t nut = (char)data[0] & 0x1f; | ||
178 | + srs_trace("sent packet: type=%s, time=%d, size=%d, fps=%d, b[0]=%#x(%s)", | ||
179 | + srs_type2string(type), timestamp, rtmp_size, fps, nut, | ||
180 | + (nut == 7? "SPS":(nut == 8? "PPS":(nut == 5? "I":(nut == 1? "P":"Unknown"))))); | ||
176 | 181 | ||
177 | // @remark, when use encode device, it not need to sleep. | 182 | // @remark, when use encode device, it not need to sleep. |
178 | usleep(1000 / fps * 1000); | 183 | usleep(1000 / fps * 1000); |
@@ -998,10 +998,53 @@ char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize) | @@ -998,10 +998,53 @@ char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize) | ||
998 | 998 | ||
999 | int srs_h264_to_rtmp(char* h264_raw_data, int h264_raw_size, u_int32_t dts, u_int32_t pts, char** prtmp_data, int* prtmp_size, u_int32_t* ptimestamp) | 999 | int srs_h264_to_rtmp(char* h264_raw_data, int h264_raw_size, u_int32_t dts, u_int32_t pts, char** prtmp_data, int* prtmp_size, u_int32_t* ptimestamp) |
1000 | { | 1000 | { |
1001 | - *prtmp_data = new char[h264_raw_size]; | ||
1002 | - memcpy(*prtmp_data, h264_raw_data, h264_raw_size); | ||
1003 | - | ||
1004 | - *prtmp_size = h264_raw_size; | 1001 | + srs_assert(h264_raw_size > 0); |
1002 | + | ||
1003 | + // the timestamp in rtmp message header is dts. | ||
1004 | + *ptimestamp = dts; | ||
1005 | + | ||
1006 | + // for h264 in RTMP video payload, there is 5bytes header: | ||
1007 | + // 1bytes, FrameType | CodecID | ||
1008 | + // 1bytes, AVCPacketType | ||
1009 | + // 3bytes, CompositionTime, the cts. | ||
1010 | + // @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78 | ||
1011 | + *prtmp_size = h264_raw_size + 5; | ||
1012 | + char* p = new char[*prtmp_size]; | ||
1013 | + memcpy(p + 5, h264_raw_data, h264_raw_size); | ||
1014 | + *prtmp_data = p; | ||
1015 | + | ||
1016 | + // 5bits, 7.3.1 NAL unit syntax, | ||
1017 | + // H.264-AVC-ISO_IEC_14496-10.pdf, page 44. | ||
1018 | + // 7: SPS, 8: PPS, 5: I Frame, 1: P Frame | ||
1019 | + u_int8_t nal_unit_type = (char)h264_raw_data[0] & 0x1f; | ||
1020 | + | ||
1021 | + // Frame Type, Type of video frame. | ||
1022 | + // @see: E.4.3 Video Tags, video_file_format_spec_v10_1.pdf, page 78 | ||
1023 | + int8_t frame_type = SrsCodecVideoAVCFrameInterFrame; | ||
1024 | + if (nal_unit_type != 1) { | ||
1025 | + frame_type = SrsCodecVideoAVCFrameKeyFrame; | ||
1026 | + } | ||
1027 | + // CodecID, Codec Identifier. | ||
1028 | + int8_t codec_id = SrsCodecVideoAVC; | ||
1029 | + // set the rtmp header | ||
1030 | + *p++ = (frame_type << 4) | codec_id; | ||
1031 | + | ||
1032 | + // AVCPacketType | ||
1033 | + if (nal_unit_type == 7 || nal_unit_type == 8) { | ||
1034 | + *p++ = SrsCodecVideoAVCTypeSequenceHeader; | ||
1035 | + } else { | ||
1036 | + *p++ = SrsCodecVideoAVCTypeNALU; | ||
1037 | + } | ||
1038 | + | ||
1039 | + // CompositionTime | ||
1040 | + // pts = dts + cts, or | ||
1041 | + // cts = pts - dts. | ||
1042 | + // where cts is the header in rtmp video packet payload header. | ||
1043 | + u_int32_t cts = pts - dts; | ||
1044 | + char* pp = (char*)&cts; | ||
1045 | + *p++ = pp[2]; | ||
1046 | + *p++ = pp[1]; | ||
1047 | + *p++ = pp[0]; | ||
1005 | 1048 | ||
1006 | return 0; | 1049 | return 0; |
1007 | } | 1050 | } |
@@ -339,14 +339,16 @@ extern char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize); | @@ -339,14 +339,16 @@ extern char* srs_amf0_human_print(srs_amf0_t amf0, char** pdata, int* psize); | ||
339 | /** | 339 | /** |
340 | * convert h264 stream data to rtmp packet. | 340 | * convert h264 stream data to rtmp packet. |
341 | * @param h264_raw_data the input h264 raw data, a encoded h.264 I/P/B frame data. | 341 | * @param h264_raw_data the input h264 raw data, a encoded h.264 I/P/B frame data. |
342 | -* @paam h264_raw_size the size of h264 raw data. | 342 | +* @paam h264_raw_size the size of h264 raw data. assert > 0. |
343 | * @param dts the dts of h.264 raw data. | 343 | * @param dts the dts of h.264 raw data. |
344 | * @param pts the pts of h.264 raw data. | 344 | * @param pts the pts of h.264 raw data. |
345 | * @param prtmp_data the output rtmp format packet, which can be send by srs_write_packet. | 345 | * @param prtmp_data the output rtmp format packet, which can be send by srs_write_packet. |
346 | * @param prtmp_size the size of rtmp packet, for srs_write_packet. | 346 | * @param prtmp_size the size of rtmp packet, for srs_write_packet. |
347 | * @param ptimestamp the timestamp of rtmp packet, for srs_write_packet. | 347 | * @param ptimestamp the timestamp of rtmp packet, for srs_write_packet. |
348 | +* | ||
348 | * @remark, user should free the h264_raw_data. | 349 | * @remark, user should free the h264_raw_data. |
349 | * @remark, user should free the prtmp_data if success. | 350 | * @remark, user should free the prtmp_data if success. |
351 | +* @remark, the tbn of dts/pts is 1/1000 for RTMP, that is, in ms. | ||
350 | * | 352 | * |
351 | * @return 0, success; otherswise, failed. | 353 | * @return 0, success; otherswise, failed. |
352 | */ | 354 | */ |
-
请 注册 或 登录 后发表评论