Browse Source

修改faac编码器

tags/v1.1.0
SmallChi(Koike) 4 years ago
parent
commit
31af02d0dc
6 changed files with 206 additions and 21 deletions
  1. +1
    -1
      src/JT1078.Flv.Test/Audio/AudioTest.cs
  2. +4
    -2
      src/JT1078.Flv.Test/JT1078.Flv.Test.csproj
  3. +185
    -6
      src/JT1078.Flv/Audio/FaacEncoder.cs
  4. +9
    -2
      src/JT1078.Flv/FlvEncoder.cs
  5. +6
    -9
      src/JT1078.Flv/JT1078.Flv.csproj
  6. +1
    -1
      src/JT1078.Protocol.Test/JT1078.Protocol.Test.csproj

+ 1
- 1
src/JT1078.Flv.Test/Audio/AudioTest.cs View File

@@ -28,7 +28,7 @@ namespace JT1078.Flv.Test.Audio
{
ReadOnlySpan<byte> fileData = File.ReadAllBytes(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"Audio/Files/testpacket.pcm"));
//注意 这里为了可以判断音频是否可用,因此使用adts,当网络传输的时候不应该使用adts
var faac = new FaacEncoder(8000, 1, 16, true);
var faac = new FaacEncoder_x64(8000, 1, 16, true);
var path = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Audio\Files\testpacket.aac");
if (File.Exists(path)) File.Delete(path);
output.WriteLine(path);


+ 4
- 2
src/JT1078.Flv.Test/JT1078.Flv.Test.csproj View File

@@ -1,11 +1,10 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="JT1078.Flv" Version="1.0.0-preview7" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.6.1" />
<PackageReference Include="xunit" Version="2.4.1" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.2">
@@ -29,6 +28,9 @@
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\JT1078.Flv\JT1078.Flv.csproj" />
</ItemGroup>
<ItemGroup>
<None Update="Audio\Files\testpacket.pcm">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>


+ 185
- 6
src/JT1078.Flv/Audio/FaacEncoder.cs View File

@@ -7,18 +7,21 @@ using JT1078.Flv.Extensions;

