Determining correct frame format in libuvc - macos

I'm trying to connect to a UVC compatible camera on OS X. Using the hello world example from libuvc, my camera outputs this:
DEVICE CONFIGURATION (2560:c114/39254404) ---
Status: idle
VideoControl:
bcdUVC: 0x0100
VideoStreaming(1):
bEndpointAddress: 131
Formats:
UncompressedFormat(1)
bits per pixel: 16
GUID: 5931362000001000800000aa00389b71
default frame: 1
aspect ration: 0x0
interlace flags: 00
copy protect: 00
FrameDescriptor(1)
capabilities: 00
size: 752x480
bit rate: 346521600-346521600
max frame size: 721920
default interval: 1/60
interval[0]: 1/60
interval[1]: 1/30
FrameDescriptor(2)
capabilities: 00
size: 640x480
bit rate: 294912000-294912000
max frame size: 614400
default interval: 1/60
interval[0]: 1/60
interval[1]: 1/30
FrameDescriptor(3)
capabilities: 00
size: 320x240
bit rate: 73728000-73728000
max frame size: 153600
default interval: 1/60
interval[0]: 1/60
UncompressedFormat(2)
bits per pixel: 24
GUID: 7deb36e44f52ce119f530020af0ba770
default frame: 1
aspect ration: 0x0
interlace flags: 00
copy protect: 00
FrameDescriptor(1)
capabilities: 00
size: 752x480
bit rate: 519782400-519782400
max frame size: 1082880
default interval: 1/60
interval[0]: 1/60
interval[1]: 1/30
FrameDescriptor(2)
capabilities: 00
size: 640x480
bit rate: 442368000-442368000
max frame size: 921600
default interval: 1/60
interval[0]: 1/60
interval[1]: 1/30
FrameDescriptor(3)
capabilities: 00
size: 320x240
bit rate: 110592000-110592000
max frame size: 230400
default interval: 1/60
interval[0]: 1/60
END DEVICE CONFIGURATION
However none of the frame formats seem to work, i.e.
res = uvc_get_stream_ctrl_format_size(
devh, &ctrl,
UVC_FRAME_FORMAT_YUYV,
752, 480, 60 /* width, height, fps */
);
Whatever frame format I try (I tried looping over the enum) I get something like this:
UVC initialized
Device found
Device opened
get_mode: Invalid mode (-51)
Device closed
UVC exited
The camera works fine in Windows and in Linux under ROS. What frame format should I use? Given the configuration, I hoped UVC_FRAME_FORMAT_RGB would work, but no dice. The code for libuvc seems to compare the UVC frame format to what the device provided, but I don't understand how it determines what's a valid format.

You have to use
const uvc_format_desc_t *uvc_get_format_descs(uvc_device_handle_t* )
The returned pointer to uvc_format_desc_t will contain the first available format that is valid for the given camera. You can then iterate through all possible formats with the next pointer in uvc_format_desc_t.
frame_descs in uvc_format_desc_t contains width height etc.
bDescriptorSubtype in uvc_format_desc_t contains the format e.g. UVC_VS_FORMAT_UNCOMPRESSED

Related

X11 (xorg) fails to set/change resolution (linux x86)

