@@ -43,6 +43,9 @@ string srs_ts_stream2string(SrsTsStream stream)
43
43
case SrsTsStreamAudioAC3: return " AC3" ;
44
44
case SrsTsStreamAudioDTS: return " AudioDTS" ;
45
45
case SrsTsStreamVideoH264: return " H.264" ;
46
+ #ifdef SRS_H265
47
+ case SrsTsStreamVideoHEVC: return " H.265" ;
48
+ #endif
46
49
case SrsTsStreamVideoMpeg4: return " MP4" ;
47
50
case SrsTsStreamAudioMpeg4: return " MP4A" ;
48
51
default : return " Other" ;
@@ -285,6 +288,14 @@ srs_error_t SrsTsContext::encode(ISrsStreamWriter* writer, SrsTsMessage* msg, Sr
285
288
vs = SrsTsStreamVideoH264;
286
289
video_pid = TS_VIDEO_AVC_PID;
287
290
break ;
291
+ case SrsVideoCodecIdHEVC:
292
+ #ifdef SRS_H265
293
+ vs = SrsTsStreamVideoHEVC;
294
+ video_pid = TS_VIDEO_AVC_PID;
295
+ break ;
296
+ #else
297
+ return srs_error_new (ERROR_HEVC_DISABLED, " H.265 is disabled" );
298
+ #endif
288
299
case SrsVideoCodecIdDisabled:
289
300
vs = SrsTsStreamReserved;
290
301
break ;
@@ -296,7 +307,6 @@ srs_error_t SrsTsContext::encode(ISrsStreamWriter* writer, SrsTsMessage* msg, Sr
296
307
case SrsVideoCodecIdOn2VP6:
297
308
case SrsVideoCodecIdOn2VP6WithAlphaChannel:
298
309
case SrsVideoCodecIdScreenVideoVersion2:
299
- case SrsVideoCodecIdHEVC:
300
310
case SrsVideoCodecIdAV1:
301
311
vs = SrsTsStreamReserved;
302
312
break ;
@@ -335,10 +345,13 @@ srs_error_t SrsTsContext::encode(ISrsStreamWriter* writer, SrsTsMessage* msg, Sr
335
345
return srs_error_new (ERROR_HLS_NO_STREAM, " ts: no a/v stream, vcodec=%d, acodec=%d" , vc, ac);
336
346
}
337
347
338
- // when any codec changed, write PAT/PMT table.
348
+ // When any codec changed, write PAT/PMT table.
339
349
if (vcodec != vc || acodec != ac) {
340
- vcodec = vc;
341
- acodec = ac;
350
+ if (vcodec != SrsVideoCodecIdReserved || acodec != SrsAudioCodecIdReserved1) {
351
+ srs_trace (" TS: Refresh PMT when vcodec=%d=>%d, acodec=%d=>%d" , vcodec, vc, acodec, ac);
352
+ }
353
+ vcodec = vc; acodec = ac;
354
+
342
355
if ((err = encode_pat_pmt (writer, video_pid, vs, audio_pid, as)) != srs_success) {
343
356
return srs_error_wrap (err, " ts: encode PAT/PMT" );
344
357
}
@@ -355,8 +368,12 @@ srs_error_t SrsTsContext::encode(ISrsStreamWriter* writer, SrsTsMessage* msg, Sr
355
368
srs_error_t SrsTsContext::encode_pat_pmt (ISrsStreamWriter* writer, int16_t vpid, SrsTsStream vs, int16_t apid, SrsTsStream as)
356
369
{
357
370
srs_error_t err = srs_success;
358
-
359
- if (vs != SrsTsStreamVideoH264 && as != SrsTsStreamAudioAAC && as != SrsTsStreamAudioMp3) {
371
+
372
+ bool codec_ok = (vs == SrsTsStreamVideoH264 || as == SrsTsStreamAudioAAC || as == SrsTsStreamAudioMp3);
373
+ #ifdef SRS_H265
374
+ codec_ok = codec_ok ? : (vs == SrsTsStreamVideoHEVC);
375
+ #endif
376
+ if (!codec_ok) {
360
377
return srs_error_new (ERROR_HLS_NO_STREAM, " ts: no PID, vs=%d, as=%d" , vs, as);
361
378
}
362
379
@@ -425,8 +442,12 @@ srs_error_t SrsTsContext::encode_pes(ISrsStreamWriter* writer, SrsTsMessage* msg
425
442
if (msg->payload ->length () == 0 ) {
426
443
return err;
427
444
}
428
-
429
- if (sid != SrsTsStreamVideoH264 && sid != SrsTsStreamAudioMp3 && sid != SrsTsStreamAudioAAC) {
445
+
446
+ bool codec_ok = (sid == SrsTsStreamVideoH264 || sid == SrsTsStreamAudioAAC || sid == SrsTsStreamAudioMp3);
447
+ #ifdef SRS_H265
448
+ codec_ok = codec_ok ? : (sid == SrsTsStreamVideoHEVC);
449
+ #endif
450
+ if (!codec_ok) {
430
451
srs_info (" ts: ignore the unknown stream, sid=%d" , sid);
431
452
return err;
432
453
}
@@ -750,10 +771,14 @@ SrsTsPacket* SrsTsPacket::create_pmt(SrsTsContext* context,
750
771
pmt->current_next_indicator = 1 ;
751
772
pmt->section_number = 0 ;
752
773
pmt->last_section_number = 0 ;
753
-
754
- // must got one valid codec.
755
- srs_assert (vs == SrsTsStreamVideoH264 || as == SrsTsStreamAudioAAC || as == SrsTsStreamAudioMp3);
756
-
774
+
775
+ // Here we must get the correct codec.
776
+ bool codec_ok = (vs == SrsTsStreamVideoH264 || as == SrsTsStreamAudioAAC || as == SrsTsStreamAudioMp3);
777
+ #ifdef SRS_H265
778
+ codec_ok = codec_ok ? : (vs == SrsTsStreamVideoHEVC);
779
+ #endif
780
+ srs_assert (codec_ok);
781
+
757
782
// if mp3 or aac specified, use audio to carry pcr.
758
783
if (as == SrsTsStreamAudioAAC || as == SrsTsStreamAudioMp3) {
759
784
// use audio to carray pcr by default.
@@ -762,8 +787,12 @@ SrsTsPacket* SrsTsPacket::create_pmt(SrsTsContext* context,
762
787
pmt->infos .push_back (new SrsTsPayloadPMTESInfo (as, apid));
763
788
}
764
789
765
- // if h.264 specified, use video to carry pcr.
766
- if (vs == SrsTsStreamVideoH264) {
790
+ // If h.264/h.265 specified, use video to carry pcr.
791
+ codec_ok = (vs == SrsTsStreamVideoH264);
792
+ #ifdef SRS_H265
793
+ codec_ok = codec_ok ? : (vs == SrsTsStreamVideoHEVC);
794
+ #endif
795
+ if (codec_ok) {
767
796
pmt->PCR_PID = vpid;
768
797
pmt->infos .push_back (new SrsTsPayloadPMTESInfo (vs, vpid));
769
798
}
@@ -2533,6 +2562,9 @@ srs_error_t SrsTsPayloadPMT::psi_decode(SrsBuffer* stream)
2533
2562
// update the apply pid table
2534
2563
switch (info->stream_type ) {
2535
2564
case SrsTsStreamVideoH264:
2565
+ #ifdef SRS_H265
2566
+ case SrsTsStreamVideoHEVC:
2567
+ #endif
2536
2568
case SrsTsStreamVideoMpeg4:
2537
2569
packet->context ->set (info->elementary_PID , SrsTsPidApplyVideo, info->stream_type );
2538
2570
break ;
@@ -2616,6 +2648,9 @@ srs_error_t SrsTsPayloadPMT::psi_encode(SrsBuffer* stream)
2616
2648
// update the apply pid table
2617
2649
switch (info->stream_type ) {
2618
2650
case SrsTsStreamVideoH264:
2651
+ #ifdef SRS_H265
2652
+ case SrsTsStreamVideoHEVC:
2653
+ #endif
2619
2654
case SrsTsStreamVideoMpeg4:
2620
2655
packet->context ->set (info->elementary_PID , SrsTsPidApplyVideo, info->stream_type );
2621
2656
break ;
@@ -2685,6 +2720,11 @@ SrsVideoCodecId SrsTsContextWriter::video_codec()
2685
2720
return vcodec;
2686
2721
}
2687
2722
2723
+ void SrsTsContextWriter::update_video_codec (SrsVideoCodecId v)
2724
+ {
2725
+ vcodec = v;
2726
+ }
2727
+
2688
2728
SrsEncFileWriter::SrsEncFileWriter ()
2689
2729
{
2690
2730
memset (iv,0 ,16 );
@@ -2832,8 +2872,17 @@ srs_error_t SrsTsMessageCache::cache_video(SrsVideoFrame* frame, int64_t dts)
2832
2872
video->dts = dts;
2833
2873
video->pts = video->dts + frame->cts * 90 ;
2834
2874
video->sid = SrsTsPESStreamIdVideoCommon;
2835
-
2836
- // write video to cache.
2875
+
2876
+ // Write H.265 video frame to cache.
2877
+ if (frame && frame->vcodec ()->id == SrsVideoCodecIdHEVC) {
2878
+ #ifdef SRS_H265
2879
+ return do_cache_hevc (frame);
2880
+ #else
2881
+ return srs_error_new (ERROR_HEVC_DISABLED, " H.265 is disabled" );
2882
+ #endif
2883
+ }
2884
+
2885
+ // Write H.264 video frame to cache.
2837
2886
if ((err = do_cache_avc (frame)) != srs_success) {
2838
2887
return srs_error_wrap (err, " ts: cache avc" );
2839
2888
}
@@ -2924,7 +2973,7 @@ srs_error_t SrsTsMessageCache::do_cache_aac(SrsAudioFrame* frame)
2924
2973
return err;
2925
2974
}
2926
2975
2927
- void srs_avc_insert_aud (SrsSimpleStream* payload, bool & aud_inserted)
2976
+ void srs_avc_insert_aud (SrsSimpleStream* payload, bool aud_inserted)
2928
2977
{
2929
2978
// mux the samples in annexb format,
2930
2979
// ISO_IEC_14496-10-AVC-2012.pdf, page 324.
@@ -3064,6 +3113,52 @@ srs_error_t SrsTsMessageCache::do_cache_avc(SrsVideoFrame* frame)
3064
3113
return err;
3065
3114
}
3066
3115
3116
+ #ifdef SRS_H265
3117
+ srs_error_t SrsTsMessageCache::do_cache_hevc (SrsVideoFrame* frame)
3118
+ {
3119
+ srs_error_t err = srs_success;
3120
+
3121
+ // Whether aud inserted.
3122
+ bool aud_inserted = false ;
3123
+
3124
+ SrsVideoCodecConfig* codec = frame->vcodec ();
3125
+ srs_assert (codec);
3126
+
3127
+ bool is_sps_pps_appended = false ;
3128
+
3129
+ // all sample use cont nalu header, except the sps-pps before IDR frame.
3130
+ for (int i = 0 ; i < frame->nb_samples ; i++) {
3131
+ SrsSample* sample = &frame->samples [i];
3132
+ int32_t size = sample->size ;
3133
+
3134
+ if (!sample->bytes || size <= 0 ) {
3135
+ return srs_error_new (ERROR_HLS_AVC_SAMPLE_SIZE, " ts: invalid avc sample length=%d" , size);
3136
+ }
3137
+
3138
+ // Insert aud before NALU for HEVC.
3139
+ SrsHevcNaluType nalu_type = (SrsHevcNaluType)SrsHevcNaluTypeParse (sample->bytes [0 ]);
3140
+ bool is_idr = (SrsHevcNaluType_CODED_SLICE_BLA <= nalu_type) && (nalu_type <= SrsHevcNaluType_RESERVED_23);
3141
+ if (is_idr && !frame->has_sps_pps && !is_sps_pps_appended) {
3142
+ for (size_t i = 0 ; i < codec->hevc_dec_conf_record_ .nalu_vec .size (); i++) {
3143
+ const SrsHevcHvccNalu& nalu = codec->hevc_dec_conf_record_ .nalu_vec [i];
3144
+ if (nalu.num_nalus <= 0 || nalu.nal_data_vec .empty ()) continue ;
3145
+
3146
+ srs_avc_insert_aud (video->payload , aud_inserted);
3147
+ const SrsHevcNalData& data = nalu.nal_data_vec .at (0 );
3148
+ video->payload ->append ((char *)&data.nal_unit_data [0 ], (int )data.nal_unit_data .size ());
3149
+ is_sps_pps_appended = true ;
3150
+ }
3151
+ }
3152
+
3153
+ // Insert the NALU to video in annexb.
3154
+ srs_avc_insert_aud (video->payload , aud_inserted);
3155
+ video->payload ->append (sample->bytes , sample->size );
3156
+ }
3157
+
3158
+ return err;
3159
+ }
3160
+ #endif
3161
+
3067
3162
SrsTsTransmuxer::SrsTsTransmuxer ()
3068
3163
{
3069
3164
writer = NULL ;
@@ -3158,10 +3253,17 @@ srs_error_t SrsTsTransmuxer::write_video(int64_t timestamp, char* data, int size
3158
3253
if (format->video ->frame_type == SrsVideoAvcFrameTypeVideoInfoFrame) {
3159
3254
return err;
3160
3255
}
3161
-
3162
- if (format->vcodec ->id != SrsVideoCodecIdAVC) {
3256
+
3257
+ bool codec_ok = (format->vcodec ->id != SrsVideoCodecIdAVC);
3258
+ #ifdef SRS_H265
3259
+ codec_ok = codec_ok ? : (format->vcodec ->id != SrsVideoCodecIdHEVC);
3260
+ #endif
3261
+ if (!codec_ok) {
3163
3262
return err;
3164
3263
}
3264
+
3265
+ // The video codec might change during streaming.
3266
+ tscw->update_video_codec (format->vcodec ->id );
3165
3267
3166
3268
// ignore sequence header
3167
3269
if (format->video ->frame_type == SrsVideoAvcFrameTypeKeyFrame && format->video ->avc_packet_type == SrsVideoAvcFrameTraitSequenceHeader) {
0 commit comments