diff --git a/.gitattributes b/.gitattributes index 3408438cb26..9bb4e97d4ae 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1794,26 +1794,34 @@ src/lib/softfloat/softfloat.c svneol=native#text/plain src/lib/softfloat/softfloat.h svneol=native#text/plain src/lib/util/astring.c svneol=native#text/plain src/lib/util/astring.h svneol=native#text/plain -src/lib/util/avcomp.c svneol=native#text/plain -src/lib/util/avcomp.h svneol=native#text/plain +src/lib/util/avhuff.c svneol=native#text/plain +src/lib/util/avhuff.h svneol=native#text/plain src/lib/util/aviio.c svneol=native#text/plain src/lib/util/aviio.h svneol=native#text/plain src/lib/util/bitmap.c svneol=native#text/plain src/lib/util/bitmap.h svneol=native#text/plain +src/lib/util/bitstream.h svneol=native#text/plain src/lib/util/cdrom.c svneol=native#text/plain src/lib/util/cdrom.h svneol=native#text/plain src/lib/util/chd.c svneol=native#text/plain src/lib/util/chd.h svneol=native#text/plain src/lib/util/chdcd.c svneol=native#text/plain src/lib/util/chdcd.h svneol=native#text/plain +src/lib/util/chdcodec.c svneol=native#text/plain +src/lib/util/chdcodec.h svneol=native#text/plain src/lib/util/corefile.c svneol=native#text/plain src/lib/util/corefile.h svneol=native#text/plain src/lib/util/corestr.c svneol=native#text/plain src/lib/util/corestr.h svneol=native#text/plain +src/lib/util/coretmpl.h svneol=native#text/plain src/lib/util/coreutil.c svneol=native#text/plain src/lib/util/coreutil.h svneol=native#text/plain +src/lib/util/flac.c svneol=native#text/plain +src/lib/util/flac.h svneol=native#text/plain src/lib/util/harddisk.c svneol=native#text/plain src/lib/util/harddisk.h svneol=native#text/plain +src/lib/util/hashing.c svneol=native#text/plain +src/lib/util/hashing.h svneol=native#text/plain src/lib/util/huffman.c svneol=native#text/plain src/lib/util/huffman.h svneol=native#text/plain src/lib/util/jedparse.c svneol=native#text/plain diff --git a/makefile b/makefile index e218d430941..7b1adf1571e 100644 --- a/makefile +++ b/makefile @@ -733,10 +733,8 @@ $(sort $(OBJDIRS)): ifndef EXECUTABLE_DEFINED -# always recompile the version string -$(VERSIONOBJ): $(DRVLIBS) $(LIBOSD) $(LIBCPU) $(LIBEMU) $(LIBSOUND) $(LIBUTIL) $(EXPAT) $(ZLIB) $(7Z_LIB) $(SOFTFLOAT) $(FORMATS_LIB) $(LIBOCORE) $(RESFILE) - $(EMULATOR): $(VERSIONOBJ) $(EMUINFOOBJ) $(DRIVLISTOBJ) $(DEVLISTOBJ) $(DRVLIBS) $(LIBOSD) $(LIBCPU) $(LIBEMU) $(LIBDASM) $(LIBSOUND) $(LIBUTIL) $(EXPAT) $(SOFTFLOAT) $(JPEG_LIB) $(FLAC_LIB) $(7Z_LIB) $(FORMATS_LIB) $(ZLIB) $(LIBOCORE) $(RESFILE) + $(CC) $(CDEFS) $(CFLAGS) -c $(SRC)/version.c -o $(VERSIONOBJ) @echo Linking $@... $(LD) $(LDFLAGS) $(LDFLAGSEMULATOR) $^ $(LIBS) -o $@ ifeq ($(TARGETOS),win32) diff --git a/src/emu/audit.c b/src/emu/audit.c index 7085ea1d6b3..42e2ed77060 100644 --- a/src/emu/audit.c +++ b/src/emu/audit.c @@ -436,27 +436,20 @@ audit_record *media_auditor::audit_one_disk(const rom_entry *rom) audit_record &record = m_record_list.append(*global_alloc(audit_record(*rom, audit_record::MEDIA_DISK))); // open the disk - emu_file *source_file; - chd_file *source; - chd_error err = open_disk_image(m_enumerator.options(), &m_enumerator.driver(), rom, &source_file, &source, NULL); + chd_file source; + chd_error err = chd_error(open_disk_image(m_enumerator.options(), &m_enumerator.driver(), rom, source, NULL)); // if we succeeded, get the hashes if (err == CHDERR_NONE) { - static const UINT8 nullhash[20] = { 0 }; - chd_header header = *chd_get_header(source); hash_collection hashes; // if there's a SHA1 hash, add them to the output hash - if (memcmp(nullhash, header.sha1, sizeof(header.sha1)) != 0) - hashes.add_from_buffer(hash_collection::HASH_SHA1, header.sha1, sizeof(header.sha1)); + if (source.sha1() != sha1_t::null) + hashes.add_from_buffer(hash_collection::HASH_SHA1, source.sha1().m_raw, sizeof(source.sha1().m_raw)); // update the actual values record.set_actual(hashes); - - // close the file and release the source - chd_close(source); - global_free(source_file); } // compute the final status diff --git a/src/emu/clifront.c b/src/emu/clifront.c index 6b623b320cd..a893197d222 100644 --- a/src/emu/clifront.c +++ b/src/emu/clifront.c @@ -38,6 +38,7 @@ ***************************************************************************/ #include "emu.h" +#include "chd.h" #include "emuopts.h" #include "jedparse.h" #include "audit.h" @@ -1492,8 +1493,8 @@ void media_identifier::identify_file(const char *name) m_total++; // attempt to open as a CHD; fail if not - chd_file *chd; - chd_error err = chd_open(name, CHD_OPEN_READ, NULL, &chd); + chd_file chd; + chd_error err = chd.open(name); if (err != CHDERR_NONE) { mame_printf_info("NOT A CHD\n"); @@ -1501,26 +1502,20 @@ void media_identifier::identify_file(const char *name) return; } - // fetch the header and close the file - chd_header header = *chd_get_header(chd); - chd_close(chd); - // error on writable CHDs - if (header.flags & CHDFLAGS_IS_WRITEABLE) + if (!chd.compressed()) { mame_printf_info("is a writeable CHD\n"); return; } // otherwise, get the hash collection for this CHD - static const UINT8 nullhash[20] = { 0 }; hash_collection hashes; - - if (memcmp(nullhash, header.sha1, sizeof(header.sha1)) != 0) - hashes.add_from_buffer(hash_collection::HASH_SHA1, header.sha1, sizeof(header.sha1)); + if (chd.sha1() != sha1_t::null) + hashes.add_from_buffer(hash_collection::HASH_SHA1, chd.sha1().m_raw, sizeof(chd.sha1().m_raw)); // determine whether this file exists - int found = find_by_hash(hashes, header.logicalbytes); + int found = find_by_hash(hashes, chd.logical_bytes()); if (found == 0) mame_printf_info("NO MATCH\n"); else diff --git a/src/emu/emu.h b/src/emu/emu.h index 2051f54af89..1d9335dc374 100644 --- a/src/emu/emu.h +++ b/src/emu/emu.h @@ -59,7 +59,6 @@ #include "profiler.h" // commonly-referenecd utilities imported from lib/util -#include "chd.h" #include "palette.h" #include "unicode.h" diff --git a/src/emu/imagedev/chd_cd.c b/src/emu/imagedev/chd_cd.c index dea7020cf1f..6680929530c 100644 --- a/src/emu/imagedev/chd_cd.c +++ b/src/emu/imagedev/chd_cd.c @@ -129,10 +129,11 @@ bool cdrom_image_device::call_load() if (software_entry() == NULL) { - if (strstr(m_image_name,".chd")) { - err = chd_open_file( image_core_file(), CHD_OPEN_READ, NULL, &chd ); /* CDs are never writeable */ + if (strstr(m_image_name,".chd") && is_loaded()) { + err = m_self_chd.open( *image_core_file() ); /* CDs are never writeable */ if ( err ) goto error; + chd = &m_self_chd; } } else { chd = get_disk_handle(device().machine(), device().subtag(tempstring,"cdrom")); @@ -150,8 +151,8 @@ bool cdrom_image_device::call_load() return IMAGE_INIT_PASS; error: - if ( chd ) - chd_close( chd ); + if ( chd && chd == &m_self_chd ) + m_self_chd.close( ); if ( err ) seterror( IMAGE_ERROR_UNSPECIFIED, chd_get_error_string( err ) ); return IMAGE_INIT_FAIL; diff --git a/src/emu/imagedev/chd_cd.h b/src/emu/imagedev/chd_cd.h index fecb1f7e6b0..f01ec4b1f98 100644 --- a/src/emu/imagedev/chd_cd.h +++ b/src/emu/imagedev/chd_cd.h @@ -57,6 +57,7 @@ protected: virtual void device_config_complete(); virtual void device_start(); + chd_file m_self_chd; cdrom_file *m_cdrom_handle; image_device_format m_format; }; diff --git a/src/emu/imagedev/harddriv.c b/src/emu/imagedev/harddriv.c index b6026f6c788..fe06cfdfb5f 100644 --- a/src/emu/imagedev/harddriv.c +++ b/src/emu/imagedev/harddriv.c @@ -146,7 +146,7 @@ bool harddisk_image_device::call_load() { int our_result; - our_result = internal_load_hd(NULL); + our_result = internal_load_hd(); /* Check if there is an image_load callback defined */ if ( m_device_image_load ) @@ -161,9 +161,9 @@ bool harddisk_image_device::call_load() bool harddisk_image_device::call_create(int create_format, option_resolution *create_args) { int err; - char metadata[256]; UINT32 sectorsize, hunksize; UINT32 cylinders, heads, sectors, totalsectors; + astring metadata; cylinders = option_resolution_lookup_int(create_args, 'C'); heads = option_resolution_lookup_int(create_args, 'H'); @@ -174,12 +174,20 @@ bool harddisk_image_device::call_create(int create_format, option_resolution *cr totalsectors = cylinders * heads * sectors; /* create the CHD file */ - err = chd_create_file(image_core_file(), (UINT64)totalsectors * (UINT64)sectorsize, hunksize, CHDCOMPRESSION_NONE, NULL); + chd_codec_type compression[4] = { CHD_CODEC_NONE }; + err = m_self_chd.create(*image_core_file(), (UINT64)totalsectors * (UINT64)sectorsize, hunksize, sectorsize, compression); if (err != CHDERR_NONE) goto error; - sprintf(metadata, HARD_DISK_METADATA_FORMAT, cylinders, heads, sectors, sectorsize); - return internal_load_hd(metadata); + /* if we created the image and hence, have metadata to set, set the metadata */ + metadata.format(HARD_DISK_METADATA_FORMAT, cylinders, heads, sectors, sectorsize); + err = m_self_chd.write_metadata(HARD_DISK_METADATA_TAG, 0, metadata); + m_self_chd.close(); + + if (err != CHDERR_NONE) + goto error; + + return internal_load_hd(); error: return IMAGE_INIT_FAIL; @@ -201,12 +209,13 @@ void harddisk_image_device::call_unload() if (m_chd != NULL) { - chd_close(m_chd); + if (m_self_chd.opened()) + m_self_chd.close(); m_chd = NULL; } } -int harddisk_image_device::internal_load_hd(const char *metadata) +int harddisk_image_device::internal_load_hd() { chd_error err = (chd_error)0; int is_writeable; @@ -220,8 +229,9 @@ int harddisk_image_device::internal_load_hd(const char *metadata) do { is_writeable = !is_readonly(); - m_chd = NULL; - err = chd_open_file(image_core_file(), is_writeable ? CHD_OPEN_READWRITE : CHD_OPEN_READ, NULL, &m_chd); + err = m_self_chd.open(*image_core_file(), is_writeable); + if (err == CHDERR_NONE) + m_chd = &m_self_chd; /* special case; if we get CHDERR_FILE_NOT_WRITEABLE, make the * image read only and repeat */ @@ -233,14 +243,6 @@ int harddisk_image_device::internal_load_hd(const char *metadata) if (!m_chd) goto done; - /* if we created the image and hence, have metadata to set, set the metadata */ - if (metadata) - { - err = chd_set_metadata(m_chd, HARD_DISK_METADATA_TAG, 0, metadata, strlen(metadata) + 1, 0); - if (err != CHDERR_NONE) - goto done; - } - /* open the hard disk file */ m_hard_disk_handle = hard_disk_open(m_chd); if (!m_hard_disk_handle) @@ -252,7 +254,8 @@ done: /* if we had an error, close out the CHD */ if (m_chd != NULL) { - chd_close(m_chd); + if (m_self_chd.opened()) + m_self_chd.close(); m_chd = NULL; } diff --git a/src/emu/imagedev/harddriv.h b/src/emu/imagedev/harddriv.h index 0bf0053f484..5f6a88cf572 100644 --- a/src/emu/imagedev/harddriv.h +++ b/src/emu/imagedev/harddriv.h @@ -64,9 +64,10 @@ protected: virtual void device_config_complete(); virtual void device_start(); - int internal_load_hd(const char *metadata); + int internal_load_hd(); chd_file *m_chd; + chd_file m_self_chd; hard_disk_file *m_hard_disk_handle; image_device_format m_format; diff --git a/src/emu/machine/idectrl.c b/src/emu/machine/idectrl.c index d3399258a1a..52cc6251b4d 100644 --- a/src/emu/machine/idectrl.c +++ b/src/emu/machine/idectrl.c @@ -1476,7 +1476,7 @@ static void ide_controller_write(device_t *device, int bank, offs_t offset, int } else if (ide->command == IDE_COMMAND_TAITO_GNET_UNLOCK_2) { - UINT8 key[5] = { 0, 0, 0, 0, 0 }; + UINT8 key[5] = { 0 }; int i, bad = 0; ide->drive[ide->cur_drive].slot->read_key(key); @@ -2073,7 +2073,8 @@ void ide_hdd_device::device_reset() mame_printf_debug("CHS: %d %d %d\n", m_num_cylinders, m_num_heads, m_num_sectors); } // build the features page - if (chd_get_metadata (m_handle, HARD_DISK_IDENT_METADATA_TAG, 0, m_features, IDE_DISK_SECTOR_SIZE, 0, 0, 0) != CHDERR_NONE) + UINT32 metalength; + if (m_handle->read_metadata (HARD_DISK_IDENT_METADATA_TAG, 0, m_features, IDE_DISK_SECTOR_SIZE, metalength) != CHDERR_NONE) ide_build_features(); } } @@ -2084,7 +2085,8 @@ void ide_hdd_device::device_reset() void ide_hdd_device::read_key(UINT8 key[]) { - chd_get_metadata(m_handle, HARD_DISK_KEY_METADATA_TAG, 0, key, 5, 0, 0, 0); + UINT32 metalength; + m_handle->read_metadata(HARD_DISK_KEY_METADATA_TAG, 0, key, 5, metalength); } //************************************************************************** @@ -2136,7 +2138,8 @@ void ide_hdd_image_device::device_reset() if (PRINTF_IDE_COMMANDS) printf("CHS: %d %d %d\n", m_num_cylinders, m_num_heads, m_num_sectors); } // build the features page - if (chd_get_metadata (m_handle, HARD_DISK_IDENT_METADATA_TAG, 0, m_features, IDE_DISK_SECTOR_SIZE, 0, 0, 0) != CHDERR_NONE) + UINT32 metalength; + if (m_handle->read_metadata (HARD_DISK_IDENT_METADATA_TAG, 0, m_features, IDE_DISK_SECTOR_SIZE, metalength) != CHDERR_NONE) ide_build_features(); } } diff --git a/src/emu/machine/laserdsc.c b/src/emu/machine/laserdsc.c index 42d50493171..a006eebda22 100644 --- a/src/emu/machine/laserdsc.c +++ b/src/emu/machine/laserdsc.c @@ -39,10 +39,11 @@ #include "emu.h" #include "laserdsc.h" -#include "avcomp.h" +#include "avhuff.h" #include "vbiparse.h" #include "config.h" #include "render.h" +#include "chd.h" @@ -93,13 +94,13 @@ laserdisc_device::laserdisc_device(const machine_config &mconfig, device_type ty m_overheight(0), m_overclip(0, -1, 0, -1), m_disc(NULL), - m_vbidata(NULL), m_width(0), m_height(0), m_fps_times_1million(0), m_samplerate(0), m_readresult(CHDERR_NONE), m_chdtracks(0), + m_work_queue(osd_work_queue_alloc(WORK_QUEUE_FLAG_IO)), m_audiosquelch(0), m_videosquelch(0), m_fieldnum(0), @@ -134,6 +135,7 @@ laserdisc_device::laserdisc_device(const machine_config &mconfig, device_type ty laserdisc_device::~laserdisc_device() { + osd_work_queue_free(m_work_queue); } @@ -362,7 +364,7 @@ void laserdisc_device::device_stop() { // make sure all async operations have completed if (m_disc != NULL) - chd_async_complete(m_disc); + osd_work_queue_wait(m_work_queue, osd_ticks_per_second() * 10); // free any textures and palettes if (m_videotex != NULL) @@ -767,13 +769,13 @@ void laserdisc_device::init_disc() m_maxtrack = VIRTUAL_LEAD_IN_TRACKS + MAX_TOTAL_TRACKS + VIRTUAL_LEAD_OUT_TRACKS; if (m_disc != NULL) { - // require the A/V codec - if (chd_get_header(m_disc)->compression != CHDCOMPRESSION_AV) + // require the A/V codec and nothing else + if (m_disc->compression(0) != CHD_CODEC_AVHUFF || m_disc->compression(1) != CHD_CODEC_NONE) throw emu_fatalerror("Laserdisc video must be compressed with the A/V codec!"); // read the metadata - char metadata[256]; - chd_error err = chd_get_metadata(m_disc, AV_METADATA_TAG, 0, metadata, sizeof(metadata), NULL, NULL, NULL); + astring metadata; + chd_error err = m_disc->read_metadata(AV_METADATA_TAG, 0, metadata); if (err != CHDERR_NONE) throw emu_fatalerror("Non-A/V CHD file specified"); @@ -789,14 +791,12 @@ void laserdisc_device::init_disc() throw emu_fatalerror("Laserdisc video must be interlaced!"); // determine the maximum track and allocate a frame buffer - UINT32 totalhunks = chd_get_header(m_disc)->totalhunks; + UINT32 totalhunks = m_disc->hunk_count(); m_chdtracks = totalhunks / 2; // allocate memory for the precomputed per-frame metadata - m_vbidata = auto_alloc_array(machine(), UINT8, totalhunks * VBI_PACKED_BYTES); - UINT32 vbilength; - err = chd_get_metadata(m_disc, AV_LD_METADATA_TAG, 0, m_vbidata, totalhunks * VBI_PACKED_BYTES, &vbilength, NULL, NULL); - if (err != CHDERR_NONE || vbilength != totalhunks * VBI_PACKED_BYTES) + err = m_disc->read_metadata(AV_LD_METADATA_TAG, 0, m_vbidata); + if (err != CHDERR_NONE || m_vbidata.count() != totalhunks * VBI_PACKED_BYTES) throw emu_fatalerror("Precomputed VBI metadata missing or incorrect size"); } m_maxtrack = MAX(m_maxtrack, VIRTUAL_LEAD_IN_TRACKS + VIRTUAL_LEAD_OUT_TRACKS + m_chdtracks); @@ -1011,7 +1011,7 @@ void laserdisc_device::read_track_data() // cheat and look up the metadata we are about to retrieve vbi_metadata vbidata = { 0 }; - if (m_vbidata != NULL) + if (m_vbidata.count() != 0) vbi_metadata_unpack(&vbidata, NULL, &m_vbidata[readhunk * VBI_PACKED_BYTES]); // if we're in the lead-in area, force the VBI data to be standard lead-in @@ -1040,29 +1040,29 @@ void laserdisc_device::read_track_data() frame->m_lastfield = m_curtrack * 2 + m_fieldnum; // set the video target information - m_avconfig.video.wrap(&frame->m_bitmap.pix16(m_fieldnum), frame->m_bitmap.width(), frame->m_bitmap.height() / 2, frame->m_bitmap.rowpixels() * 2); + m_avhuff_config.video.wrap(&frame->m_bitmap.pix16(m_fieldnum), frame->m_bitmap.width(), frame->m_bitmap.height() / 2, frame->m_bitmap.rowpixels() * 2); // set the audio target information if (m_audiobufin + m_audiomaxsamples <= m_audiobufsize) { // if we can fit without wrapping, just read the data directly - m_avconfig.audio[0] = &m_audiobuffer[0][m_audiobufin]; - m_avconfig.audio[1] = &m_audiobuffer[1][m_audiobufin]; + m_avhuff_config.audio[0] = &m_audiobuffer[0][m_audiobufin]; + m_avhuff_config.audio[1] = &m_audiobuffer[1][m_audiobufin]; } else { // otherwise, read to the beginning of the buffer - m_avconfig.audio[0] = &m_audiobuffer[0][0]; - m_avconfig.audio[1] = &m_audiobuffer[1][0]; + m_avhuff_config.audio[0] = &m_audiobuffer[0][0]; + m_avhuff_config.audio[1] = &m_audiobuffer[1][0]; } // override if we're not decoding - m_avconfig.maxsamples = m_audiomaxsamples; - m_avconfig.actsamples = &m_audiocursamples; + m_avhuff_config.maxsamples = m_audiomaxsamples; + m_avhuff_config.actsamples = &m_audiocursamples; m_audiocursamples = 0; // set the VBI data for the new field from our precomputed data - if (m_vbidata != NULL) + if (m_vbidata.count() != 0) { UINT32 vbiframe; vbi_metadata_unpack(&m_metadata[m_fieldnum], &vbiframe, &m_vbidata[readhunk * VBI_PACKED_BYTES]); @@ -1079,13 +1079,30 @@ void laserdisc_device::read_track_data() m_readresult = CHDERR_FILE_NOT_FOUND; if (m_disc != NULL && !m_videosquelch) { - m_readresult = chd_codec_config(m_disc, AV_CODEC_DECOMPRESS_CONFIG, &m_avconfig); + m_readresult = m_disc->codec_configure(CHD_CODEC_AVHUFF, AVHUFF_CODEC_DECOMPRESS_CONFIG, &m_avhuff_config); if (m_readresult == CHDERR_NONE) - m_readresult = chd_read_async(m_disc, readhunk, NULL); + { + m_queued_hunknum = readhunk; + m_readresult = CHDERR_OPERATION_PENDING; + osd_work_item_queue(m_work_queue, read_async_static, this, WORK_ITEM_FLAG_AUTO_RELEASE); + } } } +//------------------------------------------------- +// read_async_static - work item callback for +// asynchronous reads +//------------------------------------------------- + +void *laserdisc_device::read_async_static(void *param, int threadid) +{ + laserdisc_device &ld = *reinterpret_cast(param); + ld.m_readresult = ld.m_disc->read_hunk(ld.m_queued_hunknum, NULL); + return NULL; +} + + //------------------------------------------------- // process_track_data - process data from a // track after it has been read @@ -1095,27 +1112,28 @@ void laserdisc_device::process_track_data() { // wait for the async operation to complete if (m_readresult == CHDERR_OPERATION_PENDING) - m_readresult = chd_async_complete(m_disc); + osd_work_queue_wait(m_work_queue, osd_ticks_per_second() * 10); + assert(m_readresult != CHDERR_OPERATION_PENDING); // remove the video if we had an error if (m_readresult != CHDERR_NONE) - m_avconfig.video.reset(); + m_avhuff_config.video.reset(); // count the field as read if we are successful - if (m_avconfig.video.valid()) + if (m_avhuff_config.video.valid()) { m_frame[m_videoindex].m_numfields++; - player_overlay(m_avconfig.video); + player_overlay(m_avhuff_config.video); } // pass the audio to the callback if (!m_audio_callback.isnull()) - m_audio_callback(*this, m_samplerate, m_audiocursamples, m_avconfig.audio[0], m_avconfig.audio[1]); + m_audio_callback(*this, m_samplerate, m_audiocursamples, m_avhuff_config.audio[0], m_avhuff_config.audio[1]); // shift audio data if we read it into the beginning of the buffer if (m_audiocursamples != 0 && m_audiobufin != 0) for (int chnum = 0; chnum < 2; chnum++) - if (m_avconfig.audio[chnum] == &m_audiobuffer[chnum][0]) + if (m_avhuff_config.audio[chnum] == &m_audiobuffer[chnum][0]) { // move data to the end int samplesleft = m_audiobufsize - m_audiobufin; diff --git a/src/emu/machine/laserdsc.h b/src/emu/machine/laserdsc.h index b7c0df154e9..add1c2e8b5d 100644 --- a/src/emu/machine/laserdsc.h +++ b/src/emu/machine/laserdsc.h @@ -43,6 +43,7 @@ #define __LASERDSC_H__ #include "vbiparse.h" +#include "avhuff.h" //************************************************************************** @@ -315,6 +316,7 @@ private: void vblank_state_changed(screen_device &screen, bool vblank_state); frame_data ¤t_frame(); void read_track_data(); + static void *read_async_static(void *param, int threadid); void process_track_data(); void config_load(int config_type, xml_data_node *parentnode); void config_save(int config_type, xml_data_node *parentnode); @@ -332,14 +334,18 @@ private: // disc parameters chd_file * m_disc; // handle to the disc itself - UINT8 * m_vbidata; // pointer to precomputed VBI data + dynamic_buffer m_vbidata; // pointer to precomputed VBI data int m_width; // width of video int m_height; // height of video UINT32 m_fps_times_1million; // frame rate of video int m_samplerate; // audio samplerate - chd_error m_readresult; // result of the most recent read + int m_readresult; // result of the most recent read UINT32 m_chdtracks; // number of tracks in the CHD - av_codec_decompress_config m_avconfig; // decompression configuration + avhuff_decompress_config m_avhuff_config; // decompression configuration + + // async operations + osd_work_queue * m_work_queue; // work queue + UINT32 m_queued_hunknum; // queued hunk // core states UINT8 m_audiosquelch; // audio squelch state: bit 0 = audio 1, bit 1 = audio 2 diff --git a/src/emu/romload.c b/src/emu/romload.c index 25d2aca3276..85351c74b8d 100644 --- a/src/emu/romload.c +++ b/src/emu/romload.c @@ -38,33 +38,21 @@ class open_chd friend class simple_list; public: - open_chd(const char *region, emu_file &file, chd_file &chdfile, emu_file *difffile = NULL, chd_file *diffchd = NULL) + open_chd(const char *region) : m_next(NULL), - m_region(region), - m_origchd(&chdfile), - m_origfile(&file), - m_diffchd(diffchd), - m_difffile(difffile) { } - - ~open_chd() - { - if (m_diffchd != NULL) chd_close(m_diffchd); - global_free(m_difffile); - chd_close(m_origchd); - global_free(m_origfile); - } + m_region(region) { } open_chd *next() const { return m_next; } const char *region() const { return m_region; } - chd_file *chd() const { return (m_diffchd != NULL) ? m_diffchd : m_origchd; } + chd_file &chd() { return m_diffchd.opened() ? m_diffchd : m_origchd; } + chd_file &orig_chd() { return m_origchd; } + chd_file &diff_chd() { return m_diffchd; } private: open_chd * m_next; /* pointer to next in the list */ astring m_region; /* disk region we came from */ - chd_file * m_origchd; /* handle to the original CHD */ - emu_file * m_origfile; /* file handle to the original CHD file */ - chd_file * m_diffchd; /* handle to the diff CHD */ - emu_file * m_difffile; /* file handle to the diff CHD file */ + chd_file m_origchd; /* handle to the original CHD */ + chd_file m_diffchd; /* handle to the diff CHD */ }; @@ -105,21 +93,15 @@ static void rom_exit(running_machine &machine); HELPERS (also used by devimage.c) ***************************************************************************/ -file_error common_process_file(emu_options &options, const char *location, const char *ext, const rom_entry *romp, emu_file **image_file) +file_error common_process_file(emu_options &options, const char *location, const char *ext, const rom_entry *romp, emu_file &image_file) { - *image_file = global_alloc(emu_file(options.media_path(), OPEN_FLAG_READ)); file_error filerr; if (location != NULL && strcmp(location, "") != 0) - filerr = (*image_file)->open(location, PATH_SEPARATOR, ROM_GETNAME(romp), ext); + filerr = image_file.open(location, PATH_SEPARATOR, ROM_GETNAME(romp), ext); else - filerr = (*image_file)->open(ROM_GETNAME(romp), ext); + filerr = image_file.open(ROM_GETNAME(romp), ext); - if (filerr != FILERR_NONE) - { - global_free(*image_file); - *image_file = NULL; - } return filerr; } @@ -155,7 +137,7 @@ chd_file *get_disk_handle(running_machine &machine, const char *region) { for (open_chd *curdisk = machine.romload_data->chd_list.first(); curdisk != NULL; curdisk = curdisk->next()) if (strcmp(curdisk->region(), region) == 0) - return curdisk->chd(); + return &curdisk->chd(); return NULL; } @@ -165,9 +147,15 @@ chd_file *get_disk_handle(running_machine &machine, const char *region) file associated with the given region -------------------------------------------------*/ -void set_disk_handle(running_machine &machine, const char *region, emu_file &file, chd_file &chdfile) +int set_disk_handle(running_machine &machine, const char *region, const char *fullpath) { - machine.romload_data->chd_list.append(*global_alloc(open_chd(region, file, chdfile))); + open_chd *chd = global_alloc(open_chd(region)); + chd_error err = chd->orig_chd().open(fullpath); + if (err == CHDERR_NONE) + machine.romload_data->chd_list.append(*chd); + else + global_free(chd); + return err; } @@ -1010,16 +998,14 @@ static void process_rom_entries(rom_load_data *romdata, const char *regiontag, c checksum -------------------------------------------------*/ -chd_error open_disk_image(emu_options &options, const game_driver *gamedrv, const rom_entry *romp, emu_file **image_file, chd_file **image_chd, const char *locationtag) +int open_disk_image(emu_options &options, const game_driver *gamedrv, const rom_entry *romp, chd_file &image_chd, const char *locationtag) { + emu_file image_file(options.media_path(), OPEN_FLAG_READ); const rom_entry *region, *rom; const rom_source *source; file_error filerr; chd_error err; - *image_file = NULL; - *image_chd = NULL; - /* attempt to open the properly named file, scanning up through parent directories */ filerr = FILERR_NOT_FOUND; for (int searchdrv = driver_list::find(*gamedrv); searchdrv != -1 && filerr != FILERR_NONE; searchdrv = driver_list::clone(searchdrv)) @@ -1103,14 +1089,13 @@ chd_error open_disk_image(emu_options &options, const game_driver *gamedrv, cons /* did the file open succeed? */ if (filerr == FILERR_NONE) { + astring fullpath(image_file.fullpath()); + image_file.close(); + /* try to open the CHD */ - err = chd_open_file(**image_file, CHD_OPEN_READ, NULL, image_chd); + err = image_chd.open(fullpath); if (err == CHDERR_NONE) return err; - - /* close the file on failure */ - global_free(*image_file); - *image_file = NULL; } else err = CHDERR_FILE_NOT_FOUND; @@ -1141,18 +1126,16 @@ chd_error open_disk_image(emu_options &options, const game_driver *gamedrv, cons /* did the file open succeed? */ if (filerr == FILERR_NONE) { + astring fullpath(image_file.fullpath()); + image_file.close(); + /* try to open the CHD */ - err = chd_open_file(**image_file, CHD_OPEN_READ, NULL, image_chd); + err = image_chd.open(fullpath); if (err == CHDERR_NONE) return err; - - /* close the file on failure */ - global_free(*image_file); - *image_file = NULL; } } } - return err; } @@ -1161,48 +1144,43 @@ chd_error open_disk_image(emu_options &options, const game_driver *gamedrv, cons open_disk_diff - open a DISK diff file -------------------------------------------------*/ -static chd_error open_disk_diff(emu_options &options, const rom_entry *romp, chd_file *source, emu_file **diff_file, chd_file **diff_chd) +static chd_error open_disk_diff(emu_options &options, const rom_entry *romp, chd_file &source, chd_file &diff_chd) { astring fname(ROM_GETNAME(romp), ".dif"); - chd_error err; - - *diff_file = NULL; - *diff_chd = NULL; /* try to open the diff */ LOG(("Opening differencing image file: %s\n", fname.cstr())); - *diff_file = global_alloc(emu_file(options.diff_directory(), OPEN_FLAG_READ | OPEN_FLAG_WRITE)); - file_error filerr = (*diff_file)->open(fname); - if (filerr != FILERR_NONE) + emu_file diff_file(options.diff_directory(), OPEN_FLAG_READ | OPEN_FLAG_WRITE); + file_error filerr = diff_file.open(fname); + if (filerr == FILERR_NONE) { - /* didn't work; try creating it instead */ - LOG(("Creating differencing image: %s\n", fname.cstr())); - (*diff_file)->set_openflags(OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); - filerr = (*diff_file)->open(fname); - if (filerr != FILERR_NONE) - { - err = CHDERR_FILE_NOT_FOUND; - goto done; - } + astring fullpath(diff_file.fullpath()); + diff_file.close(); + + LOG(("Opening differencing image file: %s\n", fullpath.cstr())); + return diff_chd.open(fullpath, true, &source); + } + + /* didn't work; try creating it instead */ + LOG(("Creating differencing image: %s\n", fname.cstr())); + diff_file.set_openflags(OPEN_FLAG_READ | OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS); + filerr = diff_file.open(fname); + if (filerr == FILERR_NONE) + { + astring fullpath(diff_file.fullpath()); + diff_file.close(); /* create the CHD */ - err = chd_create_file(**diff_file, 0, 0, CHDCOMPRESSION_NONE, source); + LOG(("Creating differencing image file: %s\n", fullpath.cstr())); + chd_codec_type compression[4] = { CHD_CODEC_NONE }; + chd_error err = diff_chd.create(fullpath, source.logical_bytes(), source.hunk_bytes(), compression, source); if (err != CHDERR_NONE) - goto done; + return err; + + return diff_chd.clone_all_metadata(source); } - LOG(("Opening differencing image file: %s\n", fname.cstr())); - err = chd_open_file(**diff_file, CHD_OPEN_READWRITE, source, diff_chd); - if (err != CHDERR_NONE) - goto done; - -done: - if ((err != CHDERR_NONE) && (*diff_file != NULL)) - { - global_free(*diff_file); - *diff_file = NULL; - } - return err; + return CHDERR_FILE_NOT_FOUND; } @@ -1219,24 +1197,23 @@ static void process_disk_entries(rom_load_data *romdata, const char *regiontag, /* handle files */ if (ROMENTRY_ISFILE(romp)) { + open_chd *chd = global_alloc(open_chd(regiontag)); + hash_collection hashes(ROM_GETHASHDATA(romp)); - chd_header header; chd_error err; /* make the filename of the source */ astring filename(ROM_GETNAME(romp), ".chd"); /* first open the source drive */ - chd_file *origchd; - emu_file *origfile; LOG(("Opening disk image: %s\n", filename.cstr())); - err = open_disk_image(romdata->machine().options(), &romdata->machine().system(), romp, &origfile, &origchd, locationtag); + err = chd_error(open_disk_image(romdata->machine().options(), &romdata->machine().system(), romp, chd->orig_chd(), locationtag)); if (err != CHDERR_NONE) { if (err == CHDERR_FILE_NOT_FOUND) romdata->errorstring.catprintf("%s NOT FOUND\n", filename.cstr()); else - romdata->errorstring.catprintf("%s CHD ERROR: %s\n", filename.cstr(), chd_error_string(err)); + romdata->errorstring.catprintf("%s CHD ERROR: %s\n", filename.cstr(), chd_file::error_string(err)); /* if this is NO_DUMP, keep going, though the system may not be able to handle it */ if (hashes.flag(hash_collection::FLAG_NO_DUMP)) @@ -1245,13 +1222,13 @@ static void process_disk_entries(rom_load_data *romdata, const char *regiontag, romdata->warnings++; else romdata->errors++; + global_free(chd); continue; } /* get the header and extract the SHA1 */ - header = *chd_get_header(origchd); hash_collection acthashes; - acthashes.add_from_buffer(hash_collection::HASH_SHA1, header.sha1, sizeof(header.sha1)); + acthashes.add_from_buffer(hash_collection::HASH_SHA1, chd->orig_chd().sha1().m_raw, sizeof(chd->orig_chd().sha1().m_raw)); /* verify the hash */ if (hashes != acthashes) @@ -1267,23 +1244,22 @@ static void process_disk_entries(rom_load_data *romdata, const char *regiontag, } /* if not read-only, make the diff file */ - chd_file *diffchd = NULL; - emu_file *difffile = NULL; if (!DISK_ISREADONLY(romp)) { /* try to open or create the diff */ - err = open_disk_diff(romdata->machine().options(), romp, origchd, &difffile, &diffchd); + err = open_disk_diff(romdata->machine().options(), romp, chd->orig_chd(), chd->diff_chd()); if (err != CHDERR_NONE) { - romdata->errorstring.catprintf("%s DIFF CHD ERROR: %s\n", filename.cstr(), chd_error_string(err)); + romdata->errorstring.catprintf("%s DIFF CHD ERROR: %s\n", filename.cstr(), chd_file::error_string(err)); romdata->errors++; + global_free(chd); continue; } } /* we're okay, add to the list of disks */ LOG(("Assigning to handle %d\n", DISK_GETINDEX(romp))); - romdata->machine().romload_data->chd_list.append(*global_alloc(open_chd(regiontag, *origfile, *origchd, difffile, diffchd))); + romdata->machine().romload_data->chd_list.append(*chd); } } } diff --git a/src/emu/romload.h b/src/emu/romload.h index 77cc35d0626..108eabd1820 100644 --- a/src/emu/romload.h +++ b/src/emu/romload.h @@ -121,6 +121,7 @@ enum class machine_config; class emu_options; +class chd_file; typedef device_t rom_source; @@ -315,13 +316,13 @@ astring &rom_region_name(astring &result, const game_driver *drv, const rom_sour /* ----- disk handling ----- */ /* open a disk image, searching up the parent and loading by checksum */ -chd_error open_disk_image(emu_options &options, const game_driver *gamedrv, const rom_entry *romp, emu_file **image_file, chd_file **image_chd,const char *locationtag); +int open_disk_image(emu_options &options, const game_driver *gamedrv, const rom_entry *romp, chd_file &image_chd, const char *locationtag); /* return a pointer to the CHD file associated with the given region */ chd_file *get_disk_handle(running_machine &machine, const char *region); /* set a pointer to the CHD file associated with the given region */ -void set_disk_handle(running_machine &machine, const char *region, emu_file &file, chd_file &chdfile); +int set_disk_handle(running_machine &machine, const char *region, const char *fullpath); void load_software_part_region(device_t *device, char *swlist, char *swname, rom_entry *start_region); diff --git a/src/ldplayer/ldplayer.c b/src/ldplayer/ldplayer.c index 9ce38a58147..6b0a059b2ee 100644 --- a/src/ldplayer/ldplayer.c +++ b/src/ldplayer/ldplayer.c @@ -166,8 +166,6 @@ chd_file *ldplayer_state::get_disc() // iterate while we get new objects const osd_directory_entry *dir; - emu_file *image_file = NULL; - chd_file *image_chd = NULL; while ((dir = path.next()) != NULL) { int length = strlen(dir->name); @@ -180,15 +178,17 @@ chd_file *ldplayer_state::get_disc() tolower(dir->name[length - 1]) == 'd') { // open the file itself via our search path - image_file = auto_alloc(machine(), emu_file(machine().options().media_path(), OPEN_FLAG_READ)); - file_error filerr = image_file->open(dir->name); + emu_file image_file(machine().options().media_path(), OPEN_FLAG_READ); + file_error filerr = image_file.open(dir->name); if (filerr == FILERR_NONE) { + astring fullpath(image_file->fullpath(); + image_file.close(); + // try to open the CHD - chd_error chderr = chd_open_file(*image_file, CHD_OPEN_READ, NULL, &image_chd); - if (chderr == CHDERR_NONE) + + if (set_disk_handle(machine(), "laserdisc", fullpath) == CHDERR_NONE) { - set_disk_handle(machine(), "laserdisc", *image_file, *image_chd); m_filename.cpy(dir->name); break; } diff --git a/src/lib/lib.mak b/src/lib/lib.mak index a52f1651a47..5cc276f529f 100644 --- a/src/lib/lib.mak +++ b/src/lib/lib.mak @@ -32,16 +32,19 @@ OBJDIRS += \ UTILOBJS = \ $(LIBOBJ)/util/astring.o \ - $(LIBOBJ)/util/avcomp.o \ + $(LIBOBJ)/util/avhuff.o \ $(LIBOBJ)/util/aviio.o \ $(LIBOBJ)/util/bitmap.o \ $(LIBOBJ)/util/cdrom.o \ $(LIBOBJ)/util/chd.o \ $(LIBOBJ)/util/chdcd.o \ + $(LIBOBJ)/util/chdcodec.o \ $(LIBOBJ)/util/corefile.o \ $(LIBOBJ)/util/corestr.o \ $(LIBOBJ)/util/coreutil.o \ + $(LIBOBJ)/util/flac.o \ $(LIBOBJ)/util/harddisk.o \ + $(LIBOBJ)/util/hashing.o \ $(LIBOBJ)/util/huffman.o \ $(LIBOBJ)/util/jedparse.o \ $(LIBOBJ)/util/md5.o \ @@ -73,7 +76,7 @@ EXPATOBJS = \ $(OBJ)/libexpat.a: $(EXPATOBJS) -$(LIBOBJ)/expat/%.o: $(LIBSRC)/explat/%.c | $(OSPREBUILD) +$(LIBOBJ)/expat/%.o: $(LIBSRC)/expat/%.c | $(OSPREBUILD) @echo Compiling $<... $(CC) $(CDEFS) $(CCOMFLAGS) $(CONLYFLAGS) -c $< -o $@ @@ -273,6 +276,7 @@ $(LIBOBJ)/libjpeg/%.o: $(LIBSRC)/libjpeg/%.c | $(OSPREBUILD) $(CC) $(CDEFS) $(CCOMFLAGS) $(CONLYFLAGS) -I$(LIBSRC)/libjpeg -c $< -o $@ + #------------------------------------------------- # libflac library objects #------------------------------------------------- @@ -303,23 +307,12 @@ $(LIBOBJ)/libflac/%.o: $(LIBSRC)/libflac/libflac/%.c | $(OSPREBUILD) $(CC) $(CDEFS) $(FLACOPTS) $(CONLYFLAGS) -I$(LIBSRC)/libflac/include -c $< -o $@ -# LIBFLACPPOBJS = \ -# $(LIBOBJ)/libflacpp/metadata.o \ -# $(LIBOBJ)/libflacpp/stream_decoder.o \ -# $(LIBOBJ)/libflacpp/stream_encoder.o - -# $(OBJ)/libflac++.a: $(LIBFLACPPOBJS) - -# $(LIBOBJ)/libflacpp/%.o: $(LIBSRC)/libflac/libflac++/%.cpp | $(OSPREBUILD) -# @echo Compiling $<... -# $(CC) $(CDEFS) $(FLACOPTS) $(CPPONLYFLAGS) -I$(LIBSRC)/libflac/include -c $< -o $@ - #------------------------------------------------- # lib7z library objects #------------------------------------------------- -7ZOPTS=-D_7ZIP_PPMD_SUPPPORT +7ZOPTS=-D_7ZIP_PPMD_SUPPPORT -D_7ZIP_ST LIB7ZOBJS = \ $(LIBOBJ)/lib7z/7zBuf.o \ @@ -331,6 +324,9 @@ LIB7ZOBJS = \ $(LIBOBJ)/lib7z/CpuArch.o \ $(LIBOBJ)/lib7z/LzmaDec.o \ $(LIBOBJ)/lib7z/Lzma2Dec.o \ + $(LIBOBJ)/lib7z/LzmaEnc.o \ + $(LIBOBJ)/lib7z/Lzma2Enc.o \ + $(LIBOBJ)/lib7z/LzFind.o \ $(LIBOBJ)/lib7z/Bra.o \ $(LIBOBJ)/lib7z/Bra86.o \ $(LIBOBJ)/lib7z/Bcj2.o \ @@ -343,6 +339,3 @@ $(OBJ)/lib7z.a: $(LIB7ZOBJS) $(LIBOBJ)/lib7z/%.o: $(LIBSRC)/lib7z/%.c | $(OSPREBUILD) @echo Compiling $<... $(CC) $(CDEFS) $(7ZOPTS) $(CONLYFLAGS) -I$(LIBSRC)/lib7z/ -c $< -o $@ - - - diff --git a/src/lib/lib7z/LzmaDec.c b/src/lib/lib7z/LzmaDec.c index 8c1a1486df1..a85edb7dfd0 100644 --- a/src/lib/lib7z/LzmaDec.c +++ b/src/lib/lib7z/LzmaDec.c @@ -967,6 +967,27 @@ SRes LzmaDec_Allocate(CLzmaDec *p, const Byte *props, unsigned propsSize, ISzAll return SZ_OK; } +// why isn't there an interface to pass in the properties directly???? +SRes LzmaDec_Allocate_MAME(CLzmaDec *p, const CLzmaProps *propNew, ISzAlloc *alloc) +{ + SizeT dicBufSize; + RINOK(LzmaDec_AllocateProbs2(p, propNew, alloc)); + dicBufSize = propNew->dicSize; + if (p->dic == 0 || dicBufSize != p->dicBufSize) + { + LzmaDec_FreeDict(p, alloc); + p->dic = (Byte *)alloc->Alloc(alloc, dicBufSize); + if (p->dic == 0) + { + LzmaDec_FreeProbs(p, alloc); + return SZ_ERROR_MEM; + } + } + p->dicBufSize = dicBufSize; + p->prop = *propNew; + return SZ_OK; +} + SRes LzmaDecode(Byte *dest, SizeT *destLen, const Byte *src, SizeT *srcLen, const Byte *propData, unsigned propSize, ELzmaFinishMode finishMode, ELzmaStatus *status, ISzAlloc *alloc) diff --git a/src/lib/lib7z/Ppmd7.c b/src/lib/lib7z/Ppmd7.c index 060d86d2e0f..bba4d06f0ab 100644 --- a/src/lib/lib7z/Ppmd7.c +++ b/src/lib/lib7z/Ppmd7.c @@ -2,7 +2,7 @@ 2010-03-12 : Igor Pavlov : Public domain This code is based on PPMd var.H (2001): Dmitry Shkarin : Public domain */ -#include +#include #include "Ppmd7.h" diff --git a/src/lib/util/astring.h b/src/lib/util/astring.h index 09236de8f5d..665a64786fb 100644 --- a/src/lib/util/astring.h +++ b/src/lib/util/astring.h @@ -52,7 +52,7 @@ // TYPE DEFINITIONS //************************************************************************** -// derived class for C++ +// basic allocated string class class astring { public: diff --git a/src/lib/util/avcomp.c b/src/lib/util/avcomp.c deleted file mode 100644 index 91fa483d16c..00000000000 --- a/src/lib/util/avcomp.c +++ /dev/null @@ -1,898 +0,0 @@ -/*************************************************************************** - - avcomp.c - - Audio/video compression and decompression helpers. - -**************************************************************************** - - Copyright Aaron Giles - All rights reserved. - - Redistribution and use in source and binary forms, with or without - modification, are permitted provided that the following conditions are - met: - - * Redistributions of source code must retain the above copyright - notice, this list of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright - notice, this list of conditions and the following disclaimer in - the documentation and/or other materials provided with the - distribution. - * Neither the name 'MAME' nor the names of its contributors may be - used to endorse or promote products derived from this software - without specific prior written permission. - - THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR - IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT, - INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR - SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - POSSIBILITY OF SUCH DAMAGE. - -**************************************************************************** - - Each frame is compressed as a unit. The raw data is of the form: - (all multibyte values are stored in big-endian format) - - +00 = 'chav' (4 bytes) - fixed header data to identify the format - +04 = metasize (1 byte) - size of metadata in bytes (max=255 bytes) - +05 = channels (1 byte) - number of audio channels - +06 = samples (2 bytes) - number of samples per audio stream - +08 = width (2 bytes) - width of video data - +0A = height (2 bytes) - height of video data - +0C = - as raw bytes -