@@ -187,7 +187,9 @@ defmodule Membrane.MP4.Muxer.CMAF do
187187 pads_registration_order: [ ] ,
188188 sample_queues: % { } ,
189189 finish_current_segment?: false ,
190- video_pad: nil
190+ video_pad: nil ,
191+ all_input_pads_ready?: false ,
192+ buffers_awaiting_init: [ ]
191193 } )
192194 |> set_chunk_duration_range ( )
193195
@@ -309,23 +311,35 @@ defmodule Membrane.MP4.Muxer.CMAF do
309311 if are_all_group_pads_ready? ( pad , ctx , state ) do
310312 stream_format = generate_output_stream_format ( output_pad , state )
311313
314+ old_input_pads_ready? = state . all_input_pads_ready?
315+
316+ state = update_input_pads_ready ( pad , ctx , state )
317+
318+ { actions , state } =
319+ if old_input_pads_ready? != state . all_input_pads_ready? do
320+ replay_init_buffers ( ctx , state )
321+ else
322+ { [ ] , state }
323+ end
324+
312325 cond do
313326 is_nil ( ctx . pads [ output_pad ] . stream_format ) ->
314- { [ stream_format: { output_pad , stream_format } ] , state }
327+ { [ { :stream_format , { output_pad , stream_format } } | actions ] , state }
315328
316329 stream_format != ctx . pads [ output_pad ] . stream_format ->
317- { [ ] , SegmentHelper . put_awaiting_stream_format ( pad , stream_format , state ) }
330+ { actions , SegmentHelper . put_awaiting_stream_format ( pad , stream_format , state ) }
318331
319332 true ->
320- { [ ] , state }
333+ { actions , state }
321334 end
322335 else
323336 { [ ] , state }
324337 end
325338 end
326339
327340 @ impl true
328- def handle_buffer ( Pad . ref ( :input , _id ) = pad , sample , ctx , state ) do
341+ def handle_buffer ( Pad . ref ( :input , _id ) = pad , sample , ctx , state )
342+ when state . all_input_pads_ready? do
329343 use Numbers , overload_operators: true , comparison: true
330344
331345 # In case DTS is not set, use PTS. This is the case for audio tracks or H264 originated
@@ -335,7 +349,7 @@ defmodule Membrane.MP4.Muxer.CMAF do
335349
336350 { sample , state } =
337351 state
338- |> maybe_init_segment_base_timestamp ( pad , sample )
352+ |> maybe_init_segment_timestamps ( pad , sample )
339353 |> process_buffer_awaiting_duration ( pad , sample )
340354
341355 state = SegmentHelper . update_awaiting_stream_format ( state , pad )
@@ -359,6 +373,11 @@ defmodule Membrane.MP4.Muxer.CMAF do
359373 end
360374 end
361375
376+ @ impl true
377+ def handle_buffer ( pad , sample , _ctx , state ) do
378+ { [ ] , % { state | buffers_awaiting_init: [ { pad , sample } | state . buffers_awaiting_init ] } }
379+ end
380+
362381 @ impl true
363382 def handle_event ( _pad , % __MODULE__ . RequestMediaFinalization { } , _ctx , state ) do
364383 { [ ] , % { state | finish_current_segment?: true } }
@@ -438,9 +457,12 @@ defmodule Membrane.MP4.Muxer.CMAF do
438457 track_data = % {
439458 id: track_id ,
440459 track: nil ,
441- # base timestamp of the current segment, initialized with DTS of the first buffer
460+ # decoding timestamp of the current segment, initialized with DTS of the first buffer
461+ # and then incremented by duration of every produced segment
462+ segment_decoding_timestamp: nil ,
463+ # presentation timestamp of the current segment, initialized with PTS of the first buffer
442464 # and then incremented by duration of every produced segment
443- segment_base_timestamp : nil ,
465+ segment_presentation_timestamp : nil ,
444466 end_timestamp: 0 ,
445467 buffer_awaiting_duration: nil ,
446468 chunks_duration: Membrane.Time . seconds ( 0 )
@@ -587,7 +609,7 @@ defmodule Membrane.MP4.Muxer.CMAF do
587609 sequence_number: state . seq_nums [ output_pad ] ,
588610 timescale: timescale ,
589611 base_timestamp:
590- track_data . segment_base_timestamp
612+ track_data . segment_presentation_timestamp
591613 |> Helper . timescalify ( timescale )
592614 |> Ratio . trunc ( ) ,
593615 unscaled_duration: duration ,
@@ -603,7 +625,12 @@ defmodule Membrane.MP4.Muxer.CMAF do
603625 state =
604626 tracks_data
605627 |> Enum . reduce ( state , fn % { unscaled_duration: duration , pad: pad } , state ->
606- update_in ( state , [ :pad_to_track_data , pad , :segment_base_timestamp ] , & ( & 1 + duration ) )
628+ state
629+ |> update_in ( [ :pad_to_track_data , pad , :segment_decoding_timestamp ] , & ( & 1 + duration ) )
630+ |> update_in (
631+ [ :pad_to_track_data , pad , :segment_presentation_timestamp ] ,
632+ & ( & 1 + duration )
633+ )
607634 end )
608635 |> update_in ( [ :seq_nums , output_pad ] , & ( & 1 + 1 ) )
609636
@@ -712,16 +739,40 @@ defmodule Membrane.MP4.Muxer.CMAF do
712739 end
713740 end
714741
715- defp maybe_init_segment_base_timestamp ( state , pad , sample ) do
742+ defp maybe_init_segment_timestamps ( state , pad , sample ) do
716743 case state do
717- % { pad_to_track_data: % { ^ pad => % { segment_base_timestamp: nil } } } ->
718- put_in ( state , [ :pad_to_track_data , pad , :segment_base_timestamp ] , sample . dts )
744+ % { pad_to_track_data: % { ^ pad => % { segment_decoding_timestamp: nil } } } ->
745+ update_in ( state , [ :pad_to_track_data , pad ] , fn data ->
746+ Map . merge ( data , % {
747+ segment_decoding_timestamp: sample . dts ,
748+ segment_presentation_timestamp: sample . pts
749+ } )
750+ end )
719751
720752 _else ->
721753 state
722754 end
723755 end
724756
757+ defp update_input_pads_ready ( pad , ctx , state ) do
758+ all_input_pads_ready? =
759+ Enum . all? ( ctx . pads , fn
760+ { ^ pad , _data } -> true
761+ { Pad . ref ( :output , _id ) , _data } -> true
762+ { Pad . ref ( :input , _id ) , data } -> data . stream_format != nil
763+ end )
764+
765+ % { state | all_input_pads_ready?: all_input_pads_ready? }
766+ end
767+
768+ defp replay_init_buffers ( ctx , state ) do
769+ { buffers , state } = Map . pop! ( state , :buffers_awaiting_init )
770+
771+ Enum . flat_map_reduce ( buffers , state , fn { pad , buffer } , state ->
772+ handle_buffer ( pad , buffer , ctx , state )
773+ end )
774+ end
775+
725776 @ min_chunk_duration Membrane.Time . milliseconds ( 50 )
726777 defp set_chunk_duration_range (
727778 % {
0 commit comments