I'm trying to use Gstreamer API and I want to streaming internal buffer using rtsp with H.264 encoder. SO I made a code by searching but It doesn't works. I cannot find what is wrong with my code.
The code is composed that <bmp file read -> put in image buffer -> encode H.264 -> rtsp stream>
Here are my codes.
FILE* f = NULL;
unsigned char bmp_info[54];
unsigned char* read_data;
read_data = (unsigned char*)malloc(1280*720*3*sizeof(unsigned char));
f = fopen("0005.bmp","rb");
if(f==NULL)
{
APP_PRINTF("app_tidl: [ERROR] STREAMING FILE NOT EXIST!!!\n");
}
fread(bmp_info,sizeof(unsigned char),54,f);
int bmp_width = *(int*)&bmp_info[18];
int bmp_height = *(int*)&bmp_info[22];
APP_PRINTF("app_tidl: FREAD BMP WIDTH : %d / HEIGHT : %d\n",bmp_width,bmp_height);
int size = bmp_width*bmp_height*3;
fread(read_data,sizeof(unsigned char),size,f);
fclose(f);
APP_PRINTF("app_tidl: FILE BMP READ FINISHED!!!\n");
gst_cmd_params->input_data_camera = read_data;//obj->pDisplayBuf888;
APP_PRINTF("copied bmp buffer to input_data of gstreamer\n");
appCodecInit_usbCam(gst_cmd_params);
And Go to 'appCodecInit_usbCam', then
int32_t appGstInit_usbCam(app_codec_wrapper_params_t* params)
{
int32_t status = 0;
app_gst_wrapper_obj_t* p_gst_pipe_obj = &g_app_gst_wrapper_obj;
p_gst_pipe_obj->input_file = (gchar *)params->input_data_camera;
printf("gst_wrapper: inputdata transform!\n");
p_gst_pipe_obj->m_pipeline = NULL;
/* GStreamer INIT */
gst_init(NULL, NULL);
printf("gst_wrapper: gst_init!\n");
p_gst_pipe_obj->m_pipeline = gst_pipeline_new("pipeline");
printf("gst_wrapper: new pipeline!\n");
p_gst_pipe_obj->m_source = gst_element_factory_make("appsrc", "source");
printf("gst_wrapper: appsrc!\n");
p_gst_pipe_obj->m_converter = gst_element_factory_make("videoconvert", "conv");
printf("gst_wrapper: videoconvert!\n");
p_gst_pipe_obj->m_sink = gst_element_factory_make("udpsink", "videosink");
p_gst_pipe_obj->m_encoder = gst_element_factory_make("x264enc", "encode_h264");
p_gst_pipe_obj->m_payloader = gst_element_factory_make("rtph264pay", "rtph264pay");
printf("gst_wrapper: gst_init parameter set!\n");
if (!isValidIpAddress (IP_ADDRESS)) {
printf ("gst_wrapper: IP is not valid\n");
status = -1;
}
p_gst_pipe_obj->ip_address = IP_ADDRESS;
if (setup_pipeline(p_gst_pipe_obj) !=TRUE)
{
printf("gst_wrapper: setup_pipeline failed!!!!!!!!!");
gst_object_unref(p_gst_pipe_obj->m_pipeline);
status = -1;
}
GstBus *bus;
/* set element properties */
printf("gst_wrapper: set_element_properties FINISHED!!!!\n");
p_gst_pipe_obj->m_loop = g_main_loop_new(NULL,FALSE);
printf("gst_wrapper: main loop make finished.\n");
bus = gst_pipeline_get_bus(GST_PIPELINE(p_gst_pipe_obj->m_pipeline));
printf("gst_wrapper: pipeline get bus finished.\n");
gst_bus_add_watch(bus, bus_call, p_gst_pipe_obj->m_loop);
gst_object_unref(bus);
printf("gst_wrapper: bus added watch.\n");
printf("gst_wrapper: Now Streaming Ready........\n");
return status;
}
And in 'setup_pipeline',
int setup_pipeline (app_gst_wrapper_obj_t *data)
{
/* set element properties */
printf("gst_wrapper: set_element_properties start!!!!\n");
g_object_set (G_OBJECT (data->m_source),"stream-type",0,"is-live",TRUE,"format",GST_FORMAT_TIME, NULL);
printf("gst_wrapper: setting types of [m_source]\n");
g_object_set (G_OBJECT (data->m_source), "caps", gst_caps_new_simple("video/x-raw","format",G_TYPE_STRING,"RGB","width",G_TYPE_INT,1280,"height",G_TYPE_INT,720,"framerate",GST_TYPE_FRACTION,0,1,NULL), NULL);
printf("gst_wrapper: setting properties of [m_source]\n");
g_signal_connect_data(G_OBJECT(data->m_source), "need-data", G_CALLBACK(start_feed), &data, NULL, 0);
g_signal_connect_data(G_OBJECT(data->m_source), "enough-data", G_CALLBACK(stop_feed), &data, NULL, 0);
g_object_set (G_OBJECT (data->m_sink),"host","192.168.105.101","port",8887,NULL);
printf("gst_wrapper: setting properties of [m_sink]\n");
g_object_set (G_OBJECT (data->m_payloader), "config-interval", 60, NULL);
printf("gst_wrapper: setting properties of [m_payloader]\n");
/* Add the elements into the pipeline and link them together */
gst_bin_add_many (GST_BIN (data->m_pipeline), data->m_source, data->m_converter, data->m_encoder, data->m_payloader, data->m_sink, NULL);
printf("gst_wrapper: ADD bin GST FINISHED!!!!\n");
if (gst_element_link_many (data->m_source, data->m_converter, data->m_encoder, data->m_payloader, data->m_sink, NULL) != TRUE) {
g_printerr ("Elements could not be linked.\n");
return FALSE;
}
return TRUE;
}
In g_signal_connect_data, 'start_feed' & 'stop_feed' callbacks are composed like below.
static void start_feed (GstElement *source, guint size, app_gst_wrapper_obj_t *data) {
if (data->sourceid == 0) {
g_print ("Start feeding\n");
data->sourceid = g_idle_add ((GSourceFunc) cb_need_data, data);
}
}
static void stop_feed (GstElement *source, app_gst_wrapper_obj_t *data) {
if (data->sourceid != 0) {
g_print ("Stop feeding\n");
g_source_remove (data->sourceid);
data->sourceid = 0;
}
}
And the 'cb_need_data' function is like below.
static void cb_need_data (app_gst_wrapper_obj_t *data)
{
//static gboolean white = FALSE;
static GstClockTime timestamp = 0;
GstBuffer *buffer;
guint size,height,width,channels;
GstFlowReturn ret;
guchar *data1;
GstMapInfo map;
height = 720;
width = 1280;
channels = 3;
data1 = (guchar *)data->input_file;
size = height*width*channels;
buffer = gst_buffer_new_allocate (NULL, size, NULL);
gst_buffer_map (buffer, &map, GST_MAP_READ);
memcpy( (guchar *)map.data, data1, size );
gst_buffer_unmap(buffer, &map);
GST_BUFFER_PTS (buffer) = timestamp;
GST_BUFFER_DURATION (buffer) = gst_util_uint64_scale_int (1, GST_SECOND, 2);
timestamp += GST_BUFFER_DURATION (buffer);
g_signal_emit_by_name (data->m_source, "push-buffer", buffer, &ret);
//ret = gst_app_src_push_buffer(GST_APP_SRC(appsrc),buffer);
gst_buffer_unref(buffer);
if (ret!=GST_FLOW_OK)
{
printf("source push buffer has somthing WRONG [ %d ]@@@@ \n",ret);
}
}