Kapselung von rohen Opus-Frames in ogg mithilfe von ffmpeg.autogenC#

Ein Treffpunkt für C#-Programmierer
Anonymous
 Kapselung von rohen Opus-Frames in ogg mithilfe von ffmpeg.autogen

Post by Anonymous »

Ich muss rohe Opus-Frames (aus einem rtpdump-ähnlichen Format) kapseln, aber ich habe Probleme mit der Funktion ffmpeg.avformat_write_header – Fehler beim Schreiben von Opus-Headern -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] 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);
}
}
}

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post