How to provide my own cuda context to gstreamer

I know I should listen GST_MESSAGE_NEED_CONTEXT message. But I found the message is never be post. Here is my code:

...
gst_bus_add_watch_full(m_bus, G_PRIORITY_DEFAULT, on_bus_message, cfgo::make_weak_holder(weak_from_this()), cfgo::destroy_weak_holder<DataPrepareTask>);
...
if (!gst_element_set_state(m_pipeline, GST_STATE_PLAYING))
{
    throw cpptrace::runtime_error("unable to start the pipeline.");
}

and on_bus_message

        gboolean on_bus_message(GstBus *bus, GstMessage *message, gpointer user_data)
        {
            // I have put break point here, it is never be triggered.
            if (auto self = cfgo::cast_weak_holder<DataPrepareTask>(user_data)->lock())
            {
                switch (GST_MESSAGE_TYPE(message))
                {
                case GST_MESSAGE_NEED_CONTEXT:
                {
                    self->m_logger->debug("Received need context message.");
                    if (message->src)
                    {
                        const gchar * context_type = nullptr;
                        if (gst_message_parse_context_type(message, &context_type))
                        {
                            self->m_logger->debug("The context type parsed: {}", context_type);
                            if (g_str_equal(context_type, GST_CUDA_CONTEXT_TYPE))
                            {
                                auto cu_ctx = self->m_device.get_cuda_context();
                                auto dev = self->m_device.get_cuda_device();
                                self->m_logger->trace("Creating the new cuda context with device {}", dev);
                                auto cuda_ctx = gst_cuda_context_new_wrapped(cu_ctx, dev);
                                if (cuda_ctx)
                                {
                                    self->m_logger->trace("Creating the gst context using cuda context");
                                    auto ctx = gst_context_new_cuda_context(cuda_ctx);
                                    if (ctx)
                                    {
                                        gst_element_set_context(GST_ELEMENT(message->src), ctx);
                                        gst_context_unref(ctx);
                                    }
                                    else
                                    {
                                        self->m_logger->error("Unable to create the gst context using cuda context.");
                                    }
                                    gst_object_unref(cuda_ctx);
                                }
                                else
                                {
                                    self->m_logger->error("Unable to create the cuda context with CUcontext {} and CUdevice {}.", fmt::ptr(cu_ctx), dev);
                                }
                            }
                        }
                        else
                        {
                            self->m_logger->error("Unable to parse the context type from need context message.");
                        }
                    }
                    else
                    {
                        self->m_logger->debug("There is no src in need context message.");
                    }
                    break;
                }
                case GST_MESSAGE_EOS:
                    break;
                case GST_MESSAGE_ERROR:
                    break;
                
                default:
                    break;
                }
            }

            return TRUE;
        }

I found I should replace gst_bus_add_watch_full with gst_bus_set_sync_handler then I can receive the GST_MESSAGE_NEED_CONTEXT message. But it still not work. Because the decoder refuse my context because it was forced to use device 0, and I want to use device 1. Then I found the property cuda-device-id is readonly. So how can I force decodebin use device what I need?