mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2025-01-13 05:31:44 +00:00
AVC/h.264: generate timecodes if provided timecodes are not enough
This commit is contained in:
parent
b37a7b3202
commit
787339f03a
@ -569,6 +569,7 @@ mpeg4::p10::avc_es_parser_c::avc_es_parser_c()
|
||||
, m_first_keyframe_found(false)
|
||||
, m_recovery_point_valid(false)
|
||||
, m_b_frames_since_keyframe(false)
|
||||
, m_max_timecode(0)
|
||||
, m_generate_timecodes(false)
|
||||
, m_have_incomplete_frame(false)
|
||||
, m_ignore_nalu_size_length_errors(false)
|
||||
@ -684,6 +685,8 @@ mpeg4::p10::avc_es_parser_c::add_timecode(int64_t timecode) {
|
||||
--i;
|
||||
}
|
||||
m_timecodes.insert(i, timecode);
|
||||
|
||||
m_max_timecode = std::max(timecode, m_max_timecode);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1053,6 +1056,9 @@ mpeg4::p10::avc_es_parser_c::default_cleanup() {
|
||||
std::deque<avc_frame_t>::iterator i(m_frames.begin());
|
||||
std::deque<int64_t>::iterator t(m_timecodes.begin());
|
||||
|
||||
if (m_frames.size() > m_timecodes.size())
|
||||
create_missing_timecodes();
|
||||
|
||||
int64_t r = i->m_start = i->m_end = *t;
|
||||
|
||||
++i;
|
||||
@ -1094,12 +1100,8 @@ mpeg4::p10::avc_es_parser_c::cleanup() {
|
||||
// (cluster_helper etc).
|
||||
i->m_keyframe = true;
|
||||
|
||||
if (m_timecodes.size() < m_frames.size()) {
|
||||
mxverb(4, boost::format("mpeg4::p10::avc_es_parser_c::cleanup() numfr %1% sti %2%\n") % m_frames.size() % m_timecodes.size());
|
||||
m_timecodes.erase(m_timecodes.begin(), m_timecodes.begin() + m_frames.size());
|
||||
m_frames.clear();
|
||||
return;
|
||||
}
|
||||
if (m_frames.size() > m_timecodes.size())
|
||||
create_missing_timecodes();
|
||||
|
||||
slice_info_t &idr = i->m_si;
|
||||
sps_info_t &sps = m_sps_info_list[idr.sps];
|
||||
@ -1186,7 +1188,7 @@ mpeg4::p10::avc_es_parser_c::cleanup() {
|
||||
}
|
||||
|
||||
m_frames_out.insert(m_frames_out.end(), m_frames.begin(), m_frames.end());
|
||||
m_timecodes.erase(m_timecodes.begin(), m_timecodes.begin() + m_frames.size());
|
||||
m_timecodes.erase(m_timecodes.begin(), m_timecodes.begin() + std::min(num_frames, num_timecodes));
|
||||
m_frames.clear();
|
||||
}
|
||||
|
||||
@ -1300,3 +1302,14 @@ mpeg4::p10::avc_es_parser_c::init_nalu_names() {
|
||||
m_nalu_names_by_type[NALU_TYPE_END_OF_STREAM] = "end of stream";
|
||||
m_nalu_names_by_type[NALU_TYPE_FILLER_DATA] = "filler";
|
||||
}
|
||||
|
||||
void
|
||||
mpeg4::p10::avc_es_parser_c::create_missing_timecodes() {
|
||||
size_t num_timecodes = m_timecodes.size();
|
||||
size_t num_frames = m_frames.size();
|
||||
|
||||
while (num_timecodes < num_frames) {
|
||||
++num_timecodes;
|
||||
add_timecode(m_max_timecode + m_default_duration);
|
||||
}
|
||||
}
|
||||
|
@ -196,6 +196,7 @@ namespace mpeg4 {
|
||||
|
||||
std::deque<avc_frame_t> m_frames, m_frames_out;
|
||||
std::deque<int64_t> m_timecodes;
|
||||
int64_t m_max_timecode;
|
||||
|
||||
bool m_generate_timecodes;
|
||||
|
||||
@ -219,6 +220,10 @@ namespace mpeg4 {
|
||||
avc_es_parser_c();
|
||||
~avc_es_parser_c();
|
||||
|
||||
void set_default_duration(int64_t default_duration) {
|
||||
m_default_duration = default_duration;
|
||||
}
|
||||
|
||||
void enable_timecode_generation(int64_t default_duration) {
|
||||
m_default_duration = default_duration;
|
||||
m_generate_timecodes = true;
|
||||
@ -308,6 +313,7 @@ namespace mpeg4 {
|
||||
void write_nalu_size(unsigned char *buffer, size_t size, int this_nalu_size_length = -1);
|
||||
memory_cptr create_nalu_with_size(const memory_cptr &src, bool add_extra_data = false);
|
||||
void init_nalu_names();
|
||||
void create_missing_timecodes();
|
||||
};
|
||||
typedef counted_ptr<avc_es_parser_c> avc_es_parser_cptr;
|
||||
};
|
||||
|
@ -582,7 +582,7 @@ mpeg_ts_reader_c::new_stream_v_avc(unsigned char *buf,
|
||||
% sps_info.timing_info_present % sps_info.num_units_in_tick % sps_info.time_scale % sps_info.fixed_frame_rate);
|
||||
|
||||
if (sps_info.timing_info_present && sps_info.num_units_in_tick)
|
||||
track->v_frame_rate = sps_info.time_scale / sps_info.num_units_in_tick;
|
||||
track->v_frame_rate = static_cast<float>(sps_info.time_scale) / sps_info.num_units_in_tick;
|
||||
|
||||
if (sps_info.ar_found) {
|
||||
float aspect_ratio = (float)sps_info.width / (float)sps_info.height * (float)sps_info.par_num / (float)sps_info.par_den;
|
||||
@ -977,9 +977,13 @@ mpeg_ts_reader_c::create_mpeg4_p10_es_video_packetizer(mpeg_ts_track_ptr &track)
|
||||
mpeg4_p10_es_video_packetizer_c *avcpacketizer = new mpeg4_p10_es_video_packetizer_c(this, m_ti, track->v_avcc, track->v_width, track->v_height);
|
||||
track->ptzr = add_packetizer(avcpacketizer);
|
||||
|
||||
avcpacketizer->enable_timecode_generation(false);
|
||||
if (track->v_frame_rate)
|
||||
avcpacketizer->set_track_default_duration(static_cast<int64_t>(1000000000.0 / track->v_frame_rate));
|
||||
|
||||
// This is intentional so that the AVC parser knows the actual
|
||||
// default duration from above but only generates timecode in
|
||||
// emergencies.
|
||||
avcpacketizer->enable_timecode_generation(false);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -92,7 +92,7 @@ mpeg4_p10_es_video_packetizer_c::add_extra_data(memory_cptr data) {
|
||||
int
|
||||
mpeg4_p10_es_video_packetizer_c::process(packet_cptr packet) {
|
||||
try {
|
||||
if (!m_allow_timecode_generation)
|
||||
if (packet->has_timecode())
|
||||
m_parser.add_timecode(packet->timecode);
|
||||
m_parser.add_bytes(packet->data->get_buffer(), packet->data->get_size());
|
||||
flush_frames();
|
||||
@ -168,6 +168,12 @@ mpeg4_p10_es_video_packetizer_c::enable_timecode_generation(bool enable,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
mpeg4_p10_es_video_packetizer_c::set_track_default_duration(int64_t default_duration) {
|
||||
m_parser.set_default_duration(default_duration);
|
||||
generic_packetizer_c::set_track_default_duration(default_duration);
|
||||
}
|
||||
|
||||
void
|
||||
mpeg4_p10_es_video_packetizer_c::connect(generic_packetizer_c *src,
|
||||
int64_t p_append_timecode_offset) {
|
||||
|
@ -40,6 +40,7 @@ public:
|
||||
|
||||
virtual void enable_timecode_generation(bool enable, int64_t default_duration = -1);
|
||||
virtual void extract_aspect_ratio();
|
||||
virtual void set_track_default_duration(int64_t default_duration);
|
||||
|
||||
virtual const char *get_format_name() {
|
||||
return "AVC/h.264";
|
||||
|
Loading…
Reference in New Issue
Block a user