Skip to content

Commit

Permalink
Revise framerate negotiation.
Browse files Browse the repository at this point in the history
Remove unused function.
  • Loading branch information
nickel110 committed Mar 4, 2023
1 parent 0c2bd3d commit 2914a3e
Show file tree
Hide file tree
Showing 4 changed files with 92 additions and 89 deletions.
113 changes: 67 additions & 46 deletions thetauvc/gstthetauvcsrc.c
Expand Up @@ -50,6 +50,20 @@

GST_DEBUG_CATEGORY_STATIC(gst_thetauvcsrc_debug_category);
#define GST_CAT_DEFAULT gst_thetauvcsrc_debug_category
#define GST_THETAUVCSRC_CAPS_TEMPLATE "video/x-h264, " \
"width = " GST_VIDEO_SIZE_RANGE ", " \
"height = " GST_VIDEO_SIZE_RANGE ", " \
"framerate = " GST_VIDEO_FPS_RANGE ", " \
"stream-format = byte-stream, " \
"alignment = nal, " \
"profile = { high, constrained-baseline }"
#define GST_THETAUVCSRC_CAPS_BASE "video/x-h264, " \
"width = 3840, " \
"height = 1920, " \
"framerate = 30/1, " \
"stream-format = byte-stream, " \
"alignment = nal, " \
"profile = constrained-baseline"

/* prototypes */

Expand Down Expand Up @@ -111,24 +125,8 @@ gst_thetauvcsrc_class_init(GstThetauvcsrcClass * klass)

/* Setting up pads and setting metadata should be moved to
* base_class_init if you intend to subclass this class. */
GstCaps *caps, *c;
caps = gst_caps_new_simple("video/x-h264",
"width", G_TYPE_INT, 3840,
"height", G_TYPE_INT, 1920,
"framerate", GST_TYPE_FRACTION, 30000, 1001,
"stream-format", G_TYPE_STRING, "byte-stream",
"alignment", G_TYPE_STRING, "nal",
"profile", G_TYPE_STRING, "constrained-baseline", NULL);

c = gst_caps_copy(caps);
gst_caps_set_simple(c, "width", G_TYPE_INT, 1920, "height", G_TYPE_INT,
960, NULL);
gst_caps_append(caps, c);

c = gst_caps_copy_nth(caps, 1);
gst_caps_set_simple(c, "width", G_TYPE_INT, 1920, "height", G_TYPE_INT,
1080, "profile", G_TYPE_STRING, "high", NULL);
gst_caps_append(caps, c);
GstCaps *caps;
caps = gst_caps_from_string(GST_THETAUVCSRC_CAPS_TEMPLATE);

gst_element_class_add_pad_template(GST_ELEMENT_CLASS(klass),
gst_pad_template_new("src", GST_PAD_SRC, GST_PAD_ALWAYS, caps));
Expand Down Expand Up @@ -197,6 +195,7 @@ gst_thetauvcsrc_init(GstThetauvcsrc * thetauvcsrc)
thetauvcsrc->ctx = NULL;
thetauvcsrc->devh = NULL;
thetauvcsrc->dev = NULL;
thetauvcsrc->current_caps = NULL;
}

void
Expand Down Expand Up @@ -295,34 +294,23 @@ gst_thetauvcsrc_finalize(GObject * object)

uvc_exit(thetauvcsrc->ctx);
}
if (thetauvcsrc->current_caps != NULL)
gst_caps_unref(thetauvcsrc->current_caps);

G_OBJECT_CLASS(gst_thetauvcsrc_parent_class)->finalize(object);
}

static GstCaps *
get_current_caps(GstThetauvcsrc *src)
{
GstCaps *pcaps, *caps, *rcaps;
GstThetauvcModeEnum mode;
GstCaps *caps;

g_mutex_lock(&src->lock);
mode = src->mode;
g_mutex_unlock(&src->lock);
pcaps = gst_pad_get_pad_template_caps(GST_BASE_SRC_PAD(src));

switch (mode) {
case GST_THETAUVC_MODE_2K:
if (src->dev_pid == USBPID_THETAS_UVC)
caps = gst_caps_copy_nth(pcaps, 2);
else
caps = gst_caps_copy_nth(pcaps, 1);
break;
case GST_THETAUVC_MODE_4K:
caps = gst_caps_copy_nth(pcaps, 0);
break;
}
gst_caps_unref(pcaps);
if (src->current_caps != NULL)
caps = gst_caps_copy(src->current_caps);
else
caps = gst_pad_get_pad_template_caps(GST_BASE_SRC_PAD(src));

GST_DEBUG_OBJECT(src, "%s", gst_caps_to_string(caps));
return caps;
}

