Browse Source

添加unix支持

pull/14/head
Pangpang Don 3 years ago
parent
commit
0377d93ca9
1 changed files with 187 additions and 1 deletions
  1. +187
    -1
      src/JT1078.Protocol/Audio/FaacEncoder.cs

+ 187
- 1
src/JT1078.Protocol/Audio/FaacEncoder.cs View File

@@ -36,16 +36,26 @@ namespace JT1078.Protocol.Audio
{
encoder = new FaacEncoder_x86(sampleRate, channels, sampleBit, adts);
}
Console.WriteLine("Win faccEncoder loaded.");
break;

case PlatformID.MacOSX:
case PlatformID.Unix:
//TODO: 适配linux
try
{
encoder = new FaacEncoder_unix(sampleRate, channels, sampleBit, adts);
Console.WriteLine("Unix faccEncoder loaded.");
}
catch
{
throw new ApplicationException("system not support. or not found libfaac.so");
}

break;

default:
throw new ApplicationException("system not support.");
break;
}
}

@@ -411,4 +421,180 @@ namespace JT1078.Protocol.Audio

#endregion 配置结构
}

public class FaacEncoder_unix : IFaacEncoder
{
private IntPtr faacEncHandle = IntPtr.Zero;
private readonly int inputSamples;
private readonly int maxOutput;
public int frameSize { get; }
private List<byte> frameCache = new List<byte>();

public FaacEncoder_unix(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;
}
}

private const string DLLFile = @"libfaac.so.0";

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

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

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

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

[DllImport(DLLFile, EntryPoint = "faacEncGetDecoderSpecificInfo", CallingConvention = CallingConvention.StdCall)]
private static extern IntPtr FaacEncGetDecoderSpecificInfo(IntPtr hEncoder, ref IntPtr ppBuffer, ref int pSizeOfDecoderSpecificInfo);

[DllImport(DLLFile, EntryPoint = "faacEncEncode", CallingConvention = CallingConvention.StdCall)]
private static extern int FaacEncEncode(IntPtr hEncoder, IntPtr inputBuffer, int samplesInput, IntPtr outputBuffer, int bufferSize);

[DllImport(DLLFile, EntryPoint = "faacEncEncode", CallingConvention = CallingConvention.StdCall)]
private static extern int FaacEncEncode(IntPtr hEncoder, byte[] inputBuffer, int samplesInput, byte[] outputBuffer, int bufferSize);

[DllImport(DLLFile, EntryPoint = "faacEncClose", CallingConvention = CallingConvention.StdCall)]
private static extern 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 配置结构
}
}

Loading…
Cancel
Save