FFmpeg: expose block/frame size, rename totalFrames for clarity

This commit is contained in:
bnnm 2016-12-10 15:53:29 +01:00
parent 85d34a7901
commit cdfd47eb7b
8 changed files with 41 additions and 27 deletions

View File

@ -278,8 +278,8 @@ void seek_ffmpeg(VGMSTREAM *vgmstream, int32_t num_sample) {
}
/* todo fix this properly */
if (data->totalFrames) {
ts = (int)ts * (data->formatCtx->duration) / data->totalFrames;
if (data->totalSamples) {
ts = (int)ts * (data->formatCtx->duration) / data->totalSamples;
} else {
data->samplesToDiscard = num_sample;
ts = 0;

View File

@ -5,7 +5,7 @@
#ifdef VGM_USE_FFMPEG
/* internal sizes, can be any value */
#define FFMPEG_DEFAULT_BLOCK_SIZE 2048
#define FFMPEG_DEFAULT_BUFFER_SIZE 2048
#define FFMPEG_DEFAULT_IO_BUFFER_SIZE 128 * 1024
static int init_seek(ffmpeg_codec_data * data);
@ -54,7 +54,7 @@ VGMSTREAM * init_vgmstream_ffmpeg_offset(STREAMFILE *streamFile, uint64_t start,
vgmstream->codec_data = data;
vgmstream->channels = data->channels;
vgmstream->sample_rate = data->sampleRate;
vgmstream->num_samples = data->totalFrames;
vgmstream->num_samples = data->totalSamples;
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->meta_type = meta_FFmpeg;
@ -337,13 +337,18 @@ ffmpeg_codec_data * init_ffmpeg_faux_riff(STREAMFILE *streamFile, int64_t fmt_of
/* try to guess frames/samples (duration isn't always set) */
tb.num = 1; tb.den = data->codecCtx->sample_rate;
data->totalFrames = av_rescale_q(stream->duration, stream->time_base, tb);
if (data->totalFrames < 0)
data->totalFrames = 0; /* caller must consider this */
data->totalSamples = av_rescale_q(stream->duration, stream->time_base, tb);
if (data->totalSamples < 0)
data->totalSamples = 0; /* caller must consider this */
data->blockAlign = data->codecCtx->block_align;
data->frameSize = data->codecCtx->frame_size;
if(data->frameSize == 0) /* some formats don't set frame_size but can get on request, and vice versa */
data->frameSize = av_get_audio_frame_duration(data->codecCtx,0);
/* setup decode buffer */
data->samplesPerBlock = FFMPEG_DEFAULT_BLOCK_SIZE;
data->sampleBuffer = av_malloc( data->samplesPerBlock * (data->bitsPerSample / 8) * data->channels );
data->sampleBufferBlock = FFMPEG_DEFAULT_BUFFER_SIZE;
data->sampleBuffer = av_malloc( data->sampleBufferBlock * (data->bitsPerSample / 8) * data->channels );
if (!data->sampleBuffer)
goto fail;
@ -409,6 +414,7 @@ static int init_seek(ffmpeg_codec_data * data) {
if (!found_first) { /* first found */
found_first = 1;
pos = pkt->pos;
ts = pkt->dts;
continue;
} else { /* second found */
size = pkt->pos - pos; /* coded, pkt->size is decoded size */
@ -416,6 +422,11 @@ static int init_seek(ffmpeg_codec_data * data) {
}
}
/* apparently some (non-audio?) streams start with a DTS before 0, but some read_seeks expect 0, which would disrupt the index
* we may need to keep start_ts around, since avstream/codec/format isn't always set */
if (ts != 0)
goto fail;
/* add index 0 */
ret = av_add_index_entry(stream, pos, ts, size, distance, AVINDEX_KEYFRAME);
if ( ret < 0 )

View File

@ -210,7 +210,7 @@ VGMSTREAM * init_vgmstream_mp4_aac_ffmpeg(STREAMFILE *streamFile) {
vgmstream = allocate_vgmstream(ffmpeg_data->channels,loop_flag);
if (!vgmstream) goto fail;
vgmstream->num_samples = ffmpeg_data->totalFrames; /* todo compare with FFD num_samples*/
vgmstream->num_samples = ffmpeg_data->totalSamples; /* todo FFD num_samples is different from this */
vgmstream->sample_rate = ffmpeg_data->sampleRate;
vgmstream->channels = ffmpeg_data->channels;
if (loop_flag) {

View File

@ -133,13 +133,11 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_FFmpeg;
vgmstream->codec_data = ffmpeg_data;
vgmstream->num_samples = ffmpeg_data->totalFrames;
if (loop_flag) {
int atrac3_frame = 1024;
int block_align = (codec_id == 0x4 ? 96 : codec_id == 0x5 ? 152 : 192) * channel_count;
/* int block_align = ffmpeg_data->codecCtx->block_align; *//* is this always set? */
vgmstream->loop_start_sample = (loop_start / block_align) * atrac3_frame;
vgmstream->loop_end_sample = (loop_end / block_align) * atrac3_frame;
vgmstream->num_samples = ffmpeg_data->totalSamples;
if (loop_flag && ffmpeg_data->blockAlign > 0) {
vgmstream->loop_start_sample = (loop_start / ffmpeg_data->blockAlign) * ffmpeg_data->frameSize;
vgmstream->loop_end_sample = (loop_end / ffmpeg_data->blockAlign) * ffmpeg_data->frameSize;
}
break;
@ -155,12 +153,14 @@ VGMSTREAM * init_vgmstream_ps3_msf(STREAMFILE *streamFile) {
vgmstream->meta_type = meta_FFmpeg;
vgmstream->codec_data = ffmpeg_data;
/* todo check CBR better (frame_size=0?) */
/* TODO check CBR better (bitrate % X != 0?) */
if (ffmpeg_data->bitrate == 0)
goto fail;
/* vgmstream->num_samples = ffmpeg_data->totalFrames; */ /* duration is not set/innacurate for MP3 in FFMpeg */
/* vgmstream->num_samples = ffmpeg_data->totalSamples; */ /* duration may not be set/inaccurate */
vgmstream->num_samples = (int64_t)data_size * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate;
if (loop_flag) {
int frame_size = ffmpeg_data->codecCtx->frame_size;
int frame_size = ffmpeg_data->frameSize;
vgmstream->loop_start_sample = (int64_t)loop_start * ffmpeg_data->sampleRate * 8 / ffmpeg_data->bitrate;
vgmstream->loop_start_sample -= vgmstream->loop_start_sample==frame_size ? frame_size
: vgmstream->loop_start_sample % frame_size;

View File

@ -402,7 +402,7 @@ VGMSTREAM * init_vgmstream_riff(STREAMFILE *streamFile) {
ffmpeg_data = init_ffmpeg_offset(streamFile, 0, streamFile->get_size(streamFile) );
if ( !ffmpeg_data ) goto fail;
sample_count = ffmpeg_data->totalFrames; /* fact_sample_count */
sample_count = ffmpeg_data->totalSamples; /* fact_sample_count */
/* the encoder introduces some garbage (usually silent) samples to skip before the stream
* loop values include the skip samples but fact_sample_count doesn't; add them back to fix some edge loops */
if (fact_sample_skip > 0)

View File

@ -295,7 +295,7 @@ VGMSTREAM * init_vgmstream_sqex_scd(STREAMFILE *streamFile) {
vgmstream->coding_type = coding_FFmpeg;
vgmstream->layout_type = layout_none;
vgmstream->num_samples = ffmpeg_data->totalFrames;
vgmstream->num_samples = ffmpeg_data->totalSamples;
if (loop_flag) {
vgmstream->loop_start_sample = loop_start;

View File

@ -1072,7 +1072,7 @@ int get_vgmstream_samples_per_frame(VGMSTREAM * vgmstream) {
ffmpeg_codec_data *data = (ffmpeg_codec_data *) vgmstream->codec_data;
if (data) {
/* must know the full block size for edge loops */
return data->samplesPerBlock;
return data->sampleBufferBlock;
}
return 0;
}

View File

@ -868,13 +868,16 @@ typedef struct {
int bitsPerSample;
int floatingPoint;
int sampleRate;
int64_t totalFrames; // sample count, or 0 if unknown
int bitrate;
// extra info: 0 if unknown or not fixed
int64_t totalSamples; // estimated count (may not be accurate for some demuxers)
int64_t blockAlign; // coded block of bytes, counting channels (the block can be joint stereo)
int64_t frameSize; // decoded samples per block
// Intermediate buffer
// Intermediate byte buffer
uint8_t *sampleBuffer;
// max samples a block can held (can be less or more than samples per decoded frame)
size_t samplesPerBlock;
// max samples we can held (can be less or more than frameSize)
size_t sampleBufferBlock;
// FFmpeg context used for metadata
AVCodec *codec;