Motion - Support Question 2011x 01x 09x 193606

mjpeg with uvcvideo cam logitech HDPro C910

Question

Hi, I am running into trouble with this camera in mjpeg mode: v4l2_palette 2 although YUYV works fine but the framerate is too low for the later (10 fps instead of 30 in mjpeg). This camera uses uvcvideo and luvcview works perfectly in all modes and even more (see box below). I get grey screen in mjpeg mode with motion 3, and I output below the debug messages. Any help would be welcome. Ah, yes, I am indeed running motion in full HD, that's for getting nice snapshots of birds passing in front of my window smile

Cheers, Chris.

motion -n -d 100 
[0] Processing thread 0 - config file /etc/motion.conf
[0] Motion 3.2.12 Started
[0] ffmpeg LIBAVCODEC_BUILD 3426306 LIBAVFORMAT_BUILD 3424258
[0] Thread 1 is from /etc/motion.conf
[1] Thread 1 started
[0] motion-httpd/3.2.12 running, accepting connections
[0] motion-httpd: waiting for data on port TCP 8080
[1] cap.driver: "uvcvideo"
[1] cap.card: "UVC Camera (046d:0821)"
[1] cap.bus_info: "usb-0000:00:1d.7-1"
[1] cap.capabilities=0x04000001
[1] - VIDEO_CAPTURE
[1] - STREAMING
[1] v4l2_select_input: name = "Camera 1", type 0x00000002, status 00000000
[1] - CAMERA
[1] Device doesn't support VIDIOC_G_STD
[1] Test palette MJPG (1920x1088)
[1] Adjusting resolution from 1920x1088 to 1920x1080.
[1] Using palette MJPG (1920x1080) bytesperlines 0 sizeimage 4147200 colorspace 00000008
[1] found control 0x00980900, "Brightness", range 0,255 
[1]     "Brightness", default 128, current 128
[1] found control 0x00980901, "Contrast", range 0,255 
[1]     "Contrast", default 32, current 32
[1] found control 0x00980902, "Saturation", range 0,255 
[1]     "Saturation", default 32, current 32
[1] found control 0x00980913, "Gain", range 0,255 
[1]     "Gain", default 64, current 64
[1] mmap information:
[1] frames=4
[1] 0 length=4147200
[1] 1 length=4147200
[1] 2 length=4147200
[1] 3 length=4147200
[1] Using V4L2
[1] Resizing pre_capture buffer to 1 items
Corrupt JPEG data: 1 extraneous bytes before marker 0xd1
[1] mjpegtoyuv420p: Corrupt image ... continue
[0] DEBUG-2 threads_running 1 motion_threads_running 1 , finish 0
[0] DEBUG-2 threads_running 1 motion_threads_running 1 , finish 0
Corrupt JPEG data: 1 extraneous bytes before marker 0xd0
[1] mjpegtoyuv420p: Corrupt image ... continue
[0] DEBUG-2 threads_running 1 motion_threads_running 1 , finish 0
[0] DEBUG-2 threads_running 1 motion_threads_running 1 , finish 0
Corrupt JPEG data: 3 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[0] DEBUG-2 threads_running 1 motion_threads_running 1 , finish 0
[0] DEBUG-2 threads_running 1 motion_threads_running 1 , finish 0
Corrupt JPEG data: 1 extraneous bytes before marker 0xd4
[1] mjpegtoyuv420p: Corrupt image ... continue
[0] DEBUG-2 threads_running 1 motion_threads_running 1 , finish 0
[0] DEBUG-2 threads_running 1 motion_threads_running 1 , finish 0
Corrupt JPEG data: 1 extraneous bytes before marker 0xd6
[1] mjpegtoyuv420p: Corrupt image ... continue
[0] DEBUG-2 threads_running 1 motion_threads_running 1 , finish 0
[0] DEBUG-2 threads_running 1 motion_threads_running 1 , finish 0
[1] Error capturing first image
[1] Started stream webcam server in port 8081
Corrupt JPEG data: 3 extraneous bytes before marker 0xd1
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd0
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 4 extraneous bytes before marker 0xd4
[0] DEBUG-2 threads_running 1 motion_threads_running 1 , finish 0
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 4 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd5
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd6
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd0
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd6
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 2 extraneous bytes before marker 0xd3
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 2 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd1
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd6
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 2 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 2 extraneous bytes before marker 0xd5
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 2 extraneous bytes before marker 0xd4
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 3 extraneous bytes before marker 0xd3
[0] DEBUG-2 threads_running 1 motion_threads_running 1 , finish 0
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd0
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 2 extraneous bytes before marker 0xd1
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 3 extraneous bytes before marker 0xd6
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd0
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd7
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 2 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 2 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd1
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 3 extraneous bytes before marker 0xd7
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd0
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 2 extraneous bytes before marker 0xd6
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd7
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 2 extraneous bytes before marker 0xd1
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 2 extraneous bytes before marker 0xd5
[0] DEBUG-2 threads_running 1 motion_threads_running 1 , finish 0
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd5
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd4
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd5
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd0
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 2 extraneous bytes before marker 0xd5
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 3 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 2 extraneous bytes before marker 0xd4
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd5
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd7
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 5 extraneous bytes before marker 0xd0
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd6
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 3 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd4
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd7
[0] DEBUG-2 threads_running 1 motion_threads_running 1 , finish 0
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd3
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd7
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd3
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd0
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 3 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd5
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd6
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd3
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd1
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd1
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 2 extraneous bytes before marker 0xd6
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 2 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 1 extraneous bytes before marker 0xd5
[0] DEBUG-2 threads_running 1 motion_threads_running 1 , finish 0
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
Corrupt JPEG data: 2 extraneous bytes before marker 0xd2
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
^CCorrupt JPEG data: 2 extraneous bytes before marker 0xd0
[1] mjpegtoyuv420p: Corrupt image ... continue
[1] vid_return_code 2
[1] Thread exiting
[1] Calling vid_close() from motion_cleanup
[1] Closing video device /dev/video0
[0] DEBUG-1 threads_running 0 motion_threads_running 0 , finish 1
[0] httpd - Finishing
[0] httpd Closing
[0] httpd thread exit
[0] Motion terminating


