diff --git a/src/common/hacks.cpp b/src/common/hacks.cpp index 4b34e50c4..0993c808a 100644 --- a/src/common/hacks.cpp +++ b/src/common/hacks.cpp @@ -36,6 +36,7 @@ static const char *mosu_hacks[] = { ENGAGE_NO_VARIABLE_DATA, ENGAGE_NO_DEFAULT_HEADER_VALUES, ENGAGE_FORCE_PASSTHROUGH_PACKETIZER, + ENGAGE_AVC_USE_BFRAMES, NULL }; static vector engaged_hacks; diff --git a/src/common/hacks.h b/src/common/hacks.h index 94e51879e..bb99b9fe4 100644 --- a/src/common/hacks.h +++ b/src/common/hacks.h @@ -33,6 +33,7 @@ using namespace std; #define ENGAGE_NO_VARIABLE_DATA "no_variable_data" #define ENGAGE_NO_DEFAULT_HEADER_VALUES "no_default_header_values" #define ENGAGE_FORCE_PASSTHROUGH_PACKETIZER "force_passthrough_packetizer" +#define ENGAGE_AVC_USE_BFRAMES "avc_use_bframes" void MTX_DLL_API engage_hacks(const string &hacks); bool MTX_DLL_API hack_engaged(const string &hack); diff --git a/src/input/r_qtmp4.cpp b/src/input/r_qtmp4.cpp index 0bc1acde5..18eb1d1b0 100644 --- a/src/input/r_qtmp4.cpp +++ b/src/input/r_qtmp4.cpp @@ -29,6 +29,7 @@ #include "aac_common.h" #include "avilib.h" #include "common.h" +#include "hacks.h" #include "matroska.h" #include "p_aac.h" #include "p_mp3.h" @@ -1037,7 +1038,8 @@ qtmp4_reader_c::handle_video_with_bframes(qtmp4_demuxer_ptr &dmx, mxerror(FMT_FN "The video track does not start with a key " "frame and a P frame but contains B frames. This is not " "supported.\n", ti->fname.c_str()); - fref = dmx->references[1]; + if (dmx->avc_use_bframes) + fref = dmx->references[1]; } else { // This is a P frame. At the moment it references the second stored frame @@ -1452,6 +1454,10 @@ qtmp4_reader_c::create_packetizer(int64_t tid) { false, ti)); ti->private_data = NULL; + if (hack_engaged(ENGAGE_AVC_USE_BFRAMES)) + dmx->avc_use_bframes = true; + else + PTZR(dmx->ptzr)->relaxed_timecode_checking = true; } else { ti->private_size = dmx->v_stsd_size; diff --git a/src/input/r_qtmp4.h b/src/input/r_qtmp4.h index 377c89e42..11c9791de 100644 --- a/src/input/r_qtmp4.h +++ b/src/input/r_qtmp4.h @@ -118,6 +118,7 @@ struct qtmp4_demuxer_t { uint32_t v_width, v_height, v_bitdepth; int64_t v_dts_offset; deque references; + bool avc_use_bframes; int64_t max_timecode; uint32_t a_channels, a_bitdepth; float a_samplerate; @@ -137,6 +138,7 @@ struct qtmp4_demuxer_t { esds_parsed(false), v_stsd(NULL), v_stsd_size(0), v_width(0), v_height(0), v_bitdepth(0), v_dts_offset(0), + avc_use_bframes(false), max_timecode(0), a_channels(0), a_bitdepth(0), a_samplerate(0.0), priv(NULL), priv_size(0), diff --git a/src/merge/pr_generic.cpp b/src/merge/pr_generic.cpp index fbde1738b..3404d117d 100644 --- a/src/merge/pr_generic.cpp +++ b/src/merge/pr_generic.cpp @@ -55,6 +55,7 @@ generic_packetizer_c::generic_packetizer_c(generic_reader_c *nreader, enqueued_bytes = 0; safety_last_timecode = 0; safety_last_duration = 0; + relaxed_timecode_checking = false; last_cue_timecode = -1; correction_timecode_offset = 0; append_timecode_offset = 0; @@ -943,7 +944,8 @@ generic_packetizer_c::add_packet2(packet_t *pack) { // 'timecode < safety_last_timecode' may only occur for B frames. In this // case we have the coding order, e.g. IPB1B2 and the timecodes // I: 0, P: 120, B1: 40, B2: 80. - if ((pack->timecode < safety_last_timecode) && (pack->fref < 0)) { + if (!relaxed_timecode_checking && + (pack->timecode < safety_last_timecode) && (pack->fref < 0)) { if (htrack_type == track_audio) { int64_t needed_timecode_offset; diff --git a/src/merge/pr_generic.h b/src/merge/pr_generic.h index c47a59319..ebeff663c 100644 --- a/src/merge/pr_generic.h +++ b/src/merge/pr_generic.h @@ -446,6 +446,7 @@ public: int connected_to; int64_t correction_timecode_offset; int64_t append_timecode_offset, max_timecode_seen; + bool relaxed_timecode_checking; public: generic_packetizer_c(generic_reader_c *nreader, track_info_c *nti)