diff --git a/gst/isomp4/gstqtmux.c b/gst/isomp4/gstqtmux.c index d98f592a30..e16138a1b7 100644 --- a/gst/isomp4/gstqtmux.c +++ b/gst/isomp4/gstqtmux.c @@ -541,6 +541,12 @@ gst_qt_mux_pad_reset (GstQTPad * qtpad) /* reference owned elsewhere */ qtpad->tfra = NULL; + + qtpad->first_pts = GST_CLOCK_TIME_NONE; + qtpad->tc_pos = -1; + if (qtpad->first_tc) + gst_video_time_code_free (qtpad->first_tc); + qtpad->first_tc = NULL; } /* @@ -622,11 +628,6 @@ gst_qt_mux_reset (GstQTMux * qtmux, gboolean alloc) qtmux->last_moov_update = GST_CLOCK_TIME_NONE; qtmux->muxed_since_last_update = 0; qtmux->reserved_duration_remaining = GST_CLOCK_TIME_NONE; - qtmux->first_pts = GST_CLOCK_TIME_NONE; - qtmux->tc_pos = -1; - if (qtmux->first_tc) - gst_video_time_code_free (qtmux->first_tc); - qtmux->first_tc = NULL; } static void @@ -2595,14 +2596,14 @@ gst_qt_mux_update_edit_lists (GstQTMux * qtmux) } static GstFlowReturn -gst_qt_mux_update_timecode (GstQTMux * qtmux) +gst_qt_mux_update_timecode (GstQTMux * qtmux, GstQTPad * qtpad) { GstSegment segment; GstBuffer *buf; GstMapInfo map; - guint64 offset = qtmux->tc_pos; + guint64 offset = qtpad->tc_pos; - g_assert (qtmux->tc_pos != -1); + g_assert (qtpad->tc_pos != -1); gst_segment_init (&segment, GST_FORMAT_BYTES); segment.start = offset; @@ -2612,11 +2613,11 @@ gst_qt_mux_update_timecode (GstQTMux * qtmux) gst_buffer_map (buf, &map, GST_MAP_WRITE); GST_WRITE_UINT32_BE (map.data, - gst_video_time_code_frames_since_daily_jam (qtmux->first_tc)); + gst_video_time_code_frames_since_daily_jam (qtpad->first_tc)); gst_buffer_unmap (buf, &map); /* Reset this value, so the timecode won't be re-rewritten */ - qtmux->tc_pos = -1; + qtpad->tc_pos = -1; return gst_qt_mux_send_buffer (qtmux, buf, &offset, FALSE); } @@ -2627,6 +2628,7 @@ gst_qt_mux_stop_file (GstQTMux * qtmux) gboolean ret = GST_FLOW_OK; guint64 offset = 0, size = 0; gboolean large_file; + GSList *walk; GST_DEBUG_OBJECT (qtmux, "Updating remaining values and sending last data"); @@ -2641,12 +2643,16 @@ gst_qt_mux_stop_file (GstQTMux * qtmux) } gst_qt_mux_update_global_statistics (qtmux); - if (qtmux->tc_pos != -1) { - /* File is being stopped and timecode hasn't been updated. Update it now - * with whatever we have */ - ret = gst_qt_mux_update_timecode (qtmux); - if (ret != GST_FLOW_OK) - return ret; + for (walk = qtmux->collect->data; walk; walk = walk->next) { + GstQTPad *qtpad = (GstQTPad *) walk->data; + + if (qtpad->tc_pos != -1) { + /* File is being stopped and timecode hasn't been updated. Update it now + * with whatever we have */ + ret = gst_qt_mux_update_timecode (qtmux, qtpad); + if (ret != GST_FLOW_OK) + return ret; + } } switch (qtmux->mux_mode) { @@ -3104,7 +3110,7 @@ static GstFlowReturn gst_qt_mux_check_and_update_timecode (GstQTMux * qtmux, GstQTPad * pad, GstBuffer * buf, GstFlowReturn ret) { - if (buf != NULL && (pad->tc_trak == NULL || qtmux->tc_pos != -1)) { + if (buf != NULL && (pad->tc_trak == NULL || pad->tc_pos != -1)) { GstVideoTimeCodeMeta *tc_meta = gst_buffer_get_video_time_code_meta (buf); if (tc_meta) { GstVideoTimeCode *tc = &tc_meta->tc; @@ -3113,7 +3119,7 @@ gst_qt_mux_check_and_update_timecode (GstQTMux * qtmux, GstQTPad * pad, guint32 frames_since_daily_jam; /* This means we never got a timecode before */ - if (qtmux->first_tc == NULL) { + if (pad->first_tc == NULL) { #ifndef GST_DISABLE_GST_DEBUG gchar *tc_str = gst_video_time_code_to_string (tc); GST_DEBUG_OBJECT (qtmux, "Found first timecode %s", tc_str); @@ -3121,18 +3127,18 @@ gst_qt_mux_check_and_update_timecode (GstQTMux * qtmux, GstQTPad * pad, #endif g_assert (pad->tc_trak == NULL); tc_buf = gst_buffer_new_allocate (NULL, 4, NULL); - qtmux->first_tc = gst_video_time_code_copy (tc); + pad->first_tc = gst_video_time_code_copy (tc); /* If frames are out of order, the frame we're currently getting might * not be the first one. Just write a 0 timecode for now and wait * until we receive a timecode that's lower than the current one */ if (pad->is_out_of_order) { - qtmux->first_pts = GST_BUFFER_PTS (buf); + pad->first_pts = GST_BUFFER_PTS (buf); frames_since_daily_jam = 0; /* Position to rewrite */ - qtmux->tc_pos = qtmux->mdat_size; + pad->tc_pos = qtmux->mdat_size; } else { frames_since_daily_jam = - gst_video_time_code_frames_since_daily_jam (qtmux->first_tc); + gst_video_time_code_frames_since_daily_jam (pad->first_tc); frames_since_daily_jam = GUINT32_TO_BE (frames_since_daily_jam); } /* Write the timecode trak now */ @@ -3143,7 +3149,7 @@ gst_qt_mux_check_and_update_timecode (GstQTMux * qtmux, GstQTPad * pad, atom_tref_add_entry (pad->trak->tref, pad->tc_trak->tkhd.track_ID); atom_trak_set_timecode_type (pad->tc_trak, qtmux->context, - qtmux->first_tc); + pad->first_tc); szret = gst_buffer_fill (tc_buf, 0, &frames_since_daily_jam, 4); g_assert (szret == 4); @@ -3154,10 +3160,10 @@ gst_qt_mux_check_and_update_timecode (GstQTMux * qtmux, GstQTPad * pad, } else if (pad->is_out_of_order) { /* Check for a lower timecode than the one stored */ g_assert (pad->tc_trak != NULL); - if (GST_BUFFER_DTS (buf) <= qtmux->first_pts) { - if (gst_video_time_code_compare (tc, qtmux->first_tc) == -1) { - gst_video_time_code_free (qtmux->first_tc); - qtmux->first_tc = gst_video_time_code_copy (tc); + if (GST_BUFFER_DTS (buf) <= pad->first_pts) { + if (gst_video_time_code_compare (tc, pad->first_tc) == -1) { + gst_video_time_code_free (pad->first_tc); + pad->first_tc = gst_video_time_code_copy (tc); } } else { guint64 bk_size = qtmux->mdat_size; @@ -3165,7 +3171,7 @@ gst_qt_mux_check_and_update_timecode (GstQTMux * qtmux, GstQTPad * pad, /* If this frame's DTS is after the first PTS received, it means * we've already received the first frame to be presented. Otherwise * the decoder would need to go back in time */ - gst_qt_mux_update_timecode (qtmux); + gst_qt_mux_update_timecode (qtmux, pad); /* Reset writing position */ gst_segment_init (&segment, GST_FORMAT_BYTES); @@ -5031,8 +5037,6 @@ gst_qt_mux_change_state (GstElement * element, GstStateChange transition) case GST_STATE_CHANGE_READY_TO_PAUSED: gst_collect_pads_start (qtmux->collect); qtmux->state = GST_QT_MUX_STATE_STARTED; - qtmux->first_tc = NULL; - qtmux->tc_pos = -1; break; case GST_STATE_CHANGE_PAUSED_TO_PLAYING: break; diff --git a/gst/isomp4/gstqtmux.h b/gst/isomp4/gstqtmux.h index bc707bae7b..e18b5a112d 100644 --- a/gst/isomp4/gstqtmux.h +++ b/gst/isomp4/gstqtmux.h @@ -144,6 +144,11 @@ struct _GstQTPad GstQTPadPrepareBufferFunc prepare_buf_func; GstQTPadSetCapsFunc set_caps; GstQTPadCreateEmptyBufferFunc create_empty_buffer; + + /* SMPTE timecode */ + GstVideoTimeCode *first_tc; + GstClockTime first_pts; + guint64 tc_pos; }; typedef enum _GstQTMuxState @@ -212,11 +217,6 @@ struct _GstQTMux /* Set when tags are received, cleared when written to moov */ gboolean tags_changed; - /* SMPTE timecode */ - GstVideoTimeCode *first_tc; - GstClockTime first_pts; - guint64 tc_pos; - /* fragmented file index */ AtomMFRA *mfra;