c++ - GStreamer memory leak issue -
i have object generate videos gstreamer. each time want generate new video y create 1 new object , add frames. after video finished, delete object gstreamer internal memory looks not released.
after several videos generated ram allocated , linux kills process.
why happening? how can solve issue? there other way it?
gvideo.h:
#ifndef gvideo_h #define gvideo_h #include <gst/gst.h> #include <string> class gvideo { public: gvideo(); ~gvideo(); void startvideo(std::string filename); void endvideo(); void addframe(gstsample* element); bool isrecording(){return _isrecording;} bool isdataneed(){return _dataneed;} private: void setdataneed(bool dataneed){_dataneed = dataneed;} protected: bool _isrecording; bool _dataneed; int _framerate; int _duration; gstclocktime _timestamp; gstelement *_pipeline; gstelement *_source; }; #endif //gvideo_h
gvideo.cpp
#include "gvideo.h" #include <gst/app/gstappsrc.h> #include <iostream> static gboolean bus_video_call(gstbus* bus, gstmessage* msg, void* user_data) { //std::cout << "bus_call" << std::endl; gvideo* video = (gvideo*)user_data; switch (gst_message_type(msg)) { case gst_message_eos: { std::cout << "video gst_message_eos" << std::endl; video->endvideo(); break; } case gst_message_error: { std::cout << "gst_message_error" << std::endl; gerror *err; gst_message_parse_error(msg, &err, null); g_error("%s", err->message); g_error_free(err); video->endvideo(); break; } default: break; } return true; } gvideo::gvideo() : _dataneed(false), _isrecording(false) { _pipeline = null; _source = null; } gvideo::~gvideo() { std::cout << "deleting gstvideo." << std::endl; if(_pipeline != null) endvideo(); } void gvideo::startvideo(std::string filename) { _isrecording = true; _framerate = 2; _duration = 5; _timestamp = 0; _dataneed = true; _pipeline = gst_pipeline_new ("video_pipeline"); _source = gst_element_factory_make ("appsrc" , "video_source"); gstelement* _videorate = gst_element_factory_make ("videorate" , "video_vidrate"); gstelement* _capsfilter = gst_element_factory_make ("capsfilter" , "video_capsfilter"); gstelement* _videoconvert = gst_element_factory_make ("videoconvert", "video_conv"); gstelement* _encoder = gst_element_factory_make ("x264enc" , "video_enc"); gstelement* _muxer = gst_element_factory_make ("mp4mux" , "video_mux"); gstelement* _filesink = gst_element_factory_make ("filesink" , "video_filesink"); // g_object_set (g_object (_source), "num-buffers", _duration*_framerate, null); g_object_set (g_object (_source), "caps", gst_caps_new_simple ( "video/x-raw", "format", g_type_string, "i420", "width", g_type_int, 352, "height", g_type_int, 288, "framerate", gst_type_fraction, _framerate, 1, null), null); /* setup appsrc */ g_object_set (g_object (_source), // "do-timestamp", true, "stream-type", gst_app_stream_type_stream, "format", gst_format_time, null); g_object_set (g_object (_capsfilter), "caps", gst_caps_new_simple ("video/x-raw", // "format", g_type_string, "i420", "framerate", gst_type_fraction, 30, 1, null), null); gst_bin_add_many (gst_bin (_pipeline), _source, _videorate, _capsfilter, _videoconvert, _encoder, _muxer, _filesink, null); gst_element_link_many (_source, _videorate, _capsfilter, _videoconvert, _encoder, _muxer, _filesink, null); g_object_set (g_object (_filesink), "location", filename.c_str(), null); gstbus* bus = gst_pipeline_get_bus(gst_pipeline(_pipeline)); gst_bus_add_watch(bus, bus_video_call, this); gst_object_unref(bus); gst_element_set_state (_pipeline, gst_state_playing); } void gvideo::addframe(gstsample* element) { gstbuffer* buf = gst_sample_get_buffer((gstsample*)element); gst_buffer_pts (buf) = _timestamp; gst_buffer_duration (buf) = gst_util_uint64_scale_int (1, gst_second, _framerate); _timestamp += gst_buffer_duration (buf); gst_app_src_push_sample(gst_app_src(_source), element); if(_timestamp >= _duration*gst_second) { _dataneed = false; gst_app_src_end_of_stream(gst_app_src(_source)); } } void gvideo::endvideo() { std::cout << "gst_element_set_state." << std::endl; gst_element_set_state (_pipeline, gst_state_null); std::cout << "gst_object_unref." << std::endl; gst_object_unref(_pipeline); std::cout << "_pipeline= null." << std::endl; _pipeline = null; std::cout << "setdataneed." << std::endl; _isrecording = false; }
i guess whatever calling addframe() might need unref sample.
in docs there indicates "transfer: none" on sample
parameter, believe means caller needs unref. reason older method gst_app_src_push_buffer has transfer "full". dunno why.
Comments
Post a Comment