diff --git a/Source/Common/Output_Mkv.cpp b/Source/Common/Output_Mkv.cpp index 3599c401..942a060c 100644 --- a/Source/Common/Output_Mkv.cpp +++ b/Source/Common/Output_Mkv.cpp @@ -12,7 +12,7 @@ using namespace std; -static const unsigned char matroska_writer_header[] = { 0x1A, 0x45, 0xDF, 0xA3, 0xA3, 0x42, 0x86, 0x81, 0x01, 0x42, 0xF7, 0x81, 0x01, 0x42, 0xF2, 0x81, 0x04, 0x42, 0xF3, 0x81, 0x08, 0x42, 0x82, 0x88, 0x6D, 0x61, 0x74, 0x72, 0x6F, 0x73, 0x6B, 0x61, 0x42, 0x87, 0x81, 0x04, 0x42, 0x85, 0x81, 0x02, 0x18, 0x53, 0x80, 0x67, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x11, 0x4D, 0x9B, 0x74, 0xC6, 0xEC, 0x84, 0x00, 0x00, 0x00, 0x00, 0x4D, 0xBB, 0x8B, 0x53, 0xAB, 0x84, 0x15, 0x49, 0xA9, 0x66, 0x53, 0xAC, 0x81, 0xA1, 0x4D, 0xBB, 0x8B, 0x53, 0xAB, 0x84, 0x16, 0x54, 0xAE, 0x6B, 0x53, 0xAC, 0x81, 0xF3, 0xEC, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x49, 0xA9, 0x66, 0xCD, 0xEC, 0x84, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xD7, 0xB1, 0x83, 0x0F, 0x42, 0x40, 0x4D, 0x80, 0x8E, 0x44, 0x56, 0x52, 0x65, 0x73, 0x63, 0x75, 0x65, 0x20, 0x30, 0x30, 0x2E, 0x30, 0x30, 0x57, 0x41, 0x8E, 0x44, 0x56, 0x52, 0x65, 0x73, 0x63, 0x75, 0x65, 0x20, 0x30, 0x30, 0x2E, 0x30, 0x30, 0xEC, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x54, 0xAE, 0x6B, 0x41, 0x14, 0xEC, 0x84, 0x00, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xD7, 0x81, 0x01, 0x73, 0xC5, 0x81, 0x01, 0xEC, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x81, 0x00, 0x22, 0xB5, 0x9C, 0x83, 0x75, 0x6E, 0x64, 0x83, 0x81, 0x01, 0x23, 0xE3, 0x83, 0x84, 0x01, 0xFD, 0x22, 0x8A, 0x86, 0x8F, 0x56, 0x5F, 0x4D, 0x53, 0x2F, 0x56, 0x46, 0x57, 0x2F, 0x46, 0x4F, 0x55, 0x52, 0x43, 0x43, 0xE0, 0xA6, 0xB0, 0x82, 0x00, 0x00, 0xBA, 0x82, 0x00, 0x00, 0x9A, 0x81, 0x01, 0x9D, 0x81, 0x06, 0x54, 0xB0, 0x81, 0x04, 0x54, 0xBA, 0x81, 0x03, 0x54, 0xB2, 0x81, 0x03, 0xEC, 0x8A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xA2, 0xA8, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x76, 0x32, 0x31, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x8C, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xD7, 0x81, 0x02, 0x73, 0xC5, 0x81, 0x02, 0xEC, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x81, 0x00, 0x22, 0xB5, 0x9C, 0x83, 0x75, 0x6E, 0x64, 0x86, 0x8D, 0x41, 0x5F, 0x50, 0x43, 0x4D, 0x2F, 0x49, 0x4E, 0x54, 0x2F, 0x4C, 0x49, 0x54, 0x83, 0x81, 0x02, 0xE1, 0x91, 0x9F, 0x81, 0x02, 0xB5, 0x88, 0x40, 0xE7, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x64, 0x81, 0x20, 0xEC, 0x9D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; +static const unsigned char matroska_writer_header[] = { 0x1A, 0x45, 0xDF, 0xA3, 0xA3, 0x42, 0x86, 0x81, 0x01, 0x42, 0xF7, 0x81, 0x01, 0x42, 0xF2, 0x81, 0x04, 0x42, 0xF3, 0x81, 0x08, 0x42, 0x82, 0x88, 0x6D, 0x61, 0x74, 0x72, 0x6F, 0x73, 0x6B, 0x61, 0x42, 0x87, 0x81, 0x04, 0x42, 0x85, 0x81, 0x02, 0x18, 0x53, 0x80, 0x67, 0x01, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x11, 0x4D, 0x9B, 0x74, 0xC6, 0xEC, 0x84, 0x00, 0x00, 0x00, 0x00, 0x4D, 0xBB, 0x8B, 0x53, 0xAB, 0x84, 0x15, 0x49, 0xA9, 0x66, 0x53, 0xAC, 0x81, 0xA1, 0x4D, 0xBB, 0x8B, 0x53, 0xAB, 0x84, 0x16, 0x54, 0xAE, 0x6B, 0x53, 0xAC, 0x81, 0xF3, 0xEC, 0x8D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x93, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x4D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x15, 0x49, 0xA9, 0x66, 0xCD, 0xEC, 0x84, 0x00, 0x00, 0x00, 0x00, 0x2A, 0xD7, 0xB1, 0x83, 0x0F, 0x42, 0x40, 0x4D, 0x80, 0x8E, 0x44, 0x56, 0x52, 0x65, 0x73, 0x63, 0x75, 0x65, 0x20, 0x30, 0x30, 0x2E, 0x30, 0x30, 0x57, 0x41, 0x8E, 0x44, 0x56, 0x52, 0x65, 0x73, 0x63, 0x75, 0x65, 0x20, 0x30, 0x30, 0x2E, 0x30, 0x30, 0xEC, 0x91, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x16, 0x54, 0xAE, 0x6B, 0x41, 0x14, 0xEC, 0x84, 0x00, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x98, 0xD7, 0x81, 0x01, 0x73, 0xC5, 0x81, 0x01, 0xEC, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x81, 0x00, 0x22, 0xB5, 0x9C, 0x83, 0x75, 0x6E, 0x64, 0x83, 0x81, 0x01, 0x23, 0xE3, 0x83, 0x84, 0x01, 0xFD, 0x22, 0x8A, 0x86, 0x8F, 0x56, 0x5F, 0x4D, 0x53, 0x2F, 0x56, 0x46, 0x57, 0x2F, 0x46, 0x4F, 0x55, 0x52, 0x43, 0x43, 0xE0, 0xA6, 0xB0, 0x82, 0x00, 0x00, 0xBA, 0x82, 0x00, 0x00, 0x9A, 0x81, 0x01, 0x9D, 0x81, 0x06, 0x54, 0xB0, 0x81, 0x04, 0x54, 0xBA, 0x81, 0x03, 0x54, 0xB2, 0x81, 0x03, 0xEC, 0x8A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x63, 0xA2, 0xA8, 0x28, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x18, 0x00, 0x76, 0x32, 0x31, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xEC, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xAE, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x41, 0xD7, 0x81, 0x02, 0x73, 0xC5, 0x81, 0x02, 0xEC, 0x89, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x9C, 0x81, 0x00, 0x22, 0xB5, 0x9C, 0x83, 0x75, 0x6E, 0x64, 0x86, 0x8D, 0x41, 0x5F, 0x50, 0x43, 0x4D, 0x2F, 0x49, 0x4E, 0x54, 0x2F, 0x4C, 0x49, 0x54, 0x83, 0x81, 0x02, 0xE1, 0x91, 0x9F, 0x81, 0x02, 0xB5, 0x88, 0x40, 0xE7, 0x70, 0x00, 0x00, 0x00, 0x00, 0x00, 0x62, 0x64, 0x81, 0x20, 0xEC, 0xA1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const unsigned char matroska_writer_header_seek[] = { 0x4D, 0xBB, 0x92, 0x53, 0xAB, 0x84, 0x1C, 0x53, 0xBB, 0x6B, 0x53, 0xAC, 0x88 }; static const unsigned char matroska_writer_header_timecode[] = { 0x41, 0xE4, 0x8A, 0x41, 0xE7, 0x83, 0x31, 0x32, 0x31, 0x41, 0xF0, 0x81, 0x79 }; static const unsigned char matroska_writer_header_texttrack[] = { 0xAE, 0xA1, 0xD7, 0x81, 0x03, 0x73, 0xC5, 0x81, 0x03, 0xEC, 0x85, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x81, 0x11, 0x86, 0x8B, 0x53, 0x5F, 0x54, 0x45, 0x58, 0x54, 0x2F, 0x55, 0x54, 0x46, 0x38, 0x9C, 0x81, 0x00 }; @@ -290,7 +290,7 @@ void matroska_writer::write_header() void matroska_writer::write_frame(const char* video_buffer, int video_size, const char* audio_buffer, int audio_size, timecode_struct timecode) { // Cues - double timecode_ms = (double)frame_number * 1000 * framerate_den / framerate_num + 0.5; + auto timecode_ms = (frame_number * 1000 * framerate_den + framerate_num / 2 - 1) / framerate_num; auto timecode_s = timecode_ms / 1000; if (timecode_s >= cues.size()) cues.push_back({ (unsigned long long)timecode_ms, output_size }); @@ -346,6 +346,8 @@ void matroska_writer::write_frame(const char* video_buffer, int video_size, cons store_b2(cur, 0x75A1); // BlockMore store_b8(cur, 0x8FA68DEE8179A588LL); // BlockMore size + BlockAddID + BlockAdditional store_b8(cur, timecode_value); + if (!has_timecode) + has_timecode=true; // timecode track header will be written when header is written again with cues } // Audio @@ -387,15 +389,21 @@ void matroska_writer::write_frame(const char* video_buffer, int video_size, cons void matroska_writer::close(std::ofstream* output) { - char buffer[sizeof(matroska_writer_header)]; - char* cur; + auto cues_size = 6 + 27 * cues.size(); + if (buffer_size < cues_size) + { + buffer_size = cues_size; + delete[] buffer; + buffer = new char[buffer_size]; + } + auto cur = buffer; - // Cues - int cues_size = 6 + 27 * (int)cues.size(); - cur = buffer; + // Header store_b4(cur, 0x1C53BB6B); // Cues store_e4(cur, cues_size); cur += 6; // CRC-32 + + // Cues for (const auto& cue : cues) { store_b4(cur, 0xBB99B388); // CuePoint + CueTime @@ -404,22 +412,13 @@ void matroska_writer::close(std::ofstream* output) store_b1(cur, 1); store_b2(cur, 0xF188); // CueClusterPosition store_b8(cur, cue.offset); - auto size = cur - buffer; - if (sizeof(matroska_writer_header) - size < 27) - { - output->write(buffer, size); - output_size += size; - cur = buffer; - } - } - if (cur > buffer) - { - auto size = cur - buffer; - matroska_crc32_store(buffer + 8, cues_size); - output->write(buffer, size); - output_size += size; } + auto size = cur - buffer; + matroska_crc32_store(buffer + 8, cues_size); + output->write(buffer, size); + output_size += size; + output->seekp(0); if (output) write_header();