[prev in list] [next in list] [prev in thread] [next in thread]
List: mplayer-dev-eng
Subject: Re: [MPlayer-dev-eng] Strange behavior with audio delayed video files
From: Dan Oscarsson <Dan.Oscarsson () tieto ! com>
Date: 2014-03-02 17:01:58
Message-ID: 1393779718.2360.3.camel () luna ! malmo ! kicore ! net
[Download RAW message or body]
fre 2014-02-21 klockan 11:48 +0100 skrev Ingo Brückl:
>
> > In my patched mplayer I have used this for many years without problem.
>
> Well then, please share your patch with me.
It is attached. Though it is the 6th in order of my set of 12 patches
and about 9 months old as I had no need to update it as mplayer changes
so slowly. In also includes my code to sync audio and video after a
seek. It depends on some parts in my other patches but you should see
how it works.
Dan
["seek-sync.diff" (seek-sync.diff)]
--- mplayer.c.org 2013-05-05 15:50:08.751104736 +0200
+++ mplayer.c 2013-05-05 15:50:24.656103355 +0200
@@ -1171,6 +1171,116 @@
}
+static double written_audio_pts(sh_audio_t *sh_audio, demux_stream_t *d_audio);
+static int fill_audio_out_buffers(int fill_only);
+static double update_video(int *blit_frame);
+
+static void sync_audio_video(int *blit_frame,double *frame_time)
+{
+ // after a seek the audio and video are normally not fully in sync
+ // resulting in a visible/audiable resync
+ // this code does the resync so that its starts with audio and video in sync
+ double apts;
+ int sample_size = af_fmt2bits(ao_data.format)/8*ao_data.channels;
+ int delete_bytes;
+ int got_audio;
+ int audio_increased; // some audio decoders failes and return no decoded \
data + int tried_once = 0;
+ int tries;
+
+
+ // decode some audio but do not play it, to get starting audio pts
+ // try several times, after seek some streams fail first decode try, but not \
next + for (got_audio = 1, audio_increased = 0, tries = 0; tries < 3 && got_audio \
&& !audio_increased; tries++) { + audio_increased = \
mpctx->sh_audio->a_out_buffer_len; + got_audio = \
fill_audio_out_buffers(1); + audio_increased = \
mpctx->sh_audio->a_out_buffer_len-audio_increased; + }
+ apts = written_audio_pts(mpctx->sh_audio, mpctx->d_audio)-audio_delay;
+ apts -= mpctx->audio_out->get_delay(); // compensating for latency in audio out \
(needed for pulse) + mpctx->sh_audio->resyncing = 1; // restart resyncing as it is \
reset by written_audio_pts + if (got_audio && audio_increased && \
mpctx->sh_video->pts == MP_NOPTS_VALUE) { + // no valid pts from video - move \
forward till we get valid pts + while (mpctx->sh_video->pts == MP_NOPTS_VALUE) \
{ + double delay = mpctx->delay;
+ *frame_time = update_video(blit_frame);
+ mpctx->delay = delay;
+ if (*frame_time < 0) break;
+ }
+ }
+ if (start_audio_pts == MP_NOPTS_VALUE) {
+ start_audio_pts = apts; // this includes audio_delay correction which could \
be manipulated by user at start + } else if (mpctx->sh_video->pts >= \
start_audio_pts) { + if (got_audio && audio_increased && mpctx->sh_video->pts \
< apts) { + // video is behind and audio is working, move it forward
+ while (mpctx->sh_video->pts < apts) {
+ double delay = mpctx->delay;
+ *frame_time = update_video(blit_frame);
+ mpctx->delay = delay;
+ if (*frame_time < 0) break;
+ }
+ }
+ delete_bytes = (mpctx->sh_video->pts-apts)*ao_data.samplerate*sample_size /
+ (synced_playback_speed*playback_speed);
+ delete_bytes /= sample_size; // align to sample_size
+ delete_bytes *= sample_size; // align to sample_size
+
+ // move audio forward until it is in sync with video
+ while (got_audio && audio_increased && *frame_time >= 0 && delete_bytes > 0) \
{ + if (delete_bytes > mpctx->sh_audio->a_out_buffer_len) {
+ int ck = mpctx->sh_audio->a_out_buffer_len/sample_size;
+ if (ck*sample_size != mpctx->sh_audio->a_out_buffer_len) {
+ // check so audio is aligned on samples
+ mp_msg(MSGT_CPLAYER, MSGL_WARN, "Failed to align audio data on \
sample border\n"); + break;
+ } else {
+ audio_speed_o * sd;
+
+ // empty decoded audio buffer and data for it
+ mpctx->sh_audio->a_out_buffer_len = 0;
+ while (a_out_sdata) {
+ sd = a_out_sdata->next;
+ free(a_out_sdata);
+ a_out_sdata = sd;
+ }
+ // decode some more audio
+ // have to try sevel times, some demuxers fail later on in the \
stream too + // for example, lavf sometimes failes when demuxing \
latm in mpeg-ts from DVB-t + for (got_audio = 1, audio_increased = \
0, tries = 0; tries < 3 && got_audio && !audio_increased; tries++) { + \
audio_increased = mpctx->sh_audio->a_out_buffer_len; + \
got_audio = fill_audio_out_buffers(1); + audio_increased \
= mpctx->sh_audio->a_out_buffer_len-audio_increased; + }
+ apts = written_audio_pts(mpctx->sh_audio, \
mpctx->d_audio)-audio_delay; + apts -= \
mpctx->audio_out->get_delay(); // compensating for latency in audio out (needed for \
pulse) + mpctx->sh_audio->resyncing = 1; // restart resyncing as \
it is reset by written_audio_pts + if (!tried_once && \
mpctx->sh_video->pts < apts) { + // audio pts jumped, may \
happen after seek for some demuxers/decoders + // move video \
forward + while (mpctx->sh_video->pts < apts) {
+ double delay = mpctx->delay;
+ *frame_time = update_video(blit_frame);
+ mpctx->delay = delay;
+ if (*frame_time < 0) break;
+ }
+ tried_once = 1;
+ }
+ delete_bytes = \
(mpctx->sh_video->pts-apts)*ao_data.samplerate*sample_size / + \
(synced_playback_speed*playback_speed); + delete_bytes /= \
sample_size; // align to sample_size + delete_bytes *= \
sample_size; // align to sample_size + }
+ } else {
+ mpctx->sh_audio->a_out_buffer_len -= delete_bytes;
+ memmove(mpctx->sh_audio->a_out_buffer, \
&mpctx->sh_audio->a_out_buffer[delete_bytes], + \
mpctx->sh_audio->a_out_buffer_len); + a_out_sdata->len -= \
delete_bytes; + delete_bytes = 0;
+ }
+ }
+ }
+}
+
/* The next generation A-V-sync handling (end) */
/* This header requires all the global variable declarations. */
@@ -3027,7 +3137,7 @@
}
}
-static int fill_audio_out_buffers(void)
+static int fill_audio_out_buffers(int fill_only)
{
unsigned int t;
double tt;
@@ -3055,6 +3165,10 @@
// in get_space()
ao_data.pts = ((mpctx->sh_video ? mpctx->sh_video->timer : 0) + \
mpctx->delay) * 90000.0; bytes_to_write = mpctx->audio_out->get_space();
+ if (fill_only) {
+ if (bytes_to_write < ao_data.outburst) bytes_to_write = \
ao_data.outburst; + break;
+ }
if (mpctx->sh_video || bytes_to_write >= ao_data.outburst)
break;
if (timeout++ > 10) {
@@ -3112,6 +3226,8 @@
}
a_out_sdata->len += sh_audio->a_out_buffer_len-old_a_out_len;
+ if (fill_only) break;
+
// play audio:
current_module = "play_audio";
@@ -3679,6 +3795,7 @@
return -1;
mpctx->startup_decode_retry = DEFAULT_STARTUP_DECODE_RETRY;
+ if (start_audio_pts == MP_NOPTS_VALUE) start_audio_pts = 0; // seeking before \
starting play turns this off if (mpctx->sh_video) {
current_module = "seek_video_reset";
if (vo_config_count)
@@ -4690,6 +4807,7 @@
// display vsync rate matching
init_vsync_handling();
displaysynced_speed = 0;
+ start_audio_pts = MP_NOPTS_VALUE;
synced_playback_speed = 1.0;
if (play_n_frames == 0) {
@@ -4730,7 +4848,7 @@
if (!mpctx->sh_video && mpctx->sh_audio) {
// handle audio-only case:
double a_pos = 0;
- if (!fill_audio_out_buffers())
+ if (!fill_audio_out_buffers(0))
// at eof, all audio at least written to ao
if (!mpctx->sh_video)
mpctx->eof = PT_NEXT_ENTRY;
@@ -4758,6 +4876,7 @@
unsigned int work_start,work_end;
unsigned int last_decode_time = 0;
unsigned int previous_decode_time = 0;
+ int sync_av = mpctx->startup_decode_retry > 0 && mpctx->sh_audio;
work_start = GetTimer();
vo_pts = mpctx->sh_video->timer * 90000.0;
@@ -4774,6 +4893,9 @@
mpctx->startup_decode_retry--;
}
mpctx->startup_decode_retry = 0;
+ if (tng && sync_av) {
+ sync_audio_video(&blit_frame,&frame_time);
+ }
mp_dbg(MSGT_AVSYNC, MSGL_DBG2, "*** ftime=%5.3f ***\n", \
frame_time); if (mpctx->sh_video->vf_initialized < 0) {
mp_msg(MSGT_CPLAYER, MSGL_FATAL, \
MSGTR_NotInitializeVOPorVO); @@ -4804,8 +4926,8 @@
/*========================== PLAY AUDIO ============================*/
- if (mpctx->sh_audio)
- if (!fill_audio_out_buffers())
+ if (mpctx->sh_audio && (!tng || start_audio_pts < \
mpctx->sh_video->pts)) + if (!fill_audio_out_buffers(0))
// at eof, all audio at least written to ao
if (!mpctx->sh_video)
mpctx->eof = PT_NEXT_ENTRY;
_______________________________________________
MPlayer-dev-eng mailing list
MPlayer-dev-eng@mplayerhq.hu
https://lists.mplayerhq.hu/mailman/listinfo/mplayer-dev-eng
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic