void timecode_factory_v2_c::parse(mm_io_c &in) { std::string line; std::map<int64_t, int64_t> dur_map; int64_t dur_sum = 0; int line_no = 0; double previous_timecode = 0; while (in.getline2(line)) { line_no++; strip(line); if ((line.length() == 0) || (line[0] == '#')) continue; double timecode; if (!parse_double(line.c_str(), timecode)) mxerror(boost::format(Y("The line %1% of the timecode file '%2%' does not contain a valid floating point number.\n")) % line_no % m_file_name); if ((2 == m_version) && (timecode < previous_timecode)) mxerror(boost::format(Y("The timecode v2 file '%1%' contains timecodes that are not ordered. " "Due to a bug in mkvmerge versions up to and including v1.5.0 this was necessary " "if the track to which the timecode file was applied contained B frames. " "Starting with v1.5.1 mkvmerge now handles this correctly, and the timecodes in the timecode file must be ordered normally. " "For example, the frame sequence 'IPBBP...' at 25 FPS requires a timecode file with " "the first timecodes being '0', '40', '80', '120' etc and not '0', '120', '40', '80' etc.\n\n" "If you really have to specify non-sorted timecodes then use the timecode format v4. " "It is identical to format v2 but allows non-sorted timecodes.\n")) % in.get_file_name()); previous_timecode = timecode; m_timecodes.push_back((int64_t)(timecode * 1000000)); if (m_timecodes.size() > 1) { int64_t duration = m_timecodes[m_timecodes.size() - 1] - m_timecodes[m_timecodes.size() - 2]; if (dur_map.find(duration) == dur_map.end()) dur_map[duration] = 1; else dur_map[duration] = dur_map[duration] + 1; dur_sum += duration; m_durations.push_back(duration); } } if (m_timecodes.empty()) mxerror(boost::format(Y("The timecode file '%1%' does not contain any valid entry.\n")) % m_file_name); dur_sum = -1; std::pair<int64_t, int64_t> entry; for (auto entry : dur_map) { if ((0 > dur_sum) || (dur_map[dur_sum] < entry.second)) dur_sum = entry.first; mxverb(4, boost::format("ext_m_timecodes v2 dur_map %1% = %2%\n") % entry.first % entry.second); } mxverb(4, boost::format("ext_m_timecodes v2 max is %1% = %2%\n") % dur_sum % dur_map[dur_sum]); if (0 < dur_sum) m_default_fps = (double)1000000000.0 / dur_sum; m_durations.push_back(dur_sum); }
void flac_reader_c::flac_metadata_cb(const FLAC__StreamMetadata *metadata) { switch (metadata->type) { case FLAC__METADATA_TYPE_STREAMINFO: memcpy(&stream_info, &metadata->data.stream_info, sizeof(FLAC__StreamMetadata_StreamInfo)); sample_rate = metadata->data.stream_info.sample_rate; metadata_parsed = true; mxverb(2, boost::format("flac_reader: STREAMINFO block (%1% bytes):\n") % metadata->length); mxverb(2, boost::format("flac_reader: sample_rate: %1% Hz\n") % metadata->data.stream_info.sample_rate); mxverb(2, boost::format("flac_reader: channels: %1%\n") % metadata->data.stream_info.channels); mxverb(2, boost::format("flac_reader: bits_per_sample: %1%\n") % metadata->data.stream_info.bits_per_sample); break; default: mxverb(2, boost::format("%1% (%2%) block (%3% bytes)\n") % ( metadata->type == FLAC__METADATA_TYPE_PADDING ? "PADDING" : metadata->type == FLAC__METADATA_TYPE_APPLICATION ? "APPLICATION" : metadata->type == FLAC__METADATA_TYPE_SEEKTABLE ? "SEEKTABLE" : metadata->type == FLAC__METADATA_TYPE_VORBIS_COMMENT ? "VORBIS COMMENT" : metadata->type == FLAC__METADATA_TYPE_CUESHEET ? "CUESHEET" : "UNDEFINED") % metadata->type % metadata->length); break; } }
/** \brief Extract the FPS from a MPEG video sequence header This function looks for a MPEG sequence header in a buffer containing a MPEG1 or MPEG2 video frame. If such a header is found its FPS index is extracted and returned. This index can be mapped to the actual number of frames per second with the function ::mpeg_video_get_fps \param buffer The buffer to search for the header. \param buffer_size The buffer size. \return The index or \c -1 if no MPEG sequence header was found or if the buffer was too small. */ int mpeg1_2::extract_fps_idx(const unsigned char *buffer, int buffer_size) { mxverb(3, boost::format("mpeg_video_fps: start search in %1% bytes\n") % buffer_size); if (buffer_size < 8) { mxverb(3, "mpeg_video_fps: sequence header too small\n"); return -1; } auto marker = get_uint32_be(buffer); int idx = 4; while ((idx < buffer_size) && (marker != MPEGVIDEO_SEQUENCE_HEADER_START_CODE)) { marker <<= 8; marker |= buffer[idx]; idx++; } if ((idx + 3) >= buffer_size) { mxverb(3, "mpeg_video_fps: no full sequence header start code found\n"); return -1; } mxverb(3, boost::format("mpeg_video_fps: found sequence header start code at %1%\n") % (idx - 4)); return buffer[idx + 3] & 0x0f; }
void mpeg_ts_reader_c::read_headers() { try { size_t size_to_probe = std::min(m_size, static_cast<uint64_t>(TS_PIDS_DETECT_SIZE)); auto probe_buffer = memory_c::alloc(size_to_probe); m_detected_packet_size = detect_packet_size(m_in.get(), size_to_probe); m_in->setFilePointer(0); mxverb(3, boost::format("mpeg_ts: Starting to build PID list. (packet size: %1%)\n") % m_detected_packet_size); mpeg_ts_track_ptr PAT(new mpeg_ts_track_c(*this)); PAT->type = PAT_TYPE; tracks.push_back(PAT); unsigned char buf[TS_MAX_PACKET_SIZE]; // maximum TS packet size + 1 bool done = m_in->eof(); while (!done) { if (m_in->read(buf, m_detected_packet_size) != static_cast<unsigned int>(m_detected_packet_size)) break; if (buf[0] != 0x47) { if (resync(m_in->getFilePointer() - m_detected_packet_size)) continue; break; } parse_packet(buf); done = PAT_found && PMT_found && (0 == es_to_process); done |= m_in->eof() || (m_in->getFilePointer() >= TS_PIDS_DETECT_SIZE); } } catch (...) { } mxverb(3, boost::format("mpeg_ts: Detection done on %1% bytes\n") % m_in->getFilePointer()); m_in->setFilePointer(0, seek_beginning); // rewind file for later remux for (auto &track : tracks) { track->pes_payload->remove(track->pes_payload->get_size()); track->processed = false; track->data_ready = false; track->pes_payload_size = 0; // track->timecode_offset = -1; } parse_clip_info_file(); process_chapter_entries(); show_demuxer_info(); }
bool flac_header_extractor_c::extract() { mxverb(2, "flac_header_extraction: extract\n"); if (!read_page()) { mxverb(2, "flac_header_extraction: read_page() failed.\n"); return false; } int result = (int)FLAC__stream_decoder_process_until_end_of_stream(decoder); mxverb(2, boost::format("flac_header_extraction: extract, result: %1%, mdp: %2%, num_header_packets: %3%\n") % result % metadata_parsed % num_header_packets); return metadata_parsed; }
/** \brief Extract the aspect ratio from a MPEG video sequence header This function looks for a MPEG sequence header in a buffer containing a MPEG1 or MPEG2 video frame. If such a header is found its aspect ratio is extracted and returned. \param buffer The buffer to search for the header. \param buffer_size The buffer size. \return \c true if a MPEG sequence header was found and \c false otherwise. */ bool mpeg1_2::extract_ar(const unsigned char *buffer, int buffer_size, float &ar) { uint32_t marker; int idx; mxverb(3, boost::format("mpeg_video_ar: start search in %1% bytes\n") % buffer_size); if (buffer_size < 8) { mxverb(3, "mpeg_video_ar: sequence header too small\n"); return false; } marker = get_uint32_be(buffer); idx = 4; while ((idx < buffer_size) && (marker != MPEGVIDEO_SEQUENCE_HEADER_START_CODE)) { marker <<= 8; marker |= buffer[idx]; idx++; } if (idx >= buffer_size) { mxverb(3, "mpeg_video_ar: no sequence header start code found\n"); return false; } mxverb(3, boost::format("mpeg_video_ar: found sequence header start code at %1%\n") % (idx - 4)); idx += 3; // width and height if (idx >= buffer_size) { mxverb(3, "mpeg_video_ar: sequence header too small\n"); return false; } switch (buffer[idx] & 0xf0) { case MPEGVIDEO_AR_1_1: ar = 1.0f; break; case MPEGVIDEO_AR_4_3: ar = 4.0f / 3.0f; break; case MPEGVIDEO_AR_16_9: ar = 16.0f / 9.0f; break; case MPEGVIDEO_AR_2_21: ar = 2.21f; break; default: ar = -1.0f; } return true; }
void avi_reader_c::create_video_packetizer() { size_t i; mxverb_tid(4, m_ti.m_fname, 0, "frame sizes:\n"); for (i = 0; i < m_max_video_frames; i++) { m_bytes_to_process += AVI_frame_size(m_avi, i); mxverb(4, boost::format(" %1%: %2%\n") % i % AVI_frame_size(m_avi, i)); } if (m_avi->bitmap_info_header) { m_ti.m_private_data = memory_c::clone(m_avi->bitmap_info_header, get_uint32_le(&m_avi->bitmap_info_header->bi_size)); mxverb(4, boost::format("track extra data size: %1%\n") % (m_ti.m_private_data->get_size() - sizeof(alBITMAPINFOHEADER))); if (sizeof(alBITMAPINFOHEADER) < m_ti.m_private_data->get_size()) mxverb(4, boost::format(" %1%\n") % to_hex(m_ti.m_private_data->get_buffer() + sizeof(alBITMAPINFOHEADER), m_ti.m_private_data->get_size() - sizeof(alBITMAPINFOHEADER))); } const char *codec = AVI_video_compressor(m_avi); if (mpeg4::p2::is_v3_fourcc(codec)) m_divx_type = DIVX_TYPE_V3; else if (mpeg4::p2::is_fourcc(codec)) m_divx_type = DIVX_TYPE_MPEG4; if (map_has_key(m_ti.m_default_durations, 0)) m_fps = 1000000000.0 / m_ti.m_default_durations[0]; else if (map_has_key(m_ti.m_default_durations, -1)) m_fps = 1000000000.0 / m_ti.m_default_durations[-1]; m_ti.m_id = 0; // ID for the video track. if (DIVX_TYPE_MPEG4 == m_divx_type) create_mpeg4_p2_packetizer(); else if (mpeg4::p10::is_avc_fourcc(codec) && !hack_engaged(ENGAGE_ALLOW_AVC_IN_VFW_MODE)) create_mpeg4_p10_packetizer(); else if (mpeg1_2::is_fourcc(get_uint32_le(codec))) create_mpeg1_2_packetizer(); else if (FOURCC('V', 'P', '8', '0') == get_uint32_be(codec)) create_vp8_packetizer(); else create_standard_video_packetizer(); }
file_status_e ivf_reader_c::read(generic_packetizer_c *, bool) { size_t remaining_bytes = m_size - m_in->getFilePointer(); ivf::frame_header_t header; if ((sizeof(ivf::frame_header_t) > remaining_bytes) || (m_in->read(&header, sizeof(ivf::frame_header_t)) != sizeof(ivf::frame_header_t))) return flush_packetizers(); remaining_bytes -= sizeof(ivf::frame_header_t); uint32_t frame_size = get_uint32_le(&header.frame_size); if (remaining_bytes < frame_size) { m_in->setFilePointer(0, seek_end); return flush_packetizers(); } memory_cptr buffer = memory_c::alloc(frame_size); if (m_in->read(buffer->get_buffer(), frame_size) < frame_size) { m_in->setFilePointer(0, seek_end); return flush_packetizers(); } int64_t timestamp = get_uint64_le(&header.timestamp) * 1000000000ull * m_frame_rate_den / m_frame_rate_num; mxverb(3, boost::format("r_ivf.cpp: key %5% header.ts %1% num %2% den %3% res %4%\n") % get_uint64_le(&header.timestamp) % m_frame_rate_num % m_frame_rate_den % timestamp % ivf::is_keyframe(buffer)); PTZR0->process(new packet_t(buffer, timestamp)); return FILE_STATUS_MOREDATA; }
void xtr_ivf_c::handle_frame(memory_cptr &frame, KaxBlockAdditions *, int64_t timecode, int64_t, int64_t, int64_t, bool, bool, bool) { m_content_decoder.reverse(frame, CONTENT_ENCODING_SCOPE_BLOCK); uint64_t frame_number = timecode * m_frame_rate_num / m_frame_rate_den / 1000000000ull; mxverb(2, boost::format("timecode %1% num %2% den %3% frame_number %4% calculated back %5%\n") % timecode % m_frame_rate_num % m_frame_rate_den % frame_number % (frame_number * 1000000000ull * m_frame_rate_den / m_frame_rate_num)); ivf::frame_header_t frame_header; put_uint32_le(&frame_header.frame_size, frame->get_size()); put_uint32_le(&frame_header.timestamp, frame_number); m_out->write(&frame_header, sizeof(frame_header)); m_out->write(frame->get_buffer(), frame->get_size()); ++m_frame_count; }
static void fhe_error_cb(const FLAC__StreamDecoder *, FLAC__StreamDecoderErrorStatus status, void *client_data) { ((flac_header_extractor_c *)client_data)->done = true; mxverb(2, boost::format("flac_header_extraction: error (%1%)\n") % (int)status); }
bool timecode_factory_v3_c::get_next(packet_cptr &packet) { bool result = false; if (m_durations[m_current_duration].is_gap) { // find the next non-gap size_t duration_index = m_current_duration; while (m_durations[duration_index].is_gap || (0 == m_durations[duration_index].duration)) { m_current_offset += m_durations[duration_index].duration; duration_index++; } m_current_duration = duration_index; result = true; // yes, there is a gap before this frame } packet->assigned_timecode = m_current_offset + m_current_timecode; // If default_fps is 0 then the duration is unchanged, usefull for audio. if (m_durations[m_current_duration].fps && (!m_preserve_duration || (0 >= packet->duration))) packet->duration = (int64_t)(1000000000.0 / m_durations[m_current_duration].fps); packet->duration /= packet->time_factor; m_current_timecode += packet->duration; if (m_current_timecode >= m_durations[m_current_duration].duration) { m_current_offset += m_durations[m_current_duration].duration; m_current_timecode = 0; m_current_duration++; } mxverb(3, boost::format("ext_timecodes v3: tc %1% dur %2%\n") % packet->assigned_timecode % packet->duration); return result; }
int mpeg_ts_track_c::new_stream_a_truehd() { if (!m_truehd_parser) m_truehd_parser = truehd_parser_cptr(new truehd_parser_c); static int added = 0; added += pes_payload->get_size(); m_truehd_parser->add_data(pes_payload->get_buffer(), pes_payload->get_size()); pes_payload->remove(pes_payload->get_size()); while (m_truehd_parser->frame_available()) { truehd_frame_cptr frame = m_truehd_parser->get_next_frame(); if (truehd_frame_t::sync != frame->m_type) continue; mxverb(2, boost::format("first TrueHD header channels %1% sampling_rate %2% samples_per_frame %3%\n") % frame->m_channels % frame->m_sampling_rate % frame->m_samples_per_frame); a_channels = frame->m_channels; a_sample_rate = frame->m_sampling_rate; return 0; } return FILE_STATUS_MOREDATA; }
int64_t vc1::es_parser_c::get_next_timecode() { int64_t next_timecode = m_previous_timecode + (m_num_timecodes + m_num_repeated_fields) * m_default_duration - m_num_repeated_fields * m_default_duration / 2; if (is_timecode_available()) { mxverb(3, boost::format("\nvc1::es_parser_c::get_next_timecode(): provided timecode available; original next %1%, provided %2%\n") % format_timecode(next_timecode) % format_timecode(m_timecodes.front())); next_timecode = m_timecodes.front(); m_previous_timecode = m_timecodes.front(); m_num_timecodes = 0; m_num_repeated_fields = 0; m_timecodes.pop_front(); m_timecode_positions.pop_front(); } m_num_timecodes += 1 + m_current_frame->header.repeat_frame; if (m_seqhdr.interlace_flag && m_current_frame->header.repeat_first_field_flag && !m_current_frame->contains_field) ++m_num_repeated_fields; return next_timecode; }
static FLAC__StreamDecoderReadStatus fhe_read_cb(const FLAC__StreamDecoder *, FLAC__byte buffer[], size_t *bytes, void *client_data) { ogg_packet op; flac_header_extractor_c *fhe = (flac_header_extractor_c *)client_data; if (fhe->done) return FLAC__STREAM_DECODER_READ_STATUS_ABORT; if (ogg_stream_packetout(&fhe->os, &op) != 1) if (!fhe->read_page() || (ogg_stream_packetout(&fhe->os, &op) != 1)) return FLAC__STREAM_DECODER_READ_STATUS_ABORT; if (*bytes < static_cast<size_t>(op.bytes)) mxerror(boost::format(Y("flac_header_extraction: bytes (%1%) < op.bytes (%2%). Could not read the FLAC headers.\n")) % *bytes % op.bytes); int offset = 0; if ((0 == fhe->num_packets) && (ofm_post_1_1_1 == fhe->mode) && (13 < op.bytes)) offset = 9; memcpy(buffer, &op.packet[offset], op.bytes - offset); *bytes = op.bytes - offset; fhe->num_packets++; mxverb(2, boost::format("flac_header_extraction: read packet number %1% with %2% bytes and offset %3%\n") % fhe->num_packets % op.bytes % offset); return FLAC__STREAM_DECODER_READ_STATUS_CONTINUE; }
int mpeg_ts_track_c::new_stream_v_avc() { if (!m_avc_parser) { m_avc_parser = mpeg4::p10::avc_es_parser_cptr(new mpeg4::p10::avc_es_parser_c); m_avc_parser->ignore_nalu_size_length_errors(); if (map_has_key(reader.m_ti.m_nalu_size_lengths, reader.tracks.size())) m_avc_parser->set_nalu_size_length(reader.m_ti.m_nalu_size_lengths[0]); else if (map_has_key(reader.m_ti.m_nalu_size_lengths, -1)) m_avc_parser->set_nalu_size_length(reader.m_ti.m_nalu_size_lengths[-1]); } mxverb(3, boost::format("new_stream_v_avc: packet size: %1%\n") % pes_payload->get_size()); m_avc_parser->add_bytes(pes_payload->get_buffer(), pes_payload->get_size()); if (!m_avc_parser->headers_parsed()) return FILE_STATUS_MOREDATA; fourcc = FOURCC('A', 'V', 'C', '1'); v_width = m_avc_parser->get_width(); v_height = m_avc_parser->get_height(); if (m_avc_parser->has_par_been_found()) { auto dimensions = m_avc_parser->get_display_dimensions(); v_dwidth = dimensions.first; v_dheight = dimensions.second; } return 0; }
static void write_changes(options_cptr &options, kax_analyzer_c *analyzer) { std::vector<EbmlId> ids_to_write; ids_to_write.push_back(KaxInfo::ClassInfos.GlobalId); ids_to_write.push_back(KaxTracks::ClassInfos.GlobalId); ids_to_write.push_back(KaxTags::ClassInfos.GlobalId); ids_to_write.push_back(KaxChapters::ClassInfos.GlobalId); ids_to_write.push_back(KaxAttachments::ClassInfos.GlobalId); for (auto &id_to_write : ids_to_write) { for (auto &target : options->m_targets) { if (!target->get_level1_element()) continue; EbmlMaster &l1_element = *target->get_level1_element(); if (id_to_write != l1_element.Generic().GlobalId) continue; mxverb(2, boost::format(Y("Element %1% is written.\n")) % l1_element.Generic().DebugName); kax_analyzer_c::update_element_result_e result = l1_element.ListSize() ? analyzer->update_element(&l1_element, true) : analyzer->remove_elements(EbmlId(l1_element)); if (kax_analyzer_c::uer_success != result) display_update_element_result(l1_element.Generic(), result); break; } } }
int mpeg_ts_track_c::new_stream_v_mpeg_1_2() { if (!m_m2v_parser) { m_m2v_parser = std::shared_ptr<M2VParser>(new M2VParser); m_m2v_parser->SetProbeMode(); } m_m2v_parser->WriteData(pes_payload->get_buffer(), pes_payload->get_size()); int state = m_m2v_parser->GetState(); if (state != MPV_PARSER_STATE_FRAME) { mxverb(3, boost::format("new_stream_v_mpeg_1_2: no valid frame in %1% bytes\n") % pes_payload->get_size()); return FILE_STATUS_MOREDATA; } MPEG2SequenceHeader seq_hdr = m_m2v_parser->GetSequenceHeader(); std::shared_ptr<MPEGFrame> frame(m_m2v_parser->ReadFrame()); if (!frame) return FILE_STATUS_MOREDATA; fourcc = FOURCC('M', 'P', 'G', '0' + m_m2v_parser->GetMPEGVersion()); v_interlaced = !seq_hdr.progressiveSequence; v_version = m_m2v_parser->GetMPEGVersion(); v_width = seq_hdr.width; v_height = seq_hdr.height; v_frame_rate = seq_hdr.frameOrFieldRate; v_aspect_ratio = seq_hdr.aspectRatio; if ((0 >= v_aspect_ratio) || (1 == v_aspect_ratio)) v_dwidth = v_width; else v_dwidth = (int)(v_height * v_aspect_ratio); v_dheight = v_height; MPEGChunk *raw_seq_hdr_chunk = m_m2v_parser->GetRealSequenceHeader(); if (raw_seq_hdr_chunk) { mxverb(3, boost::format("new_stream_v_mpeg_1_2: sequence header size: %1%\n") % raw_seq_hdr_chunk->GetSize()); raw_seq_hdr = memory_c::clone(raw_seq_hdr_chunk->GetPointer(), raw_seq_hdr_chunk->GetSize()); } mxverb(3, boost::format("new_stream_v_mpeg_1_2: width: %1%, height: %2%\n") % v_width % v_height); if (v_width == 0 || v_height == 0) return FILE_STATUS_MOREDATA; return 0; }
static FLAC__StreamDecoderWriteStatus fhe_write_cb(const FLAC__StreamDecoder *, const FLAC__Frame *, const FLAC__int32 * const [], void *client_data) { mxverb(2, "flac_header_extraction: write cb\n"); ((flac_header_extractor_c *)client_data)->done = true; return FLAC__STREAM_DECODER_WRITE_STATUS_CONTINUE; }
void mm_write_cache_io_c::flush_cache() { if (0 == m_cache_pos) return; size_t bytes_written = mm_proxy_io_c::_write(m_cache, m_cache_pos); mxverb(2, boost::format("mm_write_cache_io_c::flush_cache(): requested %1% written %2%\n") % m_cache_pos % bytes_written); if (bytes_written != m_cache_pos) throw mtx::mm_io::insufficient_space_x(); m_cache_pos = 0; }
bool timecode_factory_v1_c::get_next(packet_cptr &packet) { packet->assigned_timecode = get_at(m_frameno); if (!m_preserve_duration || (0 >= packet->duration)) packet->duration = get_at(m_frameno + 1) - packet->assigned_timecode; m_frameno++; if ((m_frameno > m_ranges[m_current_range].end_frame) && (m_current_range < (m_ranges.size() - 1))) m_current_range++; mxverb(4, boost::format("ext_timecodes v1: tc %1% dur %2% for %3%\n") % packet->assigned_timecode % packet->duration % (m_frameno - 1)); return false; }
/** \brief Handle frame sequences in which too few timecodes are available This function gets called if mkvmerge wants to flush its frame queue but it doesn't have enough timecodes and/or durations available for each queued frame. This can happen in two cases: 1. A picture sequence is found that mkvmerge does not support. An example: Two frames have been read. The first contained a P and a B frame (that's OK so far), but the second one contained another P or I frame without an intermediate dummy frame. 2. The end of the file has been reached but the frame queue contains more frames than the timecode queue. For example: The last frame contained two frames, a P and a B frame. Right afterwards the end of the file is reached. In this case a dummy frame is missing. Both cases can be solved if the source file provides a FPS for this track. The other case is not supported. */ void mpeg4_p2_video_packetizer_c::generate_timecode_and_duration() { if (0.0 >= m_fps) { // TODO: error mxexit(1); } if (m_available_timecodes.empty()) { m_previous_timecode = (int64_t)(m_previous_timecode + 1000000000.0 / m_fps); m_available_timecodes.push_back(timecode_duration_t(m_previous_timecode, (int64_t)(1000000000.0 / m_fps))); mxverb(3, boost::format("mpeg4_p2::flush_frames(): Needed new timecode %1%\n") % m_previous_timecode); ++m_statistics.m_num_generated_timecodes; } }
int mpeg_ts_track_c::new_stream_a_mpeg() { add_pes_payload_to_probe_data(); mp3_header_t header; int offset = find_mp3_header(m_probe_data->get_buffer(), m_probe_data->get_size()); if (-1 == offset) return FILE_STATUS_MOREDATA; decode_mp3_header(m_probe_data->get_buffer() + offset, &header); a_channels = header.channels; a_sample_rate = header.sampling_frequency; fourcc = FOURCC('M', 'P', '0' + header.layer, ' '); mxverb(3, boost::format("new_stream_a_mpeg: Channels: %1%, sample rate: %2%\n") %a_channels % a_sample_rate); return 0; }
void tta_reader_c::read_headers() { if (g_identifying) return; try { int tag_size = skip_id3v2_tag(*m_in); if (0 > tag_size) mxerror_fn(m_ti.m_fname, boost::format(Y("tta_reader: tag_size < 0 in the c'tor. %1%\n")) % BUGMSG); m_size -= tag_size; if (m_in->read(&header, sizeof(tta_file_header_t)) != sizeof(tta_file_header_t)) mxerror_fn(m_ti.m_fname, Y("The file header is too short.\n")); uint64_t seek_sum = m_in->getFilePointer() + 4 - tag_size; m_size -= id3_tag_present_at_end(*m_in); uint32_t seek_point; do { seek_point = m_in->read_uint32_le(); seek_sum += seek_point + 4; seek_points.push_back(seek_point); } while (seek_sum < m_size); mxverb(2, boost::format("tta: ch %1% bps %2% sr %3% dl %4% seek_sum %5% size %6% num %7%\n") % get_uint16_le(&header.channels) % get_uint16_le(&header.bits_per_sample) % get_uint32_le(&header.sample_rate) % get_uint32_le(&header.data_length) % seek_sum % m_size % seek_points.size()); if (seek_sum != m_size) mxerror_fn(m_ti.m_fname, Y("The seek table in this TTA file seems to be broken.\n")); m_in->skip(4); pos = 0; m_ti.m_id = 0; // ID for this track. } catch (...) { throw mtx::input::open_x(); } show_demuxer_info(); }
void generic_packetizer_c::apply_factory_once(packet_cptr &packet) { if (!m_timestamp_factory) { packet->assigned_timecode = packet->timecode; packet->gap_following = false; } else packet->gap_following = m_timestamp_factory->get_next(packet); packet->factory_applied = true; mxverb(4, boost::format("apply_factory_once(): source %1% t %2% tbf %3% at %4%\n") % packet->source->get_source_track_num() % packet->timecode % packet->timecode_before_factory % packet->assigned_timecode); m_max_timecode_seen = std::max(m_max_timecode_seen, packet->assigned_timecode + packet->duration); m_reader->m_max_timecode_seen = std::max(m_max_timecode_seen, m_reader->m_max_timecode_seen); ++m_next_packet_wo_assigned_timecode; }
void mpeg4_p10_video_packetizer_c::setup_nalu_size_len_change() { if (!m_ti.m_private_data || (5 > m_ti.m_private_data->get_size())) return; auto private_data = m_ti.m_private_data->get_buffer(); m_nalu_size_len_src = (private_data[4] & 0x03) + 1; m_nalu_size_len_dst = m_nalu_size_len_src; if (!m_ti.m_nalu_size_length || (m_ti.m_nalu_size_length == m_nalu_size_len_src)) return; m_nalu_size_len_dst = m_ti.m_nalu_size_length; private_data[4] = (private_data[4] & 0xfc) | (m_nalu_size_len_dst - 1); m_max_nalu_size = 1ll << (8 * m_nalu_size_len_dst); set_codec_private(m_ti.m_private_data); mxverb(2, boost::format("mpeg4_p10: Adjusting NALU size length from %1% to %2%\n") % m_nalu_size_len_src % m_nalu_size_len_dst); }
void vc1::es_parser_c::handle_frame_packet(memory_cptr packet) { flush_frame(); vc1::frame_header_t frame_header; if (!m_seqhdr_found || !vc1::parse_frame_header(packet->get_buffer(), packet->get_size(), frame_header, m_seqhdr)) return; m_current_frame = frame_cptr(new frame_t); m_current_frame->data = packet; m_current_frame->data->grab(); memcpy(&m_current_frame->header, &frame_header, sizeof(frame_header_t)); if (!m_timecodes.empty()) mxverb(2, boost::format("vc1::es_parser_c::handle_frame_packet: next provided timecode %1% next calculated timecode %2%\n") % format_timecode(m_timecodes.front()) % format_timecode(peek_next_calculated_timecode())); }
bool wav_dts_demuxer_c::probe(mm_io_cptr &io) { io->save_pos(); int len = io->read(m_buf[m_cur_buf]->get_buffer(), DTS_READ_SIZE); io->restore_pos(); if (detect_dts(m_buf[m_cur_buf]->get_buffer(), len, m_pack_14_16, m_swap_bytes)) { len = decode_buffer(len); int pos = find_consecutive_dts_headers(m_buf[m_cur_buf]->get_buffer(), len, 5); if (0 <= pos) { if (0 > find_dts_header(m_buf[m_cur_buf]->get_buffer() + pos, len - pos, &m_dtsheader)) return false; mxverb(3, boost::format("DTSinWAV: 14->16 %1% swap %2%\n") % m_pack_14_16 % m_swap_bytes); return true; } } return false; }
int mpeg_ts_track_c::new_stream_a_ac3() { add_pes_payload_to_probe_data(); ac3::parser_c parser; parser.add_bytes(m_probe_data->get_buffer(), m_probe_data->get_size()); if (!parser.frame_available()) return FILE_STATUS_MOREDATA; ac3::frame_c header = parser.get_frame(); mxverb(2, boost::format("first ac3 header bsid %1% channels %2% sample_rate %3% bytes %4% samples %5%\n") % header.m_bs_id % header.m_channels % header.m_sample_rate % header.m_bytes % header.m_samples); a_channels = header.m_channels; a_sample_rate = header.m_sample_rate; a_bsid = header.m_bs_id; return 0; }
void mpeg_es_reader_c::read_headers() { try { M2VParser parser; // Let's find the first frame. We need its information like // resolution, MPEG version etc. parser.SetProbeMode(); if (!read_frame(parser, *m_in, 1024 * 1024)) throw mtx::input::header_parsing_x(); m_in->setFilePointer(0); MPEG2SequenceHeader seq_hdr = parser.GetSequenceHeader(); version = parser.GetMPEGVersion(); interlaced = !seq_hdr.progressiveSequence; width = seq_hdr.width; height = seq_hdr.height; frame_rate = seq_hdr.progressiveSequence ? seq_hdr.frameOrFieldRate : seq_hdr.frameOrFieldRate * 2.0f; aspect_ratio = seq_hdr.aspectRatio; if ((0 >= aspect_ratio) || (1 == aspect_ratio)) dwidth = width; else dwidth = (int)(height * aspect_ratio); dheight = height; MPEGChunk *raw_seq_hdr = parser.GetRealSequenceHeader(); if (raw_seq_hdr) { m_ti.m_private_data = (unsigned char *)safememdup(raw_seq_hdr->GetPointer(), raw_seq_hdr->GetSize()); m_ti.m_private_size = raw_seq_hdr->GetSize(); } mxverb(2, boost::format("mpeg_es_reader: version %1% width %2% height %3% FPS %4% AR %5%\n") % version % width % height % frame_rate % aspect_ratio); } catch (mtx::mm_io::exception &) { throw mtx::input::open_x(); } show_demuxer_info(); }
file_status_e tta_reader_c::read(generic_packetizer_c *, bool) { if (seek_points.size() <= pos) return flush_packetizers(); unsigned char *buf = (unsigned char *)safemalloc(seek_points[pos]); int nread = m_in->read(buf, seek_points[pos]); if (0 >= nread) return flush_packetizers(); pos++; memory_cptr mem(new memory_c(buf, nread, true)); if (seek_points.size() <= pos) { double samples_left = (double)get_uint32_le(&header.data_length) - (seek_points.size() - 1) * TTA_FRAME_TIME * get_uint32_le(&header.sample_rate); mxverb(2, boost::format("tta: samples_left %1%\n") % samples_left); PTZR0->process(new packet_t(mem, -1, irnd(samples_left * 1000000000.0l / get_uint32_le(&header.sample_rate)))); } else PTZR0->process(new packet_t(mem)); return seek_points.size() <= pos ? flush_packetizers() : FILE_STATUS_MOREDATA; }