@@ -768,13 +768,48 @@ private static void UpdateWavHeader(Stream stream)
768
768
private byte [ ] _sampledBuf = [ ] ;
769
769
private int _sampledBufSize ;
770
770
771
+ // for codec change detection
772
+ private int _lastFormat ;
773
+ private int _lastSampleRate ;
774
+ private ulong _lastChannelLayout ;
775
+
771
776
private unsafe void ResampleTo ( Stream toStream , AVFrame * frame , int targetSampleRate , int targetChannel )
772
777
{
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
+ }
775
807
776
808
if ( _swrContext == null )
777
809
{
810
+ AVChannelLayout outLayout ;
811
+ av_channel_layout_default ( & outLayout , targetChannel ) ;
812
+
778
813
// NOTE: important to reuse this context
779
814
fixed ( SwrContext * * ptr = & _swrContext )
780
815
{
@@ -803,7 +838,7 @@ private unsafe void ResampleTo(Stream toStream, AVFrame* frame, int targetSample
803
838
{
804
839
nOut += ( int ) Math . Min ( delay , Math . Max ( 4096 , nOut ) ) ;
805
840
}
806
- int needed = nOut * outLayout . nb_channels * sizeof ( ushort ) ;
841
+ int needed = nOut * targetChannel * sizeof ( ushort ) ;
807
842
808
843
if ( _sampledBufSize < needed )
809
844
{
@@ -824,7 +859,7 @@ private unsafe void ResampleTo(Stream toStream, AVFrame* frame, int targetSample
824
859
}
825
860
samplesPerChannel . ThrowExceptionIfError ( "swr_convert" ) ;
826
861
827
- int resampledDataSize = samplesPerChannel * outLayout . nb_channels * sizeof ( ushort ) ;
862
+ int resampledDataSize = samplesPerChannel * targetChannel * sizeof ( ushort ) ;
828
863
829
864
toStream . Write ( _sampledBuf , 0 , resampledDataSize ) ;
830
865
}
0 commit comments