summaryrefslogtreecommitdiffstats
path: root/libmpdemux/demux_mkv.c
diff options
context:
space:
mode:
authorUoti Urpala <uau@glyph.nonexistent.invalid>2009-07-10 19:53:26 +0300
committerUoti Urpala <uau@glyph.nonexistent.invalid>2009-07-10 22:58:56 +0300
commitbb6c06d17f661ff99edb0eb1dc9c0a12770f887f (patch)
tree087a3ed68a314c2dd4f2f8613fa2e8d13fa8557c /libmpdemux/demux_mkv.c
parent3f75062ca65cea46fa9e06ab5f5271ad310440fd (diff)
downloadmpv-bb6c06d17f661ff99edb0eb1dc9c0a12770f887f.tar.bz2
mpv-bb6c06d17f661ff99edb0eb1dc9c0a12770f887f.tar.xz
demux_mkv.c: Make some time arithmetic more precise
Some calculations in the demuxer that are in principle integer arithmetic use float divisions instead of 64-bit integer ones (as in (int64_t)(x / 1000000.0) ). When compiled with -ffast-math gcc replaces the division with multiplication by inverse. The calculation of the inverse can introduce rounding error even for divisions that would have been exact, and any rounding error down from an exact integer result in the division makes the result after cast one smaller. This caused some inaccuracy in seeking due to timecodes in the index not quite matching those calculated for actual packets. Add 0.5 to such expressions before casting to round instead of truncating, which should be enough to avoid the problem. Also replace some non-performance-critical use of float types by doubles.
Diffstat (limited to 'libmpdemux/demux_mkv.c')
-rw-r--r--libmpdemux/demux_mkv.c41
1 files changed, 21 insertions, 20 deletions
diff --git a/libmpdemux/demux_mkv.c b/libmpdemux/demux_mkv.c
index 4859bc4f53..3972c1bd6f 100644
--- a/libmpdemux/demux_mkv.c
+++ b/libmpdemux/demux_mkv.c
@@ -100,13 +100,13 @@ typedef struct mkv_track
int type;
uint32_t v_width, v_height, v_dwidth, v_dheight;
- float v_frate;
+ double v_frate;
uint32_t a_formattag;
uint32_t a_channels, a_bps;
float a_sfreq;
- float default_duration;
+ double default_duration;
int default_track;
@@ -117,8 +117,8 @@ typedef struct mkv_track
int realmedia;
int64_t rv_kf_base;
int rv_kf_pts;
- float rv_pts; /* previous video timestamp */
- float ra_pts; /* previous audio timestamp */
+ double rv_pts; /* previous video timestamp */
+ double ra_pts; /* previous audio timestamp */
/** realaudio descrambling */
int sub_packet_size; ///< sub packet size, per stream
@@ -126,13 +126,13 @@ typedef struct mkv_track
int coded_framesize; ///< coded frame size, per stream
int audiopk_size; ///< audio packet size
unsigned char *audio_buf; ///< place to store reordered audio data
- float *audio_timestamp; ///< timestamp for each audio packet
+ double *audio_timestamp; ///< timestamp for each audio packet
int sub_packet_cnt; ///< number of subpacket already received
int audio_filepos; ///< file position of first audio packet in block
/* stuff for quicktime */
int fix_i_bps;
- float qt_last_a_pts;
+ double qt_last_a_pts;
int subtitle_type;
@@ -142,7 +142,7 @@ typedef struct mkv_track
int reorder_timecodes;
demux_packet_t **cached_dps;
int num_cached_dps, num_allocated_dps;
- float max_pts;
+ double max_pts;
/* generic content encoding support */
mkv_content_encoding_t *encodings;
@@ -162,7 +162,7 @@ typedef struct mkv_demuxer
{
off_t segment_start;
- float duration, last_pts;
+ double duration, last_pts;
uint64_t last_filepos;
mkv_track_t **tracks;
@@ -1710,7 +1710,7 @@ demux_mkv_open_video (demuxer_t *demuxer, mkv_track_t *track, int vid)
sh_v->disp_w = track->v_width;
sh_v->disp_h = track->v_height;
if (track->v_dheight)
- sh_v->aspect = (float)track->v_dwidth / (float)track->v_dheight;
+ sh_v->aspect = (double)track->v_dwidth / track->v_dheight;
}
else
{
@@ -1928,7 +1928,7 @@ demux_mkv_open_audio (demuxer_t *demuxer, mkv_track_t *track, int aid)
else
{
sh_a->codecdata_len = 2;
- track->default_duration = 1024.0 / (float)sh_a->samplerate;
+ track->default_duration = 1024.0 / sh_a->samplerate;
}
}
else if (track->a_formattag == mmioFOURCC('v', 'r', 'b', 's')) /* VORBIS */
@@ -1979,25 +1979,25 @@ demux_mkv_open_audio (demuxer_t *demuxer, mkv_track_t *track, int aid)
sh_a->wf->nAvgBytesPerSec = atrc_fl2bps[flavor];
sh_a->wf->nBlockAlign = track->sub_packet_size;
track->audio_buf = malloc(track->sub_packet_h * track->audiopk_size);
- track->audio_timestamp = malloc(track->sub_packet_h * sizeof(float));
+ track->audio_timestamp = malloc(track->sub_packet_h * sizeof(double));
break;
case mmioFOURCC('c', 'o', 'o', 'k'):
sh_a->wf->nAvgBytesPerSec = cook_fl2bps[flavor];
sh_a->wf->nBlockAlign = track->sub_packet_size;
track->audio_buf = malloc(track->sub_packet_h * track->audiopk_size);
- track->audio_timestamp = malloc(track->sub_packet_h * sizeof(float));
+ track->audio_timestamp = malloc(track->sub_packet_h * sizeof(double));
break;
case mmioFOURCC('s', 'i', 'p', 'r'):
sh_a->wf->nAvgBytesPerSec = sipr_fl2bps[flavor];
sh_a->wf->nBlockAlign = track->coded_framesize;
track->audio_buf = malloc(track->sub_packet_h * track->audiopk_size);
- track->audio_timestamp = malloc(track->sub_packet_h * sizeof(float));
+ track->audio_timestamp = malloc(track->sub_packet_h * sizeof(double));
break;
case mmioFOURCC('2', '8', '_', '8'):
sh_a->wf->nAvgBytesPerSec = 3600;
sh_a->wf->nBlockAlign = track->coded_framesize;
track->audio_buf = malloc(track->sub_packet_h * track->audiopk_size);
- track->audio_timestamp = malloc(track->sub_packet_h * sizeof(float));
+ track->audio_timestamp = malloc(track->sub_packet_h * sizeof(double));
break;
}
@@ -2420,8 +2420,8 @@ handle_subtitles(demuxer_t *demuxer, mkv_track_t *track, char *block,
sub_utf8 = 1;
dp = new_demux_packet(size);
memcpy(dp->buffer, block, size);
- dp->pts = timecode / 1000.0f;
- dp->endpts = (timecode + block_duration) / 1000.0f;
+ dp->pts = timecode / 1000.0;
+ dp->endpts = (timecode + block_duration) / 1000.0;
ds_add_packet(demuxer->sub, dp);
}
@@ -2580,7 +2580,7 @@ flush_cached_dps (demuxer_t *demuxer, mkv_track_t *track)
ok = 1;
for (i = 1; i < track->num_cached_dps; i++)
if (track->cached_dps[i - 1]->pts > track->cached_dps[i]->pts) {
- float tmp_pts = track->cached_dps[i - 1]->pts;
+ double tmp_pts = track->cached_dps[i - 1]->pts;
track->cached_dps[i - 1]->pts = track->cached_dps[i]->pts;
track->cached_dps[i]->pts = tmp_pts;
ok = 0;
@@ -2654,7 +2654,7 @@ handle_block (demuxer_t *demuxer, uint8_t *block, uint64_t length,
uint32_t *lace_size;
uint8_t laces, flags;
int i, num, tmp, use_this_block = 1;
- float current_pts;
+ double current_pts;
int16_t time;
/* first byte(s): track num */
@@ -2670,7 +2670,7 @@ handle_block (demuxer_t *demuxer, uint8_t *block, uint64_t length,
return 0;
block += old_length - length;
- tc = ((time*mkv_d->tc_scale+mkv_d->cluster_tc) /1000000.0);
+ tc = (time*mkv_d->tc_scale+mkv_d->cluster_tc) / 1000000.0 + 0.5;
if (tc < 0)
tc = 0;
current_pts = tc / 1000.0;
@@ -3041,7 +3041,8 @@ demux_mkv_seek (demuxer_t *demuxer, float rel_seek_secs, float audio_delay, int
if (mkv_d->indexes[i].tnum == seek_id)
{
diff = target_timecode -
- (int64_t) mkv_d->indexes[i].timecode * mkv_d->tc_scale / 1000000.0;
+ (int64_t)(mkv_d->indexes[i].timecode * mkv_d->tc_scale
+ / 1000000.0 + 0.5);
if (flags & SEEK_BACKWARD) {
// Seek backward: find the last index position