/// <summary> /// Initializes the output context and writes the file header. /// </summary> /// <param name="inputContext">The input context</param> private void Initialize(AVFormatContext *inputContext) { var result = 0; try { var outputFilePath = GuessOutputFilePath(inputContext); AVFormatContext *outputContext; result = ffmpeg.avformat_alloc_output_context2(&outputContext, null, null, outputFilePath); if (result < 0) { throw new InvalidOperationException("Unable to allocate output context"); } OutputContext = outputContext; StreamMappings.Clear(); foreach (var streamIndex in Media.MediaInfo.Streams.Keys) { var codecParams = inputContext->streams[streamIndex]->codecpar; var stream = ffmpeg.avformat_new_stream(OutputContext, null); if (stream == null) { result = -ffmpeg.ENOMEM; throw new InvalidOperationException($"Unable to create output stream for stream index {streamIndex}"); } result = ffmpeg.avcodec_parameters_copy(stream->codecpar, codecParams); if (result < 0) { throw new InvalidOperationException($"Unable to copy codec parameters to stream index {streamIndex}"); } stream->codecpar->codec_tag = 0; StreamMappings[streamIndex] = stream->index; } result = ffmpeg.avio_open(&outputContext->pb, outputFilePath, ffmpeg.AVIO_FLAG_WRITE); if (result < 0) { throw new InvalidOperationException($"Could not open output file '{outputFilePath}'"); } result = ffmpeg.avformat_write_header(OutputContext, null); if (result < 0) { throw new InvalidOperationException($"Could not write header to '{outputFilePath}'"); } HasInitialized = true; } catch (Exception ex) { Media.LogError(nameof(TransportStreamRecorder), $"Error Code {result}: {ex.Message}"); Release(); } }