123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561 |
- #include "Tracks.h"
- #include "read.h"
- #include "global_elements.h"
- // returns bytes read. 0 means EOF
- static uint64_t ReadTracksVideo(nsmkv::MKVReader *reader, uint64_t size, nsmkv::Video &video)
- {
- 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_video_pixelwidth:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Pixel Width: %I64u\n", val);
- video.pixel_width_found=true;
- #endif
- video.pixel_width=val;
- }
- break;
- case mkv_video_pixelheight:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Pixel Height: %I64u\n", val);
- video.pixel_height_found=true;
- #endif
- video.pixel_height=val;
- }
- break;
- case mkv_video_flaginterlaced:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Flag Interlaced: 0x%I64x\n", val);
- video.flag_interlaced_found=true;
- #endif
- video.flag_interlaced = !!val;
- }
- break;
- case mkv_video_displaywidth:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Display Width: %I64u\n", val);
- video.display_width_found = true;
- #endif
- video.display_width = val;
- }
- break;
- case mkv_video_displayheight:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Display Height: %I64u\n", val);
- video.display_height_found = true;
- #endif
- video.display_height = val;
- }
- break;
- case mkv_video_pixelcropleft:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Pixel Crop Left: %I64u\n", val);
- video.pixel_crop_left_found = true;
- #endif
- video.pixel_crop_left = val;
- }
- break;
- case mkv_video_pixelcroptop:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Pixel Crop Top: %I64u\n", val);
- video.pixel_crop_top_found = true;
- #endif
- video.pixel_crop_top = val;
- }
- break;
- case mkv_video_pixelcropbottom:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Pixel Crop Bottom: %I64u\n", val);
- video.pixel_crop_bottom_found = true;
- #endif
- video.pixel_crop_bottom = val;
- }
- break;
- case mkv_video_pixelcropright:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Pixel Crop Right: %I64u\n", val);
- video.pixel_crop_right_found = true;
- #endif
- video.pixel_crop_right = val;
- }
- break;
- default:
- nsmkv::ReadGlobal(reader, node.id, node.size);
- }
- }
- return total_bytes_read;
- }
- // returns bytes read. 0 means EOF
- static uint64_t ReadTracksAudio(nsmkv::MKVReader *reader, uint64_t size, nsmkv::Audio &audio)
- {
- 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_audio_samplingfrequency:
- {
- double val;
- if (read_float(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Sampling Frequency: %g\n", val);
- audio.sampling_frequency_found = true;
- #endif
- audio.sampling_frequency = (uint64_t)val;
- }
- break;
- case mkv_audio_channels:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Channels: %I64u\n", val);
- audio.channels_found = true;
- #endif
- audio.channels = val;
- }
- break;
- case mkv_audio_output_samplingfrequency:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Output Sampling Frequency: %I64u\n", val);
- audio.output_sampling_frequency_found = true;
- #endif
- audio.output_sampling_frequency = val;
- }
- break;
- default:
- nsmkv::ReadGlobal(reader, node.id, node.size);
- }
- }
- return total_bytes_read;
- }
- static uint64_t ReadTrackEntry(nsmkv::MKVReader *reader, uint64_t size, nsmkv::TrackEntry &track_entry)
- {
- 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_tracks_tracknumber:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Track Number: %I64u\n", val);
- track_entry.track_number_found = true;
- #endif
- track_entry.track_number = val;
- }
- break;
- case mkv_tracks_trackuid:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Track UID: %I64u\n", val);
- track_entry.track_uid_found = true;
- #endif
- track_entry.track_uid = val;
- }
- break;
- case mkv_tracks_tracktype:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Track Type: 0x%I64x\n", val);
- track_entry.track_type_found = true;
- #endif
- track_entry.track_type = val;
- }
- break;
- case mkv_tracks_flagenabled:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Flag Enabled: 0x%I64x\n", val);
- track_entry.flag_enabled_found = true;
- #endif
- track_entry.flag_enabled = !!val;
- }
- break;
- case mkv_tracks_flagdefault:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Flag Default: 0x%I64x\n", val);
- track_entry.flag_default_found = true;
- #endif
- track_entry.flag_default = !!val;
- }
- break;
- case mkv_tracks_flagforced:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Flag Forced: 0x%I64x\n", val);
- track_entry.flag_forced_found = true;
- #endif
- track_entry.flag_forced = !!val;
- }
- break;
- case mkv_tracks_flaglacing:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Flag Lacing: 0x%I64x\n", val);
- track_entry.flag_lacing_found = true;
- #endif
- track_entry.flag_lacing = !!val;
- }
- break;
- case mkv_tracks_mincache:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Min Cache: %I64u\n", val);
- track_entry.min_cache_found = true;
- #endif
- track_entry.min_cache = !!val;
- }
- break;
- case mkv_tracks_tracktimecodescale:
- {
- double val;
- if (read_float(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Track Time Code Scale: %g\n", val);
- track_entry.track_timecode_scale_found = true;
- #endif
- track_entry.track_timecode_scale = val;
- }
- break;
- case mkv_tracks_maxblockadditionid:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Max Block Addition ID: %I64u\n", val);
- track_entry.max_block_additional_id_found=true;
- #endif
- track_entry.max_block_additional_id=val;
- }
- break;
- case mkv_tracks_codecid:
- {
- char *utf8=0;
- if (read_utf8(reader, node.size, &utf8) == 0)
- return 0;
- #ifdef WA_VALIDATE
- if (utf8)
- printf(" Codec ID: %s\n", utf8);
- track_entry.codec_id_found = true;
- #endif
- track_entry.Own(track_entry.codec_id, utf8);
- }
- break;
- case mkv_tracks_codecdecodeall:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Codec Decode All: %I64u\n", val);
- track_entry.decode_all_found = true;
- #endif
- track_entry.decode_all = !!val;
- }
- break;
- case mkv_tracks_defaultduration:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Default Duration: %I64u\n", val);
- track_entry.default_duration_found = true;
- #endif
- track_entry.default_duration = val;
- }
- break;
- case mkv_tracks_codecprivate:
- {
- #ifdef WA_VALIDATE
- printf(" Codec Private: binary size %I64u\n", node.size);
- #endif
- void *codec_private = malloc((size_t)node.size);
- if (!codec_private)
- return 0;
- size_t bytes_read;
- reader->Read(codec_private, (size_t)node.size, &bytes_read);
- if (bytes_read != node.size)
- {
- free(codec_private);
- return 0;
- }
- track_entry.OwnCodecPrivate(codec_private, (size_t)node.size);
- #ifdef WA_VALIDATE
- track_entry.codec_private_found = true;
- #endif
- }
- break;
- case mkv_tracks_language:
- {
- char *utf8=0;
- if (read_utf8(reader, node.size, &utf8) == 0)
- return 0;
- #ifdef WA_VALIDATE
- if (utf8)
- printf(" Codec Language: %s\n", utf8);
- track_entry.language_found = true;
- #endif
- track_entry.Own(track_entry.language, utf8);
- }
- break;
- case mkv_tracks_video:
- {
- #ifdef WA_VALIDATE
- printf(" Video Settings\n");
- #endif
- if (ReadTracksVideo(reader, node.size, track_entry.video) == 0)
- return 0;
- }
- break;
- case mkv_tracks_audio:
- {
- #ifdef WA_VALIDATE
- printf(" Audio Settings\n");
- #endif
- if (ReadTracksAudio(reader, node.size, track_entry.audio) == 0)
- return 0;
- }
- break;
- case mkv_tracks_name:
- {
- char *utf8=0;
- if (read_utf8(reader, node.size, &utf8) == 0)
- return 0;
- #ifdef WA_VALIDATE
- if (utf8)
- printf(" Track Name: %s\n", utf8);
- track_entry.name_found = true;
- #endif
- track_entry.Own(track_entry.name, utf8);
- }
- break;
- case mkv_tracks_maxcache:
- {
- uint64_t val;
- if (read_unsigned(reader, node.size, &val) == 0)
- return 0;
- #ifdef WA_VALIDATE
- printf(" Max Cache: %I64u\n", val);
- track_entry.max_cache_found = true;
- #endif
- track_entry.max_cache = val;
- }
- break;
- default:
- nsmkv::ReadGlobal(reader, node.id, node.size);
- }
- }
- return total_bytes_read;
- }
- // returns bytes read. 0 means EOF
- uint64_t nsmkv::ReadTracks(nsmkv::MKVReader *reader, uint64_t size, nsmkv::Tracks &tracks)
- {
- 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_tracks_trackentry:
- {
- #ifdef WA_VALIDATE
- printf(" Track Entry\n");
- #endif
- TrackEntry *track_entry = new TrackEntry;
- if (ReadTrackEntry(reader, node.size, *track_entry) == 0)
- {
- delete track_entry;
- return 0;
- }
- tracks.tracks.push_back(track_entry);
- }
- break;
- default:
- ReadGlobal(reader, node.id, node.size);
- }
- }
- return total_bytes_read;
- }
- const nsmkv::TrackEntry *nsmkv::Tracks::EnumTrack(size_t i) const
- {
- if (tracks.size() > i)
- {
- return tracks[i];
- }
- return 0;
- }
|