blob: 4f1d8705beb026107f09a4a7d1109ee65fbeff39 [file] [log] [blame]
Kristian Høgsberg89060c02012-05-25 11:59:53 -04001/*
2 * Copyright © 2012 Intel Corporation
3 *
4 * Permission to use, copy, modify, distribute, and sell this software and
5 * its documentation for any purpose is hereby granted without fee, provided
6 * that the above copyright notice appear in all copies and that both that
7 * copyright notice and this permission notice appear in supporting
8 * documentation, and that the name of the copyright holders not be used in
9 * advertising or publicity pertaining to distribution of the software
10 * without specific, written prior permission. The copyright holders make
11 * no representations about the suitability of this software for any
12 * purpose. It is provided "as is" without express or implied warranty.
13 *
14 * THE COPYRIGHT HOLDERS DISCLAIM ALL WARRANTIES WITH REGARD TO THIS
15 * SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
16 * FITNESS, IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY
17 * SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER
18 * RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF
19 * CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
20 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
21 */
22
23#include <stdlib.h>
24#include <stdio.h>
25#include <stdint.h>
26#include <sys/mman.h>
27#include <sys/mman.h>
28#include <sys/types.h>
29#include <sys/stat.h>
30#include <unistd.h>
31#include <string.h>
32#include <fcntl.h>
33
34#include <cairo.h>
35
36struct wcap_header {
37 uint32_t width, height;
38};
39
40struct wcap_frame_header {
41 uint32_t msecs;
42 uint32_t nrects;
43};
44
45struct wcap_rectangle {
46 int32_t x1, y1, x2, y2;
47};
48
49struct wcap_decoder {
50 int fd;
51 size_t size;
52 void *map, *p, *end;
53 uint32_t *frame;
54 int width, height;
55};
56
57static void
58wcap_decoder_decode_rectangle(struct wcap_decoder *decoder,
59 struct wcap_rectangle *rect)
60{
61 uint32_t v, *p = decoder->p, *d;
62 int width = rect->x2 - rect->x1, height = rect->y2 - rect->y1;
63 int x, i, j, k, l, count = width * height;
64
65 d = decoder->frame + (rect->y2 - 1) * decoder->width;
66 x = rect->x1;
67 i = 0;
68 while (i < count) {
69 v = *p++;
70 l = v >> 24;
71 if (l < 0xe0) {
72 j = l + 1;
73 } else {
74 j = 1 << (l - 0xe0 + 7);
75 }
76
77 for (k = 0; k < j; k++) {
78 d[x] = (d[x] + v) | 0xff000000;
79 x++;
80 if (x == rect->x2) {
81 x = rect->x1;
82 d -= decoder->width;
83 }
84 }
85 i += j;
86 }
87
88 if (i != count)
89 printf("rle encoding longer than expected (%d expected %d)\n",
90 i, count);
91
92 decoder->p = p;
93}
94
95static int
96wcap_decoder_get_frame(struct wcap_decoder *decoder)
97{
98 struct wcap_rectangle *rects;
99 struct wcap_frame_header *header;
100 uint32_t *s;
101 uint32_t i;
102 int width, height;
103
104 if (decoder->p == decoder->end)
105 return 0;
106
107 header = decoder->p;
108
109 rects = (void *) (header + 1);
110 decoder->p = (uint32_t *) (rects + header->nrects);
111 for (i = 0; i < header->nrects; i++) {
112 width = rects[i].x2 - rects[i].x1;
113 height = rects[i].y2 - rects[i].y1;
114 wcap_decoder_decode_rectangle(decoder, &rects[i]);
115 }
116
117 return 1;
118}
119
120struct wcap_decoder *
121wcap_decoder_create(const char *filename)
122{
123 struct wcap_decoder *decoder;
124 struct wcap_header *header;
125 int frame_size;
126 struct stat buf;
127
128 decoder = malloc(sizeof *decoder);
129 if (decoder == NULL)
130 return NULL;
131
132 decoder->fd = open(filename, O_RDONLY);
133 if (decoder->fd == -1)
134 return NULL;
135
136 fstat(decoder->fd, &buf);
137 decoder->size = buf.st_size;
138 decoder->map = mmap(NULL, decoder->size,
139 PROT_READ, MAP_PRIVATE, decoder->fd, 0);
140
141 header = decoder->map;
142 decoder->width = header->width;
143 decoder->height = header->height;
144 decoder->p = header + 1;
145 decoder->end = decoder->map + decoder->size;
146
147 frame_size = header->width * header->height * 4;
148 decoder->frame = malloc(frame_size);
149 memset(decoder->frame, 0, frame_size);
150
151 return decoder;
152}
153
154void
155wcap_decoder_destroy(struct wcap_decoder *decoder)
156{
157 munmap(decoder->map, decoder->size);
158 free(decoder->frame);
159 free(decoder);
160}
161
162static void
163write_png(struct wcap_decoder *decoder, const char *filename)
164{
165 cairo_surface_t *surface;
166
167 surface = cairo_image_surface_create_for_data((unsigned char *) decoder->frame,
168 CAIRO_FORMAT_ARGB32,
169 decoder->width,
170 decoder->height,
171 decoder->width * 4);
172 cairo_surface_write_to_png(surface, filename);
173 cairo_surface_destroy(surface);
174}
175
176static void
177write_all_pngs(struct wcap_decoder *decoder, int frame)
178{
179 char filename[200];
180 int i;
181
182 i = 0;
183 while (wcap_decoder_get_frame(decoder)) {
184 if (i == frame || frame == -1) {
185 snprintf(filename, sizeof filename,
186 "wcap-frame-%d.png", i);
187 write_png(decoder, filename);
188 printf("wrote %s\n", filename);
189 }
190 i++;
191 }
192}
193
194int main(int argc, char *argv[])
195{
196 struct wcap_decoder *decoder;
197 int i, output_frame;
198
199 if (argc != 2 && argc != 3) {
200 fprintf(stderr, "usage: wcap-decode WCAP_FILE [FRAME]\n");
201 return 1;
202 }
203
204 decoder = wcap_decoder_create(argv[1]);
205 output_frame = -1;
206 if (argc == 3)
207 output_frame = strtol(argv[2], NULL, 0);
208
209 if (0)
210 write_all_pngs(decoder, -1);
211 else
212 write_webm(decoder);
213
214 printf("wcap file: size %dx%d, %d frames\n",
215 decoder->width, decoder->height, i);
216
217 wcap_decoder_destroy(decoder);
218}