namespace JT1078.Flv.Audio
{
public class FaacEncoder : IDisposable
public interface IFaacEncoder:IDisposable
{
byte[] Encode(byte[] bytes);
}
public class FaacEncoder_x86 : IFaacEncoder
{
private IntPtr faacEncHandle = IntPtr.Zero;
private readonly int inputSamples;
private readonly int maxOutput;
public readonly int frameSize;
private List<byte> frameCache = new List<byte>();
public FaacEncoder(int sampleRate, int channels, int sampleBit, bool adts = false)
public FaacEncoder_x86(int sampleRate, int channels, int sampleBit, bool adts = false)
{
var inputSampleBytes = new byte[4];
var maxOutputBytes = new byte[4];

faacEncHandle = FaacEncOpen(sampleRate, channels, inputSampleBytes, maxOutputBytes);
inputSamples = BitConverter.ToInt32(inputSampleBytes, 0);
maxOutput = BitConverter.ToInt32(maxOutputBytes, 0);
@@ -63,7 +66,186 @@ namespace JT1078.Flv.Audio
}
}

const string DLLFile = @"/nativelibs/x86/libfaac.dll";

[DllImport(DLLFile, EntryPoint = "faacEncGetVersion", CallingConvention = CallingConvention.StdCall)]
//int FAACAPI faacEncGetVersion(char **faac_id_string, char **faac_copyright_string);
private extern static int FaacEncGetVersion(ref IntPtr faac_id_string, ref IntPtr faac_copyright_string);

[DllImport(DLLFile, EntryPoint = "faacEncGetCurrentConfiguration", CallingConvention = CallingConvention.StdCall)]
//faacEncConfigurationPtr FAACAPI faacEncGetCurrentConfiguration(faacEncHandle hEncoder);
private extern static IntPtr FaacEncGetCurrentConfiguration(IntPtr hEncoder);


[DllImport(DLLFile, EntryPoint = "faacEncSetConfiguration", CallingConvention = CallingConvention.StdCall)]
//int FAACAPI faacEncSetConfiguration(faacEncHandle hEncoder,faacEncConfigurationPtr config);
private extern static int FaacEncSetConfiguration(IntPtr hEncoder, IntPtr config);

[DllImport(DLLFile, EntryPoint = "faacEncOpen", CallingConvention = CallingConvention.StdCall)]
//faacEncHandle FAACAPI faacEncOpen(unsigned long sampleRate, unsigned int numChannels, unsigned long *inputSamples, unsigned long *maxOutputBytes);
private extern static IntPtr FaacEncOpen(int sampleRate, int numChannels, byte[] inputSamples, byte[] maxOutputBytes);


[DllImport(DLLFile, EntryPoint = "faacEncGetDecoderSpecificInfo", CallingConvention = CallingConvention.StdCall)]
//int FAACAPI faacEncGetDecoderSpecificInfo(faacEncHandle hEncoder, unsigned char **ppBuffer,unsigned long *pSizeOfDecoderSpecificInfo);
private extern static IntPtr FaacEncGetDecoderSpecificInfo(IntPtr hEncoder, ref IntPtr ppBuffer, ref int pSizeOfDecoderSpecificInfo);


[DllImport(DLLFile, EntryPoint = "faacEncEncode", CallingConvention = CallingConvention.StdCall)]
//int FAACAPI faacEncEncode(faacEncHandle hEncoder, int32_t * inputBuffer, unsigned int samplesInput, unsigned char *outputBuffer, unsigned int bufferSize);
private extern static int FaacEncEncode(IntPtr hEncoder, IntPtr inputBuffer, int samplesInput, IntPtr outputBuffer, int bufferSize);
[DllImport(DLLFile, EntryPoint = "faacEncEncode", CallingConvention = CallingConvention.StdCall)]
private extern static int FaacEncEncode(IntPtr hEncoder, byte[] inputBuffer, int samplesInput, byte[] outputBuffer, int bufferSize);

[DllImport(DLLFile, EntryPoint = "faacEncClose", CallingConvention = CallingConvention.StdCall)]
//int FAACAPI faacEncClose(faacEncHandle hEncoder);
private extern static IntPtr FaacEncClose(IntPtr hEncoder);

#region 配置结构
[StructLayout(LayoutKind.Sequential, Pack = 1)]
private struct FaacEncConfiguration
{
/* config version */

public int version;

/* library version */
public IntPtr name;

/* copyright string */
public IntPtr copyright;

/* MPEG version, 2 or 4 */
public uint mpegVersion;

/* AAC object type
* #define MAIN 1
#define LOW 2
#define SSR 3
#define LTP 4
* */

public uint aacObjectType;

/* Allow mid/side coding */
public uint allowMidside;

/* Use one of the channels as LFE channel */
public uint useLfe;

/* Use Temporal Noise Shaping */
public uint useTns;

/* bitrate / channel of AAC file */
public uint bitRate;

/* AAC file frequency bandwidth */
public uint bandWidth;

/* Quantizer quality */
public uint quantqual;

/* Bitstream output format (0 = Raw; 1 = ADTS) */
public int outputFormat;

/* psychoacoustic model list */
public IntPtr psymodellist;

/* selected index in psymodellist */
public int psymodelidx;

/*
PCM Sample Input Format
0 FAAC_INPUT_NULL invalid, signifies a misconfigured config
1 FAAC_INPUT_16BIT native endian 16bit
2 FAAC_INPUT_24BIT native endian 24bit in 24 bits (not implemented)
3 FAAC_INPUT_32BIT native endian 24bit in 32 bits (DEFAULT)
4 FAAC_INPUT_FLOAT 32bit floating point
*/
public int inputFormat;

/* block type enforcing (SHORTCTL_NORMAL/SHORTCTL_NOSHORT/SHORTCTL_NOLONG) */
// #define FAAC_INPUT_NULL 0
//#define FAAC_INPUT_16BIT 1
//#define FAAC_INPUT_24BIT 2
//#define FAAC_INPUT_32BIT 3
//#define FAAC_INPUT_FLOAT 4

//#define SHORTCTL_NORMAL 0
//#define SHORTCTL_NOSHORT 1
//#define SHORTCTL_NOLONG 2
public int shortctl;

/*
Channel Remapping

Default 0, 1, 2, 3 ... 63 (64 is MAX_CHANNELS in coder.h)

WAVE 4.0 2, 0, 1, 3
WAVE 5.0 2, 0, 1, 3, 4
WAVE 5.1 2, 0, 1, 4, 5, 3
AIFF 5.1 2, 0, 3, 1, 4, 5
*/
[MarshalAs(UnmanagedType.ByValArray, ArraySubType = UnmanagedType.I4, SizeConst = 64)]
public int[] channel_map;

}
#endregion
}
public class FaacEncoder_x64 : IFaacEncoder
{
private IntPtr faacEncHandle = IntPtr.Zero;
private readonly int inputSamples;
private readonly int maxOutput;
public readonly int frameSize;
private List<byte> frameCache = new List<byte>();
public FaacEncoder_x64(int sampleRate, int channels, int sampleBit, bool adts = false)
{
var inputSampleBytes = new byte[4];
var maxOutputBytes = new byte[4];
faacEncHandle = FaacEncOpen(sampleRate, channels, inputSampleBytes, maxOutputBytes);
inputSamples = BitConverter.ToInt32(inputSampleBytes, 0);
maxOutput = BitConverter.ToInt32(maxOutputBytes, 0);
frameSize = inputSamples * channels * sampleBit / 8;

var ptr = FaacEncGetCurrentConfiguration(faacEncHandle);
var configuration = InteropExtensions.IntPtrToStruct<FaacEncConfiguration>(ptr);
configuration.inputFormat = 1;
configuration.outputFormat = adts ? 1 : 0;
configuration.useTns = 0;
configuration.useLfe = 0;
configuration.aacObjectType = 2;
configuration.shortctl = 0;
configuration.quantqual = 100;
configuration.bandWidth = 0;
configuration.bitRate = 0;
InteropExtensions.IntPtrSetValue(ptr, configuration);

if (FaacEncSetConfiguration(faacEncHandle, ptr) < 0) throw new Exception("set faac configuration failed!");
}

public byte[] Encode(byte[] bytes)
{
frameCache.AddRange(bytes);
if (frameCache.Count() < frameSize)//faac必须达到一帧数据后才能正常编码
return new byte[0];
var outputBytes = new byte[maxOutput];
var len = FaacEncEncode(faacEncHandle, frameCache.Take(frameSize).ToArray(), inputSamples, outputBytes, maxOutput);
frameCache = frameCache.Skip(frameSize).ToList();
if (len <= 0)
return new byte[0];
return outputBytes.Take(len).ToArray();
}

public void Dispose()
{
frameCache = null;
if (faacEncHandle != IntPtr.Zero)
{
FaacEncClose(faacEncHandle);
faacEncHandle = IntPtr.Zero;
}
}

const string DLLFile = @"/nativelibs/x64/libfaac.dll";

@@ -71,13 +253,10 @@ namespace JT1078.Flv.Audio
//int FAACAPI faacEncGetVersion(char **faac_id_string, char **faac_copyright_string);
private extern static int FaacEncGetVersion(ref IntPtr faac_id_string, ref IntPtr faac_copyright_string);



[DllImport(DLLFile, EntryPoint = "faacEncGetCurrentConfiguration", CallingConvention = CallingConvention.StdCall)]
//faacEncConfigurationPtr FAACAPI faacEncGetCurrentConfiguration(faacEncHandle hEncoder);
private extern static IntPtr FaacEncGetCurrentConfiguration(IntPtr hEncoder);


[DllImport(DLLFile, EntryPoint = "faacEncSetConfiguration", CallingConvention = CallingConvention.StdCall)]
//int FAACAPI faacEncSetConfiguration(faacEncHandle hEncoder,faacEncConfigurationPtr config);
private extern static int FaacEncSetConfiguration(IntPtr hEncoder, IntPtr config);


+ 9
- 2
src/JT1078.Flv/FlvEncoder.cs View File

@@ -37,11 +37,18 @@ namespace JT1078.Flv
/// </summary>
public class FlvEncoder : IDisposable
{
readonly FaacEncoder faacEncoder;
readonly IFaacEncoder faacEncoder;
readonly H264Decoder h264Decoder = new H264Decoder();
public FlvEncoder(int sampleRate = 8000, int channels = 1, int sampleBit = 16, bool adts = false)
{
faacEncoder = new FaacEncoder(sampleRate, channels, sampleBit, adts);
try
{
faacEncoder = new FaacEncoder_x86(sampleRate, channels, sampleBit, adts);
}
catch
{
faacEncoder = new FaacEncoder_x64(sampleRate, channels, sampleBit, adts);
}
}

/// <summary>


+ 6
- 9
src/JT1078.Flv/JT1078.Flv.csproj View File

@@ -45,14 +45,11 @@
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="3.1.7" />
</ItemGroup>
<ItemGroup>
<Content Include="nativelibs\x64\libfaac.dll">
<PackagePath>/nativelibs/x64/libfaac.dll</PackagePath>
<Pack>true</Pack>
</Content>
<Content Include="nativelibs\x86\libfaac.dll">
<Pack>true</Pack>
<PackagePath>/nativelibs/x86/libfaac.dll</PackagePath>
</Content>
<None Update="nativelibs\x64\libfaac.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
<None Update="nativelibs\x86\libfaac.dll">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None>
</ItemGroup>
</Project>

+ 1
- 1
src/JT1078.Protocol.Test/JT1078.Protocol.Test.csproj View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>netcoreapp3.0</TargetFramework>
<TargetFramework>netcoreapp3.1</TargetFramework>

<IsPackable>false</IsPackable>
</PropertyGroup>


Loading…
Cancel
Save