private void recreateCodecContext() { if (stream == null) { return; } var codecParams = *stream->codecpar; bool openSuccessful = false; foreach (var(decoder, hwDeviceType) in GetAvailableDecoders(formatContext->iformat, codecParams.codec_id, TargetHardwareVideoDecoders.Value)) { // free context in case it was allocated in a previous iteration or recreate call. if (codecContext != null) { fixed(AVCodecContext **ptr = &codecContext) ffmpeg.avcodec_free_context(ptr); } codecContext = ffmpeg.avcodec_alloc_context3(decoder.Pointer); codecContext->pkt_timebase = stream->time_base; if (codecContext == null) { Logger.Log($"Couldn't allocate codec context. Codec: {decoder.Name}"); continue; } int paramCopyResult = ffmpeg.avcodec_parameters_to_context(codecContext, &codecParams); if (paramCopyResult < 0) { Logger.Log($"Couldn't copy codec parameters from {decoder.Name}: {getErrorMessage(paramCopyResult)}"); continue; } // initialize hardware decode context. if (hwDeviceType != AVHWDeviceType.AV_HWDEVICE_TYPE_NONE) { int hwDeviceCreateResult = ffmpeg.av_hwdevice_ctx_create(&codecContext->hw_device_ctx, hwDeviceType, null, null, 0); if (hwDeviceCreateResult < 0) { Logger.Log($"Couldn't create hardware video decoder context {hwDeviceType} for codec {decoder.Name}: {getErrorMessage(hwDeviceCreateResult)}"); continue; } Logger.Log($"Successfully opened hardware video decoder context {hwDeviceType} for codec {decoder.Name}"); } int openCodecResult = ffmpeg.avcodec_open2(codecContext, decoder.Pointer, null); if (openCodecResult < 0) { Logger.Log($"Error trying to open {decoder.Name} codec: {getErrorMessage(openCodecResult)}"); continue; } Logger.Log($"Successfully initialized decoder: {decoder.Name}"); openSuccessful = true; break; } if (!openSuccessful) { throw new InvalidOperationException("No usable decoder found"); } }