bool cluster_helper_c::add_to_cues_maybe(packet_cptr &pack) { auto &source = *pack->source; auto strategy = source.get_cue_creation(); // Update the cues (index table) either if cue entries for I frames were requested and this is an I frame... bool add = (CUE_STRATEGY_IFRAMES == strategy) && pack->is_key_frame(); // ... or if a codec state change is present ... add = add || !!pack->codec_state; // ... or if the user requested entries for all frames ... add = add || (CUE_STRATEGY_ALL == strategy); // ... or if this is an audio track, there is no video track and the // last cue entry was created more than 2s ago. add = add || ( (CUE_STRATEGY_SPARSE == strategy) && (track_audio == source.get_track_type()) && !g_video_packetizer && ( (0 > source.get_last_cue_timecode()) || ((pack->assigned_timecode - source.get_last_cue_timecode()) >= 2000000000))); if (!add) return false; source.set_last_cue_timecode(pack->assigned_timecode); ++m->num_cue_elements; g_cue_writing_requested = 1; return true; }
void cluster_helper_c::split_if_necessary(packet_cptr &packet) { if ( !splitting() || (m->split_points.end() == m->current_split_point) || (g_file_num > g_split_max_num_files) || !packet->is_key_frame() || ( (packet->source->get_track_type() != track_video) && g_video_packetizer)) return; bool split_now = false; // Maybe we want to start a new file now. if (split_point_c::size == m->current_split_point->m_type) { int64_t additional_size = 0; if (!m->packets.empty()) // Cluster + Cluster timecode: roughly 21 bytes. Add all frame sizes & their overheaders, too. additional_size = 21 + boost::accumulate(m->packets, 0, [](size_t size, const packet_cptr &p) { return size + p->data->get_size() + (p->is_key_frame() ? 10 : p->is_p_frame() ? 13 : 16); }); additional_size += 18 * m->num_cue_elements; mxdebug_if(m->debug_splitting, boost::format("cluster_helper split decision: header_overhead: %1%, additional_size: %2%, bytes_in_file: %3%, sum: %4%\n") % m->header_overhead % additional_size % m->bytes_in_file % (m->header_overhead + additional_size + m->bytes_in_file)); if ((m->header_overhead + additional_size + m->bytes_in_file) >= m->current_split_point->m_point) split_now = true; } else if ( (split_point_c::duration == m->current_split_point->m_type) && (0 <= m->first_timecode_in_file) && (packet->assigned_timecode - m->first_timecode_in_file) >= m->current_split_point->m_point) split_now = true; else if ( ( (split_point_c::timecode == m->current_split_point->m_type) || (split_point_c::parts == m->current_split_point->m_type)) && (packet->assigned_timecode >= m->current_split_point->m_point)) split_now = true; else if ( ( (split_point_c::frame_field == m->current_split_point->m_type) || (split_point_c::parts_frame_field == m->current_split_point->m_type)) && (m->frame_field_number >= m->current_split_point->m_point)) split_now = true; if (!split_now) return; split(packet); }
void cluster_helper_c::render_before_adding_if_necessary(packet_cptr &packet) { int64_t timecode = get_timecode(); int64_t timecode_delay = ( (packet->assigned_timecode > m->max_timecode_in_cluster) || (-1 == m->max_timecode_in_cluster)) ? packet->assigned_timecode : m->max_timecode_in_cluster; timecode_delay -= ( (-1 == m->min_timecode_in_cluster) || (packet->assigned_timecode < m->min_timecode_in_cluster)) ? packet->assigned_timecode : m->min_timecode_in_cluster; timecode_delay = (int64_t)(timecode_delay / g_timecode_scale); mxdebug_if(m->debug_packets, boost::format("cluster_helper_c::add_packet(): new packet { source %1%/%2% " "timecode: %3% duration: %4% bref: %5% fref: %6% assigned_timecode: %7% timecode_delay: %8% }\n") % packet->source->m_ti.m_id % packet->source->m_ti.m_fname % packet->timecode % packet->duration % packet->bref % packet->fref % packet->assigned_timecode % format_timecode(timecode_delay)); bool is_video_keyframe = (packet->source == g_video_packetizer) && packet->is_key_frame(); bool do_render = (std::numeric_limits<int16_t>::max() < timecode_delay) || (std::numeric_limits<int16_t>::min() > timecode_delay) || ( (std::max<int64_t>(0, m->min_timecode_in_cluster) > m->previous_cluster_tc) && (packet->assigned_timecode > m->min_timecode_in_cluster) && (!g_video_packetizer || !is_video_keyframe || m->first_video_keyframe_seen) && ( (packet->gap_following && !m->packets.empty()) || ((packet->assigned_timecode - timecode) > g_max_ns_per_cluster) || is_video_keyframe)); if (is_video_keyframe) m->first_video_keyframe_seen = true; mxdebug_if(m->debug_rendering, boost::format("render check cur_tc %9% min_tc_ic %1% prev_cl_tc %2% test %3% is_vid_and_key %4% tc_delay %5% gap_following_and_not_empty %6% cur_tc>min_tc_ic %8% first_video_key_seen %10% do_render %7%\n") % m->min_timecode_in_cluster % m->previous_cluster_tc % (std::max<int64_t>(0, m->min_timecode_in_cluster) > m->previous_cluster_tc) % is_video_keyframe % timecode_delay % (packet->gap_following && !m->packets.empty()) % do_render % (packet->assigned_timecode > m->min_timecode_in_cluster) % packet->assigned_timecode % m->first_video_keyframe_seen); if (!do_render) return; render(); prepare_new_cluster(); }