bool cluster_helper_c::must_duration_be_set(render_groups_c *rg, packet_cptr &new_packet) { size_t i; int64_t block_duration = 0; int64_t def_duration = rg->m_source->get_track_default_duration(); for (i = 0; rg->m_durations.size() > i; ++i) block_duration += rg->m_durations[i]; block_duration += new_packet->get_duration(); if (rg->m_duration_mandatory || new_packet->duration_mandatory) { if ( (0 == block_duration) || ( (0 < block_duration) && (block_duration != ((static_cast<int64_t>(rg->m_durations.size()) + 1) * def_duration)))) return true; } else if ( ( g_use_durations || (0 < def_duration)) && (0 < block_duration) && (RND_TIMECODE_SCALE(block_duration) != RND_TIMECODE_SCALE((rg->m_durations.size() + 1) * def_duration))) return true; return false; }
void cluster_helper_c::set_duration(render_groups_c *rg) { if (rg->m_durations.empty()) return; kax_block_blob_c *group = rg->m_groups.back().get(); int64_t def_duration = rg->m_source->get_track_default_duration(); int64_t block_duration = 0; size_t i; for (i = 0; rg->m_durations.size() > i; ++i) block_duration += rg->m_durations[i]; mxdebug_if(m->debug_duration, boost::format("cluster_helper::set_duration: block_duration %1% rounded duration %2% def_duration %3% use_durations %4% rg->m_duration_mandatory %5%\n") % block_duration % RND_TIMECODE_SCALE(block_duration) % def_duration % (g_use_durations ? 1 : 0) % (rg->m_duration_mandatory ? 1 : 0)); if (rg->m_duration_mandatory) { if ( (0 == block_duration) || ( (0 < block_duration) && (block_duration != (static_cast<int64_t>(rg->m_durations.size()) * def_duration)))) group->set_block_duration(RND_TIMECODE_SCALE(block_duration)); } else if ( ( g_use_durations || (0 < def_duration)) && (0 < block_duration) && (RND_TIMECODE_SCALE(block_duration) != RND_TIMECODE_SCALE(rg->m_durations.size() * def_duration))) group->set_block_duration(RND_TIMECODE_SCALE(block_duration)); }
void packet_t::normalize_timecodes() { // Normalize the timecodes according to the timecode scale. unmodified_assigned_timecode = assigned_timecode; unmodified_duration = duration; timecode = RND_TIMECODE_SCALE(timecode); assigned_timecode = RND_TIMECODE_SCALE(assigned_timecode); if (has_duration()) duration = RND_TIMECODE_SCALE(duration); if (has_bref()) bref = RND_TIMECODE_SCALE(bref); if (has_fref()) fref = RND_TIMECODE_SCALE(fref); }
void cues_c::write(mm_io_c &out, KaxSeekHead &seek_head) { if (!m_points.size() || !g_cue_writing_requested) return; // auto start = get_current_time_millis(); sort(); // auto end_sort = get_current_time_millis(); // Need to write the (empty) cues element so that its position will // be set for indexing in g_kax_sh_main. Necessary because there's // no API function to force the position to a certain value; nor is // there a different API function in KaxSeekHead for adding anything // by ID and position manually. out.save_pos(); kax_cues_position_dummy_c cues_dummy; cues_dummy.Render(out); out.restore_pos(); // Write meta seek information if it is not disabled. seek_head.IndexThis(cues_dummy, *g_kax_segment); // Forcefully write the correct head and copy its content from the // temporary storage location. auto total_size = calculate_total_size(); write_ebml_element_head(out, EBML_ID(KaxCues), total_size); for (auto &point : m_points) { KaxCuePoint kc_point; GetChild<KaxCueTime>(kc_point).SetValue(point.timecode / g_timecode_scale); auto &positions = GetChild<KaxCueTrackPositions>(kc_point); GetChild<KaxCueTrack>(positions).SetValue(point.track_num); GetChild<KaxCueClusterPosition>(positions).SetValue(point.cluster_position); auto codec_state_position = m_codec_state_position_map.find({ point.track_num, point.timecode }); if (codec_state_position != m_codec_state_position_map.end()) GetChild<KaxCueCodecState>(positions).SetValue(codec_state_position->second); if (point.relative_position) GetChild<KaxCueRelativePosition>(positions).SetValue(point.relative_position); if (point.duration) GetChild<KaxCueDuration>(positions).SetValue(RND_TIMECODE_SCALE(point.duration) / g_timecode_scale); kc_point.Render(out); } m_points.clear(); m_codec_state_position_map.clear(); m_num_cue_points_postprocessed = 0; // auto end_all = get_current_time_millis(); // mxinfo(boost::format("dur sort %1% write %2% total %3%\n") % (end_sort - start) % (end_all - end_sort) % (end_all - start)); }
uint64_t cues_c::calculate_point_size(cue_point_t const &point) const { uint64_t point_size = EBML_ID_LENGTH(EBML_ID(KaxCuePoint)) + 1 + EBML_ID_LENGTH(EBML_ID(KaxCuePoint)) + 1 + calculate_bytes_for_uint(point.timecode / g_timecode_scale) + EBML_ID_LENGTH(EBML_ID(KaxCueTrackPositions)) + 1 + EBML_ID_LENGTH(EBML_ID(KaxCueTrack)) + 1 + calculate_bytes_for_uint(point.track_num) + EBML_ID_LENGTH(EBML_ID(KaxCueClusterPosition)) + 1 + calculate_bytes_for_uint(point.cluster_position); auto codec_state_position = m_codec_state_position_map.find({ point.track_num, point.timecode }); if (codec_state_position != m_codec_state_position_map.end()) point_size += EBML_ID_LENGTH(EBML_ID(KaxCueCodecState)) + 1 + calculate_bytes_for_uint(codec_state_position->second); if (point.relative_position) point_size += EBML_ID_LENGTH(EBML_ID(KaxCueRelativePosition)) + 1 + calculate_bytes_for_uint(point.relative_position); if (point.duration) point_size += EBML_ID_LENGTH(EBML_ID(KaxCueDuration)) + 1 + calculate_bytes_for_uint(RND_TIMECODE_SCALE(point.duration) / g_timecode_scale); return point_size; }