++++++++++++++++++++++++++++++++++++++++


Here the output of luvcview -L listing all possible modes.

 luvcview -L
luvcview 0.2.6

SDL information:
  Video driver: x11
  A window manager is available
Device information:
  Device path:  /dev/video0
/dev/video0 does not support read i/o
{ pixelformat = 'YUYV', description = 'YUV 4:2:2 (YUYV)' }
{ discrete: width = 640, height = 480 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 160, height = 120 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 176, height = 144 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 320, height = 176 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 320, height = 240 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 432, height = 240 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 352, height = 288 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 544, height = 288 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 640, height = 360 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 752, height = 416 }
        Time interval between frame: 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 800, height = 448 }
        Time interval between frame: 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 864, height = 480 }
        Time interval between frame: 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 960, height = 544 }
        Time interval between frame: 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 1024, height = 576 }
        Time interval between frame: 1/10, 2/15, 1/5, 
{ discrete: width = 800, height = 600 }
        Time interval between frame: 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 1184, height = 656 }
        Time interval between frame: 1/10, 2/15, 1/5, 
{ discrete: width = 960, height = 720 }
        Time interval between frame: 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 1280, height = 720 }
        Time interval between frame: 1/10, 2/15, 1/5, 
{ discrete: width = 1392, height = 768 }
        Time interval between frame: 2/15, 1/5, 
{ discrete: width = 1504, height = 832 }
        Time interval between frame: 1/5, 
{ discrete: width = 1600, height = 896 }
        Time interval between frame: 1/5, 
{ discrete: width = 1280, height = 960 }
        Time interval between frame: 1/5, 
{ discrete: width = 1712, height = 960 }
        Time interval between frame: 1/5, 
{ discrete: width = 1792, height = 1008 }
        Time interval between frame: 1/5, 
{ discrete: width = 1920, height = 1080 }
        Time interval between frame: 1/2, 
{ discrete: width = 1600, height = 1200 }
        Time interval between frame: 1/2, 
{ discrete: width = 2048, height = 1536 }
        Time interval between frame: 1/2, 
{ discrete: width = 2592, height = 1944 }
        Time interval between frame: 1/2, 
{ pixelformat = 'MJPG', description = 'MJPEG' }
{ discrete: width = 640, height = 480 }
        Time interval between frame: 1/60, 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 160, height = 120 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 176, height = 144 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 320, height = 176 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 320, height = 240 }
        Time interval between frame: 1/60, 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 432, height = 240 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 352, height = 288 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 544, height = 288 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 640, height = 360 }
        Time interval between frame: 1/60, 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 752, height = 416 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 800, height = 448 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 864, height = 480 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 960, height = 544 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 1024, height = 576 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 800, height = 600 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 1184, height = 656 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 960, height = 720 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 1280, height = 720 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 1392, height = 768 }
        Time interval between frame: 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 1504, height = 832 }
        Time interval between frame: 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 1600, height = 896 }
        Time interval between frame: 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 1280, height = 960 }
        Time interval between frame: 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 1712, height = 960 }
        Time interval between frame: 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 1792, height = 1008 }
        Time interval between frame: 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 1920, height = 1080 }
        Time interval between frame: 1/30, 1/24, 1/20, 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 1600, height = 1200 }
        Time interval between frame: 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 2048, height = 1536 }
        Time interval between frame: 1/15, 1/10, 2/15, 1/5, 
{ discrete: width = 2592, height = 1944 }
        Time interval between frame: 1/10, 2/15, 1/5, 


Environment

Motion version: 3.2.12
ffmpeg version: 0.6.1
Libraries: ffmpeg, mysql, postgresql
Server OS: mandriva, kernel 2.6.37
-- EmmettBrown - 09 Jan 2011

Answer

This happens, because motion detects some junk in JPEG frames and discards frames with warnings. A code change is required to workaround this issue:

diff --git a/video_common.c b/video_common.c
index 54569c6..f98154f 100644
--- a/video_common.c
+++ b/video_common.c
@@ -394,7 +394,7 @@ int mjpegtoyuv420p(unsigned char *map, unsigned char *cap_map, int width, int he
 
     if (ret == 1) {
         MOTION_LOG(CRT, TYPE_VIDEO, NO_ERRNO, "%s: Corrupt image ... continue");
-        ret = 2;
+        ret = 0;
     }
     return ret;
 }

This issue was reported to development

-- TosiaraT - 12 Apr 2015
Topic revision: r2 - 12 Apr 2015, TosiaraT
Copyright © 1999-2017 by the contributing authors. All material on this collaboration platform is the property of the contributing authors.
Please do not email Kenneth for support questions (read why). Use the Support Requests page or join the Mailing List.
This website only use harmless session cookies. See Cookie Policy for details. By using this website you accept the use of these cookies.