1 #include "config.h"
2 
3 #include <stdio.h>
4 #include <stdlib.h>
5 #include <unistd.h>
6 #include <string.h>
7 
8 #include "grab-ng.h"
9 
10 /*-------------------------------------------------------------------------*/
11 /* color space conversion / compression helper functions                   */
12 
13 struct ng_convert_handle*
ng_convert_alloc(struct ng_video_conv * conv,struct ng_video_fmt * i,struct ng_video_fmt * o)14 ng_convert_alloc(struct ng_video_conv *conv,
15 		 struct ng_video_fmt *i,
16 		 struct ng_video_fmt *o)
17 {
18     struct ng_convert_handle *h;
19 
20     h = malloc(sizeof(*h));
21     if (NULL == h)
22 	return 0;
23     memset(h,0,sizeof(*h));
24 
25     /* fixup output image size to match incoming */
26     o->width  = i->width;
27     o->height = i->height;
28     if (0 == o->bytesperline)
29 	o->bytesperline = o->width * ng_vfmt_to_depth[o->fmtid] / 8;
30 
31     h->ifmt = *i;
32     h->ofmt = *o;
33     if (conv)
34 	h->conv = conv;
35     return h;
36 }
37 
38 void
ng_convert_init(struct ng_convert_handle * h)39 ng_convert_init(struct ng_convert_handle *h)
40 {
41     if (0 == h->ifmt.bytesperline)
42 	h->ifmt.bytesperline = h->ifmt.width *
43 	    ng_vfmt_to_depth[h->ifmt.fmtid] / 8;
44     if (0 == h->ofmt.bytesperline)
45 	h->ofmt.bytesperline = h->ofmt.width *
46 	    ng_vfmt_to_depth[h->ofmt.fmtid] / 8;
47 
48     h->isize = h->ifmt.height * h->ifmt.bytesperline;
49     if (0 == h->isize)
50 	h->isize = h->ifmt.width * h->ifmt.height * 3;
51     h->osize = h->ofmt.height * h->ofmt.bytesperline;
52     if (0 == h->osize)
53 	h->osize = h->ofmt.width * h->ofmt.height * 3;
54 
55     if (h->conv)
56 	h->chandle = h->conv->init(&h->ofmt,h->conv->priv);
57 
58     if (ng_debug) {
59 	fprintf(stderr,"convert-in : %dx%d %s (size=%d)\n",
60 		h->ifmt.width, h->ifmt.height,
61 		ng_vfmt_to_desc[h->ifmt.fmtid], h->isize);
62 	fprintf(stderr,"convert-out: %dx%d %s (size=%d)\n",
63 		h->ofmt.width, h->ofmt.height,
64 		ng_vfmt_to_desc[h->ofmt.fmtid], h->osize);
65     }
66 }
67 
68 static void
ng_convert_copyframe(struct ng_video_buf * dest,struct ng_video_buf * src)69 ng_convert_copyframe(struct ng_video_buf *dest,
70 		     struct ng_video_buf *src)
71 {
72     unsigned int i,sw,dw;
73     unsigned char *sp,*dp;
74 
75     dw = dest->fmt.width * ng_vfmt_to_depth[dest->fmt.fmtid] / 8;
76     sw = src->fmt.width * ng_vfmt_to_depth[src->fmt.fmtid] / 8;
77     if (src->fmt.bytesperline == sw && dest->fmt.bytesperline == dw) {
78 	/* can copy in one go */
79 	memcpy(dest->data, src->data,
80 	       src->fmt.bytesperline * src->fmt.height);
81     } else {
82 	/* copy line by line */
83 	dp = dest->data;
84 	sp = src->data;
85 	for (i = 0; i < src->fmt.height; i++) {
86 	    memcpy(dp,sp,dw);
87 	    dp += dest->fmt.bytesperline;
88 	    sp += src->fmt.bytesperline;
89 	}
90     }
91 }
92 
93 struct ng_video_buf*
ng_convert_frame(struct ng_convert_handle * h,struct ng_video_buf * dest,struct ng_video_buf * buf)94 ng_convert_frame(struct ng_convert_handle *h,
95 		 struct ng_video_buf *dest,
96 		 struct ng_video_buf *buf)
97 {
98     if (NULL == buf)
99 	return NULL;
100 
101     if (NULL == dest && NULL != h->conv)
102 	dest = ng_malloc_video_buf(&h->ofmt,h->osize);
103 
104     if (NULL != dest) {
105 	dest->fmt  = h->ofmt;
106 	dest->size = h->osize;
107 	if (NULL != h->conv) {
108 	    h->conv->frame(h->chandle,dest,buf);
109 	} else {
110 	    ng_convert_copyframe(dest,buf);
111 	}
112 	dest->info = buf->info;
113 	ng_release_video_buf(buf);
114 	buf = dest;
115     }
116     return buf;
117 }
118 
119 void
ng_convert_fini(struct ng_convert_handle * h)120 ng_convert_fini(struct ng_convert_handle *h)
121 {
122     if (h->conv)
123 	h->conv->fini(h->chandle);
124     free(h);
125 }
126 
127 struct ng_video_buf*
ng_convert_single(struct ng_convert_handle * h,struct ng_video_buf * in)128 ng_convert_single(struct ng_convert_handle *h, struct ng_video_buf *in)
129 {
130     struct ng_video_buf *out;
131 
132     ng_convert_init(h);
133     out = ng_convert_frame(h,NULL,in);
134     ng_convert_fini(h);
135     return out;
136 }
137 
138