Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mpc-hc/sanear.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorAlex Marsev <alex.marsev@gmail.com>2015-06-18 07:12:53 +0300
committerAlex Marsev <alex.marsev@gmail.com>2015-06-18 12:17:16 +0300
commit04609fa2c4fe8711f6312caf12861d1f53466e3a (patch)
treece29bb432aeb20d5200a5f2e62b89a6063129958 /src
parent8d5ecb05d3e28b02b15f17524e7144a2ffe1b843 (diff)
Redo AudioRenderer::NewSegment()
And related stuff.
Diffstat (limited to 'src')
-rw-r--r--src/AudioRenderer.cpp35
-rw-r--r--src/SampleCorrection.cpp144
-rw-r--r--src/SampleCorrection.h10
3 files changed, 76 insertions, 113 deletions
diff --git a/src/AudioRenderer.cpp b/src/AudioRenderer.cpp
index 6705ad3..0c1a8da 100644
--- a/src/AudioRenderer.cpp
+++ b/src/AudioRenderer.cpp
@@ -93,10 +93,10 @@ namespace SaneAudioRenderer
if (!m_device)
CreateDevice();
- // Apply sample corrections (pad, crop, guess timings).
+ // Establish time/frame relation.
chunk = m_sampleCorrection.ProcessSample(pSample, sampleProps);
- // Apply clock corrections (what we couldn't correct with sample correction).
+ // Apply clock corrections.
if (!m_live && m_device && m_state == State_Running)
ApplyClockCorrection();
@@ -113,11 +113,11 @@ namespace SaneAudioRenderer
DspChunk::ToFormat(m_device->GetDspFormat(), chunk);
}
- // Apply rate corrections (rate matching or external clock).
+ // Apply rate corrections (rate matching and clock slaving).
if (m_device && !m_device->IsBitstream() && m_device->IsRealtime() && m_state == State_Running)
ApplyRateCorrection(chunk);
- // Don't deny the allocator to reuse IMediaSample while the chunk is hanging in the buffer.
+ // Don't deny the allocator its right to reuse IMediaSample while the chunk is hanging in the buffer.
if (m_device && m_device->IsRealtime())
chunk.FreeMediaSample();
}
@@ -227,7 +227,7 @@ namespace SaneAudioRenderer
m_device->Reset();
m_sampleCorrection.NewDeviceBuffer();
InitializeProcessors();
- m_startClockOffset = m_sampleCorrection.GetLastSampleEnd();
+ m_startClockOffset = m_sampleCorrection.GetLastFrameEnd();
StartDevice();
}
else
@@ -285,14 +285,19 @@ namespace SaneAudioRenderer
{
CAutoLock objectLock(this);
+ if (m_rate != rate)
+ {
+ m_rate = rate;
+
+ if (m_device)
+ (m_device->GetEnd() > 0) ? ClearDevice() : InitializeProcessors();
+ }
+
m_startClockOffset = 0;
- m_rate = rate;
- m_sampleCorrection.NewSegment(m_rate);
+ m_clockCorrection += m_sampleCorrection.GetLastFrameEnd();
- assert(m_inputFormat);
- if (m_device)
- InitializeProcessors();
+ m_sampleCorrection.NewSegment(m_rate);
}
void AudioRenderer::Play(REFERENCE_TIME startTime)
@@ -418,7 +423,7 @@ namespace SaneAudioRenderer
InitializeProcessors();
- m_startClockOffset = m_sampleCorrection.GetLastSampleEnd();
+ m_startClockOffset = m_sampleCorrection.GetLastFrameEnd();
if (m_state == State_Running)
StartDevice();
@@ -445,7 +450,7 @@ namespace SaneAudioRenderer
// Apply corrections to internal clock.
{
- REFERENCE_TIME offset = m_sampleCorrection.GetTimingsError() - m_clockCorrection;
+ REFERENCE_TIME offset = m_sampleCorrection.GetTimeDivergence() - m_clockCorrection;
if (std::abs(offset) > 100)
{
m_myClock->OffsetSlavedClock(offset);
@@ -520,7 +525,7 @@ namespace SaneAudioRenderer
m_myClock->OffsetSlavedClock(-llMulDiv(padFrames, OneSecond,
m_device->GetWaveFormat()->nSamplesPerSec, 0));
- DebugOut("AudioRenderer pad", padFrames, "frames for clock matching", m_sampleCorrection.GetLastSampleEnd() / 10000., (myTime - graphTime) / 10000.);
+ DebugOut("AudioRenderer pad", padFrames, "frames for clock matching", m_sampleCorrection.GetLastFrameEnd() / 10000., (myTime - graphTime) / 10000.);
}
}
else if (remaining > latency)
@@ -541,7 +546,7 @@ namespace SaneAudioRenderer
m_myClock->OffsetSlavedClock(llMulDiv(dropFrames, OneSecond,
m_device->GetWaveFormat()->nSamplesPerSec, 0));
- DebugOut("AudioRenderer drop", dropFrames, "frames for clock matching", m_sampleCorrection.GetLastSampleEnd() / 10000., (myTime - graphTime) / 10000.);
+ DebugOut("AudioRenderer drop", dropFrames, "frames for clock matching", m_sampleCorrection.GetLastFrameEnd() / 10000., (myTime - graphTime) / 10000.);
}
}
@@ -617,7 +622,7 @@ namespace SaneAudioRenderer
REFERENCE_TIME graphTime;
if (m_state == State_Running &&
SUCCEEDED(m_graphClock->GetTime(&graphTime)) &&
- graphTime > m_startTime + m_sampleCorrection.GetLastSampleEnd() + m_sampleCorrection.GetTimingsError())
+ graphTime > m_startTime + m_sampleCorrection.GetLastFrameEnd() + m_sampleCorrection.GetTimeDivergence())
{
break;
}
diff --git a/src/SampleCorrection.cpp b/src/SampleCorrection.cpp
index 9ca3387..30df66b 100644
--- a/src/SampleCorrection.cpp
+++ b/src/SampleCorrection.cpp
@@ -24,14 +24,12 @@ namespace SaneAudioRenderer
m_rate = rate;
- m_freshSegment = true;
- m_segmentStartTimestamp = 0;
m_segmentTimeInPreviousFormats = 0;
m_segmentFramesInCurrentFormat = 0;
- m_lastSampleEnd = 0;
+ m_lastFrameEnd = 0;
- m_timingsError = 0;
+ m_timeDivergence = 0;
}
void SampleCorrection::NewDeviceBuffer()
@@ -43,102 +41,71 @@ namespace SaneAudioRenderer
{
assert(m_format);
- FillMissingTimings(sampleProps);
+ DspChunk chunk(pSample, sampleProps, *m_format);
- DspChunk chunk;
-
- const bool drop = (m_bitstream && m_freshBuffer && !(sampleProps.dwSampleFlags & AM_SAMPLE_SPLICEPOINT)) ||
- (!m_bitstream && m_freshSegment && sampleProps.tStop <= 0);
-
- if (drop)
+ if (m_bitstream)
{
- // Drop the sample.
- assert(chunk.IsEmpty());
- DebugOut("SampleCorrection drop [", sampleProps.tStart, sampleProps.tStop, "]");
-
- if (m_bitstream && !m_freshSegment)
+ if (m_freshBuffer && !(sampleProps.dwSampleFlags & AM_SAMPLE_SPLICEPOINT))
{
- assert(m_freshBuffer);
- m_segmentFramesInCurrentFormat += sampleProps.lActual * 8 / m_format->wBitsPerSample / m_format->nChannels;
+ // Drop the sample.
+ DebugOut("SampleCorrection drop [", sampleProps.tStart, sampleProps.tStop, "]");
+ chunk = DspChunk();
+ assert(chunk.IsEmpty());
}
}
- else if (!m_bitstream && m_freshSegment && sampleProps.tStart < 0)
+ else if (m_lastFrameEnd == 0)
{
- // Crop the sample.
- size_t cropFrames = (size_t)TimeToFrames(m_lastSampleEnd - sampleProps.tStart);
- DebugOut("SampleCorrection crop", cropFrames, "frames from [", sampleProps.tStart, sampleProps.tStop, "]");
-
- chunk = DspChunk(pSample, sampleProps, *m_format);
-
- if (cropFrames > 0)
+ if ((sampleProps.dwSampleFlags & AM_SAMPLE_STOPVALID) && sampleProps.tStop <= 0)
{
- assert(chunk.GetFrameCount() > cropFrames);
- chunk.ShrinkHead(chunk.GetFrameCount() - cropFrames);
+ // Drop the sample.
+ DebugOut("SampleCorrection drop [", sampleProps.tStart, sampleProps.tStop, "]");
+ chunk = DspChunk();
+ assert(chunk.IsEmpty());
}
-
- AccumulateTimings(sampleProps, chunk.GetFrameCount());
- }
- else if (!m_bitstream && m_freshSegment && sampleProps.tStart > 0)
- {
- // Zero-pad the sample.
- size_t padFrames = (size_t)TimeToFrames(sampleProps.tStart - m_lastSampleEnd);
- DebugOut("SampleCorrection pad", padFrames, "frames into [", sampleProps.tStart, sampleProps.tStop, "]");
-
- if (padFrames > 0)
+ else if ((sampleProps.dwSampleFlags & AM_SAMPLE_TIMEVALID) && sampleProps.tStart < 0)
{
- DspChunk tempChunk(pSample, sampleProps, *m_format);
-
- size_t padBytes = padFrames * tempChunk.GetFrameSize();
- sampleProps.pbBuffer = nullptr;
- sampleProps.lActual += (int32_t)padBytes;
- sampleProps.tStart -= FramesToTime(padFrames);
+ // Crop the sample.
+ const size_t cropFrames = (size_t)TimeToFrames(0 - sampleProps.tStart);
- AccumulateTimings(sampleProps, tempChunk.GetFrameCount() + padFrames);
+ if (cropFrames > 0)
+ {
+ DebugOut("SampleCorrection crop", cropFrames, "frames from [",
+ sampleProps.tStart, sampleProps.tStop, "]");
- chunk = DspChunk(tempChunk.GetFormat(), tempChunk.GetChannelCount(),
- tempChunk.GetFrameCount() + padFrames, tempChunk.GetRate());
-
- assert(chunk.GetSize() == tempChunk.GetSize() + padBytes);
- ZeroMemory(chunk.GetData(), padBytes);
- memcpy(chunk.GetData() + padBytes, tempChunk.GetData(), tempChunk.GetSize());
+ chunk.ShrinkHead(chunk.GetFrameCount() > cropFrames ? chunk.GetFrameCount() - cropFrames : 0);
+ }
}
- else
+ else if ((sampleProps.dwSampleFlags & AM_SAMPLE_TIMEVALID) && sampleProps.tStart > 0)
{
- chunk = DspChunk(pSample, sampleProps, *m_format);
- AccumulateTimings(sampleProps, chunk.GetFrameCount());
- }
- }
- else
- {
- // Leave the sample untouched.
- chunk = DspChunk(pSample, sampleProps, *m_format);
- AccumulateTimings(sampleProps, chunk.GetFrameCount());
- }
+ // Zero-pad the sample.
+ const size_t padFrames = (size_t)TimeToFrames(sampleProps.tStart - m_lastFrameEnd);
- return chunk;
- }
+ if (padFrames > 0 &&
+ FramesToTime(padFrames) < 50 * OneMillisecond)
+ {
+ DebugOut("SampleCorrection pad", padFrames, "frames before [",
+ sampleProps.tStart, sampleProps.tStop, "]");
- void SampleCorrection::FillMissingTimings(AM_SAMPLE2_PROPERTIES& sampleProps)
- {
- assert(m_format);
- assert(m_rate > 0.0);
+ DspChunk tempChunk(chunk.GetFormat(), chunk.GetChannelCount(),
+ chunk.GetFrameCount() + padFrames, chunk.GetRate());
- if (!(sampleProps.dwSampleFlags & AM_SAMPLE_TIMEVALID))
- {
- REFERENCE_TIME time = m_segmentTimeInPreviousFormats + FramesToTime(m_segmentFramesInCurrentFormat);
+ const size_t padBytes = padFrames * chunk.GetFrameSize();
+ sampleProps.pbBuffer = nullptr;
+ sampleProps.lActual += (int32_t)padBytes;
+ sampleProps.tStart -= FramesToTime(padFrames);
+
+ assert(tempChunk.GetSize() == chunk.GetSize() + padBytes);
+ ZeroMemory(tempChunk.GetData(), padBytes);
+ memcpy(tempChunk.GetData() + padBytes, chunk.GetData(), chunk.GetSize());
- sampleProps.tStart = m_segmentStartTimestamp + time;
- sampleProps.dwSampleFlags |= AM_SAMPLE_TIMEVALID;
+ chunk = std::move(tempChunk);
+ }
+ }
}
- if (!(sampleProps.dwSampleFlags & AM_SAMPLE_STOPVALID))
- {
- REFERENCE_TIME time = sampleProps.lActual * 8 / m_format->wBitsPerSample /
- m_format->nChannels * OneSecond / m_format->nSamplesPerSec;
+ AccumulateTimings(sampleProps, chunk.GetFrameCount());
- sampleProps.tStop = sampleProps.tStart + (REFERENCE_TIME)(time / m_rate);
- sampleProps.dwSampleFlags |= AM_SAMPLE_STOPVALID;
- }
+ return chunk;
}
uint64_t SampleCorrection::TimeToFrames(REFERENCE_TIME time)
@@ -163,20 +130,13 @@ namespace SaneAudioRenderer
if (frames == 0)
return;
- if (m_freshSegment)
- {
- assert(m_segmentStartTimestamp == 0);
- m_segmentStartTimestamp = sampleProps.tStart;
- m_freshSegment = false;
- }
-
- m_lastSampleEnd = m_segmentTimeInPreviousFormats + FramesToTime(m_segmentFramesInCurrentFormat);
-
- m_timingsError = sampleProps.tStart - m_lastSampleEnd;
+ if (sampleProps.dwSampleFlags & AM_SAMPLE_TIMEVALID)
+ m_timeDivergence = sampleProps.tStart - m_lastFrameEnd;
m_segmentFramesInCurrentFormat += frames;
- if (m_freshBuffer)
- m_freshBuffer = false;
+ m_lastFrameEnd = m_segmentTimeInPreviousFormats + FramesToTime(m_segmentFramesInCurrentFormat);
+
+ m_freshBuffer = false;
}
}
diff --git a/src/SampleCorrection.h b/src/SampleCorrection.h
index 6fecf37..42f9432 100644
--- a/src/SampleCorrection.h
+++ b/src/SampleCorrection.h
@@ -16,8 +16,8 @@ namespace SaneAudioRenderer
DspChunk ProcessSample(IMediaSample* pSample, AM_SAMPLE2_PROPERTIES& sampleProps);
- REFERENCE_TIME GetLastSampleEnd() { return m_lastSampleEnd; }
- REFERENCE_TIME GetTimingsError() { return m_timingsError; }
+ REFERENCE_TIME GetLastFrameEnd() const { return m_lastFrameEnd; }
+ REFERENCE_TIME GetTimeDivergence() const { return m_timeDivergence; }
private:
@@ -32,14 +32,12 @@ namespace SaneAudioRenderer
double m_rate = 1.0;
- bool m_freshSegment = true;
- REFERENCE_TIME m_segmentStartTimestamp = 0;
REFERENCE_TIME m_segmentTimeInPreviousFormats = 0;
uint64_t m_segmentFramesInCurrentFormat = 0;
- REFERENCE_TIME m_lastSampleEnd = 0;
+ REFERENCE_TIME m_lastFrameEnd = 0;
- REFERENCE_TIME m_timingsError = 0;
+ REFERENCE_TIME m_timeDivergence = 0;
bool m_freshBuffer = true;
};