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; }
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; }
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)); }
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()); } }
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(); }
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)); }
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; }
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(); }
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(); }
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(); }
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); }
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; }
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(); })); }
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); }
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; }
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(); }
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)); }
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; }
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; }
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; }
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; }
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(); }
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; }
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(); }
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)); }
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; }