211
211
audio_paused(false),
213
213
// Audio warping stuff
214
usevideotimebase(false),
215
214
warpfactor(1.0f), warpfactor_avg(1.0f),
216
warplbuff(NULL), warprbuff(NULL),
218
215
// Time Code stuff
219
216
prevtc(0), prevrp(0),
220
217
tc_avcheck_framecounter(0), tc_diff_estimate(0),
537
534
void NuppelVideoPlayer::PauseVideo(bool wait)
539
536
QMutexLocker locker(&pauseUnpauseLock);
542
539
video_actually_paused = false;
543
540
pausevideo = true;
545
542
for (uint i = 0; wait && !video_actually_paused; i++)
547
544
videoThreadPaused.wait(&pauseUnpauseLock, 250);
1144
1141
isDummy = true;
1146
1143
float displayAspect =
1147
gContext->GetFloatSettingOnHost("XineramaMonitorAspectRatio",
1144
gContext->GetFloatSettingOnHost("XineramaMonitorAspectRatio",
1148
1145
gContext->GetHostName(), 1.3333);
1150
1147
if (!videoOutput)
2259
2256
/// Max amount the warpfactor can change in 1 frame.
2260
2257
#define MAXWARPDIFF 0.0005f
2261
/// How much dwe multiply the warp by when storing it in an integer.
2262
#define WARPMULTIPLIER 1000000000
2263
2258
/// How long to average the warp over.
2264
2259
#define WARPAVLEN (video_frame_rate * 600)
2265
2260
/** How much we allow the warp to deviate from 1.0 (normal speed). */
2321
2316
repeat_delay = 0;
2323
if (usevideotimebase)
2325
warpfactor_avg = gContext->GetNumSetting("WarpFactor", 0);
2327
warpfactor_avg /= WARPMULTIPLIER;
2330
// Reset the warpfactor if it's obviously bogus
2331
if (warpfactor_avg < (1 - WARPCLIP))
2333
if (warpfactor_avg > (1 + (WARPCLIP * 2)) )
2336
warpfactor = warpfactor_avg;
2339
2318
refreshrate = videoOutput ? videoOutput->GetDisplayInfo().rate : 0;
2340
2319
if (refreshrate <= 0)
2341
2320
refreshrate = frame_interval;
2344
2323
if (!using_null_videoout)
2346
if (usevideotimebase)
2347
VERBOSE(VB_PLAYBACK, "Using video as timebase");
2349
VERBOSE(VB_PLAYBACK, "Using audio as timebase");
2351
2325
QString timing_type = videosync->getName();
2353
2327
QString msg = QString("Video timing method: %1").arg(timing_type);
2573
2547
if (avsync_delay > 2000000 && player_ctx->buffer->isDVD())
2574
2548
avsync_delay = 90000;
2575
2549
avsync_avg = (avsync_delay + (avsync_avg * 3)) / 4;
2576
if (!usevideotimebase)
2551
/* If the audio time codes and video diverge, shift
2552
the video by one interlaced field (1/2 frame) */
2578
/* If the audio time codes and video diverge, shift
2579
the video by one interlaced field (1/2 frame) */
2583
if (avsync_avg > frame_interval * 3 / 2)
2585
avsync_adjustment = refreshrate;
2588
else if (avsync_avg < 0 - frame_interval * 3 / 2)
2590
avsync_adjustment = -refreshrate;
2555
if (avsync_avg > frame_interval * 3 / 2)
2557
avsync_adjustment = refreshrate;
2560
else if (avsync_avg < 0 - frame_interval * 3 / 2)
2562
avsync_adjustment = -refreshrate;
2600
2571
avsync_avg = 0;
2601
2572
avsync_oldavg = 0;
2605
2576
audio_lock.unlock();
2608
void NuppelVideoPlayer::ShutdownAVSync(void)
2610
if (usevideotimebase)
2612
gContext->SaveSetting("WarpFactor",
2613
(int)(warpfactor_avg * WARPMULTIPLIER));
2630
2579
void NuppelVideoPlayer::DisplayPauseFrame(void)
2632
2581
if (!video_actually_paused)
4063
4008
audioOutput->Drain();
4066
// If there is no warping, just send it to the audioOutput.
4067
if (!usevideotimebase)
4069
if (!audioOutput->AddSamples(buffer, samples, timecode))
4070
VERBOSE(VB_PLAYBACK, "NVP::AddAudioData():p1: "
4071
"Audio buffer overflow, audio data lost!");
4075
// If we need warping, do it...
4076
int newsamples = (int)(samples / warpfactor);
4077
int newlen = newsamples * samplesize;
4079
// We resize the buffers if they aren't big enough
4080
if ((warpbuffsize < newlen) || (!warplbuff))
4082
warplbuff = (short int*) realloc(warplbuff, newlen);
4083
warprbuff = (short int*) realloc(warprbuff, newlen);
4084
warpbuffsize = newlen;
4088
float incount = 0.0f;
4090
while ((incount < samples) && (outcount < newsamples))
4092
char *out_ptr = ((char*)warplbuff) + (outcount * samplesize);
4093
char *in_ptr = buffer + (((int)incount) * samplesize);
4094
memcpy(out_ptr, in_ptr, samplesize);
4097
incount += warpfactor;
4101
// Send new warped audio to audioOutput
4102
if (!audioOutput->AddSamples((char*)warplbuff, samples, timecode))
4103
VERBOSE(VB_PLAYBACK,"NVP::AddAudioData():p2: "
4011
if (!audioOutput->AddSamples(buffer, samples, timecode))
4012
VERBOSE(VB_PLAYBACK, "NVP::AddAudioData():p1: "
4104
4013
"Audio buffer overflow, audio data lost!");
4107
4017
/** \fn NuppelVideoPlayer::AddAudioData(short int*,short int*,int,long long)
4122
4032
if (!audioOutput)
4125
// If there is no warping, just send it to the audioOutput.
4126
if (!usevideotimebase)
4128
buffers[0] = (char*) lbuffer;
4129
buffers[1] = (char*) rbuffer;
4130
if (!audioOutput->AddSamples(buffers, samples, timecode))
4131
VERBOSE(VB_PLAYBACK, "NVP::AddAudioData():p3: "
4132
"Audio buffer overflow, audio data lost!");
4136
// If we need warping, do it...
4137
int samplesize = sizeof(short int);
4138
int newsamples = (int)(samples / warpfactor);
4139
int newlen = newsamples * samplesize;
4141
// We resize the buffers if they aren't big enough
4142
if ((warpbuffsize < newlen) || (!warplbuff) || (!warprbuff))
4144
warplbuff = (short int*) realloc(warplbuff, newlen);
4145
warprbuff = (short int*) realloc(warprbuff, newlen);
4146
warpbuffsize = newlen;
4150
float incount = 0.0f;
4152
while ((incount < samples) && (outcount < newsamples))
4154
warplbuff[outcount] = lbuffer[(uint)round(incount)];
4155
warprbuff[outcount] = rbuffer[(uint)round(incount)];
4158
incount += warpfactor;
4162
// Send new warped audio to audioOutput
4163
buffers[0] = (char*) warplbuff;
4164
buffers[1] = (char*) warprbuff;
4035
buffers[0] = (char*) lbuffer;
4036
buffers[1] = (char*) rbuffer;
4165
4037
if (!audioOutput->AddSamples(buffers, samples, timecode))
4166
VERBOSE(VB_PLAYBACK, "NVP::AddAudioData():p4: "
4038
VERBOSE(VB_PLAYBACK, "NVP::AddAudioData():p2: "
4167
4039
"Audio buffer overflow, audio data lost!");
7333
// Like frame based subtitles this can get out of sync after
7334
// transcoding, using the raw timecode doesn't work either
7335
// with DTV broadcasts where the timecode isn't zero on the
7336
// first frame, and may roll over during the broadcast.
7337
playPos = (uint64_t)
7338
((currentFrame->frameNumber / video_frame_rate) * 1000);
7205
// Use timecodes for time based SRT subtitles. Feeding this into
7206
// NormalizeVideoTimecode() should adjust for non-zero start times
7207
// and wraps. For MPEG, wraps will occur just once every 26.5 hours
7208
// and other formats less frequently so this should be sufficient.
7209
// Note: timecodes should now always be valid even in the case
7210
// when a frame doesn't have a valid timestamp. If an exception is
7211
// found where this is not true then we need to use the frameNumber
7212
// when timecode is not defined by uncommenting the following lines.
7213
//if (currentFrame->timecode == 0)
7214
// playPos = (uint64_t)
7215
// ((currentFrame->frameNumber / video_frame_rate) * 1000);
7217
playPos = GetDecoder()->NormalizeVideoTimecode(currentFrame->timecode);
7342
7220
if (!textSubtitles.HasSubtitleChanged(playPos))
7863
7731
VERBOSE(VB_VBI, LOC + QString("DeleteWindows(%1, 0x%2)")
7864
7732
.arg(service_num).arg(window_map,0,16));
7733
for (uint i=0; i<8; i++)
7734
if ((1<<i) & window_map)
7735
GetCCWin(service_num, i).Clear();
7866
7736
CC708DelayedDeletes[service_num&63] |= window_map;
8091
7961
if (!(textDisplayMode & kDisplayCC708))
8094
for (uint i = 0; i < (uint)len; i++)
8095
GetCCWin(service_num).AddChar(QChar(unicode_string[i]));
7965
CC708Window &win = GetCCWin(service_num);
7966
QMutexLocker locker(&win.lock);
7967
for (uint i = 0; i < (uint)len; i++)
7968
win.AddChar(QChar(unicode_string[i]));
8098
7972
GetOSD()->CC708Updated();