mirror of
https://gitlab.com/mbunkus/mkvtoolnix.git
synced 2024-12-23 19:31:44 +00:00
Modified getting the FPS from MP4 files. More cases (CTTS present or not, durmap table with more than one entry) are handled now.
This commit is contained in:
parent
6f662a61ba
commit
f4365020f0
@ -1,5 +1,8 @@
|
||||
2005-03-06 Moritz Bunkus <moritz@bunkus.org>
|
||||
|
||||
* mkvmerge: bug fix: Extracting the FPS from some AVC MP4 files
|
||||
did not work.
|
||||
|
||||
* mkvmerge: bug fix: Appending + splitting was segfaulting if used
|
||||
together and at least one split occured after a track has been
|
||||
appended.
|
||||
|
@ -892,6 +892,9 @@ qtmp4_reader_c::handle_stss_atom(qtmp4_demuxer_ptr &new_dmx,
|
||||
new_dmx->keyframe_table.push_back(io->read_uint32_be());
|
||||
|
||||
mxverb(2, PFX "%*sSync/keyframe table: %u entries\n", level * 2, "", count);
|
||||
for (i = 0; i < count; ++i)
|
||||
mxverb(4, PFX "%*skeyframe at %u\n", (level + 1) * 2, "",
|
||||
new_dmx->keyframe_table[i]);
|
||||
}
|
||||
|
||||
void
|
||||
@ -1417,46 +1420,7 @@ qtmp4_reader_c::create_packetizer(int64_t tid) {
|
||||
"that it looks like you expected it to.\n",
|
||||
ti.fname.c_str(), (int64_t)dmx->id);
|
||||
|
||||
fps = 0.0;
|
||||
if ((dmx->durmap_table.size() == 1) &&
|
||||
(dmx->durmap_table[0].duration != 0)) {
|
||||
if ((dmx->sample_size != 0) ||
|
||||
(dmx->frame_offset_table.size() == 0)) {
|
||||
// Constant FPS. Let's set the default duration.
|
||||
fps = (double)dmx->timescale /
|
||||
(double)dmx->durmap_table[0].duration;
|
||||
mxverb(3, PFX "fps1: %f\n", fps);
|
||||
|
||||
} else if ((dmx->sample_table.size() > 0) &&
|
||||
(dmx->sample_table.size() ==
|
||||
dmx->frame_offset_table.size())) {
|
||||
// Constant FPS but the frame offsets are used. This one is
|
||||
// a bit trickier. I have to find the maximum timecode including
|
||||
// the frame offsets (for PTS/DTS conversion) and divide that
|
||||
// by the number of frames.
|
||||
int64_t max_tc;
|
||||
int i;
|
||||
|
||||
max_tc = 0;
|
||||
|
||||
for (i = 0; i < dmx->sample_table.size(); i++) {
|
||||
int64_t timecode;
|
||||
|
||||
timecode = ((int64_t)dmx->sample_table[i].pts +
|
||||
(int64_t)dmx->frame_offset_table[dmx->pos]) *
|
||||
1000000000 / dmx->timescale;
|
||||
if (timecode > max_tc)
|
||||
max_tc = timecode;
|
||||
}
|
||||
if (max_tc > 0)
|
||||
fps = (double)dmx->sample_table.size() * 1000000000.0 /
|
||||
(double)max_tc;
|
||||
|
||||
mxverb(3, PFX "fps2: max_tc %lld s_t.s %u fps %f\n", max_tc,
|
||||
dmx->sample_table.size(), fps);
|
||||
}
|
||||
}
|
||||
|
||||
fps = dmx->calculate_fps();
|
||||
ti.private_size = dmx->priv_size;
|
||||
ti.private_data = dmx->priv;
|
||||
dmx->ptzr =
|
||||
@ -1618,3 +1582,65 @@ qtmp4_reader_c::add_available_track_ids() {
|
||||
for (i =0 ; i < demuxers.size(); i++)
|
||||
available_track_ids.push_back(demuxers[i]->id);
|
||||
}
|
||||
|
||||
double
|
||||
qtmp4_demuxer_t::calculate_fps() {
|
||||
double fps;
|
||||
|
||||
fps = 0.0;
|
||||
|
||||
if ((1 == durmap_table.size()) && (0 != durmap_table[0].duration) &&
|
||||
((0 != sample_size) || (0 == frame_offset_table.size()))) {
|
||||
// Constant FPS. Let's set the default duration.
|
||||
fps = (double)timescale / (double)durmap_table[0].duration;
|
||||
mxverb(3, PFX "calculate_fps: case 1: %f\n", fps);
|
||||
return fps;
|
||||
}
|
||||
|
||||
if ((0 < sample_table.size()) &&
|
||||
(sample_table.size() == frame_offset_table.size())) {
|
||||
// Constant FPS but the frame offsets are used. This one is
|
||||
// a bit trickier. I have to find the maximum timecode including
|
||||
// the frame offsets (for PTS/DTS conversion) and divide that
|
||||
// by the number of frames.
|
||||
int64_t max_tc;
|
||||
int i;
|
||||
|
||||
max_tc = 0;
|
||||
|
||||
for (i = 0; i < sample_table.size(); ++i) {
|
||||
int64_t timecode;
|
||||
|
||||
timecode = ((int64_t)sample_table[i].pts +
|
||||
(int64_t)frame_offset_table[pos]) * 1000000000 / timescale;
|
||||
if (timecode > max_tc)
|
||||
max_tc = timecode;
|
||||
}
|
||||
if (0 < max_tc)
|
||||
fps = (double)sample_table.size() * 1000000000.0 / (double)max_tc;
|
||||
|
||||
mxverb(3, PFX "calculate_fps: case 2: max_tc %lld s_t.s %u fps %f\n",
|
||||
max_tc, sample_table.size(), fps);
|
||||
return fps;
|
||||
}
|
||||
|
||||
if (0 < sample_table.size()) {
|
||||
int64_t max_tc;
|
||||
int i;
|
||||
|
||||
max_tc = 0;
|
||||
|
||||
for (i = 0; i < sample_table.size(); ++i)
|
||||
if ((int64_t)sample_table[i].pts > max_tc)
|
||||
max_tc = (int64_t)sample_table[i].pts;
|
||||
if (0 < max_tc)
|
||||
fps = (double)sample_table.size() * 1000000000.0 / (double)max_tc;
|
||||
|
||||
mxverb(3, PFX "calculate_fps: case 3: max_tc %lld s_t.s %u fps %f\n",
|
||||
max_tc, sample_table.size(), fps);
|
||||
return fps;
|
||||
}
|
||||
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
|
@ -156,6 +156,8 @@ struct qtmp4_demuxer_t {
|
||||
safefree(esds.decoder_config);
|
||||
safefree(esds.sl_config);
|
||||
}
|
||||
|
||||
double calculate_fps();
|
||||
};
|
||||
typedef counted_ptr<qtmp4_demuxer_t> qtmp4_demuxer_ptr;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user