Remove custom FFmpeg, as custom IO streamfile can be used instead

This commit is contained in:
bnnm 2018-09-10 02:19:34 +02:00
parent 5ed95d07d4
commit 804fceb5e7
9 changed files with 57 additions and 206 deletions

View File

@ -266,8 +266,6 @@ void free_celt_fsb(celt_codec_data *data);
/* ffmpeg_decoder */
ffmpeg_codec_data *init_ffmpeg_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size);
ffmpeg_codec_data *init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size);
ffmpeg_codec_data *init_ffmpeg_config(STREAMFILE *streamFile, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size, ffmpeg_custom_config * config);
ffmpeg_codec_data * init_ffmpeg_switch_opus(STREAMFILE *streamFile, off_t start_offset, size_t data_size, int channels, int skip, int sample_rate);
void decode_ffmpeg(VGMSTREAM *stream, sample * outbuf, int32_t samples_to_do, int channels);

View File

@ -1,10 +1,9 @@
#include "coding.h"
#include "ffmpeg_decoder_utils.h"
#ifdef VGM_USE_FFMPEG
/* internal sizes, can be any value */
#define FFMPEG_DEFAULT_BUFFER_SIZE 2048
#define FFMPEG_DEFAULT_SAMPLE_BUFFER_SIZE 2048
#define FFMPEG_DEFAULT_IO_BUFFER_SIZE 128 * 1024
@ -185,49 +184,38 @@ fail:
/* ******************************************** */
/* AVIO callback: read stream, handling custom data */
static int ffmpeg_read(void *opaque, uint8_t *buf, int buf_size) {
static int ffmpeg_read(void *opaque, uint8_t *buf, int read_size) {
ffmpeg_codec_data *data = (ffmpeg_codec_data *) opaque;
int ret = 0;
int bytes = 0;
int max_to_copy = 0;
//;VGM_LOG("AVIO read: r_off=%"PRIx64", v_off=%"PRIx64", b_size=%x\n", data->real_offset, data->virtual_offset, buf_size);fflush(stdout);
/* clamp reads */
if (data->virtual_offset + buf_size > data->virtual_size)
buf_size = data->virtual_size - data->virtual_offset;
if (buf_size == 0)
return ret;
if (data->logical_offset + read_size > data->logical_size)
read_size = data->logical_size - data->logical_offset;
if (read_size == 0)
return bytes;
/* handle reads on inserted header */
if (data->header_size) {
if (data->virtual_offset < data->header_size) {
max_to_copy = (int)(data->header_size - data->virtual_offset);
if (max_to_copy > buf_size) {
max_to_copy = buf_size;
}
if (data->header_size && data->logical_offset < data->header_size) {
max_to_copy = (int)(data->header_size - data->logical_offset);
if (max_to_copy > read_size)
max_to_copy = read_size;
//;VGM_LOG("AVIO header: v_off=%lx, h_size=%lx, mtc=%x, b_size=%x\n", (off_t)data->virtual_offset, (off_t)data->header_size, max_to_copy, buf_size);fflush(stdout);
memcpy(buf, data->header_insert_block + data->virtual_offset, max_to_copy);
buf += max_to_copy;
buf_size -= max_to_copy;
data->virtual_offset += max_to_copy; /* adjust for reads below */
memcpy(buf, data->header_insert_block + data->logical_offset, max_to_copy);
buf += max_to_copy;
read_size -= max_to_copy;
data->logical_offset += max_to_copy;
if (buf_size == 0) {
return max_to_copy; /* offset still in header */
}
if (read_size == 0) {
return max_to_copy; /* offset still in header */
}
}
/* main read */
switch(data->config.type) {
default: ret = ffmpeg_custom_read_standard(data, buf, buf_size); break;
}
data->virtual_offset += ret;
//data->real_offset = ; /* must be updated in function */
//;VGM_LOG("AVIO read done: ret=%x, r_off=%"PRIx64", v_off=%"PRIx64"\n", ret + max_to_copy, data->real_offset, data->virtual_offset);fflush(stdout);
//;VGM_LOGB((buf - max_to_copy),ret + max_to_copy,0);
return ret + max_to_copy;
bytes = read_streamfile(buf, data->offset, read_size, data->streamfile);
data->logical_offset += bytes;
data->offset += bytes;
return bytes + max_to_copy;
}
/* AVIO callback: write stream not needed */
@ -242,79 +230,50 @@ static int64_t ffmpeg_seek(void *opaque, int64_t offset, int whence) {
/* get cache'd size */
if (whence & AVSEEK_SIZE) {
//;VGM_LOG("AVIO size: v_size=%"PRIx64", h_size=%"PRIx64", r_size=%"PRIx64", r_start=%"PRIx64"\n", data->virtual_size, data->header_size, data->real_size, data->real_start);fflush(stdout);
return data->virtual_size;
return data->logical_size;
}
//;VGM_LOG("AVIO seek: off=%"PRIx64" r_off=%"PRIx64", v_off=%"PRIx64"\n", offset, data->real_offset, data->virtual_offset);fflush(stdout);
whence &= ~(AVSEEK_SIZE | AVSEEK_FORCE);
/* find the final offset FFmpeg sees (within fake header + virtual size) */
switch (whence) {
case SEEK_SET: /* absolute */
break;
case SEEK_CUR: /* relative to current */
offset += data->virtual_offset;
offset += data->logical_offset;
break;
case SEEK_END: /* relative to file end (should be negative) */
offset += data->virtual_size;
offset += data->logical_size;
break;
}
/* clamp offset; fseek does this too */
if (offset > data->virtual_size)
offset = data->virtual_size;
if (offset > data->logical_size)
offset = data->logical_size;
else if (offset < 0)
offset = 0;
/* no change */
if (data->virtual_offset == offset) {
return ret;
}
/* seeks inside fake header */
if (offset < data->header_size) {
data->virtual_offset = offset;
data->real_offset = data->real_start;
data->logical_offset = offset;
data->offset = data->start;
return ret;
}
/* main seek */
switch(data->config.type) {
default: offset = ffmpeg_custom_seek_standard(data, offset); break;
}
data->virtual_offset = offset;
//data->real_offset = ; /* must be updated in function */
//;VGM_LOG("AVIO seek done: r_off=%"PRIx64", v_off=%"PRIx64"\n", data->real_offset, data->virtual_offset);fflush(stdout);
data->logical_offset = offset;
data->offset = data->start + (offset - data->header_size);
return ret;
}
/* called on init, not a callback */ //todo rename to ffmpeg_init
static int64_t ffmpeg_size(ffmpeg_codec_data * data) {
int64_t bytes;
switch(data->config.type) {
default: bytes = ffmpeg_custom_size_standard(data); break;
}
return bytes;
}
/* ******************************************** */
/* MAIN INIT/DECODER */
/* ******************************************** */
ffmpeg_codec_data * init_ffmpeg_offset(STREAMFILE *streamFile, uint64_t start, uint64_t size) {
return init_ffmpeg_config(streamFile, NULL,0, start,size, NULL);
return init_ffmpeg_header_offset(streamFile, NULL,0, start,size);
}
ffmpeg_codec_data * init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size) {
return init_ffmpeg_config(streamFile, header,header_size, start,size, NULL);
}
/**
* Manually init FFmpeg, from a fake header / offset.
@ -323,17 +282,17 @@ ffmpeg_codec_data * init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t *
* This header will be seamlessly inserted before 'start' offset, and total filesize will be 'header_size' + 'size'.
* The header buffer will be copied and memory-managed internally.
* NULL header can used given if the stream has internal data recognized by FFmpeg at offset.
* Stream index can be passed to FFmpeg, if the format has multiple streams (1=first).
* Stream index can be passed to FFmpeg in the streamFile, if the format has multiple streams (1=first).
*/
ffmpeg_codec_data * init_ffmpeg_config(STREAMFILE *streamFile, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size, ffmpeg_custom_config * config) {
ffmpeg_codec_data * init_ffmpeg_header_offset(STREAMFILE *streamFile, uint8_t * header, uint64_t header_size, uint64_t start, uint64_t size) {
char filename[PATH_LIMIT];
ffmpeg_codec_data * data;
int errcode, i;
int targetSubsong = streamFile->stream_index;
int streamIndex, streamCount;
AVStream *stream;
AVCodecParameters *codecPar = NULL;
AVRational tb;
@ -344,14 +303,9 @@ ffmpeg_codec_data * init_ffmpeg_config(STREAMFILE *streamFile, uint8_t * header,
if (!data) return NULL;
streamFile->get_name( streamFile, filename, sizeof(filename) );
data->streamfile = streamFile->open(streamFile, filename, STREAMFILE_DEFAULT_BUFFER_SIZE);
if (!data->streamfile) goto fail;
if (config) {
memcpy(&data->config, config, sizeof(ffmpeg_custom_config));
}
/* ignore bad combos */
if ((header && !header_size) || (!header && header_size))
goto fail;
@ -363,17 +317,15 @@ ffmpeg_codec_data * init_ffmpeg_config(STREAMFILE *streamFile, uint8_t * header,
if (!data->header_insert_block) goto fail;
}
data->real_start = start;
data->real_offset = data->real_start;
data->real_size = size;
if (data->real_start + data->real_size > get_streamfile_size(streamFile)) {
data->start = start;
data->offset = start;
data->size = size;
if (data->size == 0 || data->start + data->size > get_streamfile_size(streamFile)) {
VGM_LOG("FFmpeg: wrong start+size found\n");
data->real_size = get_streamfile_size(streamFile) - data->real_start;
data->size = get_streamfile_size(streamFile) - data->start;
}
data->virtual_offset = 0;
data->virtual_size = ffmpeg_size(data);
data->virtual_base = 0;
if (data->virtual_size == 0) goto fail;
data->logical_offset = 0;
data->logical_size = data->header_size + data->size;
/* setup IO, attempt to autodetect format and gather some info */
data->buffer = av_malloc(FFMPEG_DEFAULT_IO_BUFFER_SIZE);
@ -403,7 +355,7 @@ ffmpeg_codec_data * init_ffmpeg_config(STREAMFILE *streamFile, uint8_t * header,
streamCount++;
/* select Nth audio stream if specified, or first one */
if (streamIndex < 0 || (data->config.stream_index > 0 && streamCount == data->config.stream_index)) {
if (streamIndex < 0 || (targetSubsong > 0 && streamCount == targetSubsong)) {
codecPar = stream->codecpar;
streamIndex = i;
}
@ -412,7 +364,7 @@ ffmpeg_codec_data * init_ffmpeg_config(STREAMFILE *streamFile, uint8_t * header,
if (i != streamIndex)
stream->discard = AVDISCARD_ALL; /* disable demuxing for other streams */
}
if (streamCount < data->config.stream_index) goto fail;
if (streamCount < targetSubsong) goto fail;
if (streamIndex < 0 || !codecPar) goto fail;
data->streamIndex = streamIndex;
@ -499,7 +451,7 @@ ffmpeg_codec_data * init_ffmpeg_config(STREAMFILE *streamFile, uint8_t * header,
data->frameSize = av_get_audio_frame_duration(data->codecCtx,0);
/* setup decode buffer */
data->sampleBufferBlock = FFMPEG_DEFAULT_BUFFER_SIZE;
data->sampleBufferBlock = FFMPEG_DEFAULT_SAMPLE_BUFFER_SIZE;
data->sampleBuffer = av_malloc( data->sampleBufferBlock * (data->bitsPerSample / 8) * data->channels );
if (!data->sampleBuffer)
goto fail;

View File

@ -1,30 +0,0 @@
#include "coding.h"
#include "ffmpeg_decoder_utils.h"
#ifdef VGM_USE_FFMPEG
/**
* Standard read mode: virtual values are 1:1 but inside a portion of the streamfile (between real_start and real_size).
*/
int ffmpeg_custom_read_standard(ffmpeg_codec_data *data, uint8_t *buf, int buf_size) {
size_t bytes = read_streamfile(buf, data->real_offset, buf_size, data->streamfile);
data->real_offset += bytes;
return bytes;
}
int64_t ffmpeg_custom_seek_standard(ffmpeg_codec_data *data, int64_t virtual_offset) {
int64_t seek_virtual_offset = virtual_offset - data->header_size;
data->real_offset = data->real_start + seek_virtual_offset;
return virtual_offset;
}
int64_t ffmpeg_custom_size_standard(ffmpeg_codec_data *data) {
return data->real_size + data->header_size;
}
#endif

View File

@ -1,28 +0,0 @@
#ifndef _FFMPEG_DECODER_UTILS_
#define _FFMPEG_DECODER_UTILS_
#ifdef VGM_USE_FFMPEG
/* used by ffmpeg_decoder.c, but scattered in other .c files */
/**
* Custom read/seek for data transformation. Must handle seeks+reads from virtual offsets, ie.-
* reads "real/file" data, not decodable by FFmpeg, and transforms to decodable "virtual/buffer" data,
* block by block (must seek to closest file offset and adjust on reads).
*
* To simplify, functions won't be called in common cases (seek over filesize, no change in offset, etc),
* and fake header seeks/reads are handled externally. Real offset must be updated internally though.
*
* example (a 0x100 block transforms to a 0x150 block):
* - seek 0: file-offset=0, virtual-offset=0
* - read 0x150: file-read=0x100 transforms to buffer=0x150
* - new file-offset=0x100, virtual-offset=0x150
* - seek 0x310: file-offset=0x200, virtual-offset=0x310 (closest virtual block is 0x150+0x150, + 0x10 adjusted on reads)
*/
int ffmpeg_custom_read_standard(ffmpeg_codec_data *data, uint8_t *buf, int buf_size);
int64_t ffmpeg_custom_seek_standard(ffmpeg_codec_data *data, int64_t virtual_offset);
int64_t ffmpeg_custom_size_standard(ffmpeg_codec_data *data);
#endif
#endif/*_FFMPEG_DECODER_UTILS_*/

View File

@ -1629,10 +1629,6 @@
<File
RelativePath=".\coding\ea_mt_decoder_utk.h"
>
</File>
<File
RelativePath=".\coding\ffmpeg_decoder_utils.h"
>
</File>
<File
RelativePath=".\coding\g72x_state.h"
@ -1717,10 +1713,6 @@
<File
RelativePath=".\coding\ffmpeg_decoder_utils_switch_opus.c"
>
</File>
<File
RelativePath=".\coding\ffmpeg_decoder_utils.c"
>
</File>
<File
RelativePath=".\coding\g719_decoder.c"

View File

@ -114,7 +114,6 @@
<ClInclude Include="coding\acm_decoder_libacm.h" />
<ClInclude Include="coding\coding.h" />
<ClInclude Include="coding\ea_mt_decoder_utk.h" />
<ClInclude Include="coding\ffmpeg_decoder_utils.h" />
<ClInclude Include="coding\fsb_vorbis_data.h" />
<ClInclude Include="coding\g72x_state.h" />
<ClInclude Include="coding\nwa_decoder.h" />
@ -127,7 +126,6 @@
<ClCompile Include="coding\coding_utils.c" />
<ClCompile Include="coding\ffmpeg_decoder.c" />
<ClCompile Include="coding\ffmpeg_decoder_utils_switch_opus.c" />
<ClCompile Include="coding\ffmpeg_decoder_utils.c" />
<ClCompile Include="coding\lsf_decoder.c" />
<ClCompile Include="coding\mp4_aac_decoder.c" />
<ClCompile Include="coding\mtaf_decoder.c" />

View File

@ -125,9 +125,6 @@
<ClInclude Include="coding\ea_mt_decoder_utk.h">
<Filter>coding\Header Files</Filter>
</ClInclude>
<ClInclude Include="coding\ffmpeg_decoder_utils.h">
<Filter>coding\Header Files</Filter>
</ClInclude>
<ClInclude Include="coding\fsb_vorbis_data.h">
<Filter>coding\Header Files</Filter>
</ClInclude>
@ -1414,9 +1411,6 @@
<ClCompile Include="coding\ffmpeg_decoder_utils_switch_opus.c">
<Filter>coding\Source Files</Filter>
</ClCompile>
<ClCompile Include="coding\ffmpeg_decoder_utils.c">
<Filter>coding\Source Files</Filter>
</ClCompile>
<ClCompile Include="coding\coding_utils.c">
<Filter>coding\Source Files</Filter>
</ClCompile>

View File

@ -2,16 +2,15 @@
#include "../coding/coding.h"
#include "../util.h"
static int bink_get_info(STREAMFILE *streamFile, int * out_total_streams, size_t *out_stream_size, int * out_channel_count, int * out_sample_rate, int * out_num_samples);
static int bink_get_info(STREAMFILE *streamFile, int target_subsong, int * out_total_streams, size_t *out_stream_size, int * out_channel_count, int * out_sample_rate, int * out_num_samples);
/* BINK 1/2 - RAD Game Tools movies (audio/video format) */
VGMSTREAM * init_vgmstream_bik(STREAMFILE *streamFile) {
VGMSTREAM * vgmstream = NULL;
int channel_count = 0, loop_flag = 0, sample_rate = 0, num_samples = 0;
int total_subsongs = 0, stream_index = streamFile->stream_index;
int total_subsongs = 0, target_subsong = streamFile->stream_index;
size_t stream_size;
/* checks */
/* .bik/bik2/bk2: standard
* .bika = fake extension for demuxed audio */
@ -23,7 +22,7 @@ VGMSTREAM * init_vgmstream_bik(STREAMFILE *streamFile) {
(read_32bitBE(0x00,streamFile) & 0xffffff00) != 0x4B423200 ) goto fail;
/* find target stream info and samples */
if (!bink_get_info(streamFile, &total_subsongs, &stream_size, &channel_count, &sample_rate, &num_samples))
if (!bink_get_info(streamFile, target_subsong, &total_subsongs, &stream_size, &channel_count, &sample_rate, &num_samples))
goto fail;
/* build the VGMSTREAM */
@ -39,11 +38,9 @@ VGMSTREAM * init_vgmstream_bik(STREAMFILE *streamFile) {
#ifdef VGM_USE_FFMPEG
{
ffmpeg_custom_config cfg = {0};
/* target_subsong should be passed with the streamFile */
cfg.stream_index = stream_index;
vgmstream->codec_data = init_ffmpeg_config(streamFile, NULL,0, 0x0,get_streamfile_size(streamFile), &cfg);
vgmstream->codec_data = init_ffmpeg_header_offset(streamFile, NULL,0, 0x0,get_streamfile_size(streamFile));
if (!vgmstream->codec_data) goto fail;
vgmstream->coding_type = coding_FFmpeg;
}
@ -63,12 +60,12 @@ fail:
* as they are not in the main header. The header for BINK1 and 2 is the same.
* (a ~3 min movie needs ~6000-7000 frames = fseeks, should be fast enough)
*/
static int bink_get_info(STREAMFILE *streamFile, int * out_total_subsongs, size_t * out_stream_size, int * out_channel_count, int * out_sample_rate, int * out_num_samples) {
static int bink_get_info(STREAMFILE *streamFile, int target_subsong, int * out_total_subsongs, size_t * out_stream_size, int * out_channel_count, int * out_sample_rate, int * out_num_samples) {
uint32_t *offsets = NULL;
uint32_t num_frames, num_samples_b = 0;
off_t cur_offset;
int i, j, sample_rate, channel_count;
int total_subsongs, target_subsong = streamFile->stream_index;
int total_subsongs;
size_t stream_size = 0;
size_t filesize = get_streamfile_size(streamFile);

View File

@ -1114,41 +1114,19 @@ typedef struct {
} hca_codec_data;
#ifdef VGM_USE_FFMPEG
/* Custom FFMPEG modes */
typedef enum {
FFMPEG_STANDARD, /* default FFmpeg */
} ffmpeg_custom_t;
/* config for the above modes */
typedef struct {
int stream_index; /* FFmpeg's sub-stream (as opposed to an internal stream in custom read/seeks) */
int codec_endian;
int channels;
ffmpeg_custom_t type; /* ffmpeg subtype */
size_t virtual_size; /* external value, if meta needs to know/supply it */
/* internal sequences, when needed */
int sequence;
int samples_done;
} ffmpeg_custom_config;
typedef struct {
/*** IO internals ***/
STREAMFILE *streamfile;
uint64_t real_start; // absolute start within the streamfile
uint64_t real_offset; // absolute offset within the streamfile
uint64_t real_size; // max size within the streamfile
uint64_t virtual_offset; // computed offset FFmpeg sees (including fake header)
uint64_t virtual_size; // computed size FFmpeg sees (including fake header)
uint64_t virtual_base; // info/base virtual_offset equivalent to current real_offset, block aligned (*not* including fake header)
uint64_t start; // absolute start within the streamfile
uint64_t offset; // absolute offset within the streamfile
uint64_t size; // max size within the streamfile
uint64_t logical_offset; // computed offset FFmpeg sees (including fake header)
uint64_t logical_size; // computed size FFmpeg sees (including fake header)
uint64_t header_size; // fake header (parseable by FFmpeg) prepended on reads
uint8_t *header_insert_block; // fake header data (ie. RIFF)
ffmpeg_custom_config config; /* custom config/state */
/*** "public" API (read-only) ***/
// stream info
int channels;