diff options
Diffstat (limited to 'Src/nsmkv/SegmentInfo.cpp')
-rw-r--r-- | Src/nsmkv/SegmentInfo.cpp | 235 |
1 files changed, 235 insertions, 0 deletions
diff --git a/Src/nsmkv/SegmentInfo.cpp b/Src/nsmkv/SegmentInfo.cpp new file mode 100644 index 00000000..a1877a19 --- /dev/null +++ b/Src/nsmkv/SegmentInfo.cpp @@ -0,0 +1,235 @@ +#include "SegmentInfo.h" +#include "read.h" +#include "global_elements.h" +#include <time.h> +#include <TCHAR.h> +#include <sys/stat.h> + +int FileExists(const char * filename); + +// returns bytes read. 0 means EOF +uint64_t nsmkv::ReadSegmentInfo(nsmkv::MKVReader *reader, uint64_t size, nsmkv::SegmentInfo &segment_info) +{ + uint64_t total_bytes_read=0; + while (size) + { + ebml_node node; + uint64_t bytes_read = read_ebml_node(reader, &node); + + if (bytes_read == 0) + return 0; + + // benski> checking bytes_read and node.size separately prevents possible integer overflow attack + if (bytes_read > size) + return 0; + total_bytes_read+=bytes_read; + size-=bytes_read; + + if (node.size > size) + return 0; + total_bytes_read+=node.size; + size-=node.size; + + switch(node.id) + { + case mkv_segmentinfo_timecodescale: + { + uint64_t val; + if (read_unsigned(reader, node.size, &val) == 0) + return 0; + +#ifdef WA_VALIDATE + printf(" Time Code Scale: %I64u\n", val); + segment_info.time_code_scale_found = true; +#endif + segment_info.time_code_scale = val; + } + break; + case mkv_segmentinfo_muxingapp: + { + char *utf8 = 0; + if (node.size && read_utf8(reader, node.size, &utf8) == 0) + return 0; + if (utf8) +#ifdef WA_VALIDATE + printf(" Muxing App: %s\n", utf8); + segment_info.muxing_app_found = true; +#endif + segment_info.Own(segment_info.muxing_app, utf8); + } + break; + case mkv_segmentinfo_writingapp: + { + char *utf8 = 0; + if (node.size && read_utf8(reader, node.size, &utf8) == 0) + return 0; + if (utf8) +#ifdef WA_VALIDATE + printf(" Writing App: %s\n", utf8); + segment_info.writing_app_found = true; +#endif + segment_info.Own(segment_info.writing_app, utf8); + } + break; + case mkv_segmentinfo_duration: + { + double val; + if (read_float(reader, node.size, &val) == 0) + return 0; + +#ifdef WA_VALIDATE + printf(" Duration: %g\n", val); + segment_info.duration_found = true; +#endif + segment_info.duration = val; + } + break; + case mkv_segmentinfo_dateutc: + { + uint64_t val; + if (read_unsigned(reader, node.size, &val) == 0) + return 0; + + segment_info.production_date = val; + // value is in nanoseconds, relative to jan 01, 2001. ugh + + __time64_t val_time = mkv_date_as_time_t(val); +#ifdef WA_VALIDATE + printf(" Date UTC: %s", _ctime64(&val_time)); + segment_info.production_date_found = true; +#endif + } + break; + case mkv_segmentinfo_segmentuid: + { +#ifdef WA_VALIDATE + printf(" Segment UID: binary size %I64u\n", node.size); + segment_info.segment_uid_found = true; +#endif + if (node.size == 16) + { + size_t bytes_read; + reader->Read(&segment_info.segment_uid, (size_t)node.size, &bytes_read); + if (bytes_read != node.size) + return 0; + } + else // bad size, let's just skip it + { + reader->Skip(node.size); + } + } + break; + case mkv_segmentinfo_prevuid: + { +#ifdef WA_VALIDATE + printf(" Previous UID: binary size %I64u\n", node.size); + segment_info.prev_uid_found = true; +#endif + if (node.size == 16) + { + size_t bytes_read; + reader->Read(&segment_info.prev_uid, (size_t)node.size, &bytes_read); + if (bytes_read != node.size) + return 0; + } + else // bad size, let's just skip it + { + reader->Skip(node.size); + } + } + break; + case mkv_segmentinfo_nextuid: + { +#ifdef WA_VALIDATE + printf(" Next Segment UID: binary size %I64u\n", node.size); + segment_info.next_uid_found = true; +#endif + if (node.size == 16) + { + size_t bytes_read; + reader->Read(&segment_info.next_uid, (size_t)node.size, &bytes_read); + if (bytes_read != node.size) + return 0; + } + else // bad size, let's just skip it + { + reader->Skip(node.size); + } + } + break; + case mkv_segmentinfo_title: + { + char *utf8 = 0; + if (read_utf8(reader, node.size, &utf8) == 0) + return 0; + if (utf8) +#ifdef WA_VALIDATE + printf(" Title: %s\n", utf8); + segment_info.title_found = true; +#endif + segment_info.Own(segment_info.title, utf8); + } + break; + case mkv_segmentinfo_prevfilename: + { + char *utf8 = 0; + if (read_utf8(reader, node.size, &utf8) == 0) + return 0; + if (utf8) +#ifdef WA_VALIDATE + printf(" Previous Filename: %s\n", utf8); + segment_info.prev_filename_found = true; + if (FileExists(segment_info.prev_filename) != 0) + { + printf("****Specified previous filename not found"); + } +#endif + segment_info.Own(segment_info.prev_filename,utf8); + } + break; + case mkv_segmentinfo_nextfilename: + { + char *utf8 = 0; + if (read_utf8(reader, node.size, &utf8) == 0) + return 0; + if (utf8) +#ifdef WA_VALIDATE + printf(" Next Filename: %s\n", utf8); + segment_info.next_filename_found = true; + if (FileExists(segment_info.next_filename) != 0) + { + printf("****Specified next filename not found"); + } +#endif + segment_info.Own(segment_info.next_filename, utf8); + } + break; + + default: + nsmkv::ReadGlobal(reader, node.id, node.size); + } + } + return total_bytes_read; +} + +int nsmkv::SegmentInfo::GetDurationMilliseconds() const +{ + double nanoseconds = (double)time_code_scale * duration; + double microseconds = nanoseconds / 1000.0; + double milliseconds = microseconds / 1000.0; + return (int)milliseconds; +} + +uint64_t nsmkv::SegmentInfo::ConvertMillisecondsToTime(int milliseconds) const +{ + double time_code = (double)milliseconds * 1000000.0 / (double)time_code_scale; + return (uint64_t)time_code; +} + +int FileExists(const char * filename) { + int iStat; + struct _stat64 fileInfo; + + // get the file attributes + return (iStat = _stat64(filename,&fileInfo)); +} |