@@ -93,6 +93,53 @@ srs_error_t SrsInitMp4Segment::write(SrsFormat* format, int v_tid, int a_tid)
93
93
{
94
94
srs_error_t err = srs_success;
95
95
96
+ if ((err = init_encoder ()) != srs_success) {
97
+ return srs_error_wrap (err, " init encoder" );
98
+ }
99
+
100
+ if ((err = init_->write (format, v_tid, a_tid)) != srs_success) {
101
+ return srs_error_wrap (err, " write init" );
102
+ }
103
+
104
+ return err;
105
+ }
106
+
107
+ srs_error_t SrsInitMp4Segment::write_video_only (SrsFormat* format, int v_tid)
108
+ {
109
+ srs_error_t err = srs_success;
110
+
111
+ if ((err = init_encoder ()) != srs_success) {
112
+ return srs_error_wrap (err, " init encoder" );
113
+ }
114
+
115
+ if ((err = init_->write (format, true , v_tid)) != srs_success) {
116
+ return srs_error_wrap (err, " write init" );
117
+ }
118
+
119
+ return err;
120
+ }
121
+
122
+ srs_error_t SrsInitMp4Segment::write_audio_only (SrsFormat* format, int a_tid)
123
+ {
124
+ srs_error_t err = srs_success;
125
+
126
+ if ((err = init_encoder ()) != srs_success) {
127
+ return srs_error_wrap (err, " init encoder" );
128
+ }
129
+
130
+ if ((err = init_->write (format, false , a_tid)) != srs_success) {
131
+ return srs_error_wrap (err, " write init" );
132
+ }
133
+
134
+ return err;
135
+ }
136
+
137
+ srs_error_t SrsInitMp4Segment::init_encoder ()
138
+ {
139
+ srs_error_t err = srs_success;
140
+
141
+ srs_assert (!fullpath ().empty ());
142
+
96
143
string path_tmp = tmppath ();
97
144
if ((err = fw_->open (path_tmp)) != srs_success) {
98
145
return srs_error_wrap (err, " Open init mp4 failed, path=%s" , path_tmp.c_str ());
@@ -101,14 +148,11 @@ srs_error_t SrsInitMp4Segment::write(SrsFormat* format, int v_tid, int a_tid)
101
148
if ((err = init_->initialize (fw_)) != srs_success) {
102
149
return srs_error_wrap (err, " init" );
103
150
}
104
-
105
- if ((err = init_->write (format, v_tid, a_tid)) != srs_success) {
106
- return srs_error_wrap (err, " write init" );
107
- }
108
-
151
+
109
152
return err;
110
153
}
111
154
155
+
112
156
SrsHlsM4sSegment::SrsHlsM4sSegment ()
113
157
{
114
158
fw_ = new SrsFileWriter ();
@@ -428,7 +472,7 @@ srs_error_t SrsHlsFmp4Muxer::on_publish(SrsRequest* req)
428
472
return err;
429
473
}
430
474
431
- srs_error_t SrsHlsFmp4Muxer::write_init_mp4 (SrsFormat* format)
475
+ srs_error_t SrsHlsFmp4Muxer::write_init_mp4 (SrsFormat* format, bool has_video, bool has_audio )
432
476
{
433
477
srs_error_t err = srs_success;
434
478
@@ -448,8 +492,20 @@ srs_error_t SrsHlsFmp4Muxer::write_init_mp4(SrsFormat* format)
448
492
449
493
init_mp4->set_path (path);
450
494
451
- if ((err = init_mp4->write (format, video_track_id_, audio_track_id_)) != srs_success) {
452
- return srs_error_wrap (err, " write hls init.mp4 with audio and video" );
495
+ if (has_video && has_audio) {
496
+ if ((err = init_mp4->write (format, video_track_id_, audio_track_id_)) != srs_success) {
497
+ return srs_error_wrap (err, " write hls init.mp4 with audio and video" );
498
+ }
499
+ } else if (has_video) {
500
+ if ((err = init_mp4->write_video_only (format, video_track_id_)) != srs_success) {
501
+ return srs_error_wrap (err, " write hls init.mp4 with video only" );
502
+ }
503
+ } else if (has_audio) {
504
+ if ((err = init_mp4->write_audio_only (format, audio_track_id_)) != srs_success) {
505
+ return srs_error_wrap (err, " write hls init.mp4 with audio only" );
506
+ }
507
+ } else {
508
+ return srs_error_new (ERROR_HLS_WRITE_FAILED, " no video and no audio sequence header" );
453
509
}
454
510
455
511
if ((err = init_mp4->rename ()) != srs_success) {
@@ -471,6 +527,16 @@ srs_error_t SrsHlsFmp4Muxer::write_audio(SrsSharedPtrMessage* shared_audio, SrsF
471
527
return srs_error_wrap (err, " open segment" );
472
528
}
473
529
}
530
+
531
+ if (current_->duration () >= hls_fragment_) {
532
+ if ((err = segment_close ()) != srs_success) {
533
+ return srs_error_wrap (err, " segment close" );
534
+ }
535
+
536
+ if ((err = segment_open (shared_audio->timestamp * SRS_UTIME_MILLISECONDS)) != srs_success) {
537
+ return srs_error_wrap (err, " open segment" );
538
+ }
539
+ }
474
540
475
541
current_->write (shared_audio, format);
476
542
return err;
@@ -488,7 +554,8 @@ srs_error_t SrsHlsFmp4Muxer::write_video(SrsSharedPtrMessage* shared_video, SrsF
488
554
}
489
555
}
490
556
491
- bool reopen = format->video ->frame_type == SrsVideoAvcFrameTypeKeyFrame && current_->duration () >= hls_fragment_;
557
+ // TODO: reap segment only when get key frame?
558
+ bool reopen = current_->duration () >= hls_fragment_;
492
559
if (reopen) {
493
560
if ((err = segment_close ()) != srs_success) {
494
561
return srs_error_wrap (err, " segment close" );
@@ -499,7 +566,6 @@ srs_error_t SrsHlsFmp4Muxer::write_video(SrsSharedPtrMessage* shared_video, SrsF
499
566
}
500
567
}
501
568
502
- // TODO: do reap segment here.
503
569
current_->write (shared_video, format);
504
570
505
571
return err;
@@ -2046,7 +2112,7 @@ srs_error_t SrsHlsMp4Controller::on_sequence_header(SrsSharedPtrMessage* msg, Sr
2046
2112
has_audio_sh_ = true ;
2047
2113
}
2048
2114
2049
- muxer_->write_init_mp4 (format);
2115
+ muxer_->write_init_mp4 (format, has_video_sh_, has_audio_sh_ );
2050
2116
2051
2117
return err;
2052
2118
}
@@ -2291,8 +2357,14 @@ void SrsHls::on_unpublish()
2291
2357
2292
2358
srs_error_t SrsHls::on_audio (SrsSharedPtrMessage* shared_audio, SrsFormat* format)
2293
2359
{
2360
+ // srs_warn("hls: on_audio, is_aac_sh=%s, aac_extra_data.size=%d", format->is_aac_sequence_header() ? "true" : "false", format->acodec->aac_extra_data.size());
2361
+
2294
2362
srs_error_t err = srs_success;
2295
2363
2364
+ if (format->acodec ->aac_extra_data .size () == 0 ) {
2365
+ srs_trace (" the audio codec's aac extra data is empty" );
2366
+ return err;
2367
+ }
2296
2368
// If not able to transmux to HLS, ignore.
2297
2369
if (!enabled || unpublishing_) return err;
2298
2370
if (async_reload_) return reload ();
@@ -2317,7 +2389,8 @@ srs_error_t SrsHls::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* forma
2317
2389
2318
2390
// ignore sequence header
2319
2391
srs_assert (format->audio );
2320
- if (acodec == SrsAudioCodecIdAAC && format->audio ->aac_packet_type == SrsAudioAacFrameTraitSequenceHeader) {
2392
+ // TODO: verify mp3 play by HLS.
2393
+ if (format->is_aac_sequence_header () || format->is_mp3_sequence_header ()) {
2321
2394
return controller->on_sequence_header (audio.get (), format);
2322
2395
}
2323
2396
@@ -2335,6 +2408,7 @@ srs_error_t SrsHls::on_audio(SrsSharedPtrMessage* shared_audio, SrsFormat* forma
2335
2408
2336
2409
srs_error_t SrsHls::on_video (SrsSharedPtrMessage* shared_video, SrsFormat* format)
2337
2410
{
2411
+ // srs_warn("hls: on_video, is_avc_sh=%s", format->is_avc_sequence_header() ? "true" : "false");
2338
2412
srs_error_t err = srs_success;
2339
2413
2340
2414
// If not able to transmux to HLS, ignore.
@@ -2364,8 +2438,10 @@ srs_error_t SrsHls::on_video(SrsSharedPtrMessage* shared_video, SrsFormat* forma
2364
2438
return err;
2365
2439
}
2366
2440
2367
- // ignore sequence header
2368
- if (format->video ->avc_packet_type == SrsVideoAvcFrameTraitSequenceHeader) {
2441
+ // ignore sequence header avc and hevc
2442
+ // is avc|hevc|av1 sequence header check, but av1 packet already ignored above. so it's ok to use
2443
+ // below method.
2444
+ if (format->is_avc_sequence_header ()) {
2369
2445
return controller->on_sequence_header (video.get (), format);
2370
2446
}
2371
2447
0 commit comments