#include "vint.h" #include "header.h" #include "ebml_float.h" #include "segment.h" #include "ebml_unsigned.h" #include "ebml_signed.h" #include #include #include "SeekTable.h" #include #include "parser.h" #include "SegmentInfo.h" #include "global_elements.h" #include "Tracks.h" #include "Cluster.h" #include "Cues.h" #include "Chapters.h" #include "Tags.h" #include "read.h" #include "Attachments.h" using namespace nsmkv; static nsmkv::SeekTable seekTable; static nsmkv::Header header; static SegmentInfo segment_info; static Tracks tracks; static Cues cues; static Attachments attachments; static Tags tags; uint64_t max_id_length = header.ebml_max_id_length; uint64_t max_size_length = header.ebml_max_size_length; uint32_t num_seekhead_elements_found = 0; uint32_t num_seek_elements_found = 0; bool ebml_segment_found = false; uint64_t segment_data_offset = 0; // returns bytes read. 0 means EOF uint64_t read_vsint(FILE *f, int64_t *val) { uint8_t data[9]; size_t bytes_read = fread(data, 1, 1, f); if (bytes_read != 1) return 0; uint8_t length = vint_get_number_bytes(data[0]); bytes_read = fread(data+1, 1, length, f); if (bytes_read != length) return 0; *val = vsint_read_ptr_len(length+1, data); return bytes_read+1; } char *read_utf8(FILE *f, size_t size) { char *doctype = (char *)malloc(size + 1); if (doctype) { doctype[size]=0; if (fread(doctype, 1, size, f) == size) return doctype; } free(doctype); return 0; } // returns bytes read. 0 means EOF uint64_t ReadSegment(FILE *f, uint64_t size) { uint64_t total_bytes_read=0; // store the segment element data offset for later use segment_data_offset = ftell(f); #ifdef WA_VALIDATE printf("[%I64u] Segment element data offset\n", segment_data_offset); #endif while (size) { uint64_t this_position = ftell(f); #ifdef WA_VALIDATE printf("[%I64u] ", this_position); #endif ebml_node node; uint64_t bytes_read = read_ebml_node((nsmkv::MKVReader*)f, &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_segment_attachments: { printf(" Attachments\n"); ReadAttachment((nsmkv::MKVReader*)f, node.size, attachments); } break; case mkv_metaseek_seekhead: { printf(" SeekHead\n"); ReadSeekHead((nsmkv::MKVReader*)f, node.size, seekTable); } break; case mkv_segment_segmentinfo: { printf(" SegmentInfo\n"); ReadSegmentInfo((nsmkv::MKVReader*)f, node.size, segment_info); } break; case mkv_segment_tracks: { printf(" Tracks\n"); ReadTracks((nsmkv::MKVReader*)f, node.size, tracks); } break; case mkv_segment_cues: { printf(" Cues\n"); ReadCues((nsmkv::MKVReader*)f, node.size, cues); } break; case mkv_segment_cluster: { printf(" Clusters\n"); nsmkv::Cluster cluster; ReadCluster((nsmkv::MKVReader*)f, node.size, cluster); } break; case mkv_segment_chapters: { printf(" Chapters\n"); } break; case mkv_segment_tags: { printf(" Tags\n"); nsmkv::ReadTags(f, node.size, tags); } break; default: ReadGlobal((nsmkv::MKVReader*)f, node.id, node.size); } } return total_bytes_read; } int main() { // char *file_in = "\\\\o2d2\\ftp\\usr\\nullsoft\\test media\\mkv\\Ratatouille.2007.nHD.720.x264.NhaNc3.mkv"; //char *file_in = "\\\\o2d2\\ftp\\usr\\nullsoft\\test media\\mkv\\cham_mp4v_aac.mkv"; char *file_in = "c:/users/benski/desktop/metadata.mkv"; FILE *f = fopen(file_in, "rb"); if (f == NULL) { printf("****Error attempting to open file: %s\n",file_in); return -1; } else { printf("Starting Processing of File: %s\n",file_in); } ebml_node node; while (read_ebml_node((nsmkv::MKVReader*)f, &node)) { switch(node.id) { case mkv_header: if (header.ebml_header_found == false) { #ifdef WA_VALIDATE printf("MKV header found, processing...\n"); #endif header.ebml_header_found = true; nsmkv::ReadHeader((nsmkv::MKVReader*)f, node.size, header); } else { #ifdef WA_VALIDATE printf("Extra MKV header found, ignoring...\n"); #endif nsmkv::Header extraHeader; nsmkv::ReadHeader((nsmkv::MKVReader*)f, node.size, extraHeader); } break; case mkv_segment: printf("MKV Segment element found, processing\n"); #ifdef WA_VALIDATE ebml_segment_found = true; #endif ReadSegment(f, node.size); break; default: ReadGlobal((nsmkv::MKVReader*)f, node.id, node.size); } } // seekTable.Dump(); fclose(f); printf("Number of SeekHead elements found: %I32u\n",num_seekhead_elements_found); printf("Number of Seek elements found: %I32u\n",num_seek_elements_found); }