diff --git a/modules/mux/mp4/mp4.c b/modules/mux/mp4/mp4.c index eb1c659baf92ac96d5f7dd28b78726b5ee8b0fff..6dc41da6963f69509fbd5bdde29878e4c133f565 100644 --- a/modules/mux/mp4/mp4.c +++ b/modules/mux/mp4/mp4.c @@ -583,111 +583,105 @@ static inline mtime_t dts_fb_pts( const block_t *p_data ) return p_data->i_dts > VLC_TS_INVALID ? p_data->i_dts: p_data->i_pts; } -static int Mux(sout_mux_t *p_mux) +static int MuxStream(sout_mux_t *p_mux, sout_input_t *p_input, mp4_stream_t *p_stream) { sout_mux_sys_t *p_sys = p_mux->p_sys; - for (;;) { - int i_stream = sout_MuxGetStream(p_mux, 2, NULL); - if (i_stream < 0) - return(VLC_SUCCESS); - - sout_input_t *p_input = p_mux->pp_inputs[i_stream]; - mp4_stream_t *p_stream = (mp4_stream_t*)p_input->p_sys; - - block_t *p_data = BlockDequeue(p_input, p_stream); - if(!p_data) - return VLC_SUCCESS; + block_t *p_data = BlockDequeue(p_input, p_stream); + if(!p_data) + return VLC_SUCCESS; - /* Reset reference dts in case of discontinuity (ex: gather sout) */ - if (p_data->i_flags & BLOCK_FLAG_DISCONTINUITY && p_stream->mux.i_entry_count) + /* Reset reference dts in case of discontinuity (ex: gather sout) */ + if (p_data->i_flags & BLOCK_FLAG_DISCONTINUITY && p_stream->mux.i_entry_count) + { + if(p_stream->i_first_dts != VLC_TS_INVALID) { - if(p_stream->i_first_dts != VLC_TS_INVALID) + if(!CreateCurrentEdit(p_stream, p_sys->i_start_dts, p_sys->b_fragmented)) { - if(!CreateCurrentEdit(p_stream, p_sys->i_start_dts, p_sys->b_fragmented)) - { - block_Release( p_data ); - return VLC_ENOMEM; - } + block_Release( p_data ); + return VLC_ENOMEM; } - - p_stream->i_length_neg = 0; - p_stream->i_first_dts = VLC_TS_INVALID; - p_stream->i_last_dts = VLC_TS_INVALID; - p_stream->i_last_pts = VLC_TS_INVALID; } - /* XXX: -1 to always have 2 entry for easy adding of empty SPU */ - if (p_stream->mux.i_entry_count >= p_stream->mux.i_entry_max - 2) { - p_stream->mux.i_entry_max += 1000; - p_stream->mux.entry = xrealloc(p_stream->mux.entry, - p_stream->mux.i_entry_max * sizeof(mp4mux_entry_t)); - } + p_stream->i_length_neg = 0; + p_stream->i_first_dts = VLC_TS_INVALID; + p_stream->i_last_dts = VLC_TS_INVALID; + p_stream->i_last_pts = VLC_TS_INVALID; + } - /* Set current segment ranges */ - if( p_stream->i_first_dts == VLC_TS_INVALID ) - { - p_stream->i_first_dts = dts_fb_pts( p_data ); - if( p_sys->i_start_dts == VLC_TS_INVALID ) - p_sys->i_start_dts = p_stream->i_first_dts; - } + /* XXX: -1 to always have 2 entry for easy adding of empty SPU */ + if (p_stream->mux.i_entry_count >= p_stream->mux.i_entry_max - 2) { + p_stream->mux.i_entry_max += 1000; + p_stream->mux.entry = xrealloc(p_stream->mux.entry, + p_stream->mux.i_entry_max * sizeof(mp4mux_entry_t)); + } - if (p_stream->mux.fmt.i_cat != SPU_ES) { - /* Fix length of the sample */ - if (block_FifoCount(p_input->p_fifo) > 0) { - block_t *p_next = block_FifoShow(p_input->p_fifo); - if ( p_next->i_flags & BLOCK_FLAG_DISCONTINUITY ) - { /* we have no way to know real length except by decoding */ - if ( p_stream->mux.fmt.i_cat == VIDEO_ES ) - { - p_data->i_length = CLOCK_FREQ * - p_stream->mux.fmt.video.i_frame_rate_base / - p_stream->mux.fmt.video.i_frame_rate; - if( p_data->i_flags & BLOCK_FLAG_SINGLE_FIELD ) - p_data->i_length >>= 1; - msg_Dbg( p_mux, "video track %u fixup to %"PRId64" for sample %u", - p_stream->mux.i_track_id, p_data->i_length, p_stream->mux.i_entry_count ); - } - else if ( p_stream->mux.fmt.i_cat == AUDIO_ES && - p_stream->mux.fmt.audio.i_rate && - p_data->i_nb_samples ) - { - p_data->i_length = CLOCK_FREQ * p_data->i_nb_samples / - p_stream->mux.fmt.audio.i_rate; - msg_Dbg( p_mux, "audio track %u fixup to %"PRId64" for sample %u", - p_stream->mux.i_track_id, p_data->i_length, p_stream->mux.i_entry_count ); - } - else if ( p_data->i_length <= 0 ) - { - msg_Warn( p_mux, "unknown length for track %u sample %u", - p_stream->mux.i_track_id, p_stream->mux.i_entry_count ); - p_data->i_length = 1; - } + /* Set current segment ranges */ + if( p_stream->i_first_dts == VLC_TS_INVALID ) + { + p_stream->i_first_dts = dts_fb_pts( p_data ); + if( p_sys->i_start_dts == VLC_TS_INVALID ) + p_sys->i_start_dts = p_stream->i_first_dts; + } + + if (p_stream->mux.fmt.i_cat != SPU_ES) + { + /* Fix length of the sample */ + if (block_FifoCount(p_input->p_fifo) > 0) + { + block_t *p_next = block_FifoShow(p_input->p_fifo); + if ( p_next->i_flags & BLOCK_FLAG_DISCONTINUITY ) + { /* we have no way to know real length except by decoding */ + if ( p_stream->mux.fmt.i_cat == VIDEO_ES ) + { + p_data->i_length = CLOCK_FREQ * + p_stream->mux.fmt.video.i_frame_rate_base / + p_stream->mux.fmt.video.i_frame_rate; + if( p_data->i_flags & BLOCK_FLAG_SINGLE_FIELD ) + p_data->i_length >>= 1; + msg_Dbg( p_mux, "video track %u fixup to %"PRId64" for sample %u", + p_stream->mux.i_track_id, p_data->i_length, p_stream->mux.i_entry_count ); } - else + else if ( p_stream->mux.fmt.i_cat == AUDIO_ES && + p_stream->mux.fmt.audio.i_rate && + p_data->i_nb_samples ) { - int64_t i_diff = dts_fb_pts( p_next ) - dts_fb_pts( p_data ); - if (i_diff < CLOCK_FREQ) /* protection */ - p_data->i_length = i_diff; + p_data->i_length = CLOCK_FREQ * p_data->i_nb_samples / + p_stream->mux.fmt.audio.i_rate; + msg_Dbg( p_mux, "audio track %u fixup to %"PRId64" for sample %u", + p_stream->mux.i_track_id, p_data->i_length, p_stream->mux.i_entry_count ); + } + else if ( p_data->i_length <= 0 ) + { + msg_Warn( p_mux, "unknown length for track %u sample %u", + p_stream->mux.i_track_id, p_stream->mux.i_entry_count ); + p_data->i_length = 1; } } - if (p_data->i_length <= 0) { - msg_Warn(p_mux, "i_length <= 0"); - p_stream->i_length_neg += p_data->i_length - 1; - p_data->i_length = 1; - } else if (p_stream->i_length_neg < 0) { - int64_t i_recover = __MIN(p_data->i_length / 4, - p_stream->i_length_neg); - - p_data->i_length -= i_recover; - p_stream->i_length_neg += i_recover; + else + { + int64_t i_diff = dts_fb_pts( p_next ) - dts_fb_pts( p_data ); + if (i_diff < CLOCK_FREQ) /* protection */ + p_data->i_length = i_diff; } } - - if (p_stream->mux.fmt.i_cat == SPU_ES && - p_stream->mux.i_entry_count > 0 && + if (p_data->i_length <= 0) { + msg_Warn(p_mux, "i_length <= 0"); + p_stream->i_length_neg += p_data->i_length - 1; + p_data->i_length = 1; + } else if (p_stream->i_length_neg < 0) { + int64_t i_recover = __MIN(p_data->i_length / 4, - p_stream->i_length_neg); + + p_data->i_length -= i_recover; + p_stream->i_length_neg += i_recover; + } + } + else /* SPU_ES */ + { + if (p_stream->mux.i_entry_count > 0 && p_stream->mux.entry[p_stream->mux.i_entry_count-1].i_length == 0) { - /* length of previous spu, stored in spu clearer */ + /* length of previous spu, stored in spu clearer */ int64_t i_length = dts_fb_pts( p_data ) - p_stream->i_last_dts; if(i_length < 0) i_length = 0; @@ -695,77 +689,96 @@ static int Mux(sout_mux_t *p_mux) p_stream->mux.entry[p_stream->mux.i_entry_count-1].i_length = i_length; p_stream->mux.i_read_duration += i_length; } + } - /* Update (Not earlier for SPU!) */ - p_stream->i_last_dts = dts_fb_pts( p_data ); - if( p_data->i_pts > p_stream->i_last_pts ) - p_stream->i_last_pts = p_data->i_pts; + /* Update (Not earlier for SPU!) */ + p_stream->i_last_dts = dts_fb_pts( p_data ); + if( p_data->i_pts > p_stream->i_last_pts ) + p_stream->i_last_pts = p_data->i_pts; - /* add index entry */ - mp4mux_entry_t *e = &p_stream->mux.entry[p_stream->mux.i_entry_count++]; - e->i_pos = p_sys->i_pos; - e->i_size = p_data->i_buffer; + /* add index entry */ + mp4mux_entry_t *e = &p_stream->mux.entry[p_stream->mux.i_entry_count++]; + e->i_pos = p_sys->i_pos; + e->i_size = p_data->i_buffer; - if ( p_data->i_dts > VLC_TS_INVALID && p_data->i_pts > p_data->i_dts ) - { - e->i_pts_dts = p_data->i_pts - p_data->i_dts; - if ( !p_stream->mux.b_hasbframes ) - p_stream->mux.b_hasbframes = true; - } - else e->i_pts_dts = 0; + if ( p_data->i_dts > VLC_TS_INVALID && p_data->i_pts > p_data->i_dts ) + { + e->i_pts_dts = p_data->i_pts - p_data->i_dts; + if ( !p_stream->mux.b_hasbframes ) + p_stream->mux.b_hasbframes = true; + } + else e->i_pts_dts = 0; - e->i_length = p_data->i_length; - e->i_flags = p_data->i_flags; + e->i_length = p_data->i_length; + e->i_flags = p_data->i_flags; - /* update */ - p_stream->mux.i_read_duration += __MAX( 0, p_data->i_length ); - p_stream->i_last_dts = dts_fb_pts( p_data ); + /* update */ + p_stream->mux.i_read_duration += __MAX( 0, p_data->i_length ); + p_stream->i_last_dts = dts_fb_pts( p_data ); - /* write data */ - p_sys->i_pos += p_data->i_buffer; - sout_AccessOutWrite(p_mux->p_access, p_data); + /* write data */ + p_sys->i_pos += p_data->i_buffer; + sout_AccessOutWrite(p_mux->p_access, p_data); - /* Add SPU clearing tag (duration tb fixed on next SPU or stream end )*/ - if (p_stream->mux.fmt.i_cat == SPU_ES) + /* Add SPU clearing tag (duration tb fixed on next SPU or stream end )*/ + if (p_stream->mux.fmt.i_cat == SPU_ES ) + { + block_t *p_empty = NULL; + if(p_stream->mux.fmt.i_codec == VLC_CODEC_SUBT) { - block_t *p_empty = NULL; - if(p_stream->mux.fmt.i_codec == VLC_CODEC_SUBT) - { - p_empty = block_Alloc(3); - if (p_empty) - { - /* point to start of our empty */ - p_stream->i_last_dts += e->i_length; - - /* Write a " " */ - p_empty->p_buffer[0] = 0; - p_empty->p_buffer[1] = 1; - p_empty->p_buffer[2] = ' '; - } - } - + p_empty = block_Alloc(3); if(p_empty) { - /* Append a idx entry */ - /* XXX: No need to grow the entry here */ - mp4mux_entry_t *e_empty = &p_stream->mux.entry[p_stream->mux.i_entry_count++]; - e_empty->i_pos = p_sys->i_pos; - e_empty->i_size = p_empty->i_buffer; - e_empty->i_pts_dts= 0; - e_empty->i_length = 0; /* will add dts diff later*/ - e_empty->i_flags = 0; - - p_sys->i_pos += p_empty->i_buffer; - sout_AccessOutWrite(p_mux->p_access, p_empty); + /* point to start of our empty */ + p_stream->i_last_dts += e->i_length; + + /* Write a " " */ + p_empty->p_buffer[0] = 0; + p_empty->p_buffer[1] = 1; + p_empty->p_buffer[2] = ' '; } } - /* Update the global segment/media duration */ - if( p_stream->mux.i_read_duration > p_sys->i_read_duration ) - p_sys->i_read_duration = p_stream->mux.i_read_duration; + if(p_empty) + { + /* Append a idx entry */ + /* XXX: No need to grow the entry here */ + mp4mux_entry_t *e_empty = &p_stream->mux.entry[p_stream->mux.i_entry_count++]; + e_empty->i_pos = p_sys->i_pos; + e_empty->i_size = p_empty->i_buffer; + e_empty->i_pts_dts= 0; + e_empty->i_length = 0; /* will add dts diff later*/ + e_empty->i_flags = 0; + + p_sys->i_pos += p_empty->i_buffer; + sout_AccessOutWrite(p_mux->p_access, p_empty); + } } - return(VLC_SUCCESS); + /* Update the global segment/media duration */ + if( p_stream->mux.i_read_duration > p_sys->i_read_duration ) + p_sys->i_read_duration = p_stream->mux.i_read_duration; + + return VLC_SUCCESS; +} + +static int Mux(sout_mux_t *p_mux) +{ + int i_ret = VLC_SUCCESS; + + do + { + int i_stream = sout_MuxGetStream(p_mux, 2, NULL); + if (i_stream < 0) + break; + + sout_input_t *p_input = p_mux->pp_inputs[i_stream]; + mp4_stream_t *p_stream = (mp4_stream_t*)p_input->p_sys; + + i_ret = MuxStream(p_mux, p_input, p_stream); + } while( i_ret == VLC_SUCCESS ); + + return i_ret; } /*****************************************************************************