I'm trying to get a 10-inch touch display (native resolution: 1280x800) to switch to 1024x768, but everything I try is either ignored or results in an error. The display reportedly supports the resolution, though, xrandr --verbose reports (I'm using the default VESA driver):
xrandr: Failed to get size of gamma for output default
Screen 0: minimum 640 x 480, current 640 x 480, maximum 1280 x 800
default connected 640x480+0+0 (0x180) normal (normal) 0mm x 0mm
Identifier: 0x17d
Timestamp: 635022581
Subpixel: horizontal rgb
Clones:
CRTC: 0
CRTCs: 0
Transform: 1.000000 0.000000 0.000000
0.000000 1.000000 0.000000
0.000000 0.000000 1.000000
filter:
1280x800 (0x17e) 0.0MHz
h: width 1280 start 0 end 0 total 1280 skew 0 clock 0.0KHz
v: height 800 start 0 end 0 total 800 clock 0.0Hz
800x600 (0x17f) 0.0MHz
h: width 800 start 0 end 0 total 800 skew 0 clock 0.0KHz
v: height 600 start 0 end 0 total 600 clock 0.0Hz
640x480 (0x180) 0.0MHz *current
h: width 640 start 0 end 0 total 640 skew 0 clock 0.0KHz
v: height 480 start 0 end 0 total 480 clock 0.0Hz
1024x768 (0x181) 0.0MHz
h: width 1024 start 0 end 0 total 1024 skew 0 clock 0.0KHz
v: height 768 start 0 end 0 total 768 clock 0.0Hz
If I try to change the resolution via xrandr --output default --mode 1027x768, i just get:
xrandr: Failed to get size of gamma for output default
xrandr: Configure crtc 0 failed
As far as I can see, only the second line is relevant to my problem; I don't know why xrandr would want to configre crtc 0, though, I only have the touch screen connected.
Failing that, I tried to configure the mode directly using the following xorg.conf:
Section "InputClass"
Identifier "calibration"
MatchProduct "DIALOGUE INC PenMount USB"
Option "Calibration" "95 911 93 919"
Option "SwapAxes" "0"
EndSection
Section "Monitor"
Identifier "disp0"
Modeline "1024x768_60.00" 63.50 1024 1072 1176 1328 768 771 775 798 -hsync +vsync
Option "PreferredMode" "1024x768_60.00"
EndSection
Section "Device"
Identifier "card0"
Driver "vesa"
EndSection
Section "Screen"
Identifier "src0"
Device "card0"
Monitor "disp0"
SubSection "Display"
Modes "1024x768_60.00" "1024x768"
EndSubSection
EndSection
Unfortunately, This doesn't work, either Xorg.log shows the following:
[634043.694] (II) VESA(0): Not using mode "1024x768_60.00" (no mode of this name)
[634043.694] (II) VESA(0): Not using built-in mode "1024x768" (no mode of this name)
Why doesn't this work? And what else can I try to get the display to switch to 1024x768?
I've uploaded the full logfile to Pastebin.
You can try to perform the following actions
cvt -r 1024 768
xrandr --newmode "1024x768_60.00" 63.50 1024 1072 1176 1328 768 771 775 798 -hsync +vsync
xrandr --addmode default 1024x768_60.00
xrandr --output default --mode 1024x768_60.00

Why does every encoded frame's size increase after I had use to set one frame to be key in intel qsv of ffmpeg

I used intel's qsv to encode h264 video in ffmpeg. My av codec context settings is like as below:
m_ctx->width = m_width;
m_ctx->height = m_height;
m_ctx->time_base = { 1, (int)fps };
m_ctx->qmin = 10;
m_ctx->qmax = 35;
m_ctx->gop_size = 3000;
m_ctx->max_b_frames = 0;
m_ctx->has_b_frames = false;
m_ctx->refs = 2;
m_ctx->slices = 0;
m_ctx->codec_id = m_encoder->id;
m_ctx->codec_type = AVMEDIA_TYPE_VIDEO;
m_ctx->pix_fmt = m_h264InputFormat;
m_ctx->compression_level = 4;
m_ctx->flags &= ~AV_CODEC_FLAG_CLOSED_GOP;
AVDictionary *param = nullptr;
av_dict_set(&param, "idr_interval", "0", 0);
av_dict_set(&param, "async_depth", "1", 0);
av_dict_set(&param, "forced_idr", "1", 0);
and in the encoding, I set the AVFrame to be AV_PICTURE_TYPE_I when key frame is needed:
if(key_frame){
encodeFrame->pict_type = AV_PICTURE_TYPE_I;
}else{
encodeFrame->pict_type = AV_PICTURE_TYPE_NONE;
}
avcodec_send_frame(m_ctx, encodeFrame);
avcodec_receive_packet(m_ctx, m_packet);
std::cerr<<"packet size is "<<m_packet->size<<",is key frame "<<key_frame<<std::endl;
The strange phenomenon is that if I had set one frame to AV_PICTURE_TYPE_I, then every encoded frame's size after the key frame would increase. If I change the h264 encoder to x264, then it's ok.
The packet size is as below before I call "encodeFrame->pict_type = AV_PICTURE_TYPE_I":
packet size is 26839
packet size is 2766
packet size is 2794
packet size is 2193
packet size is 1820
packet size is 2542
packet size is 2024
packet size is 1692
packet size is 2095
packet size is 2550
packet size is 1685
packet size is 1800
packet size is 2276
packet size is 1813
packet size is 2206
packet size is 2745
packet size is 2334
packet size is 2623
packet size is 2055
If I call "encodeFrame->pict_type = AV_PICTURE_TYPE_I", then the packet size is as below:
packet size is 23720,is key frame 1
packet size is 23771,is key frame 0
packet size is 23738,is key frame 0
packet size is 23752,is key frame 0
packet size is 23771,is key frame 0
packet size is 23763,is key frame 0
packet size is 23715,is key frame 0
packet size is 23686,is key frame 0
packet size is 23829,is key frame 0
packet size is 23774,is key frame 0
packet size is 23850,is key frame 0
FFMPEG doesn't reset the mfxEncodeCtrl's FrameType when encoding the next frame, it causes every frame after key frame to be IDR frame

