Skip to content

Commit ab06ce2

Browse files
committed
fix(ASR): reinitialize SwrContext when codec is changed
The number of channels, etc. may change in the middle of a specific video format (confirmed with m2ts). In this case, a native error occurs, so SwrContext is to be initialized again.
1 parent 53ce771 commit ab06ce2

File tree

1 file changed

+39
-4
lines changed

1 file changed

+39
-4
lines changed

FlyleafLib/MediaPlayer/SubtitlesASR.cs

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -768,13 +768,48 @@ private static void UpdateWavHeader(Stream stream)
768768
private byte[] _sampledBuf = [];
769769
private int _sampledBufSize;
770770

771+
// for codec change detection
772+
private int _lastFormat;
773+
private int _lastSampleRate;
774+
private ulong _lastChannelLayout;
775+
771776
private unsafe void ResampleTo(Stream toStream, AVFrame* frame, int targetSampleRate, int targetChannel)
772777
{
773-
AVChannelLayout outLayout;
774-
av_channel_layout_default(&outLayout, targetChannel);
778+
bool codecChanged = false;
779+
780+
if (_lastFormat != frame->format)
781+
{
782+
_lastFormat = frame->format;
783+
codecChanged = true;
784+
}
785+
if (_lastSampleRate != frame->sample_rate)
786+
{
787+
_lastSampleRate = frame->sample_rate;
788+
codecChanged = true;
789+
}
790+
if (_lastChannelLayout != frame->ch_layout.u.mask)
791+
{
792+
_lastChannelLayout = frame->ch_layout.u.mask;
793+
codecChanged = true;
794+
}
795+
796+
// Reinitialize SwrContext because codec changed
797+
// Note that native error will occur if not reinitialized.
798+
// Reference: AudioDecoder::RunInternal
799+
if (_swrContext != null && codecChanged)
800+
{
801+
fixed (SwrContext** ptr = &_swrContext)
802+
{
803+
swr_free(ptr);
804+
}
805+
_swrContext = null;
806+
}
775807

776808
if (_swrContext == null)
777809
{
810+
AVChannelLayout outLayout;
811+
av_channel_layout_default(&outLayout, targetChannel);
812+
778813
// NOTE: important to reuse this context
779814
fixed (SwrContext** ptr = &_swrContext)
780815
{
@@ -803,7 +838,7 @@ private unsafe void ResampleTo(Stream toStream, AVFrame* frame, int targetSample
803838
{
804839
nOut += (int)Math.Min(delay, Math.Max(4096, nOut));
805840
}
806-
int needed = nOut * outLayout.nb_channels * sizeof(ushort);
841+
int needed = nOut * targetChannel * sizeof(ushort);
807842

808843
if (_sampledBufSize < needed)
809844
{
@@ -824,7 +859,7 @@ private unsafe void ResampleTo(Stream toStream, AVFrame* frame, int targetSample
824859
}
825860
samplesPerChannel.ThrowExceptionIfError("swr_convert");
826861

827-
int resampledDataSize = samplesPerChannel * outLayout.nb_channels * sizeof(ushort);
862+
int resampledDataSize = samplesPerChannel * targetChannel * sizeof(ushort);
828863

829864
toStream.Write(_sampledBuf, 0, resampledDataSize);
830865
}

0 commit comments

Comments
 (0)