2 * Copyright © 2012 Intel Corporation
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.
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.
30 #include <sys/types.h>
39 #include "wcap-decode.h"
42 write_png(struct wcap_decoder *decoder, const char *filename)
44 cairo_surface_t *surface;
46 surface = cairo_image_surface_create_for_data((unsigned char *) decoder->frame,
51 cairo_surface_write_to_png(surface, filename);
52 cairo_surface_destroy(surface);
56 rgb_to_yuv(uint32_t format, uint32_t p, int *u, int *v)
61 case WCAP_FORMAT_XRGB8888:
66 case WCAP_FORMAT_XBGR8888:
75 y = (19595 * r + 38469 * g + 7472 * b) >> 16;
79 *u += 46727 * (r - y);
80 *v += 36962 * (b - y);
88 int clamp = (u >> 18) + 128;
99 convert_to_yv12(struct wcap_decoder *decoder, unsigned char *out)
101 unsigned char *y1, *y2, *u, *v;
102 uint32_t *p1, *p2, *end;
103 int i, u_accum, v_accum, stride0, stride1;
104 uint32_t format = decoder->format;
106 stride0 = decoder->width;
107 stride1 = decoder->width / 2;
108 for (i = 0; i < decoder->height; i += 2) {
109 y1 = out + stride0 * i;
111 v = out + stride0 * decoder->height + stride1 * i / 2;
112 u = v + stride1 * decoder->height / 2;
113 p1 = decoder->frame + decoder->width * i;
114 p2 = p1 + decoder->width;
115 end = p1 + decoder->width;
120 y1[0] = rgb_to_yuv(format, p1[0], &u_accum, &v_accum);
121 y1[1] = rgb_to_yuv(format, p1[1], &u_accum, &v_accum);
122 y2[0] = rgb_to_yuv(format, p2[0], &u_accum, &v_accum);
123 y2[1] = rgb_to_yuv(format, p2[1], &u_accum, &v_accum);
124 u[0] = clamp_uv(u_accum);
125 v[0] = clamp_uv(v_accum);
138 convert_to_yuv444(struct wcap_decoder *decoder, unsigned char *out)
141 unsigned char *yp, *up, *vp;
144 int i, stride, psize;
145 uint32_t format = decoder->format;
147 stride = decoder->width;
148 psize = stride * decoder->height;
149 for (i = 0; i < decoder->height; i++) {
150 yp = out + stride * i;
151 up = yp + (psize * 2);
152 vp = yp + (psize * 1);
153 rp = decoder->frame + decoder->width * i;
154 end = rp + decoder->width;
158 yp[0] = rgb_to_yuv(format, rp[0], &u, &v);
159 up[0] = clamp_uv(u/.3);
160 vp[0] = clamp_uv(v/.3);
170 output_yuv_frame(struct wcap_decoder *decoder, int depth)
172 static unsigned char *out;
176 size = decoder->width * decoder->height * 3;
178 size = decoder->width * decoder->height * 3 / 2;
184 convert_to_yuv444(decoder, out);
186 convert_to_yv12(decoder, out);
190 fwrite(out, 1, size, stdout);
196 fprintf(stderr, "usage: wcap-decode "
197 "[--help] [--yuv4mpeg2] [--frame=<frame>] [--all] \n"
198 "\t[--rate=<num:denom>] <wcap file>\n\n"
199 "\t--help\t\t\tthis help text\n"
200 "\t--yuv4mpeg2\t\tdump wcap file to stdout in yuv4mpeg2 format\n"
201 "\t--yuv4mpeg2-444\t\tdump wcap file to stdout in yuv4mpeg2 444 format\n"
202 "\t--frame=<frame>\t\twrite out the given frame number as png\n"
203 "\t--all\t\t\twrite all frames as pngs\n"
204 "\t--rate=<num:denom>\treplay frame rate for yuv4mpeg2,\n"
205 "\t\t\t\tspecified as an integer fraction\n\n");
210 int main(int argc, char *argv[])
212 struct wcap_decoder *decoder;
213 int i, j, output_frame = -1, yuv4mpeg2 = 0, all = 0, has_frame;
214 int num = 30, denom = 1;
217 uint32_t msecs, frame_time;
219 for (i = 1, j = 1; i < argc; i++) {
220 if (strcmp(argv[i], "--yuv4mpeg2-444") == 0) {
222 } else if (strcmp(argv[i], "--yuv4mpeg2") == 0) {
224 } else if (strcmp(argv[i], "--help") == 0) {
226 } else if (strcmp(argv[i], "--all") == 0) {
228 } else if (sscanf(argv[i], "--frame=%d", &output_frame) == 1) {
230 } else if (sscanf(argv[i], "--rate=%d", &num) == 1) {
232 } else if (sscanf(argv[i], "--rate=%d:%d", &num, &denom) == 2) {
234 } else if (strcmp(argv[i], "--") == 0) {
236 } else if (argv[i][0] == '-') {
238 "unknown option or invalid argument: %s\n", argv[i]);
249 fprintf(stderr, "invalid rate, denom can not be 0\n");
253 decoder = wcap_decoder_create(argv[1]);
254 if (decoder == NULL) {
255 fprintf(stderr, "Creating wcap decoder failed\n");
259 if (yuv4mpeg2 && isatty(1)) {
260 fprintf(stderr, "Not dumping yuv4mpeg2 data to terminal. Pipe output to a file or a process.\n");
261 fprintf(stderr, "For example, to encode to webm, use something like\n\n");
262 fprintf(stderr, "\t$ wcap-decode --yuv4mpeg2 ../capture.wcap |\n"
263 "\t\tvpxenc --target-bitrate=1024 --best -t 4 -o foo.webm -\n\n");
269 if (yuv4mpeg2 == 444) {
274 printf("YUV4MPEG2 %s W%d H%d F%d:%d Ip A0:0\n",
275 mode, decoder->width, decoder->height, num, denom);
280 has_frame = wcap_decoder_get_frame(decoder);
281 msecs = decoder->msecs;
282 frame_time = 1000 * denom / num;
284 if (all || i == output_frame) {
285 snprintf(filename, sizeof filename,
286 "wcap-frame-%d.png", i);
287 write_png(decoder, filename);
288 fprintf(stderr, "wrote %s\n", filename);
291 output_yuv_frame(decoder, yuv4mpeg2);
294 while (decoder->msecs < msecs && has_frame)
295 has_frame = wcap_decoder_get_frame(decoder);
298 fprintf(stderr, "wcap file: size %dx%d, %d frames\n",
299 decoder->width, decoder->height, i);
301 wcap_decoder_destroy(decoder);