Hello, we have found an issue with gstreamer plugin nvjpegenc when using NV12 as the input format. In our application we have a need to dynamically change the resolution being encoded so we are feeding nvjpegenc via nvvidconv, the resolution being set by a capsfilter. To change resolution we NULL the pipeline, change the caps and then set the pipeline playing again. When going from a smaller to a larger resolution this works fine, but going from larger to smaller results in the top left of the larger image instead of the whole frame. This only seems to affect NV12 format, it works fine with I420. Also if we use nvv4l2h264enc this works fine with either format.
Below is a minimal application that shows the issue. It firstly encodes to 640x480, waits 10 seconds, switches to 1280x720, waits 10 seconds, switches back to 640x480, waits another 10 seconds then exits. There are commented out options to switch format and/or codec. Output is via RTP over UDP. After the listing are two .sdp files that can be used to play the streams using vlc.
#include <gst/gst.h>
#define DEST_IP_ADDRESS "192.168.1.58"
#define DEST_PORT 5678
#define TEN_SECONDS 10000000
#define FORMAT "NV12"
//#define FORMAT "I420"
//#define CODEC_H264
#ifdef CODEC_H264
#define CODEC "H264"
#else
#define CODEC "MJPEG"
#endif
int main(int argc, char **argv)
{
GstElement *pipeline;
GstElement *videotestsrc;
GstElement *capsfilter;
GstElement *nvvidconv;
GstElement *nvenc;
GstElement *rtppay;
GstElement *udpsink;
GstCaps *caps_640_480;
GstCaps *caps_1280_720;
gst_init(&argc, &argv);
caps_640_480 = gst_caps_new_simple("video/x-raw",
"format", G_TYPE_STRING, FORMAT,
"width", G_TYPE_INT, 640, "height", G_TYPE_INT, 480, NULL);
caps_1280_720 = gst_caps_new_simple("video/x-raw",
"format", G_TYPE_STRING, FORMAT,
"width", G_TYPE_INT, 1280, "height", G_TYPE_INT, 720, NULL);
pipeline = gst_pipeline_new(NULL);
videotestsrc = gst_element_factory_make("videotestsrc", NULL);
capsfilter = gst_element_factory_make("capsfilter", NULL);
nvvidconv = gst_element_factory_make("nvvidconv", NULL);
#ifdef CODEC_H264
nvenc = gst_element_factory_make("nvv4l2h264enc", NULL);
rtppay = gst_element_factory_make("rtph264pay", NULL);
#else
nvenc = gst_element_factory_make("nvjpegenc", NULL);
rtppay = gst_element_factory_make("rtpjpegpay", NULL);
#endif
udpsink = gst_element_factory_make("udpsink", NULL);
gst_bin_add_many(GST_BIN(pipeline), videotestsrc, capsfilter,
nvvidconv, nvenc, rtppay, udpsink, NULL);
gst_element_link_many(videotestsrc, capsfilter, nvvidconv,
nvenc, rtppay, udpsink, NULL);
#ifdef CODEC_H264
g_object_set(nvenc, "idrinterval", 10, "insert-sps-pps", TRUE, NULL);
#endif
g_object_set(udpsink, "host", DEST_IP_ADDRESS, "port", DEST_PORT, NULL);
g_print("Codec: %s, Format: %s, Resolution: 640 x 480\n", CODEC, FORMAT);
g_object_set(capsfilter, "caps", caps_640_480, NULL);
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_usleep(TEN_SECONDS);
gst_element_set_state(pipeline, GST_STATE_NULL);
g_print("Codec: %s, Format: %s, Resolution: 1280 x 720\n", CODEC, FORMAT);
g_object_set(capsfilter, "caps", caps_1280_720, NULL);
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_usleep(TEN_SECONDS);
gst_element_set_state(pipeline, GST_STATE_NULL);
g_print("Codec: %s, Format: %s, Resolution: 640 x 480\n", CODEC, FORMAT);
g_object_set(capsfilter, "caps", caps_640_480, NULL);
gst_element_set_state(pipeline, GST_STATE_PLAYING);
g_usleep(TEN_SECONDS);
gst_element_set_state(pipeline, GST_STATE_NULL);
gst_object_unref(pipeline);
return 0;
}
SDP file for MJPEG playback:
c=IN IP4 192.168.1.71
m=video 5678 RTP/AVP 26
a=rtpmap:26 JPEG/90000
SDP file for H264 playback:
c=IN IP4 192.168.1.71
m=video 5678 RTP/AVP 96
a=rtpmap:96 H264/90000
Best regards,
Howard