Example #1
0
void
mpeg_ts_track_c::handle_timecode_wrap(timecode_c &pts,
                                      timecode_c &dts) {
  static auto const s_wrap_add    = timecode_c::mpeg(1ll << 33);
  static auto const s_wrap_limit  = timecode_c::mpeg(1ll << 30);
  static auto const s_reset_limit = timecode_c::h(1);

  if (!m_timecodes_wrapped) {
    m_timecodes_wrapped = detect_timecode_wrap(pts) || detect_timecode_wrap(dts);
    if (m_timecodes_wrapped) {
      m_timecode_wrap_add += s_wrap_add;
      mxdebug_if(m_debug_timecode_wrapping,
                 boost::format("Timecode wrapping detected for PID %1% pts %2% dts %3% previous_valid %4% global_offset %5% new wrap_add %6%\n")
                 % pid % pts % dts % m_previous_valid_timecode % reader.m_global_timecode_offset % m_timecode_wrap_add);

    }

  } else if (pts.valid() && (pts < s_wrap_limit) && (pts > s_reset_limit)) {
    m_timecodes_wrapped = false;
    mxdebug_if(m_debug_timecode_wrapping,
               boost::format("Timecode wrapping reset for PID %1% pts %2% dts %3% previous_valid %4% global_offset %5% current wrap_add %6%\n")
               % pid % pts % dts % m_previous_valid_timecode % reader.m_global_timecode_offset % m_timecode_wrap_add);
  }

  if (pts.valid() && (pts < s_wrap_limit))
    pts += m_timecode_wrap_add;

  if (dts.valid() && (dts < s_wrap_limit))
    dts += m_timecode_wrap_add;
}
Example #2
0
void
cluster_helper_c::handle_discarded_duration(bool create_new_file,
                                            bool previously_discarding) {
  m->previous_discarded_duration = m->discarded_duration;

  if (create_new_file) { // || (!previously_discarding && m->discarding)) {
    mxdebug_if(m->debug_splitting,
               boost::format("RESETTING discarded duration of %1%, create_new_file %2% previously_discarding %3% m->discarding %4%\n")
               % format_timecode(m->discarded_duration) % create_new_file % previously_discarding % m->discarding);
    m->discarded_duration = 0;

  } else if (previously_discarding && !m->discarding) {
    auto diff              = m->last_discarded_timecode_and_duration - std::max<int64_t>(m->first_discarded_timecode, 0);
    m->discarded_duration += diff;

    mxdebug_if(m->debug_splitting,
               boost::format("ADDING to discarded duration TC at %1% / %2% diff %3% new total %4% create_new_file %5% previously_discarding %6% m->discarding %7%\n")
               % format_timecode(m->first_discarded_timecode) % format_timecode(m->last_discarded_timecode_and_duration) % format_timecode(diff) % format_timecode(m->discarded_duration)
               % create_new_file % previously_discarding % m->discarding);
  } else
    mxdebug_if(m->debug_splitting,
               boost::format("KEEPING discarded duration at %1%, create_new_file %2% previously_discarding %3% m->discarding %4%\n")
               % format_timecode(m->discarded_duration) % create_new_file % previously_discarding % m->discarding);

  m->first_discarded_timecode             = -1;
  m->last_discarded_timecode_and_duration =  0;
}
Example #3
0
static mtx::xml::document_cptr
retrieve_and_parse_xml(std::string const &url) {
  bool debug = debugging_requested("version_check|releases_info|curl");

  std::string data;
  auto result = url_retriever_c().set_timeout(10, 20).retrieve(url, data);

  if (0 != result) {
    mxdebug_if(debug, boost::format("CURL error for %2%: %1%\n") % static_cast<unsigned int>(result) % url);
    return mtx::xml::document_cptr();
  }

  try {
    data = compressor_c::create_from_file_name(url)->decompress(data);

    mtx::xml::document_cptr doc(new pugi::xml_document);
    std::stringstream sdata(data);
    auto xml_result = doc->load(sdata);

    if (xml_result) {
      mxdebug_if(debug, boost::format("Doc loaded fine from %1%\n") % url);
      return doc;

    } else
      mxdebug_if(debug, boost::format("Doc load error for %1%: %1% at %2%\n") % url % xml_result.description() % xml_result.offset);

  } catch (mtx::compression_x &ex) {
    mxdebug_if(debug, boost::format("Decompression exception for %2%: %1%\n") % ex.what() % url);
  }

  return mtx::xml::document_cptr();
}
void
timestamp_calculator_c::add_timecode(timestamp_c const &timecode) {
  if (!timecode.valid())
    return;

  if (   (!m_last_timecode_returned.valid() || (timecode > m_last_timecode_returned))
      && (m_available_timecodes.empty()     || (timecode > m_available_timecodes.back()))) {
    mxdebug_if(m_debug, boost::format("timestamp_calculator::add_timecode: adding %1%\n") % format_timestamp(timecode));
    m_available_timecodes.push_back(timecode);

  } else
    mxdebug_if(m_debug, boost::format("timestamp_calculator::add_timecode: dropping %1%\n") % format_timestamp(timecode));
}
Example #5
0
void
xtr_oggopus_c::handle_frame(xtr_frame_t &f) {
  try {
    auto toc = mtx::opus::toc_t::decode(f.frame);
    mxdebug_if(m_debug, boost::format("Position: %1% discard_duration: %2% TOC: %3%\n") % m_position % f.discard_duration % toc);

    m_position = m_position + toc.packet_duration - f.discard_duration;
    queue_frame(f.frame, m_position.to_samples(48000));

  } catch (mtx::opus::exception &ex) {
    mxdebug_if(m_debug, boost::format("Exception: %1%\n") % ex.what());
  }
}
Example #6
0
void
cues_c::postprocess_cues(KaxCues &cues,
                         KaxCluster &cluster) {
  add(cues);

  if (m_no_cue_duration && m_no_cue_relative_position)
    return;

  auto cluster_data_start_pos = cluster.GetElementPosition() + cluster.HeadSize();
  auto block_positions        = calculate_block_positions(cluster);

  for (auto point = m_points.begin() + m_num_cue_points_postprocessed, end = m_points.end(); point != end; ++point) {
    // Set CueRelativePosition for all cues.
    if (!m_no_cue_relative_position) {
      auto position_itr      = block_positions.find({ point->track_num, point->timecode });
      auto relative_position = block_positions.end() != position_itr ? std::max(position_itr->second, cluster_data_start_pos) - cluster_data_start_pos : 0ull;

      assert(relative_position <= static_cast<uint64_t>(std::numeric_limits<uint32_t>::max()));

      point->relative_position = relative_position;

      mxdebug_if(m_debug_cue_relative_position,
                 boost::format("cue_relative_position: looking for <%1%:%2%>: cluster_data_start_pos %3% position %4%\n")
                 % point->track_num % point->timecode % cluster_data_start_pos % relative_position);
    }

    // Set CueDuration if the packetizer wants them.
    if (m_no_cue_duration)
      continue;

    auto duration_itr = m_id_timecode_duration_map.find({ point->track_num, point->timecode });
    auto ptzr         = g_packetizers_by_track_num[point->track_num];

    if (!ptzr || !ptzr->wants_cue_duration())
      continue;

    if (m_id_timecode_duration_map.end() != duration_itr)
      point->duration = duration_itr->second;

    mxdebug_if(m_debug_cue_duration,
               boost::format("cue_duration: looking for <%1%:%2%>: %3%\n")
               % point->track_num % point->timecode % (duration_itr == m_id_timecode_duration_map.end() ? static_cast<int64_t>(-1) : duration_itr->second));
  }

  m_num_cue_points_postprocessed = m_points.size();

  m_id_timecode_duration_map.clear();
}
Example #7
0
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));
}
Example #8
0
EbmlElement *
kax_file_c::read_one_element() {
  if (m_segment_end && (m_in->getFilePointer() >= m_segment_end))
    return nullptr;

  int upper_lvl_el = 0;
  EbmlElement *l1  = m_es->FindNextElement(EBML_CLASS_CONTEXT(KaxSegment), upper_lvl_el, 0xFFFFFFFFL, true);

  if (!l1)
    return nullptr;

  const EbmlCallbacks *callbacks = find_ebml_callbacks(EBML_INFO(KaxSegment), EbmlId(*l1));
  if (!callbacks)
    callbacks = &EBML_CLASS_CALLBACK(KaxSegment);

  EbmlElement *l2 = nullptr;
  try {
    l1->Read(*m_es.get(), EBML_INFO_CONTEXT(*callbacks), upper_lvl_el, l2, true);

  } catch (libebml::CRTError &e) {
    mxdebug_if(m_debug_resync, boost::format("exception reading element data: %1% (%2%)\n") % e.what() % e.getError());
    m_in->setFilePointer(l1->GetElementPosition() + 1);
    delete l1;
    return nullptr;
  }

  unsigned long element_size = get_element_size(l1);
  if (m_debug_resync)
    mxinfo(boost::format("kax_file::read_one_element(): read element at %1% calculated size %2% stored size %3%\n")
           % l1->GetElementPosition() % element_size % (l1->IsFiniteSize() ? (boost::format("%1%") % l1->ElementSize()).str() : std::string("unknown")));
  m_in->setFilePointer(l1->GetElementPosition() + element_size, seek_beginning);

  return l1;
}
Example #9
0
void
mpeg4_p10_video_packetizer_c::set_headers() {
  static auto s_debug_fix_bistream_timing_info = debugging_option_c{"fix_bitstream_timing_info"};

  if (m_ti.m_private_data && m_ti.m_private_data->get_size())
    extract_aspect_ratio();

  if (m_ti.m_private_data && m_ti.m_private_data->get_size() && m_ti.m_fix_bitstream_frame_rate) {
    int64_t l_track_default_duration = -1;

    if (m_timestamp_factory)
      l_track_default_duration = m_timestamp_factory->get_default_duration(-1);

    if ((-1 == l_track_default_duration) && m_default_duration_forced)
      l_track_default_duration = m_htrack_default_duration;

    if ((-1 == l_track_default_duration) && (0.0 < m_fps))
      l_track_default_duration = static_cast<int64_t>(1000000000.0 / m_fps);

    if (-1 != l_track_default_duration)
      l_track_default_duration /= 2;

    mxdebug_if(s_debug_fix_bistream_timing_info,
               boost::format("fix_bitstream_timing_info: factory default_duration %1% default_duration_forced? %2% htrack_default_duration %3% fps %4% l_track_default_duration %5%\n")
               % (m_timestamp_factory ? m_timestamp_factory->get_default_duration(-1) : -2)
               % m_default_duration_forced % m_htrack_default_duration
               % m_fps % l_track_default_duration);

    set_codec_private(mpeg4::p10::fix_sps_fps(m_ti.m_private_data, l_track_default_duration));
  }

  generic_video_packetizer_c::set_headers();
}
Example #10
0
void
dts_reader_c::read_headers() {
  try {
    m_in->setFilePointer(m_current_chunk->data_start);
    auto bytes_to_read = std::min<int64_t>(m_current_chunk->data_size, READ_SIZE);
    if (m_in->read(m_buf[m_cur_buf], bytes_to_read) != bytes_to_read)
      throw mtx::input::header_parsing_x();
    m_in->setFilePointer(m_current_chunk->data_start);

  } catch (...) {
    throw mtx::input::open_x();
  }

  mtx::dts::detect(m_buf[m_cur_buf], READ_SIZE, m_dts14_to_16, m_swap_bytes);

  mxdebug_if(m_debug, boost::format("DTS: 14->16 %1% swap %2%\n") % m_dts14_to_16 % m_swap_bytes);

  decode_buffer(READ_SIZE);
  int pos = mtx::dts::find_header(reinterpret_cast<const unsigned char *>(m_buf[m_cur_buf]), READ_SIZE, m_dtsheader);

  if (0 > pos)
    throw mtx::input::header_parsing_x();

  m_ti.m_id = 0;          // ID for this track.

  m_codec.set_specialization(m_dtsheader.get_codec_specialization());

  show_demuxer_info();
}
Example #11
0
void
dts_reader_c::read_headers() {
  try {
    if (m_in->read(m_buf[m_cur_buf], READ_SIZE) != READ_SIZE)
      throw mtx::input::header_parsing_x();
    m_in->setFilePointer(0, seek_beginning);

  } catch (...) {
    throw mtx::input::open_x();
  }

  detect_dts(m_buf[m_cur_buf], READ_SIZE, m_dts14_to_16, m_swap_bytes);

  mxdebug_if(m_debug, boost::format("DTS: 14->16 %1% swap %2%\n") % m_dts14_to_16 % m_swap_bytes);

  decode_buffer(READ_SIZE);
  int pos = find_dts_header(reinterpret_cast<const unsigned char *>(m_buf[m_cur_buf]), READ_SIZE, &m_dtsheader);

  if (0 > pos)
    throw mtx::input::header_parsing_x();

  m_ti.m_id = 0;          // ID for this track.

  show_demuxer_info();
}
Example #12
0
void
translation_c::set_active_translation(const std::string &locale) {
  int idx                   = look_up_translation(locale);
  ms_active_translation_idx = std::max(idx, 0);

  mxdebug_if(debugging_c::requested("locale"), boost::format("[translation_c::set_active_translation() active_translation_idx %1% for locale %2%]\n") % ms_active_translation_idx % locale);
}
Example #13
0
bool
parser_c::parse() {
  try {
    mm_file_io_c m_file(m_file_name, MODE_READ);

    int64_t file_size   = m_file.get_size();
    memory_cptr content = memory_c::alloc(file_size);

    if (file_size != m_file.read(content, file_size))
      throw false;
    m_file.close();

    mtx::bits::reader_cptr bc(new mtx::bits::reader_c(content->get_buffer(), file_size));

    parse_header(*bc);
    parse_program_info(*bc);

    if (m_debug)
      dump();

    m_ok = true;

  } catch (...) {
    mxdebug_if(m_debug, "Parsing NOT OK\n");
  }

  return m_ok;
}
Example #14
0
void
cluster_helper_c::dump_split_points()
  const {
  mxdebug_if(m->debug_splitting,
             boost::format("Split points:%1%\n")
             % boost::accumulate(m->split_points, std::string(""), [](std::string const &accu, split_point_c const &point) { return accu + " " + point.str(); }));
}
Example #15
0
void
parser_c::parse_header(mtx::bits::reader_c &bc) {
  bc.set_bit_position(0);

  uint32_t magic = bc.get_bits(32);
  mxdebug_if(m_debug, boost::format("File magic 1: 0x%|1$08x|\n") % magic);
  if (CLPI_FILE_MAGIC != magic)
    throw false;

  magic = bc.get_bits(32);
  mxdebug_if(m_debug, boost::format("File magic 2: 0x%|1$08x|\n") % magic);
  if ((CLPI_FILE_MAGIC2A != magic) && (CLPI_FILE_MAGIC2B != magic) && (CLPI_FILE_MAGIC2C != magic))
    throw false;

  m_sequence_info_start = bc.get_bits(32);
  m_program_info_start  = bc.get_bits(32);
}
Example #16
0
std::string
translation_c::get_default_ui_locale() {
  std::string locale;

#if defined(HAVE_LIBINTL_H)
  bool debug = debugging_c::requested("locale");

# if defined(SYS_WINDOWS)
  std::string env_var = mtx::sys::get_environment_variable("LC_MESSAGES");
  if (!env_var.empty() && (-1 != look_up_translation(env_var)))
    return env_var;

  env_var = mtx::sys::get_environment_variable("LANG");
  if (!env_var.empty() && (-1 != look_up_translation(env_var)))
    return env_var;

  auto lang_id = GetUserDefaultUILanguage();
  int idx      = translation_c::look_up_translation(lang_id & 0x3ff, (lang_id >> 10) & 0x3f);
  if (-1 != idx)
    locale = ms_available_translations[idx].get_locale();

  mxdebug_if(debug, boost::format("[lang_id %|1$04x| idx %2% locale %3%\n") % lang_id % idx % locale);

# else  // SYS_WINDOWS

  char *data = setlocale(LC_MESSAGES, nullptr);
  if (data) {
    std::string previous_locale = data;
    mxdebug_if(debug, boost::format("[get_default_ui_locale previous %1%]\n") % previous_locale);
    setlocale(LC_MESSAGES, "");
    data = setlocale(LC_MESSAGES, nullptr);

    if (data)
      locale = data;

    mxdebug_if(debug, boost::format("[get_default_ui_locale new %1%]\n") % locale);

    setlocale(LC_MESSAGES, previous_locale.c_str());
  } else
    mxdebug_if(debug, boost::format("[get_default_ui_locale get previous failed]\n"));

# endif // SYS_WINDOWS
#endif  // HAVE_LIBINTL_H

  return locale;
}
Example #17
0
void
cluster_helper_c::split(packet_cptr &packet) {
  render();

  m->num_cue_elements = 0;

  bool create_new_file       = m->current_split_point->m_create_new_file;
  bool previously_discarding = m->discarding;

  mxdebug_if(m->debug_splitting, boost::format("Splitting: splitpoint %1% reached before timecode %2%, create new? %3%.\n") % m->current_split_point->str() % format_timecode(packet->assigned_timecode) % create_new_file);

  finish_file(false, create_new_file, previously_discarding);

  if (m->current_split_point->m_use_once) {
    if (   m->current_split_point->m_discard
        && (   (split_point_c::parts             == m->current_split_point->m_type)
            || (split_point_c::parts_frame_field == m->current_split_point->m_type))
        && (m->split_points.end() == (m->current_split_point + 1))) {
      mxdebug_if(m->debug_splitting, boost::format("Splitting: Last part in 'parts:' splitting mode finished\n"));
      m->splitting_and_processed_fully = true;
    }

    m->discarding = m->current_split_point->m_discard;
    ++m->current_split_point;
  }

  if (create_new_file) {
    create_next_output_file();
    if (g_no_linking) {
      m->previous_cluster_tc = -1;
      m->timecode_offset = g_video_packetizer ? m->max_video_timecode_rendered : packet->assigned_timecode;
    }

    m->bytes_in_file          =  0;
    m->first_timecode_in_file = -1;
    m->max_timecode_in_file   = -1;
    m->min_timecode_in_file.reset();
  }

  m->first_timecode_in_part = -1;

  handle_discarded_duration(create_new_file, previously_discarding);

  prepare_new_cluster();
}
Example #18
0
void
mm_read_buffer_io_c::setFilePointer(int64 offset,
                                    seek_mode mode) {
  if (!m_buffering) {
    m_proxy_io->setFilePointer(offset, mode);
    return;
  }

  int64_t new_pos = 0;
  // FIXME int64_t overflow

  // No need to actually compute this here; _read() will do just that
  m_eof = false;

  switch (mode) {
    case seek_beginning:
      new_pos = offset;
      break;

    case seek_current:
      new_pos  = m_offset;
      new_pos += m_cursor;
      new_pos += offset;
      break;

    case seek_end:
      new_pos = -1;
      break;

    default:
      throw mtx::mm_io::seek_x();
  }

  // Still within the current buffer?
  int64_t in_buf = new_pos - m_offset;
  if ((0 <= in_buf) && (in_buf <= static_cast<int64_t>(m_fill))) {
    m_cursor = in_buf;
    return;
  }

  int64_t previous_pos = m_proxy_io->getFilePointer();

  // Actual seeking
  if (new_pos < 0)
    m_proxy_io->setFilePointer(offset, seek_end);
  else
    m_proxy_io->setFilePointer(std::min(new_pos, get_size()), seek_beginning);

  // Get the actual offset from the underlying stream
  // Better be safe than sorry and use this instead of just taking
  m_offset = m_proxy_io->getFilePointer();

  // "Drop" the buffer content
  m_cursor = m_fill = 0;

  mxdebug_if(m_debug_seek, boost::format("seek on proxy from %1% to %2% relative %3%\n") % previous_pos % m_offset % (m_offset - previous_pos));
}
Example #19
0
int64_t
cluster_helper_c::get_duration()
  const {
  auto result = m->max_timecode_and_duration - m->min_timecode_in_file.to_ns(0) - m->discarded_duration;
  mxdebug_if(m->debug_duration,
             boost::format("cluster_helper_c::get_duration(): max_tc_and_dur %1% - min_tc_in_file %2% - discarded_duration %3% = %4% ; first_tc_in_file = %5%\n")
             % m->max_timecode_and_duration % m->min_timecode_in_file.to_ns(0) % m->discarded_duration % result % m->first_timecode_in_file);
  return result;
}
Example #20
0
stream_t
parser_c::parse_stream() {
  auto str        = stream_t();

  auto length     = m_bc->get_bits(8);
  auto position   = m_bc->get_bit_position() / 8u;

  str.stream_type = m_bc->get_bits(8);

  if (1 == str.stream_type)
    str.pid = m_bc->get_bits(16);

  else if ((2 == str.stream_type) || (4 == str.stream_type)) {
    str.sub_path_id = m_bc->get_bits(8);
    str.sub_clip_id = m_bc->get_bits(8);
    str.pid         = m_bc->get_bits(16);

  } else if (3 == str.stream_type) {
    str.sub_path_id = m_bc->get_bits(8);
    str.pid         = m_bc->get_bits(16);

  } else if (m_debug)
    mxdebug(boost::format("Unknown stream type %1%\n") % str.stream_type);

  m_bc->set_bit_position((length + position) * 8);

  length          = m_bc->get_bits(8);
  position        = m_bc->get_bit_position() / 8u;

  str.coding_type = m_bc->get_bits(8);

  if ((0x01 == str.coding_type) || (0x02 == str.coding_type) || (0x1b == str.coding_type) || (0xea == str.coding_type)) {
    str.format = m_bc->get_bits(4);
    str.rate   = m_bc->get_bits(4);

  } else if (   (0x03 == str.coding_type) || (0x04 == str.coding_type) || (0x80 == str.coding_type) || (0x81 == str.coding_type) || (0x82 == str.coding_type)
             || (0x83 == str.coding_type) || (0x84 == str.coding_type) || (0x85 == str.coding_type) || (0x86 == str.coding_type)) {
    str.format   = m_bc->get_bits(4);
    str.rate     = m_bc->get_bits(4);
    str.language = read_string(3);

  } else if ((0x90 == str.coding_type) || (0x91 == str.coding_type))
    str.language = read_string(3);

  else if (0x92 == str.coding_type) {
    str.char_code = m_bc->get_bits(8);
    str.language  = read_string(3);

  } else
    mxdebug_if(m_debug, boost::format("Unrecognized coding type %|1$02x|\n") % str.coding_type);

  m_bc->set_bit_position((position + length) * 8);

  return str;
}
Example #21
0
int
translation_c::look_up_translation(int language_id, int sub_language_id) {
  auto ptr = brng::find_if(ms_available_translations, [language_id,sub_language_id](translation_c const &tr) {
      return (tr.m_language_id == language_id) && (!tr.m_sub_language_id || (tr.m_sub_language_id == sub_language_id));
    });

  int idx = ptr == ms_available_translations.end() ? -1 : std::distance(ms_available_translations.begin(), ptr);
  mxdebug_if(debugging_c::requested("locale"), boost::format("look_up_translation for 0x%|1$04x|/0x%|2$02x|: %3%\n") % language_id % sub_language_id % idx);

  return idx;
}
Example #22
0
int
avc_es_reader_c::probe_file(mm_io_c *in,
                            uint64_t size) {
  try {
    if (PROBESIZE > size)
      return 0;

    memory_cptr buf = memory_c::alloc(READ_SIZE);
    int num_read, i;
    bool first = true;

    mtx::avc::es_parser_c parser;
    parser.ignore_nalu_size_length_errors();
    parser.set_nalu_size_length(4);

    in->setFilePointer(0, seek_beginning);
    for (i = 0; MAX_PROBE_BUFFERS > i; ++i) {
      num_read = in->read(buf->get_buffer(), READ_SIZE);
      if (4 > num_read)
        return 0;

      // MPEG TS starts with 0x47.
      if (first && (0x47 == buf->get_buffer()[0]))
        return 0;
      first = false;

      parser.add_bytes(buf->get_buffer(), num_read);

      if (parser.headers_parsed())
        return 1;
    }

  } catch (mtx::exception &e) {
    mxdebug_if(ms_debug, (boost::format(Y("Error %1%\n")) % e.error()));

  } catch (...) {
    mxdebug_if(ms_debug, Y("have an xcptn\n"));
  }

  return 0;
}
Example #23
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();
}
Example #24
0
bool
parser_c::parse(mm_io_c *file) {
  try {
    file->setFilePointer(0);
    int64_t file_size = file->get_size();

    if ((4 * 5 > file_size) || (10 * 1024 * 1024 < file_size))
      throw mtx::mpls::exception(boost::format("File too small or too big: %1%") % file_size);

    auto content = file->read(4 * 5);
    m_bc         = std::make_shared<bit_reader_c>(content->get_buffer(), 4 * 5);
    parse_header();

    file->setFilePointer(0);

    content = file->read(file_size);
    m_bc    = std::make_shared<bit_reader_c>(content->get_buffer(), file_size);

    parse_playlist();
    parse_chapters();

    m_bc.reset();

    m_ok = true;

  } catch (mtx::mpls::exception &ex) {
    mxdebug_if(m_debug, boost::format("MPLS exception: %1%\n") % ex.what());
  } catch (mtx::mm_io::exception &ex) {
    mxdebug_if(m_debug, boost::format("I/O exception: %1%\n") % ex.what());
  }

  if (m_debug)
    dump();

  file->setFilePointer(0);

  return m_ok;
}
Example #25
0
void
mm_write_buffer_io_c::flush_buffer() {
  if (!m_fill)
    return;

  size_t written = mm_proxy_io_c::_write(m_buffer, m_fill);
  size_t fill    = m_fill;
  m_fill         = 0;

  mxdebug_if(m_debug_write, boost::format("flush_buffer() at %1% for %2% written %3%\n") % (mm_proxy_io_c::getFilePointer() - written) % fill % written);

  if (written != fill)
    throw mtx::mm_io::insufficient_space_x();
}
Example #26
0
void
TrackModel::trackUpdated(Track *track) {
  if (!m_tracks) {
    mxdebug_if(m_debug, boost::format("trackUpdated() called but !m_tracks!?\n"));
    return;
  }

  int row = rowForTrack(*m_tracks, track);
  mxdebug(boost::format("trackUpdated(): row is %1%\n") % row);
  if (-1 == row)
    return;

  emit dataChanged(createIndex(row, 0, track), createIndex(row, NumberOfColumns - 1, track));
}
Example #27
0
int
mpeg_ts_track_c::new_stream_a_aac() {
  add_pes_payload_to_probe_data();

  if (0 > find_aac_header(m_probe_data->get_buffer(), m_probe_data->get_size(), &m_aac_header, false))
    return FILE_STATUS_MOREDATA;

  mxdebug_if(reader.m_debug_aac, boost::format("first AAC header: %1%\n") % m_aac_header.to_string());

  a_channels    = m_aac_header.channels;
  a_sample_rate = m_aac_header.sample_rate;

  return 0;
}
void
AttachmentModel::attachmentUpdated(Attachment *attachment) {
  if (!m_attachments) {
    mxdebug_if(m_debug, boost::format("attachmentUpdated() called but !m_attachments!?\n"));
    return;
  }

  auto it = brng::find_if(*m_attachments, [&](AttachmentPtr const &candidate) { return candidate.get() == attachment; });
  if (it == m_attachments->end())
    return;

  int row = std::distance(m_attachments->begin(), it);
  emit dataChanged(createIndex(row, 0, attachment), createIndex(row, NumberOfColumns - 1, attachment));
}
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);
}
timestamp_c
timestamp_calculator_c::get_next_timecode(int64_t samples_in_frame) {
  if (!m_available_timecodes.empty()) {
    m_last_timecode_returned           = m_available_timecodes.front();
    m_reference_timecode               = m_last_timecode_returned;
    m_samples_since_reference_timecode = samples_in_frame;

    m_available_timecodes.pop_front();

    mxdebug_if(m_debug, boost::format("timestamp_calculator_c::get_next_timecode: returning available %1%\n") % format_timestamp(m_last_timecode_returned));

    return m_last_timecode_returned;
  }

  if (!m_samples_per_second)
    throw std::invalid_argument{"samples per second must not be 0"};

  m_last_timecode_returned           = m_reference_timecode + timestamp_c::ns(m_samples_to_timestamp * m_samples_since_reference_timecode);
  m_samples_since_reference_timecode += samples_in_frame;

  mxdebug_if(m_debug, boost::format("timestamp_calculator_c::get_next_timecode: returning calculated %1%\n") % format_timestamp(m_last_timecode_returned));

  return m_last_timecode_returned;
}