-
Notifications
You must be signed in to change notification settings - Fork 0
/
capture.c
2370 lines (1924 loc) · 86.4 KB
/
capture.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*
*
* Adapted by Sam Siewert for use with UVC web cameras and Bt878 frame
* grabber NTSC cameras to acquire digital video from a source,
* time-stamp each frame acquired, save to a PGM or PPM file.
*
* The original code adapted was open source from V4L2 API and had the
* following use and incorporation policy:
*
* This program can be used and distributed without restrictions.
*
* This program is provided with the V4L2 API
* see http://linuxtv.org/docs.php for more information
*/
///< This is necessary for CPU affinity macros in Linux
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <getopt.h> /* getopt_long() */
#include <fcntl.h> /* low-level i/o */
#include <unistd.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/time.h>
#include <sys/mman.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>
#include <time.h>
#include <pthread.h>
#include <sched.h>
#include <semaphore.h>
#include <signal.h>
#include <syslog.h>
#include <sys/sysinfo.h>
#define CLEAR(x) memset(&(x), 0, sizeof(x))
//#define COLOR_CONVERT_RGB
#define HRES 640
#define VRES 480
#define HRES_STR "640"
#define VRES_STR "480"
//#define HRES 320
//#define VRES 240
//#define HRES_STR "320"
//#define VRES_STR "240"
/*************************************************************************
* Insert my code below
*************************************************************************/
///< Which clock to utilize in Linux
#define MY_CLOCK CLOCK_REALTIME
//#define MY_CLOCK CLOCK_MONOTONIC
//#define MY_CLOCK CLOCK_MONOTONIC_RAW
//#define MY_CLOCK CLOCK_REALTIME_COARSE
//#define MY_CLOCK CLOCK_MONOTONIC_COARSE
///< Return codes
#define TRUE (1)
#define FALSE (0)
//#define EXIT_SUCCESS (0)
//#define EXIT_FAILURE (1)
#define EXIT_FAILURE_N (-1)
///< Conversion values
#define NANOSEC_PER_SEC (1000000000)
#define NANOSEC_PER_MICROSEC (1000)
#define MICROSEC_PER_SEC (1000000)
#define MILLISEC_PER_SEC (1000)
#define SEC_PER_MIN (60)
///< Number of RT services requiring their own threads
///< - NOTE: S0 - Sequencer WILL NOT REQUIRE ITS OWN THREAD
///< S1 - Frame Acquisition for capturing frames of clock
///< S2 - Frame Difference Threshold for matrix subtraction to see if seconds hand has moved
///< S3 - Frame Select for selecting the "best" frame to send to Frame Write-Back buffer
///< S4 - Frame Process for processing the frame (in my case, to grayscale)
///< S5 - Frame Write-Back for writing the processed frame from buffer to FLASH
#define NUM_OF_THREADS 5
#define S1 0
#define S2 1
#define S3 2
#define S4 3
#define S5 4
///< Desired frequencies in Hz for all S0-S5
#define S0_FREQ (120)
#define S1_FREQ (10)
#define S2_FREQ (2)
#define S3_FREQ (1)
#define S4_FREQ (0.5)
#define S5_FREQ (0.25)
///< Desired time to run in s
#define S0_RUN_TIME_SEC (60)
#define S0_RUN_TIME_MIN (S0_RUN_TIME_SEC/SEC_PER_MIN)
///< How many periods S0 Sequencer should run for
#define S0_PERIODS (S0_FREQ*(S0_RUN_TIME_SEC + 1))
///< Resolution of pictures captured by S1 Frame Acquisition
#define PHOTO_RES (1280*960)
///< Number of frames to initially skip during first S1 Frame Acquisition
#define NUM_FRAMES_INITIALLY_SKIPPED ((2*S1_FREQ)/5)
///< Store 60 seconds of data at 20 Hz
#define BIGBUFFER_READ_MAX_NUM_OF_FRAMES_STORED ((S0_RUN_TIME_SEC + 1)*S1_FREQ)
#define BIGBUFFER_READ_TEST_SEC_OF_FRAMES ((unsigned int)((30 + 1)*S1_FREQ))
///< Same size as bigbuffer_read
#define BIGBUFFER_DIFF_THRESHOLD_MAX_NUM_OF_FRAMES_STORED (BIGBUFFER_READ_MAX_NUM_OF_FRAMES_STORED)
#define BIGBUFFER_DIFF_THRESHOLD_TEST_SEC_OF_FRAMES ((unsigned int)(BIGBUFFER_READ_TEST_SEC_OF_FRAMES))
///< Thresholds determined by outputting differences between consecutive frames
#define DIFF_THRESHOLD_LOWER 200000
#define DIFF_THRESHOLD_UPPER 400000
///< Store 60 seconds of data at 1 Hz + 1 extra frame
#define BIGBUFFER_SELECT_MAX_NUM_OF_FRAMES_STORED (((S0_RUN_TIME_SEC + 1)*S2_FREQ))
#define BIGBUFFER_SELECT_TEST_SEC_OF_FRAMES ((unsigned int)((30 + 1)*S3_FREQ))
///< Store 60 seconds of data at 1 Hz + 1 extra frame
#define BIGBUFFER_PROCESS_MAX_NUM_OF_FRAMES_STORED (((S0_RUN_TIME_SEC + 1)*S2_FREQ))
#define BIGBUFFER_PROCESS_TEST_SEC_OF_FRAMES ((unsigned int)((30 + 1)*S4_FREQ))
///< Number of frames expected at the end of the test
///< Example (1) - Running for 1800 sec for 1 Hz synchronome will be (S0_RUN_TIME_SEC + 1)*(S3_FREQ) + Initial Frames = (1800 sec)*(1 Hz) + 9 Initial Frames = 1809 frames
///< Thus, for 1800 sec at 1 Hz selection this would be set to 1809
///< Example (2) - Running for 180 sec for 10 Hz synchronome will be (S0_RUN_TIME_SEC + 1)*(S3_FREQ) + Initial Frames = (180 sec)*(10 Hz) + 9 Initial Frames = 1809 frames
///< Thus, for 180 sec at 10 Hz selection this would be set to 1809
#define FRAME_COUNT ((S0_RUN_TIME_SEC + 1)*(S3_FREQ) + 9)
///< Raspberry Pi 4b+ has 4 cores
#define NUM_OF_CPU_CORES 4
///< S0 Sequencer will run on this core
#define SEQ_CORE 3
///< All services S1-S5 will run on this core
#define RT_CORE 2
///< Structure to store thread IDs + number of S0 Sequencer periods
typedef struct
{
int threadIdx;
} threadParams_t;
///< POSIX thread declarations
pthread_t threads[NUM_OF_THREADS];
///< POSIX thread parameters to pass per entry point
threadParams_t threadParams[NUM_OF_THREADS];
///< POSIX scheduling parameters to create scheduling attributes with for main thread + service threads
struct sched_param main_param;
struct sched_param rt_param[NUM_OF_THREADS];
///< POSIX scheduling attributes for main thread + service threads
pthread_attr_t main_attr;
pthread_attr_t rt_sched_attr[NUM_OF_THREADS];
///< Semaphore for each service S1-S5 all controlled by S0 Sequencer
sem_t sem[NUM_OF_THREADS];
///< Keep track of global times
double start_realtime;
double end_realtime;
struct timespec start_time_val;
///< Controls for aborting all services S0-S5
int abort_test = FALSE;
int abort_threads[NUM_OF_THREADS];
///< Counter for S0 Sequencer
static unsigned long long seqCnt = 0;
///< timer + timer specs for S0 Sequencer
static timer_t timer_1;
static struct itimerspec itime = { {1,0}, {1,0} };
static struct itimerspec last_itime;
///< Store S0_PERIODS into unsigned long long
unsigned long long sequencePeriods;
///< Use to calculate dt for S0 Sequencer
double current_realtime_seq = 0;
double current_realtime_last_seq = 0;
///< Buffer info for S1 Frame Acquisition
unsigned char bigbuffer_read[PHOTO_RES * BIGBUFFER_READ_MAX_NUM_OF_FRAMES_STORED];
int size_buf_read[BIGBUFFER_READ_MAX_NUM_OF_FRAMES_STORED];
double timestamp_read[BIGBUFFER_READ_MAX_NUM_OF_FRAMES_STORED];
int head_read = 0;
int tail_read = 0;
int head_read_test = 0;
int tail_read_test = 0;
///< Counter for amount of frames read by S1 Frame Acquisition. Always ignore the first 8 frames
int framecnt_read = (-(NUM_FRAMES_INITIALLY_SKIPPED));
///< Buffer info for S2 Frame Difference Threshold
//enum frame_quality {untouched, next_frame_is_diff, next_frame_is_same};
enum frame_quality { untouched, good, bad };
enum frame_quality bigbuffer_diff_threshold[BIGBUFFER_DIFF_THRESHOLD_MAX_NUM_OF_FRAMES_STORED];
int head_diff_threshold = 0;
int tail_diff_threshold = 0;
int head_diff_threshold_test = 0;
int tail_diff_threshold_test = 0;
///< Counter for amount of frames marked by S2 Frame Difference Threshold
int framecnt_diff_threshold = 0;
int framecnt_diff_threshold_first = 0;
int framecnt_diff_threshold_last = 0;
int framecnt_next_untouched = 0;
int framecnt_next_diff = 0;
int framecnt_next_same = 0;
int first_diff_threshold = -1;
///< Buffer info for S3 Frame Select
unsigned char bigbuffer_select[PHOTO_RES/2 * BIGBUFFER_SELECT_MAX_NUM_OF_FRAMES_STORED];
int size_buf_select[BIGBUFFER_SELECT_MAX_NUM_OF_FRAMES_STORED];
double timestamp_select[BIGBUFFER_SELECT_MAX_NUM_OF_FRAMES_STORED];
int head_select = 0;
int tail_select = 0;
int head_select_test = 0;
int tail_select_test = 0;
///< Counter for amount of frames selected by S3 Frame Select
int framecnt_select = 0;
int framecnt_select_first = 0;
int framecnt_select_last = 0;
///< Frame number selected from bigbuffer_read by S3 Frame Select
int frame_selected_from_bigbuffer_read = 0;
///< Counter for amount of frames read by S4 Frame Process
int framecnt_process = 0;
int framecnt_process_first = 0;
int framecnt_process_last = 0;
///< Frame number selected from bigbuffer_read by S4 Frame Process
int frame_selected_from_bigbuffer_select = 0;
///< Buffer info for S4 Frame Process
unsigned char bigbuffer_process[PHOTO_RES/2 * BIGBUFFER_PROCESS_MAX_NUM_OF_FRAMES_STORED];
int size_buf_process[BIGBUFFER_PROCESS_MAX_NUM_OF_FRAMES_STORED];
double timestamp_process[BIGBUFFER_PROCESS_MAX_NUM_OF_FRAMES_STORED];
int head_process = 0;
int tail_process = 0;
int head_process_test = 0;
int tail_process_test = 0;
///< Counter for amount of frames read by S5 Frame Writeback
int framecnt_writeback = 0;
int framecnt_writeback_first = 0;
int framecnt_writeback_last = 0;
///< Frame number selected from bigbuffer_process by S5 Frame Writeback
int frame_selected_from_bigbuffer_process = 0;
/*************************************************************************
* Insert my code above
*************************************************************************/
// Format is used by a number of functions, so made as a file global
static struct v4l2_format fmt;
enum io_method
{
IO_METHOD_READ,
IO_METHOD_MMAP,
IO_METHOD_USERPTR,
};
struct buffer
{
void* start;
size_t length;
};
static char* dev_name;
//static enum io_method io = IO_METHOD_USERPTR;
//static enum io_method io = IO_METHOD_READ;
static enum io_method io = IO_METHOD_MMAP;
static int fd = -1;
struct buffer* buffers;
static unsigned int n_buffers;
static int out_buf;
static int force_format = 1;
static int frame_count = (FRAME_COUNT);
// always ignore first 8 frames
int framecnt = -8;
unsigned char bigbuffer[PHOTO_RES];
static void errno_exit(const char* s)
{
fprintf(stderr, "%s error %d, %s\n", s, errno, strerror(errno));
perror("errno_exit");
exit(EXIT_FAILURE);
}
static int xioctl(int fh, int request, void* arg)
{
int r;
do
{
r = ioctl(fh, request, arg);
} while (-1 == r && EINTR == errno);
return r;
}
char ppm_header[] = "P6\n#9999999999 sec 9999999999 msec \n"HRES_STR" "VRES_STR"\n255\n";
char ppm_dumpname[] = "frames/test0000.ppm";
static void dump_ppm(const void* p, int size, unsigned int tag, struct timespec* time)
{
int written, total, dumpfd;
snprintf(&ppm_dumpname[11], 9, "%04d", tag);
strncat(&ppm_dumpname[15], ".ppm", 5);
dumpfd = open(ppm_dumpname, O_WRONLY | O_NONBLOCK | O_CREAT, 00666);
snprintf(&ppm_header[4], 11, "%010d", (int)time->tv_sec);
strncat(&ppm_header[14], " sec ", 5);
snprintf(&ppm_header[19], 11, "%010d", (int)((time->tv_nsec) / 1000000));
strncat(&ppm_header[29], " msec \n"HRES_STR" "VRES_STR"\n255\n", 19);
written = write(dumpfd, ppm_header, sizeof(ppm_header));
total = 0;
do
{
written = write(dumpfd, p, size);
total += written;
} while (total < size);
syslog(LOG_INFO, "FinalProject (S5_frame_writeback): DUMP_PPM Wrote %04d %d bytes\n", tag, total);
close(dumpfd);
}
char pgm_header[] = "P5\n#9999999999 sec 9999999999 msec \n"HRES_STR" "VRES_STR"\n255\n";
char pgm_dumpname[] = "frames/test0000.pgm";
//char pgm_dumpname[] = "frames/test0000-0000.0000.pgm";
static void dump_pgm(const void* p, int size, unsigned int tag, struct timespec* time)
{
int written, total, dumpfd;
unsigned char* pptr = (unsigned char*)p;
snprintf(&pgm_dumpname[11], 9, "%04d", tag);
//snprintf(&pgm_dumpname[15], 1, "X");
strncat(&pgm_dumpname[15], ".pgm", 5);
dumpfd = open(pgm_dumpname, O_WRONLY | O_NONBLOCK | O_CREAT, 00666);
snprintf(&pgm_header[4], 11, "%010d", (int)time->tv_sec);
strncat(&pgm_header[14], " sec ", 5);
snprintf(&pgm_header[19], 11, "%010d", (int)((time->tv_nsec) / 1000000));
strncat(&pgm_header[29], " msec \n"HRES_STR" "VRES_STR"\n255\n", 19);
written = write(dumpfd, pgm_header, sizeof(pgm_header));
total = 0;
do
{
written = write(dumpfd, (const void*)(&(pptr[size * framecnt_writeback])), size);
total += written;
} while (total < size);
syslog(LOG_INFO, "FinalProject (S5_frame_writeback): DUMP_PGM Wrote frame %04d (%d bytes)", tag, total);
close(dumpfd);
}
static void store_buf_read(const void* p, int size, unsigned int tag, struct timespec* time)
{
if (framecnt_read >= 0) {
int i;
unsigned char* pptr = (unsigned char*)p;
for (i = 0; i < size; i = i + 1) {
//bigbuffer_read[(PHOTO_RES * framecnt_read) + i] = pptr[i];
bigbuffer_read[(PHOTO_RES * head_read) + i] = pptr[i];
}
}
}
static void store_buf_select(const void* p, int size, unsigned int tag, struct timespec* time)
{
if (framecnt_select >= 0) {
int i;
unsigned char* pptr = (unsigned char*)p;
for (i = 0; i < size; i = i + 1) {
//bigbuffer_select[(PHOTO_RES * framecnt_select) + i] = pptr[(PHOTO_RES * frame_selected_from_bigbuffer_read) + i];
bigbuffer_select[(PHOTO_RES * head_select) + i] = pptr[(PHOTO_RES * frame_selected_from_bigbuffer_read) + i];
}
}
}
static void store_buf_process(const void* p, int size, unsigned int tag, struct timespec* time)
{
if (framecnt_process >= 0) {
int i;
unsigned char* pptr = (unsigned char*)p;
syslog(LOG_INFO, "FinalProject (S4_frame_process): STORE_BUF_PROCESS size=%d, framecnt_process=%d, frame_selected_from_bigbuffer_select=%d", size, framecnt_process, frame_selected_from_bigbuffer_select);
for (i = 0; i < size; i = i + 1) {
//bigbuffer_process[(size * framecnt_process) + i] = pptr[i];
bigbuffer_process[(size * head_process) + i] = pptr[i];
}
}
}
void yuv2rgb_float(float y, float u, float v,
unsigned char* r, unsigned char* g, unsigned char* b)
{
float r_temp, g_temp, b_temp;
// R = 1.164(Y-16) + 1.1596(V-128)
r_temp = 1.164 * (y - 16.0) + 1.1596 * (v - 128.0);
*r = r_temp > 255.0 ? 255 : (r_temp < 0.0 ? 0 : (unsigned char)r_temp);
// G = 1.164(Y-16) - 0.813*(V-128) - 0.391*(U-128)
g_temp = 1.164 * (y - 16.0) - 0.813 * (v - 128.0) - 0.391 * (u - 128.0);
*g = g_temp > 255.0 ? 255 : (g_temp < 0.0 ? 0 : (unsigned char)g_temp);
// B = 1.164*(Y-16) + 2.018*(U-128)
b_temp = 1.164 * (y - 16.0) + 2.018 * (u - 128.0);
*b = b_temp > 255.0 ? 255 : (b_temp < 0.0 ? 0 : (unsigned char)b_temp);
}
// This is probably the most acceptable conversion from camera YUYV to RGB
//
// Wikipedia has a good discussion on the details of various conversions and cites good references:
// http://en.wikipedia.org/wiki/YUV
//
// Also http://www.fourcc.org/yuv.php
//
// What's not clear without knowing more about the camera in question is how often U & V are sampled compared
// to Y.
//
// E.g. YUV444, which is equivalent to RGB, where both require 3 bytes for each pixel
// YUV422, which we assume here, where there are 2 bytes for each pixel, with two Y samples for one U & V,
// or as the name implies, 4Y and 2 UV pairs
// YUV420, where for every 4 Ys, there is a single UV pair, 1.5 bytes for each pixel or 36 bytes for 24 pixels
void yuv2rgb(int y, int u, int v, unsigned char* r, unsigned char* g, unsigned char* b)
{
int r1, g1, b1;
// replaces floating point coefficients
int c = y - 16, d = u - 128, e = v - 128;
// Conversion that avoids floating point
r1 = (298 * c + 409 * e + 128) >> 8;
g1 = (298 * c - 100 * d - 208 * e + 128) >> 8;
b1 = (298 * c + 516 * d + 128) >> 8;
// Computed values may need clipping.
if (r1 > 255) r1 = 255;
if (g1 > 255) g1 = 255;
if (b1 > 255) b1 = 255;
if (r1 < 0) r1 = 0;
if (g1 < 0) g1 = 0;
if (b1 < 0) b1 = 0;
*r = r1;
*g = g1;
*b = b1;
}
static void process_image(const void* p, int size)
{
int i, newi, newsize = 0;
struct timespec frame_time;
int y_temp, y2_temp, u_temp, v_temp;
unsigned char* pptr = (unsigned char*)p;
// record when process was called
clock_gettime(MY_CLOCK, &frame_time);
// This just dumps the frame to a file now, but you could replace with whatever image
// processing you wish.
//
if (fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_GREY)
{
syslog(LOG_INFO, "FinalProject (S4_frame_process): PROCESS_IMAGE Dump graymap as-is size %d\n", size);
for (i = 0; i < size; i = i + 1)
{
bigbuffer[i] = pptr[i];
}
//size_buf_process[framecnt_process] = size;
size_buf_process[head_process] = size;
store_buf_process(bigbuffer, size, framecnt_process, &frame_time);
}
else if (fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV)
{
#if defined(COLOR_CONVERT_RGB)
// Pixels are YU and YV alternating, so YUYV which is 4 bytes
// We want RGB, so RGBRGB which is 6 bytes
//
for (i = 0, newi = 0; i < size; i = i + 4, newi = newi + 6)
{
y_temp = (int)pptr[i]; u_temp = (int)pptr[i + 1]; y2_temp = (int)pptr[i + 2]; v_temp = (int)pptr[i + 3];
yuv2rgb(y_temp, u_temp, v_temp, &bigbuffer[newi], &bigbuffer[newi + 1], &bigbuffer[newi + 2]);
yuv2rgb(y2_temp, u_temp, v_temp, &bigbuffer[newi + 3], &bigbuffer[newi + 4], &bigbuffer[newi + 5]);
}
if (framecnt_process > -1)
{
//size_buf_process[framecnt_process] = ((size * 6) / 4);
size_buf_process[head_process] = ((size * 6) / 4);
store_buf_process(bigbuffer, ((size * 6) / 4), framecnt_process, &frame_time);
syslog(LOG_INFO, "FinalProject (S4_frame_process): PROCESS_IMAGE Dump YUYV converted to RGB size %d\n", size);
}
#else
// Pixels are YU and YV alternating, so YUYV which is 4 bytes
// We want Y, so YY which is 2 bytes
//
for (i = 0, newi = 0; i < size; i = i + 4, newi = newi + 2)
{
// Y1=first byte and Y2=third byte
bigbuffer[newi] = pptr[(PHOTO_RES * frame_selected_from_bigbuffer_select) + i];
bigbuffer[newi + 1] = pptr[(PHOTO_RES * frame_selected_from_bigbuffer_select) + i + 2];
}
if (framecnt_process > -1)
{
syslog(LOG_INFO, "FinalProject (S4_frame_process): PROCESS_IMAGE about to fill size_buf_process[%d] with %d", framecnt_process, (size / 2));
//size_buf_process[framecnt_process] = (size / 2);
size_buf_process[head_process] = (size / 2);
syslog(LOG_INFO, "FinalProject (S4_frame_process): PROCESS_IMAGE about to store %d", framecnt_process);
store_buf_process(bigbuffer, (size / 2), framecnt_process, &frame_time);
syslog(LOG_INFO, "FinalProject (S4_frame_process): PROCESS_IMAGE Dump YUYV (%d) converted to YY (%d)\n", size, (size / 2));
}
#endif
}
else if (fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24)
{
syslog(LOG_INFO, "FinalProject (S4_frame_process): Dump RGB as-is size %d\n", size);
//size_buf_process[framecnt_process] = size;;
size_buf_process[head_process] = size;
store_buf_process(bigbuffer, size, framecnt_process, &frame_time);
}
else
{
syslog(LOG_ERR, "FinalProject (S4_frame_process): ERROR - unknown dump format\n");
}
fflush(stderr);
//fprintf(stderr, ".");
//syslog(LOG_ERR, ".");
fflush(stdout);
}
static void mark_frames(void) {
int diff;
int i;
int j;
unsigned char* bigbuffer_read_ptr = bigbuffer_read;
///< Get current range of frames we need to mark
framecnt_diff_threshold_first = framecnt_diff_threshold_last;
//framecnt_diff_threshold_last = framecnt_read;
framecnt_diff_threshold_last = head_read;
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES framecnt_diff_threshold_first=%d, framecnt_diff_threshold_last=%d", framecnt_diff_threshold_first, framecnt_diff_threshold_last);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES tail_read=%d, head_read=%d", tail_read, head_read);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES tail_read_test=%d, head_read_test=%d", tail_read_test, head_read_test);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES tail_diff_threshold=%d, head_diff_threshold=%d", tail_diff_threshold, head_diff_threshold);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES tail_diff_threshold_test=%d, head_diff_threshold_test=%d", tail_diff_threshold_test, head_diff_threshold_test);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES first_diff_threshold=%d", first_diff_threshold);
if (first_diff_threshold < 0) {
///< Check if current frame is different from next frame
for (i = framecnt_diff_threshold_first; i < framecnt_diff_threshold_last; i++) {
///< Calculate sum of difference between each byte of current frame and next frame
diff = 0;
for (j = 0; j < PHOTO_RES; j++) {
diff += abs((unsigned int)bigbuffer_read_ptr[i * PHOTO_RES + j] - (unsigned int)bigbuffer_read_ptr[(i + 1) * PHOTO_RES + j]);
}
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES framecnt_diff_threshold=%d", framecnt_diff_threshold);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES tail_read=%d, head_read=%d", tail_read, head_read);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES tail_read_test=%d, head_read_test=%d", tail_read_test, head_read_test);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES tail_diff_threshold=%d, head_diff_threshold=%d", tail_diff_threshold, head_diff_threshold);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES tail_diff_threshold_test=%d, head_diff_threshold_test=%d", tail_diff_threshold_test, head_diff_threshold_test);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES size_buf_read[%d]=%d", i, size_buf_read[i]);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES bigbuffer_read[%d] - bigbuffer_read[%d + 1]=%u", i, i, diff);
///< If the next frame is significantly different from the current frame then mark 2 frames before as a good frame
if (diff > DIFF_THRESHOLD_LOWER) {
first_diff_threshold = i;
bigbuffer_diff_threshold[first_diff_threshold + 2] = good; /// REMINDER: ADJUST TO + 1
framecnt_next_diff++;
framecnt_next_untouched--;
}
///< We have performed another frame difference calculation
framecnt_diff_threshold++;
head_diff_threshold++;
head_diff_threshold = head_diff_threshold % BIGBUFFER_DIFF_THRESHOLD_MAX_NUM_OF_FRAMES_STORED;
head_diff_threshold_test++;
head_diff_threshold_test = head_diff_threshold_test % BIGBUFFER_DIFF_THRESHOLD_TEST_SEC_OF_FRAMES;
//head_diff_threshold = head_diff_threshold % BIGBUFFER_DIFF_THRESHOLD_60_SEC_OF_FRAMES;
//head_diff_threshold = head_diff_threshold % BIGBUFFER_DIFF_THRESHOLD_30_SEC_OF_FRAMES;
}
}
else {
///< Check if current frame is different from next frame
for (i = framecnt_diff_threshold_first; i < framecnt_diff_threshold_last; i++) {
///< Calculate sum of difference between each byte of current frame and next frame
diff = 0;
for (j = 0; j < PHOTO_RES; j++) {
diff += abs((unsigned int)bigbuffer_read_ptr[i * PHOTO_RES + j] - (unsigned int)bigbuffer_read_ptr[(i - 1) * PHOTO_RES + j]);
}
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES framecnt_diff_threshold=%d", framecnt_diff_threshold);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES tail_read=%d, head_read=%d", tail_read, head_read);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES tail_read_test=%d, head_read_test=%d", tail_read_test, head_read_test);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES tail_diff_threshold=%d, head_diff_threshold=%d", tail_diff_threshold, head_diff_threshold);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES tail_diff_threshold_test=%d, head_diff_threshold_test=%d", tail_diff_threshold_test, head_diff_threshold_test);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES size_buf_read[%d]=%d", i, size_buf_read[i]);
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES bigbuffer_read[%d] - bigbuffer_read[%d - 1]=%u", i, i, diff);
///< We have performed another frame difference calculation
framecnt_diff_threshold++;
head_diff_threshold++;
head_diff_threshold = head_diff_threshold % BIGBUFFER_DIFF_THRESHOLD_MAX_NUM_OF_FRAMES_STORED;
head_diff_threshold_test++;
head_diff_threshold_test = head_diff_threshold_test % BIGBUFFER_DIFF_THRESHOLD_TEST_SEC_OF_FRAMES;
//head_diff_threshold = head_diff_threshold % BIGBUFFER_DIFF_THRESHOLD_60_SEC_OF_FRAMES;
//head_diff_threshold = head_diff_threshold % BIGBUFFER_DIFF_THRESHOLD_30_SEC_OF_FRAMES;
}
///< Mark next good frame with shotgun method
if (first_diff_threshold < BIGBUFFER_DIFF_THRESHOLD_MAX_NUM_OF_FRAMES_STORED) {
if (first_diff_threshold == 0) {
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES zero");
first_diff_threshold = first_diff_threshold + 2 * (S1_FREQ / S2_FREQ);
bigbuffer_diff_threshold[first_diff_threshold + 1] = good;
framecnt_next_diff++;
framecnt_next_untouched--;
}
else if ((first_diff_threshold % 5) < (((framecnt_diff_threshold_first + framecnt_diff_threshold_last) / 2) % 5)) {
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES add");
first_diff_threshold = first_diff_threshold + 2 * (S1_FREQ / S2_FREQ);
if (first_diff_threshold >= BIGBUFFER_DIFF_THRESHOLD_MAX_NUM_OF_FRAMES_STORED) {
first_diff_threshold = BIGBUFFER_DIFF_THRESHOLD_MAX_NUM_OF_FRAMES_STORED - 1;
bigbuffer_diff_threshold[first_diff_threshold] = good;
}
else {
bigbuffer_diff_threshold[first_diff_threshold + 2] = good;
}
framecnt_next_diff++;
framecnt_next_untouched--;
}
else {
syslog(LOG_INFO, "FinalProject (S2_frame_difference_threshold): MARK_FRAMES subtract");
first_diff_threshold = first_diff_threshold + 2 * (S1_FREQ / S2_FREQ);
if (first_diff_threshold >= BIGBUFFER_DIFF_THRESHOLD_MAX_NUM_OF_FRAMES_STORED) {
first_diff_threshold = BIGBUFFER_DIFF_THRESHOLD_MAX_NUM_OF_FRAMES_STORED - 1;
bigbuffer_diff_threshold[first_diff_threshold] = good;
}
else {
bigbuffer_diff_threshold[first_diff_threshold - 2] = good;
}
framecnt_next_diff++;
framecnt_next_untouched--;
}
}
else {
framecnt_next_diff++;
framecnt_next_untouched--;
}
}
}
static void select_frames(void) {
int i;
struct timespec frame_time;
///< Get current range of frames we need to select from
framecnt_select_first = framecnt_select_last;
//framecnt_select_last = framecnt_diff_threshold;
framecnt_select_last = head_diff_threshold;
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES framecnt_select_first=%d, framecnt_select_last=%d", framecnt_select_first, framecnt_select_last);
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES tail_read=%d, head_read=%d", tail_read, head_read);
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES tail_read_test=%d, head_read_test=%d", tail_read_test, head_read_test);
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES tail_diff_threshold=%d, head_diff_threshold=%d", tail_diff_threshold, head_diff_threshold);
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES tail_diff_threshold_test=%d, head_diff_threshold_test=%d", tail_diff_threshold_test, head_diff_threshold_test);
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES tail_select=%d, head_select=%d", tail_select, head_select);
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES tail_select_test=%d, head_select_test=%d", tail_select_test, head_select_test);
///< For testing, store all stable frames into bigbuffer_select
for (i = framecnt_select_first; i < framecnt_select_last; i++) {
if (bigbuffer_diff_threshold[i] == good) {
///< Select this stable frame's index in bigbuffer_read for the call to store_buf_select
frame_selected_from_bigbuffer_read = i;
clock_gettime(MY_CLOCK, &frame_time);
///< Store the size of selected frame (in bytes) into global select buffer
//size_buf_select[framecnt_select] = size_buf_read[frame_selected_from_bigbuffer_read];
size_buf_select[head_select] = size_buf_read[frame_selected_from_bigbuffer_read];
timestamp_select[head_select] = timestamp_read[frame_selected_from_bigbuffer_read];
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES framecnt_select=%d", framecnt_select);
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES tail_read=%d, head_read=%d", tail_read, head_read);
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES tail_read_test=%d, head_read_test=%d", tail_read_test, head_read_test);
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES tail_diff_threshold=%d, head_diff_threshold=%d", tail_diff_threshold, head_diff_threshold);
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES tail_diff_threshold_test=%d, head_diff_threshold_test=%d", tail_diff_threshold_test, head_diff_threshold_test);
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES tail_select=%d, head_select=%d", tail_select, head_select);
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES tail_select_test=%d, head_select_test=%d", tail_select_test, head_select_test);
//syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES size_buf_select[%d]=%d", framecnt_select, size_buf_select[framecnt_select]);
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES size_buf_select[%d]=%d", head_select, size_buf_select[head_select]);
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES bigbuffer_diff_threshold[%d]=%d", frame_selected_from_bigbuffer_read, bigbuffer_diff_threshold[frame_selected_from_bigbuffer_read]);
syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMES selecting size_buf_read[%d] to store", frame_selected_from_bigbuffer_read);
///< Now store the frame into global select buffer
store_buf_select(bigbuffer_read, size_buf_read[frame_selected_from_bigbuffer_read], framecnt_select, &frame_time);
///< We have stored another selected frame
framecnt_select++;
tail_read++;
tail_read = tail_read % BIGBUFFER_READ_MAX_NUM_OF_FRAMES_STORED;
tail_read_test++;
tail_read_test = tail_read_test % BIGBUFFER_READ_TEST_SEC_OF_FRAMES;
//tail_read = tail_read % BIGBUFFER_READ_60_SEC_OF_FRAMES;
//tail_read = tail_read % BIGBUFFER_READ_30_SEC_OF_FRAMES;
tail_diff_threshold++;
tail_diff_threshold = tail_diff_threshold % BIGBUFFER_DIFF_THRESHOLD_MAX_NUM_OF_FRAMES_STORED;
tail_diff_threshold_test++;
tail_diff_threshold_test = tail_diff_threshold_test % BIGBUFFER_DIFF_THRESHOLD_TEST_SEC_OF_FRAMES;
//tail_diff_threshold = tail_diff_threshold % BIGBUFFER_DIFF_THRESHOLD_60_SEC_OF_FRAMES;
//tail_diff_threshold = tail_diff_threshold % BIGBUFFER_DIFF_THRESHOLD_30_SEC_OF_FRAMES;
head_select++;
head_select = head_select % BIGBUFFER_SELECT_MAX_NUM_OF_FRAMES_STORED;
head_select_test++;
head_select_test = head_select_test % BIGBUFFER_SELECT_TEST_SEC_OF_FRAMES;
//head_select = head_select % BIGBUFFER_SELECT_60_SEC_OF_FRAMES;
//head_select = head_select % BIGBUFFER_SELECT_30_SEC_OF_FRAMES;
//syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMESX framecnt_select=%d", framecnt_select);
//syslog(LOG_INFO, "FinalProject (S3_frame_select): SELECT_FRAMESX tail_select=%d, head_select=%d", tail_select, head_select);
}
}
}
static void process_frames(void) {
int i;
struct timespec frame_time;
///< Get current range of frames we need to select from
framecnt_process_first = framecnt_process_last;
//framecnt_process_last = framecnt_select;
framecnt_process_last = head_select;
syslog(LOG_INFO, "FinalProject (S4_frame_process): PROCESS_FRAMES framecnt_process_first=%d, framecnt_process_last=%d", framecnt_process_first, framecnt_process_last);
syslog(LOG_INFO, "FinalProject (S4_frame_process): PROCESS_FRAMES tail_select=%d, head_select=%d", tail_select, head_select);
syslog(LOG_INFO, "FinalProject (S4_frame_process): PROCESS_FRAMES tail_select_test=%d, head_select_test=%d", tail_select_test, head_select_test);
syslog(LOG_INFO, "FinalProject (S4_frame_process): PROCESS_FRAMES tail_process=%d, head_process=%d", tail_process, head_process);
syslog(LOG_INFO, "FinalProject (S4_frame_process): PROCESS_FRAMES tail_process_test=%d, head_process_test=%d", tail_process_test, head_process_test);
///< Process new selected frames
for (i = framecnt_process_first; i < framecnt_process_last; i++) {
///< Select this frame's index in bigbuffer_select for the call to store_buf_process
frame_selected_from_bigbuffer_select = i;
clock_gettime(MY_CLOCK, &frame_time);
///< Process the current image
process_image(bigbuffer_select, size_buf_select[i]);
timestamp_process[head_process] = timestamp_select[i];
syslog(LOG_INFO, "FinalProject (S4_frame_process): PROCESS_FRAMES framecnt_process=%d", framecnt_process);
syslog(LOG_INFO, "FinalProject (S4_frame_process): PROCESS_FRAMES tail_select=%d, head_select=%d", tail_select, head_select);
syslog(LOG_INFO, "FinalProject (S4_frame_process): PROCESS_FRAMES tail_select_test=%d, head_select_test=%d", tail_select_test, head_select_test);
syslog(LOG_INFO, "FinalProject (S4_frame_process): PROCESS_FRAMES tail_process=%d, head_process=%d", tail_process, head_process);
syslog(LOG_INFO, "FinalProject (S4_frame_process): PROCESS_FRAMES tail_process_test=%d, head_process_test=%d", tail_process_test, head_process_test);
syslog(LOG_INFO, "FinalProject (S4_frame_process): PROCESS_FRAMES size_buf_select[%d]=%d, size_buf_process[%d]=%d", i, size_buf_select[i], i, size_buf_process[i]);
///< We have stored another processed frame
framecnt_process++;
tail_select++;
tail_select = tail_select % BIGBUFFER_SELECT_MAX_NUM_OF_FRAMES_STORED;
tail_select_test++;
tail_select_test = tail_select_test % BIGBUFFER_SELECT_TEST_SEC_OF_FRAMES;
//tail_select = tail_select % BIGBUFFER_SELECT_60_SEC_OF_FRAMES;
//tail_select = tail_select % BIGBUFFER_SELECT_30_SEC_OF_FRAMES;
head_process++;
head_process = head_process % BIGBUFFER_PROCESS_MAX_NUM_OF_FRAMES_STORED;
head_process_test++;
head_process_test = head_process_test % BIGBUFFER_PROCESS_TEST_SEC_OF_FRAMES;
//head_process = head_process % BIGBUFFER_PROCESS_60_SEC_OF_FRAMES;
//head_process = head_process % BIGBUFFER_PROCESS_30_SEC_OF_FRAMES;
}
}
static void writeback_frames(void) {
int i;
struct timespec frame_time;
///< Get current range of frames we need to select from
framecnt_writeback_first = framecnt_writeback_last;
//framecnt_writeback_last = framecnt_process;
framecnt_writeback_last = head_process;
syslog(LOG_INFO, "FinalProject (S5_frame_writeback): WRITEBACK_FRAMES framecnt_writeback_first=%d, framecnt_writeback_last=%d", framecnt_writeback_first, framecnt_writeback_last);
syslog(LOG_INFO, "FinalProject (S5_frame_writeback): WRITEBACK_FRAMES tail_process=%d, head_process=%d", tail_process, head_process);
syslog(LOG_INFO, "FinalProject (S5_frame_writeback): WRITEBACK_FRAMES tail_process_test=%d, head_process_test=%d", tail_process_test, head_process_test);
///< Writeback frames
for (i = framecnt_writeback_first; i < framecnt_writeback_last; i++) {
syslog(LOG_INFO, "FinalProject (S5_frame_writeback): WRITEBACK_FRAMES framecnt_writeback=%d", framecnt_writeback);
syslog(LOG_INFO, "FinalProject (S5_frame_writeback): WRITEBACK_FRAMES tail_process=%d, head_process=%d", tail_process, head_process);
syslog(LOG_INFO, "FinalProject (S5_frame_writeback): WRITEBACK_FRAMES tail_process_test=%d, head_process_test=%d", tail_process_test, head_process_test);
syslog(LOG_INFO, "FinalProject (S5_frame_writeback): WRITEBACK_FRAMES size_buf_process[%d]=%d", i, size_buf_process[i]);
///< Select this frame's index in bigbuffer_process for the call to dump it into FLASH
frame_selected_from_bigbuffer_process = i;
clock_gettime(MY_CLOCK, &frame_time);
if (fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_GREY) {
///< Writeback the current image
dump_pgm(bigbuffer_process, size_buf_process[i], i, &frame_time);
///< We have written back another frame
framecnt_writeback++;
tail_process++;
tail_process = tail_process % BIGBUFFER_PROCESS_MAX_NUM_OF_FRAMES_STORED;
tail_process_test++;
tail_process_test = tail_process_test % BIGBUFFER_PROCESS_TEST_SEC_OF_FRAMES;
//tail_process = tail_process % BIGBUFFER_PROCESS_60_SEC_OF_FRAMES;
//tail_process = tail_process % BIGBUFFER_PROCESS_30_SEC_OF_FRAMES;
}
else if (fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_YUYV) {
#if defined(COLOR_CONVERT_RGB)
///< Writeback the current image
dump_ppm(bigbuffer_process, size_buf_process[i], i, &frame_time);
///< We have written back another frame
framecnt_writeback++;
tail_process++;
tail_process = tail_process % BIGBUFFER_PROCESS_MAX_NUM_OF_FRAMES_STORED;
tail_process_test++;
tail_process_test = tail_process_test % BIGBUFFER_PROCESS_TEST_SEC_OF_FRAMES;
//tail_process = tail_process % BIGBUFFER_PROCESS_60_SEC_OF_FRAMES;
//tail_process = tail_process % BIGBUFFER_PROCESS_30_SEC_OF_FRAMES;
#else
///< Writeback the current image
dump_pgm(bigbuffer_process, size_buf_process[i], i, &frame_time);
///< We have written back another frame
framecnt_writeback++;
tail_process++;
tail_process = tail_process % BIGBUFFER_PROCESS_MAX_NUM_OF_FRAMES_STORED;
tail_process_test++;
tail_process_test = tail_process_test % BIGBUFFER_PROCESS_TEST_SEC_OF_FRAMES;
//tail_process = tail_process % BIGBUFFER_PROCESS_60_SEC_OF_FRAMES;
//tail_process = tail_process % BIGBUFFER_PROCESS_30_SEC_OF_FRAMES;
#endif
}
else if (fmt.fmt.pix.pixelformat == V4L2_PIX_FMT_RGB24) {
///< Writeback the current image
dump_ppm(bigbuffer_process, size_buf_process[i], i, &frame_time);
///< We have written back another frame
framecnt_writeback++;
tail_process++;
tail_process = tail_process % BIGBUFFER_PROCESS_MAX_NUM_OF_FRAMES_STORED;
tail_process_test++;
tail_process_test = tail_process_test % BIGBUFFER_PROCESS_TEST_SEC_OF_FRAMES;
//tail_process = tail_process % BIGBUFFER_PROCESS_60_SEC_OF_FRAMES;
//tail_process = tail_process % BIGBUFFER_PROCESS_30_SEC_OF_FRAMES;
}
else {
syslog(LOG_INFO, "FinalProject (S5_frame_writeback): WRITEBACK_FRAMES cannot writeback unknown dump format for bigbuffer_process[%d]", i);
}
}
}
double realtime(struct timespec* tsptr)
{
return ((double)(tsptr->tv_sec) + (((double)tsptr->tv_nsec) / 1000000000.0));
}
static int read_frame(void)
{
struct v4l2_buffer buf;
unsigned int i;
switch (io)
{
case IO_METHOD_READ:
if (-1 == read(fd, buffers[0].start, buffers[0].length))
{
switch (errno)
{
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, see spec. */
/* fall through */
default:
errno_exit("read");
}
}
process_image(buffers[0].start, buffers[0].length);
break;
case IO_METHOD_MMAP:
CLEAR(buf);
buf.type = V4L2_BUF_TYPE_VIDEO_CAPTURE;
buf.memory = V4L2_MEMORY_MMAP;
if (-1 == xioctl(fd, VIDIOC_DQBUF, &buf))
{
switch (errno)
{
case EAGAIN:
return 0;
case EIO:
/* Could ignore EIO, but drivers should only set for serious errors, although some set for
non-fatal errors too.
*/
return 0;
default:
//printf("mmap failure\n");
//syslog(LOG_INFO, "mmap failure\n");
errno_exit("VIDIOC_DQBUF");
}
}
assert(buf.index < n_buffers);
///< Declare and grab the time frame has been read
struct timespec frame_time;
clock_gettime(MY_CLOCK, &frame_time);
///< Store the size of frame (in bytes) into global read buffer
//size_buf_read[framecnt_read] = buf.bytesused;
size_buf_read[head_read] = buf.bytesused;
///< Store timestamp