I'm using gstreamer to stream video from a camera to an HLS sink and to also record that video to the filesystem as an MP4. I use a tee to split the video into the two paths. I wrote some code and got it working if I connect it all up and switch state to "play". But when I start the streaming and try to connect the splitmuxsink dynamically to the tee, the video files I record aren't valid (at least VLC won't play them). (The web stream continues to work just fine)
I've reduced my code to a simple version (below) where I start with one splimuxsink, sleep a while and then add a second one. Although the first splitmuxsink works great, the new one never generates usable video. To make the transitions, I switch the playing pipeline to pause, add the new elements (all in the paused state) and switch everything to play.
Following the gstream manual, I've tried more complicated switching procedures; adding a probe to block the new branch of the tee, etc. but the results are the same.
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <ctype.h> #include <gst/gst.h> #include <assert.h> using namespace std; int main() { // Create a pipeline to write a file printf("starting\n"); gst_init(NULL, NULL); // Create the pipeline to host the elements GstElement* pipeline = gst_pipeline_new("pipeline"); assert(pipeline != nullptr); GstElement* camera = gst_element_factory_make("v4l2src", "v4l2src"); assert(camera != nullptr); g_object_set(G_OBJECT(camera), "device", "/dev/video2", NULL); GstElement* caps = gst_element_factory_make("capsfilter", "capsfilter"); assert(caps != nullptr); g_object_set(G_OBJECT(caps), "caps", gst_caps_from_string("video/x-h264,width=640,height=480,framerate=30/1"), NULL); GstElement* tee = gst_element_factory_make("tee", "tee"); GstElement* queue1 = gst_element_factory_make("queue", "queue1"); GstElement* h264parse1 = gst_element_factory_make("h264parse", "h264parse1"); GstElement* splitmux1 = gst_element_factory_make("splitmuxsink", "splitmux1"); g_object_set(G_OBJECT(splitmux1), "location", "file%03d.mp4", "max-size-time", 10000000000, NULL); assert(tee != nullptr && queue1 != nullptr && h264parse1 != nullptr && splitmux1 != nullptr); // Attach them all to the pipeline gst_bin_add_many(GST_BIN (pipeline), camera, caps, tee, queue1, h264parse1, splitmux1, NULL); // Link the pieces assert(true == gst_element_link_many(camera, caps, tee, NULL)); GstPad* srcpad = gst_element_get_request_pad(tee, "src_%u"); assert(srcpad != nullptr); GstPad* dstpad = gst_element_get_static_pad (queue1, "sink"); assert(dstpad != nullptr); assert(GST_PAD_LINK_OK == gst_pad_link(srcpad, dstpad)); assert(true == gst_element_link_many (queue1, h264parse1, splitmux1, NULL)); assert(GST_STATE_CHANGE_ASYNC == gst_element_set_state (pipeline, GST_STATE_PLAYING)); sleep(35); printf("Attach the splitmuxsink\n"); // Now attach another sink GstElement* queue2 = gst_element_factory_make("queue", "queue2"); assert(nullptr != queue2); GstElement* h264parse2 = gst_element_factory_make("h264parse", "h264parse2"); assert(nullptr != h264parse2); GstElement* splitmux2 = gst_element_factory_make("splitmuxsink", "splitmux2"); assert(nullptr != splitmux2); g_object_set(G_OBJECT(splitmux2), "location", "alt%03d.mp4", "max-size-time", 10000000000, NULL); // Set all the states to paused before attaching assert(GST_STATE_CHANGE_ASYNC == gst_element_set_state (splitmux2, GST_STATE_PAUSED)); assert(GST_STATE_CHANGE_SUCCESS == gst_element_set_state (h264parse2, GST_STATE_PAUSED)); assert(GST_STATE_CHANGE_SUCCESS == gst_element_set_state (queue2, GST_STATE_PAUSED)); assert(GST_STATE_CHANGE_NO_PREROLL == gst_element_set_state (pipeline, GST_STATE_PAUSED)); gst_bin_add_many (GST_BIN (pipeline), queue2, h264parse2, splitmux2, NULL); assert(true == gst_element_link_many (queue2, h264parse2, splitmux2, NULL)); GstPad* srcpad2 = gst_element_get_request_pad(tee, "src_%u"); assert(nullptr != srcpad2); GstPad* dstpad2 = gst_element_get_static_pad (queue2, "sink"); assert(nullptr != dstpad2); assert(GST_PAD_LINK_OK == gst_pad_link(srcpad2, dstpad2)); assert(GST_STATE_CHANGE_ASYNC == gst_element_set_state (pipeline, GST_STATE_PLAYING)); sleep(65); printf("all done\n"); } https://stackoverflow.com/questions/66837804/connecting-to-a-tee-thats-playing March 28, 2021 at 10:06AM
没有评论:
发表评论