Expand All @@ -335,11 +323,7 @@ gst_thetauvcsrc_get_caps(GstBaseSrc * src, GstCaps * filter)

GST_DEBUG_OBJECT(thetauvcsrc, "get_caps");

if (thetauvcsrc->devh) {
caps = get_current_caps(thetauvcsrc);
} else {
caps = gst_pad_get_pad_template_caps(GST_BASE_SRC_PAD(thetauvcsrc));
}
caps = get_current_caps(thetauvcsrc);

if (filter) {
rcaps =
Expand All @@ -348,6 +332,8 @@ gst_thetauvcsrc_get_caps(GstBaseSrc * src, GstCaps * filter)
} else {
rcaps = caps;
}
GST_DEBUG_OBJECT(src, "filter: %s", gst_caps_to_string(filter));
GST_DEBUG_OBJECT(src, "rcaps: %s", gst_caps_to_string(rcaps));
return rcaps;
}

Expand Down Expand Up @@ -436,6 +422,39 @@ cb(uvc_frame_t * frame, void *ptr)
return;
}

static GstCaps *
thetauvcsrc_fixate_srccaps(GstThetauvcsrc *thetauvcsrc)
{
GstCaps *caps;
caps = gst_caps_from_string(GST_THETAUVCSRC_CAPS_BASE);
gst_caps_set_simple(caps, "width", G_TYPE_INT, thetauvcsrc->mode_val.width,
"height", G_TYPE_INT, thetauvcsrc->mode_val.height, NULL);

if (thetauvcsrc->dev_pid == USBPID_THETAS_UVC)
gst_caps_set_simple(caps, "profile", G_TYPE_STRING, "high", NULL);

unsigned int den, num;
den = 1001;
switch(thetauvcsrc->ctrl.dwFrameInterval) {
case 417083: /* 23.98fps */
num = 25000;
break;
case 333667: /* 29.97fps */
num = 30000;
break;
case 166833: /* 59.94fps */
num = 60000;
break;
default: /* integer framerate */
num = 10000000 / thetauvcsrc->ctrl.dwFrameInterval;
den = 1;
break;
}
gst_caps_set_simple(caps, "framerate", GST_TYPE_FRACTION, num, den, NULL);

return caps;
}

/* start and stop processing, ideal for opening/closing the resource */
static gboolean
gst_thetauvcsrc_start(GstBaseSrc * src)
Expand Down Expand Up @@ -539,23 +558,25 @@ gst_thetauvcsrc_start(GstBaseSrc * src)
switch (thetauvcsrc->mode) {
case GST_THETAUVC_MODE_2K:
if (thetauvcsrc->dev_pid == USBPID_THETAS_UVC)
mode = THETAUVC_MODE_FHD_2997S;
mode = THETAUVC_MODE_FHD_S;
else
mode = THETAUVC_MODE_FHD_2997;
mode = THETAUVC_MODE_FHD;
break;
case GST_THETAUVC_MODE_4K:
mode = THETAUVC_MODE_UHD_2997;
mode = THETAUVC_MODE_UHD;
break;
}
res = thetauvc_get_stream_ctrl_format_size(thetauvcsrc->devh,
mode, &thetauvcsrc->ctrl);
mode, &thetauvcsrc->ctrl, &thetauvcsrc->mode_val);

if (res != UVC_SUCCESS) {
GST_ELEMENT_ERROR(src, RESOURCE, OPEN_READ_WRITE,
("No available stream"), (NULL));
return FALSE;
}

thetauvcsrc->current_caps = thetauvcsrc_fixate_srccaps(thetauvcsrc);

uvc_start_streaming(thetauvcsrc->devh, &thetauvcsrc->ctrl, cb,
thetauvcsrc, 0);
thetauvcsrc->framecount = 0;
Expand Down
2 changes: 2 additions & 0 deletions thetauvc/gstthetauvcsrc.h
Expand Up @@ -58,6 +58,8 @@ struct _GstThetauvcsrc
gint device_index;
gchar *serial;
GstThetauvcModeEnum mode;
GstCaps *current_caps;
thetauvc_mode_t mode_val;

uvc_context_t *ctx;
uvc_device_t *dev;
Expand Down
48 changes: 9 additions & 39 deletions thetauvc/thetauvc.c
Expand Up @@ -38,34 +38,24 @@
#include "libuvc/libuvc.h"
#include "thetauvc.h"

