<div dir="ltr">Hi All,<div><br></div><div>I am trying to create a pipeline in C++ with appsrc as a source and filesink as a sink element. For simplicity I am creating a buffer with alternating black and white frames and pushing it into appsrc. My goal is to create an mp4 video as output. The program is creating the file that grows in size with time of execution. But when I open it to read, it doesn't open up.</div><div>Could someone please point me in the right direction to solve the problem?</div><div><br></div><div>Thanks in advance.</div><div><br></div><div>Best,</div><div>Manoj</div><div><br></div><div><br></div><div>Here goes the code:</div><div><br></div><div><div>#include <gst/gst.h></div><div>#include <gst/app/gstappsrc.h></div><div>#include <iostream></div><div><br></div><div>static GMainLoop *loop;</div><div>GstElement *pipeline, *appsrc, *filter1, *conv, *filter2, *encoder, *parser, *muxer, *filesink;</div><div>GstCaps *filter1_caps;</div><div>GstCaps *filter2_caps;</div><div>GstBus *bus;</div><div>guint bus_watch_id;</div><div><br></div><div>static void cb_need_data(GstElement *appsrc, guint unused_size,</div><div><span style="white-space:pre">                </span>gpointer user_data) {</div><div><span style="white-space:pre"> </span>static gboolean white = FALSE;</div><div><span style="white-space:pre">        </span>static GstClockTime timestamp = 0;</div><div><span style="white-space:pre">    </span>GstBuffer *buffer;</div><div><span style="white-space:pre">    </span>guint size;</div><div><span style="white-space:pre">   </span>GstFlowReturn ret;</div><div><br></div><div><span style="white-space:pre">   </span>size = 640 * 480 * 3;</div><div><br></div><div><span style="white-space:pre">        </span>buffer = gst_buffer_new_allocate(NULL, size, NULL);</div><div><span style="white-space:pre">   </span>/* this makes the image black/white */</div><div><span style="white-space:pre">        </span>gst_buffer_memset(buffer, 0, white ? 0xff : 0x0, size);</div><div><br></div><div><span style="white-space:pre">      </span>white = !white;</div><div><br></div><div><span style="white-space:pre">      </span>GST_BUFFER_PTS (buffer) = timestamp;</div><div><span style="white-space:pre">  </span>GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int(1, GST_SECOND, 2);</div><div><span style="white-space:pre">   </span>timestamp += GST_BUFFER_DURATION(buffer);</div><div><br></div><div><span style="white-space:pre">    </span>g_signal_emit_by_name(appsrc, "push-buffer", buffer, &ret);</div><div><span style="white-space:pre">     </span>gst_buffer_unref(buffer);</div><div><br></div><div><span style="white-space:pre">    </span>if (ret != GST_FLOW_OK) {</div><div><span style="white-space:pre">             </span>/* something wrong, send EOS event and stop pushing */</div><div><span style="white-space:pre">                </span>gst_element_send_event(pipeline, gst_event_new_eos());</div><div><span style="white-space:pre">                </span>g_main_loop_quit(loop);</div><div><span style="white-space:pre">       </span>}</div><div>}</div><div><br></div><div>static gboolean my_bus_callback(GstBus *bus, GstMessage *message,</div><div><span style="white-space:pre">            </span>gpointer data) {</div><div><span style="white-space:pre">      </span>g_print("Got %s message\n", GST_MESSAGE_TYPE_NAME(message));</div><div><br></div><div><span style="white-space:pre">       </span>switch (GST_MESSAGE_TYPE(message)) {</div><div><span style="white-space:pre">  </span>case GST_MESSAGE_ERROR: {</div><div><span style="white-space:pre">             </span>GError *err;</div><div><span style="white-space:pre">          </span>gchar *debug;</div><div><br></div><div><span style="white-space:pre">                </span>gst_message_parse_error(message, &err, &debug);</div><div><span style="white-space:pre">               </span>g_printerr("ERROR from element %s: %s\n", GST_OBJECT_NAME(message->src),</div><div><span style="white-space:pre">                         </span>err->message);</div><div><span style="white-space:pre">             </span>g_printerr("Debugging info: %s\n", (debug) ? debug : "none");</div><div><span style="white-space:pre">             </span></div><div><span style="white-space:pre">              </span>g_error_free(err);</div><div><span style="white-space:pre">            </span>g_free(debug);</div><div><br></div><div><span style="white-space:pre">               </span>std::cin.get();</div><div><span style="white-space:pre">               </span>g_main_loop_quit(loop);</div><div><span style="white-space:pre">               </span>break;</div><div><span style="white-space:pre">        </span>}</div><div><span style="white-space:pre">     </span>case GST_MESSAGE_EOS:</div><div><span style="white-space:pre">         </span>/* end-of-stream */</div><div><span style="white-space:pre">           </span>std::cin.get();</div><div><span style="white-space:pre">               </span>g_main_loop_quit(loop);</div><div><span style="white-space:pre">               </span>break;</div><div><span style="white-space:pre">        </span>default:</div><div><span style="white-space:pre">              </span>g_print("Debug raw message: %s\n", message);</div><div><span style="white-space:pre">                </span>break;</div><div><span style="white-space:pre">        </span>}</div><div><br></div><div><span style="white-space:pre">    </span>return TRUE;</div><div>}</div><div><br></div><div>gint main(gint argc, gchar *argv[]) {</div><div><span style="white-space:pre">     </span>/* init GStreamer */</div><div><span style="white-space:pre">  </span>gst_init(&argc, &argv);</div><div><span style="white-space:pre">       </span>gst_debug_set_default_threshold(GST_LEVEL_INFO);</div><div><span style="white-space:pre">      </span>loop = g_main_loop_new(NULL, FALSE);</div><div><br></div><div><span style="white-space:pre"> </span>/* setup pipeline */</div><div><span style="white-space:pre">  </span>pipeline = gst_pipeline_new("pipeline");</div><div><span style="white-space:pre">    </span>appsrc = gst_element_factory_make("appsrc", "source");</div><div><span style="white-space:pre">    </span>filter1  = gst_element_factory_make ("capsfilter",<span style="white-space:pre">        </span>"filter1");</div><div><span style="white-space:pre"> </span>conv = gst_element_factory_make("autovideoconvert", "conv");</div><div><span style="white-space:pre">      </span>encoder = gst_element_factory_make("x264enc", "encoder");</div><div><span style="white-space:pre"> </span>filter2<span style="white-space:pre">      </span> = gst_element_factory_make ("capsfilter", "filter2");</div><div><span style="white-space:pre">    </span>parser<span style="white-space:pre">       </span> = gst_element_factory_make ("h264parse", "parser");</div><div><span style="white-space:pre">      </span>muxer = gst_element_factory_make("mp4mux", "muxer");</div><div><span style="white-space:pre">      </span>filesink = gst_element_factory_make("filesink", "filesink");</div><div><br></div><div><span style="white-space:pre">     </span>/* setup appsrc */</div><div><span style="white-space:pre">    </span>g_object_set(G_OBJECT(appsrc),</div><div><span style="white-space:pre">                        </span>"stream-type", GST_APP_STREAM_TYPE_STREAM,</div><div><span style="white-space:pre">                  </span>"format", GST_FORMAT_TIME,</div><div><span style="white-space:pre">                  </span>NULL);</div><div><span style="white-space:pre">        </span>g_signal_connect(appsrc, "need-data", G_CALLBACK (cb_need_data), NULL);</div><div><br></div><div><span style="white-space:pre">    </span>/* setup */</div><div><span style="white-space:pre">   </span>g_object_set(G_OBJECT(appsrc), "caps",</div><div><span style="white-space:pre">                      </span>gst_caps_new_simple("video/x-raw",</div><div><span style="white-space:pre">                                  </span>"format", G_TYPE_STRING, "RGB",</div><div><span style="white-space:pre">                                   </span>"width", G_TYPE_INT, 640,</div><div><span style="white-space:pre">                                   </span>"height", G_TYPE_INT, 480,</div><div><span style="white-space:pre">                                  </span>"framerate", GST_TYPE_FRACTION, 0, 1,</div><div><span style="white-space:pre">                                       </span>NULL), NULL);</div><div><span style="white-space:pre"> </span>filter1_caps = gst_caps_new_simple ("video/x-raw",</div><div><span style="white-space:pre">                  </span>"format", G_TYPE_STRING, "RGB",</div><div><span style="white-space:pre">                   </span>"width", G_TYPE_INT, 640,</div><div><span style="white-space:pre">                   </span>"height", G_TYPE_INT, 480,</div><div><span style="white-space:pre">                  </span>NULL);</div><div><br></div><div><span style="white-space:pre">       </span>filter2_caps = gst_caps_new_simple ("video/x-h264",</div><div><span style="white-space:pre">                 </span>"stream-format", G_TYPE_STRING, "byte-stream",</div><div><span style="white-space:pre">                    </span>NULL);</div><div><span style="white-space:pre">        </span>g_object_set (G_OBJECT (filter1), "caps", filter1_caps, NULL);</div><div><span style="white-space:pre">      </span>g_object_set (G_OBJECT (filter2), "caps", filter2_caps, NULL);</div><div><span style="white-space:pre">      </span>gst_caps_unref (filter1_caps);</div><div><span style="white-space:pre">        </span>gst_caps_unref (filter2_caps);</div><div><br></div><div><span style="white-space:pre">       </span>g_object_set(G_OBJECT(filesink), "location",</div><div><span style="white-space:pre">                        </span>"C:\\CppWorkspace\\GstreamerApps\\testout.mp4", NULL);</div><div><br></div><div><span style="white-space:pre">     </span>gst_bin_add_many(GST_BIN(pipeline), appsrc, filter1, conv, encoder, filter2, parser, muxer, filesink, NULL);</div><div><span style="white-space:pre">  </span>gst_element_link_many(appsrc, filter1, conv, encoder, filter2, parser, muxer, filesink, NULL);</div><div><br></div><div><span style="white-space:pre">       </span>/* adds a watch for new message on our pipeline's message bus to</div><div><span style="white-space:pre">  </span> * the default GLib main context, which is the main context that our</div><div><span style="white-space:pre">  </span> * GLib main loop is attached to below</div><div><span style="white-space:pre">        </span> */</div><div><span style="white-space:pre">   </span>bus = gst_pipeline_get_bus(GST_PIPELINE(pipeline));</div><div><span style="white-space:pre">   </span>bus_watch_id = gst_bus_add_watch(bus, my_bus_callback, NULL);</div><div><span style="white-space:pre"> </span>std::cout << bus_watch_id;</div><div><br></div><div><span style="white-space:pre">     </span>/* play */</div><div><span style="white-space:pre">    </span>gst_element_set_state(pipeline, GST_STATE_PLAYING);</div><div><span style="white-space:pre">   </span>g_main_loop_run(loop);</div><div><br></div><div><span style="white-space:pre">       </span>/* clean up */</div><div><span style="white-space:pre">        </span>gst_element_set_state(pipeline, GST_STATE_NULL);</div><div><span style="white-space:pre">      </span>gst_object_unref(GST_OBJECT(pipeline));</div><div><span style="white-space:pre">       </span>gst_object_unref(bus);</div><div><span style="white-space:pre">        </span>g_main_loop_unref(loop);</div><div><br></div><div><span style="white-space:pre">     </span>return 0;</div><div>}</div></div><div><br></div></div>