예제 #1
0
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;
}
예제 #2
0
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);
}
예제 #3
0
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();
}