I need to encapsulate raw opus frames ( from rtpdump similar format ), but i have trouble with function ffmpeg.avformat_write_header - Error writing opus headers -1094995529
public unsafe class OpusMuxer
{
public static void ConvertRawOpusToOggOpus(string inputPath, string outputPath, int sampleRate = 48000, int channels = 2)
{
ffmpeg.av_log_set_level(ffmpeg.AV_LOG_INFO);
AVOutputFormat* fmt = ffmpeg.av_guess_format("ogg", null, null);
if (fmt == null)
{
Console.WriteLine("Nepodařilo se zjistit výstupní formát (ogg).");
return;
}
AVFormatContext* oc = null;
ffmpeg.avformat_alloc_output_context2(&oc, fmt, null, null);
if (oc == null)
{
Console.WriteLine("Nepodařilo se vytvořit výstupní formátovací kontext.");
return;
}
AVStream* st = ffmpeg.avformat_new_stream(oc, null);
if (st == null)
{
Console.WriteLine("Nelze vytvořit nový stream.");
goto cleanup;
}
AVCodecParameters* codecpar = st->codecpar;
codecpar->codec_type = AVMediaType.AVMEDIA_TYPE_AUDIO;
codecpar->codec_id = AVCodecID.AV_CODEC_ID_OPUS;
codecpar->format = 8;//ffmpeg.AV_SAMPLE_FMT_FLTP;
codecpar->sample_rate = sampleRate;
ffmpeg.av_channel_layout_from_mask(&st->codecpar->ch_layout, ffmpeg.AV_CH_LAYOUT_STEREO);
codecpar->ch_layout.nb_channels = channels;
st->time_base = new AVRational { num = 1, den = codecpar->sample_rate };
byte[] opusHeader = new byte[] {
(byte)'O', (byte)'p', (byte)'u', (byte)'s', // Magic Signature "Opus"
1, // Version
2, // Channel count
0, 0, // Pre-skip
0x80, 0xBB, 0, 0, // Original sample rate (48000 Hz)
0, // Gain
0 // Channel mapping
};
codecpar->extradata = (byte*)ffmpeg.av_malloc((ulong)opusHeader.Length);
Marshal.Copy(opusHeader, 0, (IntPtr)codecpar->extradata, opusHeader.Length);
codecpar->extradata_size = opusHeader.Length;
if ((fmt->flags & ffmpeg.AVFMT_NOFILE) == 0)
{
int ret = ffmpeg.avio_open(&oc->pb, outputPath, ffmpeg.AVIO_FLAG_WRITE);
if (ret < 0)
{
Console.WriteLine("Nelze otevřít výstupní soubor.");
goto cleanup;
}
}
int re = ffmpeg.avformat_write_header(oc, null);
if (re < 0)
{
goto cleanup;
}
using (var fs = File.OpenRead(inputPath))
using (var br = new BinaryReader(fs))
{
while (br.BaseStream.Position < br.BaseStream.Length)
{
// Čteme délku framu (2 bajty)
byte[] lengthBytes = br.ReadBytes(2);
if (lengthBytes.Length < 2) break;
int frameLen = lengthBytes[0] | (lengthBytes[1] << 8);
if (frameLen <= 0 || frameLen > 65535) break;
byte[] frameData = br.ReadBytes(frameLen);
if (frameData.Length < frameLen) break;
AVPacket pkt;
ffmpeg.av_init_packet(&pkt);
pkt.data = (byte*)ffmpeg.av_malloc((ulong)frameLen);
Marshal.Copy(frameData, 0, (IntPtr)pkt.data, frameLen);
pkt.size = frameLen;
pkt.stream_index = st->index;
int writeRet = ffmpeg.av_interleaved_write_frame(oc, &pkt);
ffmpeg.av_free(pkt.data);
if (writeRet < 0)
{
Console.WriteLine("Chyba při zápisu framu.");
break;
}
}
}
ffmpeg.av_write_trailer(oc);
cleanup:
if (oc != null && oc->pb != null)
{
ffmpeg.avio_closep(&oc->pb);
}
if (oc != null)
{
ffmpeg.avformat_free_context(oc);
}
}
}