Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@ set(CHDR_SOURCES
src/libchdr_bitstream.c
src/libchdr_cdrom.c
src/libchdr_chd.c
src/libchdr_codec_avhuff.c
src/libchdr_codec_cdfl.c
src/libchdr_codec_cdlz.c
src/libchdr_codec_cdzl.c
Expand Down
1 change: 1 addition & 0 deletions include/libchdr/chd.h
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,7 @@ extern "C" {
#define CHD_CODEC_HUFFMAN CHD_MAKE_TAG('h','u','f','f')
#define CHD_CODEC_FLAC CHD_MAKE_TAG('f','l','a','c')
#define CHD_CODEC_ZSTD CHD_MAKE_TAG('z', 's', 't', 'd')
#define CHD_CODEC_AVHUFF CHD_MAKE_TAG('a','v','h','u')
/* general codecs with CD frontend */
#define CHD_CODEC_CD_ZLIB CHD_MAKE_TAG('c','d','z','l')
#define CHD_CODEC_CD_LZMA CHD_MAKE_TAG('c','d','l','z')
Expand Down
52 changes: 52 additions & 0 deletions src/codec_avhuff.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
/* license:BSD-3-Clause
* copyright-holders:Aaron Giles
*
* codec_avhuff.h
*
* AVHuff (audio/video) codec decompressor private data.
* Used by CHDv5 'avhu' codec for laserdisc CHDs.
*/

#ifndef __CODEC_AVHUFF_H__
#define __CODEC_AVHUFF_H__

#include <stdint.h>

#include "../include/libchdr/chd.h"
#include "../include/libchdr/flac.h"

struct huffman_decoder;

/* codec-private data for the AVHuff codec */
typedef struct _avhuff_codec_data avhuff_codec_data;
struct _avhuff_codec_data
{
/* video delta-RLE decoder state (Y, Cb, Cr) */
struct huffman_decoder *ycontext;
struct huffman_decoder *cbcontext;
struct huffman_decoder *crcontext;
uint8_t y_prev;
uint8_t cb_prev;
uint8_t cr_prev;
int y_rlecount;
int cb_rlecount;
int cr_rlecount;

/* audio delta-RLE decoder state (hi byte, lo byte) */
struct huffman_decoder *audiohi;
struct huffman_decoder *audiolo;
uint8_t ahi_prev;
uint8_t alo_prev;
int ahi_rlecount;
int alo_rlecount;

/* FLAC decoder (reused per channel when treesize == 0xffff) */
flac_decoder flac;
};

chd_error avhuff_codec_init(void *codec, uint32_t hunkbytes);
void avhuff_codec_free(void *codec);
chd_error avhuff_codec_decompress(void *codec, const uint8_t *src, uint32_t complen,
uint8_t *dest, uint32_t destlen);

#endif /* __CODEC_AVHUFF_H__ */
50 changes: 47 additions & 3 deletions src/libchdr_chd.c
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@

#include "../include/libchdr/chd.h"
#include "../include/libchdr/cdrom.h"
#include "codec_avhuff.h"
#include "codec_cdfl.h"
#include "codec_cdlz.h"
#include "codec_cdzl.h"
Expand Down Expand Up @@ -231,6 +232,7 @@ struct _chd_file
cdlz_codec_data cdlz; /* cdlz codec data */
cdfl_codec_data cdfl; /* cdfl codec data */
cdzs_codec_data cdzs; /* cdzs codec data */
avhuff_codec_data avhuff; /* avhuff codec data */
} codec_data;

uint8_t * file_cache; /* cache of underlying file */
Expand Down Expand Up @@ -409,8 +411,27 @@ static const codec_interface codec_interfaces[] =
cdzs_codec_free,
cdzs_codec_decompress,
NULL
},
/* V5 A/V Huffman (laserdisc) */
{
CHD_CODEC_AVHUFF,
"A/V Huffman",
FALSE,
avhuff_codec_init,
avhuff_codec_free,
avhuff_codec_decompress,
NULL
},
/* V3/V4 A/V Huffman (laserdisc) — CHDCOMPRESSION_AV */
{
CHDCOMPRESSION_AV,
"A/V Huffman (v3/v4)",
FALSE,
avhuff_codec_init,
avhuff_codec_free,
avhuff_codec_decompress,
NULL
}

};

/***************************************************************************
Expand Down Expand Up @@ -1001,7 +1022,11 @@ CHD_EXPORT chd_error chd_open_core_file_callbacks(const core_file_callbacks *cal
/* initialize the codec */
if (newchd->codecintf[0]->init != NULL)
{
err = newchd->codecintf[0]->init(&newchd->codec_data.zlib, newchd->header.hunkbytes);
/* v1-v4 codecs that use their own state blob; zlib is the default */
void* codec = &newchd->codec_data.zlib;
if (newchd->header.compression[0] == CHDCOMPRESSION_AV)
codec = &newchd->codec_data.avhuff;
err = newchd->codecintf[0]->init(codec, newchd->header.hunkbytes);
if (err != CHDERR_NONE)
EARLY_EXIT(err);
}
Expand Down Expand Up @@ -1081,6 +1106,10 @@ CHD_EXPORT chd_error chd_open_core_file_callbacks(const core_file_callbacks *cal
case CHD_CODEC_CD_ZSTD:
codec = &newchd->codec_data.cdzs;
break;

case CHD_CODEC_AVHUFF:
codec = &newchd->codec_data.avhuff;
break;
}

if (codec == NULL)
Expand Down Expand Up @@ -1177,7 +1206,12 @@ CHD_EXPORT void chd_close(chd_file *chd)
if (chd->header.version < 5)
{
if (chd->codecintf[0] != NULL && chd->codecintf[0]->free != NULL)
chd->codecintf[0]->free(&chd->codec_data.zlib);
{
void *codec = &chd->codec_data.zlib;
if (chd->header.compression[0] == CHDCOMPRESSION_AV)
codec = &chd->codec_data.avhuff;
chd->codecintf[0]->free(codec);
}
}
else
{
Expand Down Expand Up @@ -1242,6 +1276,10 @@ CHD_EXPORT void chd_close(chd_file *chd)
case CHD_CODEC_CD_ZSTD:
codec = &chd->codec_data.cdzs;
break;

case CHD_CODEC_AVHUFF:
codec = &chd->codec_data.avhuff;
break;
}

if (codec)
Expand Down Expand Up @@ -1833,6 +1871,8 @@ static chd_error hunk_read_into_memory(chd_file *chd, uint32_t hunknum, uint8_t
/* now decompress using the codec */
err = CHDERR_NONE;
codec = &chd->codec_data.zlib;
if (chd->header.compression[0] == CHDCOMPRESSION_AV)
codec = &chd->codec_data.avhuff;
if (chd->codecintf[0]->decompress != NULL)
err = chd->codecintf[0]->decompress(codec, compressed_bytes, entry->length, dest, chd->header.hunkbytes);
if (err != CHDERR_NONE)
Expand Down Expand Up @@ -1953,6 +1993,10 @@ static chd_error hunk_read_into_memory(chd_file *chd, uint32_t hunknum, uint8_t
case CHD_CODEC_CD_ZSTD:
codec = &chd->codec_data.cdzs;
break;

case CHD_CODEC_AVHUFF:
codec = &chd->codec_data.avhuff;
break;
}
if (codec==NULL)
return CHDERR_CODEC_ERROR;
Expand Down
Loading
Loading