@ -79,12 +79,18 @@ struct Context
// whether the sps and pps sent,
// @see https://github.com/winlinvip/simple-rtmp-server/issues/203
bool h264_sps_pps_sent ;
// only send the ssp and pps when both changed.
// @see https://github.com/winlinvip/simple-rtmp-server/issues/204
bool h264_sps_changed ;
bool h264_pps_changed ;
Context ( ) {
rtmp = NULL ;
skt = NULL ;
stream_id = 0 ;
h264_sps_pps_sent = false ;
h264_sps_changed = false ;
h264_pps_changed = false ;
}
virtual ~ Context ( ) {
srs_freep ( rtmp ) ;
@ -1127,8 +1133,8 @@ int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts)
{
int ret = ERROR_SUCCESS ;
// when pps or sps not ready, ignore .
if ( context - > h264_pps . empty ( ) | | context - > h264_sps . empty ( ) ) {
// only send when both sps and pps changed .
if ( ! context - > h264_sps_changed | | ! context - > h264_pps_changed ) {
return ret ;
}
@ -1207,8 +1213,8 @@ int __srs_write_h264_sps_pps(Context* context, u_int32_t dts, u_int32_t pts)
}
// reset sps and pps.
context - > h264_ pps = " " ;
context - > h264_ sps = " " ;
context - > h264_ sps_changed = false ;
context - > h264_ pps_changed = false ;
context - > h264_sps_pps_sent = true ;
// TODO: FIXME: for more profile.
@ -1307,13 +1313,26 @@ int __srs_write_h264_raw_frame(Context* context,
return ret ;
}
context - > h264_sps = " " ;
context - > h264_sps . append ( frame , frame_size ) ;
std : : string sps ;
sps . append ( frame , frame_size ) ;
if ( context - > h264_sps = = sps ) {
return ERROR_H264_DUPLICATED_SPS ;
}
context - > h264_sps_changed = true ;
context - > h264_sps = sps ;
return __srs_write_h264_sps_pps ( context , dts , pts ) ;
} else if ( nal_unit_type = = 8 ) {
context - > h264_pps = " " ;
context - > h264_pps . append ( frame , frame_size ) ;
std : : string pps ;
pps . append ( frame , frame_size ) ;
if ( context - > h264_pps = = pps ) {
return ERROR_H264_DUPLICATED_PPS ;
}
context - > h264_pps_changed = true ;
context - > h264_pps = pps ;
return __srs_write_h264_sps_pps ( context , dts , pts ) ;
} else {
@ -1341,6 +1360,11 @@ int srs_h264_write_raw_frames(srs_rtmp_t rtmp,
return ret ;
}
// use the last error
// @see https://github.com/winlinvip/simple-rtmp-server/issues/203
// @see https://github.com/winlinvip/simple-rtmp-server/issues/204
int error_code_return = ret ;
// send each frame.
while ( ! context - > h264_raw_stream . empty ( ) ) {
// each frame must prefixed by annexb format.
@ -1363,12 +1387,24 @@ int srs_h264_write_raw_frames(srs_rtmp_t rtmp,
// send out the frame.
char * frame = context - > h264_raw_stream . data ( ) + start ;
// it may be return error, but we must process all packets.
if ( ( ret = __srs_write_h264_raw_frame ( context , frame , size , dts , pts ) ) ! = ERROR_SUCCESS ) {
error_code_return = ret ;
// ignore known error, process all packets.
if ( srs_h264_is_dvbsp_error ( ret )
| | srs_h264_is_duplicated_sps_error ( ret )
| | srs_h264_is_duplicated_pps_error ( ret )
) {
continue ;
}
return ret ;
}
}
return ret ;
return error_code_ return ;
}
srs_h264_bool srs_h264_is_dvbsp_error ( int error_code )
@ -1376,6 +1412,16 @@ srs_h264_bool srs_h264_is_dvbsp_error(int error_code)
return error_code = = ERROR_H264_DROP_BEFORE_SPS_PPS ;
}
srs_h264_bool srs_h264_is_duplicated_sps_error ( int error_code )
{
return error_code = = ERROR_H264_DUPLICATED_SPS ;
}
srs_h264_bool srs_h264_is_duplicated_pps_error ( int error_code )
{
return error_code = = ERROR_H264_DUPLICATED_PPS ;
}
int srs_h264_startswith_annexb ( char * h264_raw_data , int h264_raw_size , int * pnb_start_code )
{
SrsStream stream ;