struct thetauvc_mode
{
unsigned int mode;
unsigned int width;
unsigned int height;
unsigned int fps;
};

typedef struct thetauvc_mode thetauvc_mode_t;

static thetauvc_mode_t stream_mode[] = {
{
.mode = THETAUVC_MODE_UHD_2997,
.mode = THETAUVC_MODE_UHD,
.width = 3840,
.height = 1920,
.fps = 29,
.fps = 0,
},
{
.mode = THETAUVC_MODE_FHD_2997,
.mode = THETAUVC_MODE_FHD,
.width = 1920,
.height = 960,
.fps = 29,
.fps = 0,
},
{
.mode = THETAUVC_MODE_FHD_2997S,
.mode = THETAUVC_MODE_FHD_S,
.width = 1920,
.height = 1080,
.fps = 29,
.fps = 0,
},
{
.mode = THETAUVC_MODE_NUM,
Expand Down Expand Up @@ -248,7 +238,8 @@ thetauvc_find_device_by_serial(uvc_context_t * ctx, uvc_device_t ** devh,
uvc_error_t
thetauvc_get_stream_ctrl_format_size(uvc_device_handle_t * devh,
unsigned int mode,
uvc_stream_ctrl_t * ctrl)
uvc_stream_ctrl_t * ctrl,
thetauvc_mode_t *mode_val)
{
uvc_error_t res;
thetauvc_mode_t *m;
Expand All @@ -262,35 +253,14 @@ thetauvc_get_stream_ctrl_format_size(uvc_device_handle_t * devh,
m = &stream_mode[i];
}

memcpy(mode_val, m, sizeof(thetauvc_mode_t));
res = uvc_get_stream_ctrl_format_size(devh, ctrl,
UVC_FRAME_FORMAT_H264, m->width,
m->height, m->fps);

return res;
}

uvc_error_t
thetauvc_run_streaming(uvc_device_t * dev, uvc_device_handle_t ** devh,
unsigned int mode, uvc_frame_callback_t * cb,
void *pdata)
{
uvc_error_t res;
uvc_stream_ctrl_t ctrl;

res = uvc_open(dev, devh);
if (res != UVC_SUCCESS)
return res;
thetauvc_get_stream_ctrl_format_size(*devh, mode, &ctrl);
if (res != UVC_SUCCESS)
printf("error");

res = uvc_start_streaming(*devh, &ctrl, cb, pdata, 0);

uvc_close(*devh);

return UVC_SUCCESS;
}

uvc_error_t
thetauvc_switch_configuration(uint8_t bus, uint8_t addr, uint8_t ncfg)
{
Expand Down
18 changes: 14 additions & 4 deletions thetauvc/thetauvc.h
Expand Up @@ -43,20 +43,30 @@ extern "C" {
#define USBPID_THETAX_UVC 0x2717

enum thetauvc_mode_code {
THETAUVC_MODE_FHD_2997 = 0,
THETAUVC_MODE_UHD_2997,
THETAUVC_MODE_FHD_2997S,
THETAUVC_MODE_FHD = 0,
THETAUVC_MODE_UHD,
THETAUVC_MODE_FHD_S,
THETAUVC_MODE_NUM
};

struct thetauvc_mode
{
unsigned int mode;
unsigned int width;
unsigned int height;
unsigned int fps;
};

typedef struct thetauvc_mode thetauvc_mode_t;

extern uvc_error_t thetauvc_find_devices(uvc_context_t *, uvc_device_t ***);
extern uvc_error_t thetauvc_print_devices(uvc_context_t *, FILE *);
extern uvc_error_t thetauvc_find_device(uvc_context_t *, uvc_device_t **,
unsigned int);
extern uvc_error_t thetauvc_find_device_by_serial(uvc_context_t *,
uvc_device_t **, const char *);
extern uvc_error_t thetauvc_get_stream_ctrl_format_size(uvc_device_handle_t *,
unsigned int, uvc_stream_ctrl_t *);
unsigned int, uvc_stream_ctrl_t *, thetauvc_mode_t *);
extern uvc_error_t thetauvc_run_streaming(uvc_device_t *, uvc_device_handle_t **,
unsigned int, uvc_frame_callback_t *, void *);
extern uvc_error_t thetauvc_switch_configuration(uint8_t, uint8_t, uint8_t);
Expand Down

0 comments on commit 2914a3e

Please sign in to comment.