From f4365020f0e5d99e4b7522f3d2dacc2f5e9c1102 Mon Sep 17 00:00:00 2001 From: Moritz Bunkus Date: Sun, 6 Mar 2005 19:07:17 +0000 Subject: [PATCH] Modified getting the FPS from MP4 files. More cases (CTTS present or not, durmap table with more than one entry) are handled now. --- ChangeLog | 3 ++ src/input/r_qtmp4.cpp | 106 ++++++++++++++++++++++++++---------------- src/input/r_qtmp4.h | 2 + 3 files changed, 71 insertions(+), 40 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0b1d0172f..04954b792 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,8 @@ 2005-03-06 Moritz Bunkus + * 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. diff --git a/src/input/r_qtmp4.cpp b/src/input/r_qtmp4.cpp index 3f484de47..d088719f6 100644 --- a/src/input/r_qtmp4.cpp +++ b/src/input/r_qtmp4.cpp @@ -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; +} + diff --git a/src/input/r_qtmp4.h b/src/input/r_qtmp4.h index 3049a5bc3..a42631b99 100644 --- a/src/input/r_qtmp4.h +++ b/src/input/r_qtmp4.h @@ -156,6 +156,8 @@ struct qtmp4_demuxer_t { safefree(esds.decoder_config); safefree(esds.sl_config); } + + double calculate_fps(); }; typedef counted_ptr qtmp4_demuxer_ptr;