File: avi.c

package info (click to toggle)
picturebook 0.0pre3-3
  • links: PTS
  • area: main
  • in suites: woody
  • size: 328 kB
  • ctags: 427
  • sloc: ansic: 2,717; makefile: 55; sh: 37; awk: 31
file content (173 lines) | stat: -rw-r--r-- 4,195 bytes parent folder | download
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
/* a very simple AVI writer - no fancy stuff 
   Tridge, July 2000
*/
/* 
   Copyright (C) Andrew Tridgell 2000
   
   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.
   
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
   
   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/

#include "capture.h"


static int nframes;
static int totalsize;

/* start writing an AVI file */
void avi_start(int fd)
{
	int ofs = sizeof(struct riff_head)+
		sizeof(struct list_head)+
		sizeof(struct avi_head)+
		sizeof(struct list_head)+
		sizeof(struct stream_head)+
		sizeof(struct frame_head)+
		sizeof(struct list_head);

	lseek(fd, ofs, SEEK_SET);

	nframes = 0;
	totalsize = 0;
}


/* add a jpeg frame to an AVI file */
void avi_add(int fd, u8 *buf, int size)
{
	struct db_head db = {"00db", size};
	write(fd, &db, sizeof(db));
	write(fd, buf, size);
	nframes++;
	totalsize += size;
}

/* finish writing the AVI file - filling in the header */
void avi_end(int fd, int width, int height, int fps)
{
	struct riff_head rh = {"RIFF", 0, "AVI "};
	struct list_head lh1 = {"LIST", 0, "hdrl"};
	struct avi_head ah;
	struct list_head lh2 = {"LIST", 0, "strl"};
	struct stream_head sh;
	struct frame_head fh;
	struct list_head lh3 = {"LIST", 0, "movi"};

	bzero(&ah, sizeof(ah));
	strcpy(ah.avih, "avih");
	ah.time = 1e6 / fps;
	ah.numstreams = 1;
	ah.scale = 1;
	ah.rate = fps;
	ah.length = fps * nframes;

	bzero(&sh, sizeof(sh));
	strcpy(sh.strh, "strh");
	strcpy(sh.vids, "vids");
	strcpy(sh.codec, "MJPG");
	sh.scale = 1;
	sh.rate = fps;
	sh.length = fps * nframes;
	sh.quality = -1;

	bzero(&fh, sizeof(fh));
	strcpy(fh.strf, "strf");
	fh.width = width;
	fh.height = height;
	fh.planes = 1;
	fh.bitcount = 24;
	strcpy(fh.codec,"MJPG");
	fh.unpackedsize = 3*width*height;

	rh.size = sizeof(lh1)+sizeof(ah)+sizeof(lh2)+sizeof(sh)+
		sizeof(fh)+sizeof(lh3)+
		nframes*sizeof(struct db_head)+
		totalsize;
	lh1.size = 4+sizeof(ah)+sizeof(lh2)+sizeof(sh)+sizeof(fh);
	ah.size = sizeof(ah)-8;
	lh2.size = 4+sizeof(sh)+sizeof(fh);
	sh.size = sizeof(sh)-8;
	fh.size = sizeof(fh)-8;
	fh.size2 = fh.size;
	lh3.size = 4+
		nframes*sizeof(struct db_head)+
		totalsize;

	lseek(fd, 0, SEEK_SET);
	
	write(fd, &rh, sizeof(rh));
	write(fd, &lh1, sizeof(lh1));
	write(fd, &ah, sizeof(ah));
	write(fd, &lh2, sizeof(lh2));
	write(fd, &sh, sizeof(sh));
	write(fd, &fh, sizeof(fh));
	write(fd, &lh3, sizeof(lh3));
}


/* NOTE: This is not a general purpose routine - it is meant to only
   cope with AVIs saved using the other functions in this file */
void avi_explode(char *fname)
{
	struct riff_head rh;
	struct list_head lh1;
	struct avi_head ah;
	struct list_head lh2;
	struct stream_head sh;
	struct frame_head fh;
	struct list_head lh3;
	int hsize, qsize;
	u16 *htables = jpeg_huffman_tables(&hsize);
	u16 *qtables = jpeg_quantisation_tables(&qsize, image_quality);
	int fd, i;

	fd = open(fname,O_RDONLY);
	if (fd == -1) {
		perror(fname);
		return;
	}

	read(fd, &rh, sizeof(rh));
	read(fd, &lh1, sizeof(lh1));
	read(fd, &ah, sizeof(ah));
	read(fd, &lh2, sizeof(lh2));
	read(fd, &sh, sizeof(sh));
	read(fd, &fh, sizeof(fh));
	read(fd, &lh3, sizeof(lh3));
	
	for (i=0; ; i++) {
		u8 buf[500*1024];
		struct db_head db;
		char fname[100];
		int fd2;

		if (read(fd, &db, sizeof(db)) != sizeof(db) ||
		    read(fd, buf, db.size) != db.size) break;

		snprintf(fname, sizeof(fname)-1,"frame.%d", i);

		fd2 = open(fname,O_WRONLY|O_CREAT, 0644);
		if (fd2 == -1) {
			perror(fname);
			continue;
		}
		write(fd2, buf, 2);
		write(fd2, qtables, qsize);
		write(fd2, htables, hsize);
		write(fd2, buf+2, db.size-2);
		close(fd2);
	}
	close(fd);
	printf("exploded %d frames\n", i);
}