Fix hang on full loops with xma1 formats

- happens with FFmpeg n5.1.2
This commit is contained in:
bnnm 2023-01-19 00:08:33 +01:00
parent ebb9b51e04
commit 41bad49872
11 changed files with 123 additions and 117 deletions

View File

@ -622,6 +622,9 @@ ffmpeg_codec_data* init_ffmpeg_atrac3_riff(STREAMFILE* sf, off_t offset, int* ou
ffmpeg_codec_data* init_ffmpeg_aac(STREAMFILE* sf, off_t offset, size_t size, int skip_samples); ffmpeg_codec_data* init_ffmpeg_aac(STREAMFILE* sf, off_t offset, size_t size, int skip_samples);
ffmpeg_codec_data* init_ffmpeg_xwma(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int format, int channels, int sample_rate, int avg_bitrate, int block_size); ffmpeg_codec_data* init_ffmpeg_xwma(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int format, int channels, int sample_rate, int avg_bitrate, int block_size);
ffmpeg_codec_data* init_ffmpeg_xma1_raw(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int channels, int sample_rate, int stream_mode);
/* ffmpeg_decoder_custom_opus.c (helper-things) */ /* ffmpeg_decoder_custom_opus.c (helper-things) */
typedef struct { typedef struct {
int channels; int channels;
@ -680,7 +683,6 @@ ffmpeg_codec_data* init_ffmpeg_mp4_custom_lyn(STREAMFILE* sf, mp4_custom_t* mp4)
/* coding_utils */ /* coding_utils */
int ffmpeg_fmt_chunk_swap_endian(uint8_t* chunk, size_t chunk_size, uint16_t codec); int ffmpeg_fmt_chunk_swap_endian(uint8_t* chunk, size_t chunk_size, uint16_t codec);
int ffmpeg_make_riff_atrac3plus(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int encoder_delay); int ffmpeg_make_riff_atrac3plus(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_align, int encoder_delay);
int ffmpeg_make_riff_xma1(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int stream_mode);
int ffmpeg_make_riff_xma2(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_count, int block_size); int ffmpeg_make_riff_xma2(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_count, int block_size);
int ffmpeg_make_riff_xma_from_fmt_chunk(uint8_t* buf, size_t buf_size, off_t fmt_offset, size_t fmt_size, size_t data_size, STREAMFILE* sf, int big_endian); int ffmpeg_make_riff_xma_from_fmt_chunk(uint8_t* buf, size_t buf_size, off_t fmt_offset, size_t fmt_size, size_t data_size, STREAMFILE* sf, int big_endian);
int ffmpeg_make_riff_xma2_from_xma2_chunk(uint8_t* buf, size_t buf_size, off_t xma2_offset, size_t xma2_size, size_t data_size, STREAMFILE* sf); int ffmpeg_make_riff_xma2_from_xma2_chunk(uint8_t* buf, size_t buf_size, off_t xma2_offset, size_t xma2_size, size_t data_size, STREAMFILE* sf);

View File

@ -80,90 +80,6 @@ int ffmpeg_make_riff_atrac3plus(uint8_t* buf, size_t buf_size, size_t sample_cou
return riff_size; return riff_size;
} }
int ffmpeg_make_riff_xma1(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int stream_mode) {
uint16_t codec_XMA1 = 0x0165;
size_t riff_size;
int streams, i;
/* stream disposition:
* 0: default (ex. 5ch = 2ch + 2ch + 1ch = 3 streams)
* 1: lineal (ex. 5ch = 1ch + 1ch + 1ch + 1ch + 1ch = 5 streams), unusual but exists
* others: not seen (ex. maybe 5ch = 2ch + 1ch + 1ch + 1ch = 4 streams) */
switch(stream_mode) {
case 0 : streams = (channels + 1) / 2; break;
case 1 : streams = channels; break;
default: return 0;
}
riff_size = 4+4+ 4 + 0x14 + 0x14*streams + 4+4;
if (buf_size < riff_size)
return -1;
memcpy(buf+0x00, "RIFF", 4);
put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */
memcpy(buf+0x08, "WAVE", 4);
memcpy(buf+0x0c, "fmt ", 4);
put_32bitLE(buf+0x10, 0xc + 0x14*streams);/*fmt size*/
put_16bitLE(buf+0x14, codec_XMA1);
put_16bitLE(buf+0x16, 16); /* bits per sample */
put_16bitLE(buf+0x18, 0x10D6); /* encoder options */
put_16bitLE(buf+0x1a, 0); /* largest stream skip (wrong, unneeded) */
put_16bitLE(buf+0x1c, streams); /* number of streams */
put_8bit (buf+0x1e, 0); /* loop count */
put_8bit (buf+0x1f, 2); /* version */
for (i = 0; i < streams; i++) {
int stream_channels;
uint32_t speakers;
off_t off = 0x20 + 0x14*i;/* stream riff offset */
if (stream_mode == 1) {
/* lineal */
stream_channels = 1;
switch(i) { /* per stream, values observed */
case 0: speakers = 0x0001; break;/* L */
case 1: speakers = 0x0002; break;/* R */
case 2: speakers = 0x0004; break;/* C */
case 3: speakers = 0x0008; break;/* LFE */
case 4: speakers = 0x0040; break;/* LB */
case 5: speakers = 0x0080; break;/* RB */
case 6: speakers = 0x0000; break;/* ? */
case 7: speakers = 0x0000; break;/* ? */
default: speakers = 0;
}
}
else {
/* with odd channels the last stream is mono */
stream_channels = channels / streams + (channels%2 != 0 && i+1 != streams ? 1 : 0);
switch(i) { /* per stream, values from xmaencode */
case 0: speakers = stream_channels == 1 ? 0x0001 : 0x0201; break;/* L R */
case 1: speakers = stream_channels == 1 ? 0x0004 : 0x0804; break;/* C LFE */
case 2: speakers = stream_channels == 1 ? 0x0040 : 0x8040; break;/* LB RB */
case 3: speakers = stream_channels == 1 ? 0x0000 : 0x0000; break;/* somehow empty (maybe should use 0x2010 LS RS) */
default: speakers = 0;
}
}
put_32bitLE(buf+off+0x00, sample_rate*stream_channels / sizeof(sample)); /* average bytes per second (wrong, unneeded) */
put_32bitLE(buf+off+0x04, sample_rate);
put_32bitLE(buf+off+0x08, 0); /* loop start */
put_32bitLE(buf+off+0x0c, 0); /* loop end */
put_8bit (buf+off+0x10, 0); /* loop subframe */
put_8bit (buf+off+0x11, stream_channels);
put_16bitLE(buf+off+0x12, speakers);
}
/* xmaencode decoding rejects XMA1 without "seek" chunk, though it doesn't seem to use it
* (needs to be have entries but can be bogus, also generates seek for even small sounds) */
memcpy(buf+riff_size-4-4, "data", 4);
put_32bitLE(buf+riff_size-4, data_size); /* data size */
return riff_size;
}
int ffmpeg_make_riff_xma2(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_count, int block_size) { int ffmpeg_make_riff_xma2(uint8_t* buf, size_t buf_size, size_t sample_count, size_t data_size, int channels, int sample_rate, int block_count, int block_size) {
uint16_t codec_XMA2 = 0x0166; uint16_t codec_XMA2 = 0x0166;
size_t riff_size = 4+4+ 4 + 0x3c + 4+4; size_t riff_size = 4+4+ 4 + 0x3c + 4+4;
@ -235,7 +151,7 @@ int ffmpeg_make_riff_xma_from_fmt_chunk(uint8_t* buf, size_t buf_size, off_t fmt
goto fail; goto fail;
if (big_endian) { if (big_endian) {
int codec = read_16bitBE(fmt_offset,sf); int codec = read_16bitBE(fmt_offset,sf);//TODO read from buf
ffmpeg_fmt_chunk_swap_endian(chunk, fmt_size, codec); ffmpeg_fmt_chunk_swap_endian(chunk, fmt_size, codec);
} }

View File

@ -220,4 +220,106 @@ fail:
return NULL; return NULL;
} }
static int ffmpeg_make_riff_xma1(uint8_t* buf, size_t buf_size, size_t data_size, int channels, int sample_rate, int stream_mode) {
uint16_t codec_XMA1 = 0x0165;
size_t riff_size;
int streams, i;
/* stream disposition:
* 0: default (ex. 5ch = 2ch + 2ch + 1ch = 3 streams)
* 1: lineal (ex. 5ch = 1ch + 1ch + 1ch + 1ch + 1ch = 5 streams), unusual but exists
* others: not seen (ex. maybe 5ch = 2ch + 1ch + 1ch + 1ch = 4 streams) */
switch(stream_mode) {
case 0 : streams = (channels + 1) / 2; break;
case 1 : streams = channels; break;
default: return 0;
}
riff_size = 4+4+ 4 + 0x14 + 0x14*streams + 4+4;
if (buf_size < riff_size)
return -1;
memcpy(buf+0x00, "RIFF", 4);
put_32bitLE(buf+0x04, (int32_t)(riff_size-4-4 + data_size)); /* riff size */
memcpy(buf+0x08, "WAVE", 4);
memcpy(buf+0x0c, "fmt ", 4);
put_32bitLE(buf+0x10, 0xc + 0x14*streams);/*fmt size*/
put_16bitLE(buf+0x14, codec_XMA1);
put_16bitLE(buf+0x16, 16); /* bits per sample */
put_16bitLE(buf+0x18, 0x10D6); /* encoder options */
put_16bitLE(buf+0x1a, 0); /* largest stream skip (wrong, unneeded) */
put_16bitLE(buf+0x1c, streams); /* number of streams */
put_8bit (buf+0x1e, 0); /* loop count */
put_8bit (buf+0x1f, 2); /* version */
for (i = 0; i < streams; i++) {
int stream_channels;
uint32_t speakers;
off_t off = 0x20 + 0x14*i;/* stream riff offset */
if (stream_mode == 1) {
/* lineal */
stream_channels = 1;
switch(i) { /* per stream, values observed */
case 0: speakers = 0x0001; break;/* L */
case 1: speakers = 0x0002; break;/* R */
case 2: speakers = 0x0004; break;/* C */
case 3: speakers = 0x0008; break;/* LFE */
case 4: speakers = 0x0040; break;/* LB */
case 5: speakers = 0x0080; break;/* RB */
case 6: speakers = 0x0000; break;/* ? */
case 7: speakers = 0x0000; break;/* ? */
default: speakers = 0;
}
}
else {
/* with odd channels the last stream is mono */
stream_channels = channels / streams + (channels%2 != 0 && i+1 != streams ? 1 : 0);
switch(i) { /* per stream, values from xmaencode */
case 0: speakers = stream_channels == 1 ? 0x0001 : 0x0201; break;/* L R */
case 1: speakers = stream_channels == 1 ? 0x0004 : 0x0804; break;/* C LFE */
case 2: speakers = stream_channels == 1 ? 0x0040 : 0x8040; break;/* LB RB */
case 3: speakers = stream_channels == 1 ? 0x0000 : 0x0000; break;/* somehow empty (maybe should use 0x2010 LS RS) */
default: speakers = 0;
}
}
put_32bitLE(buf+off+0x00, sample_rate*stream_channels / sizeof(sample)); /* average bytes per second (wrong, unneeded) */
put_32bitLE(buf+off+0x04, sample_rate);
put_32bitLE(buf+off+0x08, 0); /* loop start */
put_32bitLE(buf+off+0x0c, 0); /* loop end */
put_8bit (buf+off+0x10, 0); /* loop subframe */
put_8bit (buf+off+0x11, stream_channels);
put_16bitLE(buf+off+0x12, speakers);
}
/* xmaencode decoding rejects XMA1 without "seek" chunk, though it doesn't seem to use it
* (needs to be have entries but can be bogus, also generates seek for even small sounds) */
memcpy(buf+riff_size-4-4, "data", 4);
put_32bitLE(buf+riff_size-4, data_size); /* data size */
return riff_size;
}
ffmpeg_codec_data* init_ffmpeg_xma1_raw(STREAMFILE* sf, uint32_t data_offset, uint32_t data_size, int channels, int sample_rate, int stream_mode) {
ffmpeg_codec_data* data = NULL;
uint8_t buf[0x100];
int bytes;
bytes = ffmpeg_make_riff_xma1(buf, sizeof(buf), data_size, channels, sample_rate, stream_mode);
data = init_ffmpeg_header_offset(sf, buf, bytes, data_offset, data_size);
/* n5.1.2 XMA1 hangs on seeks near end (infinite loop), presumably due to missing flush in wmapro.c's ff_xma1_decoder + frame skip samples */
ffmpeg_set_force_seek(data);
return data;
fail:
free_ffmpeg(data);
return NULL;
}
#endif #endif

View File

@ -179,11 +179,7 @@ VGMSTREAM * init_vgmstream_baf(STREAMFILE *sf) {
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
case 0x08: { case 0x08: {
uint8_t buf[0x100]; vgmstream->codec_data = init_ffmpeg_xma1_raw(sf, start_offset, stream_size, vgmstream->channels, vgmstream->sample_rate, 0);
int bytes;
bytes = ffmpeg_make_riff_xma1(buf,0x100, 0, stream_size, vgmstream->channels, vgmstream->sample_rate, 0);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, start_offset,stream_size);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;

View File

@ -1863,11 +1863,13 @@ static layered_layout_data* build_layered_eaaudiocore(STREAMFILE *sf_data, eaac_
* (SNS with XMA2 do exist). Decoder should work when playing XMA1 as XMA2, but * (SNS with XMA2 do exist). Decoder should work when playing XMA1 as XMA2, but
* the other way around can cause issues, so it's safer to just use XMA2. */ * the other way around can cause issues, so it's safer to just use XMA2. */
is_xma1 = 0; //eaac->version == EAAC_VERSION_V0; /* approximate */ is_xma1 = 0; //eaac->version == EAAC_VERSION_V0; /* approximate */
if (is_xma1) if (is_xma1) {
bytes = ffmpeg_make_riff_xma1(buf, 0x100, data->layers[i]->num_samples, stream_size, data->layers[i]->channels, data->layers[i]->sample_rate, 0); data->layers[i]->codec_data = init_ffmpeg_xma1_raw(temp_sf, 0x00, stream_size, data->layers[i]->channels, data->layers[i]->sample_rate, 0);
else }
else {
bytes = ffmpeg_make_riff_xma2(buf, 0x100, data->layers[i]->num_samples, stream_size, data->layers[i]->channels, data->layers[i]->sample_rate, block_count, block_size); bytes = ffmpeg_make_riff_xma2(buf, 0x100, data->layers[i]->num_samples, stream_size, data->layers[i]->channels, data->layers[i]->sample_rate, block_count, block_size);
data->layers[i]->codec_data = init_ffmpeg_header_offset(temp_sf, buf,bytes, 0x00, stream_size); data->layers[i]->codec_data = init_ffmpeg_header_offset(temp_sf, buf,bytes, 0x00, stream_size);
}
if (!data->layers[i]->codec_data) goto fail; if (!data->layers[i]->codec_data) goto fail;
data->layers[i]->coding_type = coding_FFmpeg; data->layers[i]->coding_type = coding_FFmpeg;

View File

@ -391,16 +391,17 @@ VGMSTREAM* init_vgmstream_fsb(STREAMFILE* sf) {
uint8_t buf[0x100]; uint8_t buf[0x100];
size_t bytes, block_size, block_count; size_t bytes, block_size, block_count;
if (fsb.version != FMOD_FSB_VERSION_4_0) { /* 3.x, though no actual output changes [ex. Guitar Hero III (X360)] */ if (fsb.version != FMOD_FSB_VERSION_4_0) {
bytes = ffmpeg_make_riff_xma1(buf, sizeof(buf), fsb.num_samples, fsb.stream_size, fsb.channels, fsb.sample_rate, 0); /* 3.x, though no actual output changes [ex. Guitar Hero III (X360), The Bourne Conspiracy (X360)] */
vgmstream->codec_data = init_ffmpeg_xma1_raw(sf, fsb.stream_offset, fsb.stream_size, fsb.channels, fsb.sample_rate, 0);
} }
else { else {
block_size = 0x8000; /* FSB default */ block_size = 0x8000; /* FSB default */
block_count = fsb.stream_size / block_size; /* not accurate but not needed (custom_data_offset+0x14 -1?) */ block_count = fsb.stream_size / block_size; /* not accurate but not needed (custom_data_offset+0x14 -1?) */
bytes = ffmpeg_make_riff_xma2(buf, sizeof(buf), fsb.num_samples, fsb.stream_size, fsb.channels, fsb.sample_rate, block_count, block_size); bytes = ffmpeg_make_riff_xma2(buf, sizeof(buf), fsb.num_samples, fsb.stream_size, fsb.channels, fsb.sample_rate, block_count, block_size);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, fsb.stream_offset,fsb.stream_size);
} }
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, fsb.stream_offset,fsb.stream_size);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;

View File

@ -333,8 +333,7 @@ VGMSTREAM * init_vgmstream_genh(STREAMFILE *streamFile) {
else if (genh.codec == XMA1) { else if (genh.codec == XMA1) {
int xma_stream_mode = genh.codec_mode == 1 ? 1 : 0; int xma_stream_mode = genh.codec_mode == 1 ? 1 : 0;
bytes = ffmpeg_make_riff_xma1(buf, 100, vgmstream->num_samples, genh.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode); ffmpeg_data = init_ffmpeg_xma1_raw(streamFile, genh.start_offset, genh.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
ffmpeg_data = init_ffmpeg_header_offset(streamFile, buf,bytes, genh.start_offset,genh.data_size);
if ( !ffmpeg_data ) goto fail; if ( !ffmpeg_data ) goto fail;
} }
else if (genh.codec == XMA2) { else if (genh.codec == XMA2) {

View File

@ -62,16 +62,12 @@ VGMSTREAM* init_vgmstream_ivaud(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
case 0x0000: { /* XMA2 (X360) */ case 0x0000: { /* XMA2 (X360) */
uint8_t buf[0x100];
size_t bytes;
if (ivaud.is_music) { if (ivaud.is_music) {
goto fail; goto fail;
} }
else { else {
/* regular XMA for sfx */ /* regular XMA for sfx */
bytes = ffmpeg_make_riff_xma1(buf, 0x100, ivaud.num_samples, ivaud.stream_size, ivaud.channel_count, ivaud.sample_rate, 0); vgmstream->codec_data = init_ffmpeg_xma1_raw(sf, ivaud.stream_offset, ivaud.stream_size, ivaud.channel_count, ivaud.sample_rate, 0);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf,bytes, ivaud.stream_offset, ivaud.stream_size);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;

View File

@ -252,8 +252,6 @@ static layered_layout_data* build_layered_mul(STREAMFILE* sf, off_t offset, int
switch(codec) { switch(codec) {
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
case XMA1: { case XMA1: {
uint8_t buf[0x100];
int bytes;
size_t stream_size; size_t stream_size;
int layer_channels = 1; int layer_channels = 1;
@ -269,12 +267,11 @@ static layered_layout_data* build_layered_mul(STREAMFILE* sf, off_t offset, int
data->layers[i]->sample_rate = vgmstream->sample_rate; data->layers[i]->sample_rate = vgmstream->sample_rate;
data->layers[i]->num_samples = vgmstream->num_samples; data->layers[i]->num_samples = vgmstream->num_samples;
bytes = ffmpeg_make_riff_xma1(buf, 0x100, data->layers[i]->num_samples, stream_size, data->layers[i]->channels, data->layers[i]->sample_rate, 0); data->layers[i]->codec_data = init_ffmpeg_xma1_raw(temp_sf, 0x00, stream_size, data->layers[i]->channels, data->layers[i]->sample_rate, 0);
data->layers[i]->codec_data = init_ffmpeg_header_offset(temp_sf, buf,bytes, 0x00, stream_size);
if (!data->layers[i]->codec_data) goto fail; if (!data->layers[i]->codec_data) goto fail;
data->layers[i]->coding_type = coding_FFmpeg; data->layers[i]->coding_type = coding_FFmpeg;
data->layers[i]->layout_type = layout_none; data->layers[i]->layout_type = layout_none;
data->layers[i]->stream_size = stream_size; data->layers[i]->stream_size = stream_size;
xma_fix_raw_samples(data->layers[i], temp_sf, 0x00,stream_size, 0, 0,0); /* ? */ xma_fix_raw_samples(data->layers[i], temp_sf, 0x00,stream_size, 0, 0,0); /* ? */

View File

@ -574,8 +574,7 @@ VGMSTREAM* init_vgmstream_txth(STREAMFILE* sf) {
else if (txth.codec == XMA1) { else if (txth.codec == XMA1) {
int xma_stream_mode = txth.codec_mode == 1 ? 1 : 0; int xma_stream_mode = txth.codec_mode == 1 ? 1 : 0;
bytes = ffmpeg_make_riff_xma1(buf, sizeof(buf), vgmstream->num_samples, txth.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode); ffmpeg_data = init_ffmpeg_xma1_raw(txth.sf_body, txth.start_offset, txth.data_size, vgmstream->channels, vgmstream->sample_rate, xma_stream_mode);
ffmpeg_data = init_ffmpeg_header_offset(txth.sf_body, buf,bytes, txth.start_offset,txth.data_size);
if ( !ffmpeg_data ) goto fail; if ( !ffmpeg_data ) goto fail;
} }
else if (txth.codec == XMA2) { else if (txth.codec == XMA2) {

View File

@ -484,11 +484,7 @@ VGMSTREAM* init_vgmstream_xwb(STREAMFILE* sf) {
#ifdef VGM_USE_FFMPEG #ifdef VGM_USE_FFMPEG
case XMA1: { /* Kameo (X360), Table Tennis (X360) */ case XMA1: { /* Kameo (X360), Table Tennis (X360) */
uint8_t buf[0x100]; vgmstream->codec_data = init_ffmpeg_xma1_raw(sf, xwb.stream_offset, xwb.stream_size, vgmstream->channels, vgmstream->sample_rate, 0);
int bytes;
bytes = ffmpeg_make_riff_xma1(buf, sizeof(buf), vgmstream->num_samples, xwb.stream_size, vgmstream->channels, vgmstream->sample_rate, 0);
vgmstream->codec_data = init_ffmpeg_header_offset(sf, buf, bytes, xwb.stream_offset,xwb.stream_size);
if (!vgmstream->codec_data) goto fail; if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg; vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none; vgmstream->layout_type = layout_none;