animated webp only has key frame?

i want to cover a mp4 to animated webp, so i use ffmpeg command:
mp4 file is http://myvideodata.oss-cn-shenzhen.aliyuncs.com/crs_bcb3f246273d4dbb8ec7f93239fbea6e.mp4
ffmpeg -i ./test.mp4 ./test.webp
it is ok, and animated webp has been created, so i use webpinfo tool (download from https://developers.google.com/speed/webp/download and build example in it, or use this one http://myvideodata.oss-cn-shenzhen.aliyuncs.com/webpInfo)
./webinfo ./test.webp
and get information like this
RIFF HEADER:
File size: 1968244
Chunk VP8X at offset 12, length 18
ICCP: 0
Alpha: 1
EXIF: 0
XMP: 0
Animation: 1
Canvas size 362 x 330
Chunk ANIM at offset 30, length 14
Background color:(ARGB) ff ff ff ff
Loop count : 1
Chunk ANMF at offset 44, length 25116
Offset_X: 0
Offset_Y: 0
Width: 362
Height: 330
Duration: 42
Dispose: 0
Blend: 0
Chunk VP8 at offset 68, length 25092
Width: 362
Height: 330
Alpha: 0
Animation: 0
Format: Lossy (1)
every frame size is about 25k, my question is: all frames in animated webp are key frames?
can any one help
Yes, all frames are marked as key frames by the libwebp_anim encoder.

CGDisplayModeGetWidth/Height() sometimes returns pixels, sometimes points

According to Apple, both CGDisplayModeGetWidth() and CGDisplayModeGetHeight() should return points instead of pixels starting in macOS 10.8. But Apple's word on those APIs isn't consistent because here they say that the functions return pixels and not points.
This confusion is also reflected in practice because both functions only seem to return points sometimes, not all the time. Sometimes they also return pixels. Consider this example:
CGDirectDisplayID id = CGMainDisplayID();
CFArrayRef modes = CGDisplayCopyAllDisplayModes(id, NULL);
CGDisplayModeRef mode;
int c = 0, k, n;
n = CFArrayGetCount(modes);
for(k = 0; k < n; k++) {
mode = (CGDisplayModeRef) CFArrayGetValueAtIndex(modes, k);
printf("GOT SIZE: %d %d\n", (int) CGDisplayModeGetWidth(mode), (int) CGDisplayModeGetHeight(mode));
}
CFRelease(modes);
The code iterates over all available screen modes. In this example, the output is in pixels.
When using this code, however, the output is in points:
CGDirectDisplayID id = CGMainDisplayID();
mode = CGDisplayCopyDisplayMode(id);
printf("NEW GOT SIZE: %d %d\n", (int) CGDisplayModeGetWidth(mode), (int) CGDisplayModeGetHeight(mode));
CGDisplayModeRelease(mode);
But why? Why do CGDisplayModeGetWidth() and CGDisplayModeGetHeight() return pixels in the first code snippet and points in the second? This is confusing me.
To make things even more complicated, starting with macOS 10.8 there are two new APIs, namely CGDisplayModeGetPixelWidth() and CGDisplayModeGetPixelHeight(). These always return pixels, but I still don't understand why CGDisplayModeGetWidth() and CGDisplayModeGetHeight() return pixels in the first code snippet above... is this a bug?
EDIT
Here is the output for my 1680x1050 monitor. I am using Quartz Debug to put the monitor in 840x525 screen mode to do Retina tests. You can see that the output of the first code snippet must be in pixels because it returns modes such as 1680x1050 which would correspond to 3360x2100 pixels if it were points. Another proof that the first code snippet returns pixels not points lies in the fact that the screen mode the monitor is currently in (i.e. 840x525) isn't returned at all. Only the second code snippet returns this mode.
GOT SIZE: 1680 1050
GOT SIZE: 1152 870
GOT SIZE: 1280 1024
GOT SIZE: 1024 768
GOT SIZE: 1024 768
GOT SIZE: 1024 768
GOT SIZE: 832 624
GOT SIZE: 800 600
GOT SIZE: 800 600
GOT SIZE: 800 600
GOT SIZE: 800 600
GOT SIZE: 640 480
GOT SIZE: 640 480
GOT SIZE: 640 480
GOT SIZE: 640 480
GOT SIZE: 1280 1024
GOT SIZE: 1280 960
GOT SIZE: 848 480
GOT SIZE: 1280 960
GOT SIZE: 1360 768
GOT SIZE: 800 500
GOT SIZE: 1024 640
GOT SIZE: 1280 800
GOT SIZE: 1344 1008
GOT SIZE: 1344 840
GOT SIZE: 1600 1000
--------------------------
NEW GOT SIZE: 840 525

Why are my JPEG files larger than expected?

gm convert +profile "*" -resize 800x800 -quality 90.0 -background white -flatten test.jpg test01.jpg
the test01.jpg file size is 140262, but the test.jpg file size is 114698, I think the test01.jpg file is less than test.jpg, why?
gm identify -verbose test.jpg command info:
Image: test.jpg
Format: JPEG (Joint Photographic Experts Group JFIF format)
Geometry: 960x1280
Class: DirectClass
Type: true color
Depth: 8 bits-per-pixel component
Channel Depths:
Red: 8 bits
Green: 8 bits
Blue: 8 bits
Channel Statistics:
Red:
Minimum: 0.00 (0.0000)
Maximum: 255.00 (1.0000)
Mean: 158.69 (0.6223)
Standard Deviation: 74.34 (0.2915)
Green:
Minimum: 0.00 (0.0000)
Maximum: 255.00 (1.0000)
Mean: 142.36 (0.5583)
Standard Deviation: 72.48 (0.2842)
Blue:
Minimum: 0.00 (0.0000)
Maximum: 255.00 (1.0000)
Mean: 105.80 (0.4149)
Standard Deviation: 73.05 (0.2865)
Resolution: 72x72 pixels
Filesize: 112.0Ki
Interlace: No
Orientation: TopLeft
Background Color: white
Border Color: #DFDFDF
Matte Color: #BDBDBD
Page geometry: 960x1280+0+0
Compose: Over
Dispose: Undefined
Iterations: 0
Compression: JPEG
JPEG-Quality: 64
JPEG-Colorspace: 2
JPEG-Colorspace-Name: RGB
JPEG-Sampling-factors: 2x2,1x1,1x1
Signature: ea09bde85095c8c8b2345e5301d581a8002490ecfefa63ae81c0cb14b8c2fbf8
Profile-iptc: 40 bytes
Profile-EXIF: 86 bytes
Orientation: 1
Exif Offset: 38
Color Space: 1
Exif Image Width: 960
Exif Image Length: 1280
Tainted: False
User Time: 0.020u
Elapsed Time: 0:01
Pixels Per Second: 39.1Mi
According to the "identify" output that you presented for the input image "test.jpg", the JPEG quality was estimated to be 64. You requested quality 90 for your output image.
Higher quality means bigger filesize. The increase in quality from 64 to 90 doesn't actually improve the visual quality of the image; it only forces the compressor to faithfully reproduce the compression artifacts in the input image.

Resources