@@ -31,21 +31,30 @@ uint32_t FrameBuffer::getBufferSize() {
3131	if  (this ->vbuf ) {
3232		return  this ->vbuf ->bytesused ;
3333	}
34+ 	return  0 ;
3435}
3536
3637uint8_t  *FrameBuffer::getBuffer () {
3738	if  (this ->vbuf ) {
3839		return  this ->vbuf ->buffer ;
3940	}
41+ 	return  nullptr ;
4042}
4143
42- Camera::Camera () : vdev(NULL ), byte_swap(false ), yuv_to_gray(false ) {
44+ Camera::Camera ()
45+ 	: vdev(NULL ), byte_swap(false ), yuv_to_gray(false ),
46+ 	  snapshot_mode(CONFIG_VIDEO_BUFFER_POOL_NUM_MAX <= 1 ) {
4347	for  (size_t  i = 0 ; i < ARRAY_SIZE (this ->vbuf ); i++) {
4448		this ->vbuf [i] = NULL ;
4549	}
4650}
4751
4852bool  Camera::begin (uint32_t  width, uint32_t  height, uint32_t  pixformat, bool  byte_swap) {
53+ 	return  begin (width, height, width, height, pixformat, byte_swap);
54+ }
55+ 
56+ bool  Camera::begin (uint32_t  width, uint32_t  height, uint32_t  crop_width, uint32_t  crop_height,
57+ 				   uint32_t  pixformat, bool  byte_swap) {
4958#if  DT_HAS_CHOSEN(zephyr_camera)
5059	this ->vdev  = DEVICE_DT_GET (DT_CHOSEN (zephyr_camera));
5160#endif 
@@ -74,20 +83,21 @@ bool Camera::begin(uint32_t width, uint32_t height, uint32_t pixformat, bool byt
7483		return  false ;
7584	}
7685
77- 	for  (size_t  i = 0 ; caps.format_caps [i].pixelformat  != NULL ; i++) {
86+ 	for  (size_t  i = 0 ; caps.format_caps [i].pixelformat  != 0 ; i++) {
7887		const  struct  video_format_cap  *fcap = &caps.format_caps [i];
79- 		if  (fcap->width_min  = = width && fcap->height_min  = = height &&
80- 			fcap->pixelformat  == pixformat) {
88+ 		if  (fcap->width_min  <= width && fcap-> width_max  > = width && fcap->height_min  < = height &&
89+ 			fcap->height_max  >= height && fcap-> pixelformat  == pixformat) {
8190			break ;
8291		}
83- 		if  (caps.format_caps [i + 1 ].pixelformat  == NULL ) {
92+ 		if  (caps.format_caps [i + 1 ].pixelformat  == 0 ) {
8493			Serial.println (" The specified format is not supported" 
8594			return  false ;
8695		}
8796	}
8897
8998	//  Set format.
9099	static  struct  video_format  fmt = {
100+ 		.type  = VIDEO_BUF_TYPE_OUTPUT,
91101		.pixelformat  = pixformat,
92102		.width  = width,
93103		.height  = height,
@@ -99,6 +109,34 @@ bool Camera::begin(uint32_t width, uint32_t height, uint32_t pixformat, bool byt
99109		return  false ;
100110	}
101111
112+ 	//  optionally set the crop values
113+ 	if  (width != crop_width || height != crop_height) {
114+ 		struct  video_selection  vselCrop;
115+ 		vselCrop.type  = VIDEO_BUF_TYPE_OUTPUT;
116+ 		vselCrop.target  = VIDEO_SEL_TGT_CROP;
117+ 		vselCrop.rect .left  = (width - crop_width) / 2 ;
118+ 		vselCrop.rect .top  = (height - crop_height) / 2 ;
119+ 		vselCrop.rect .width  = crop_width;
120+ 		vselCrop.rect .height  = crop_height;
121+ 		;
122+ 
123+ 		int  ret;
124+ 		if  ((ret = setSelection (&vselCrop)) != 0 ) {
125+ 			printk (" ERROR: %d\n " 
126+ 		}
127+ 	}
128+ 	//  this should compute the sizes needed.
129+ 	video_get_format (this ->vdev , &fmt);
130+ 
131+ 	//  If we are in snapshot mode, try starting the video stream with no buffers
132+ 	//  to tell it that we want snapshot...
133+ 	if  (snapshot_mode) {
134+ 		if  (video_stream_start (this ->vdev , VIDEO_BUF_TYPE_OUTPUT)) {
135+ 			Serial.println (" Snapshot mode Failed to start capture" 
136+ 			//  return false;
137+ 		}
138+ 	}
139+ 
102140	//  Allocate video buffers.
103141	for  (size_t  i = 0 ; i < ARRAY_SIZE (this ->vbuf ); i++) {
104142		this ->vbuf [i] = video_buffer_aligned_alloc (fmt.pitch  * fmt.height ,
@@ -111,23 +149,24 @@ bool Camera::begin(uint32_t width, uint32_t height, uint32_t pixformat, bool byt
111149	}
112150
113151	//  Start video capture
114- 	if  (video_stream_start (this ->vdev , VIDEO_BUF_TYPE_OUTPUT)) {
115- 		Serial.println (" Failed to start capture" 
116- 		return  false ;
152+ 	if  (!snapshot_mode) {
153+ 		if  (video_stream_start (this ->vdev , VIDEO_BUF_TYPE_OUTPUT)) {
154+ 			Serial.println (" Failed to start capture" 
155+ 			return  false ;
156+ 		}
117157	}
118- 
119158	return  true ;
120159}
121160
122161bool  Camera::grabFrame (FrameBuffer &fb, uint32_t  timeout) {
123162	if  (this ->vdev  == NULL ) {
124163		return  false ;
125164	}
126- 
165+ 	 //  printk("Camera::grabFrame called\n"); 
127166	if  (video_dequeue (this ->vdev , &fb.vbuf , K_MSEC (timeout))) {
128167		return  false ;
129168	}
130- 
169+ 	 //  printk("video_dequeue returned :%p\n", fb.vbuf->buffer); 
131170	if  (this ->byte_swap ) {
132171		uint16_t  *pixels = (uint16_t  *)fb.vbuf ->buffer ;
133172		for  (size_t  i = 0 ; i < fb.vbuf ->bytesused  / 2 ; i++) {
@@ -151,6 +190,13 @@ bool Camera::releaseFrame(FrameBuffer &fb) {
151190		return  false ;
152191	}
153192
193+ 	int  ret;
194+ 	//  printk("Camera::ReleaseFrame called\n");
195+ 	if  ((ret = video_enqueue (this ->vdev , fb.vbuf )) != 0 ) {
196+ 		printk (" Failed to enqueue buffer %d\n " 
197+ 		return  false ;
198+ 	}
199+ 
154200	if  (video_enqueue (this ->vdev , fb.vbuf )) {
155201		return  false ;
156202	}
@@ -167,3 +213,58 @@ bool Camera::setHorizontalMirror(bool mirror_enable) {
167213	struct  video_control  ctrl = {.id  = VIDEO_CID_HFLIP, .val  = mirror_enable};
168214	return  video_set_ctrl (this ->vdev , &ctrl) == 0 ;
169215}
216+ 
217+ int  Camera::setSelection (struct  video_selection  *sel) {
218+ 	return  video_set_selection (vdev, sel);
219+ }
220+ 
221+ /* *
222+  * @brief Get video selection (crop/compose). 
223+  * 
224+  * Retrieve the current settings related to the crop and compose of the video device. 
225+  * This can also be used to read the native size of the input stream of the video 
226+  * device. 
227+  * This function can be used to read crop / compose capabilities of the device prior 
228+  * to performing configuration via the @ref video_set_selection api. 
229+  * 
230+  * @param sel Pointer to a video selection structure, @c type and @c target set by the caller 
231+  * 
232+  * @retval 0 Is successful. 
233+  * @retval -EINVAL If parameters are invalid. 
234+  * @retval -ENOTSUP If format is not supported. 
235+  * @retval -EIO General input / output error. 
236+  */  
237+ int  Camera::getSelection (struct  video_selection  *sel) {
238+ 	return  video_get_selection (vdev, sel);
239+ }
240+ 
241+ /* *
242+  * @brief returns if snapshot mode is turned on or off. 
243+  * 
244+  * @param snapshot_mode pointer to Turn Snaphsot mode on or off.. 
245+  */  
246+ bool  Camera::getSnapshotMode () {
247+ 	return  snapshot_mode;
248+ }
249+ 
250+ /* *
251+  * @brief returns if snapshot mode is turned on or off. 
252+  * 
253+  * Must be called before begin to take effect. 
254+  * 
255+  * @param snap_shot mode if true. 
256+  * 
257+  * @retval 0 is successful. 
258+  */  
259+ int  Camera::setSnapshotMode (bool  snap_shot) {
260+ 	if  (snap_shot) {
261+ 		snapshot_mode = snap_shot;
262+ 		return  0 ;
263+ 	} else  {
264+ #if  CONFIG_VIDEO_BUFFER_POOL_NUM_MAX <= 1
265+ 		return  -EINVAL;
266+ #endif 
267+ 		snapshot_mode = snap_shot;
268+ 		return  0 ;
269+ 	}
270+ }
0 commit comments