5
* Copyright (C) 1998 Rasca, Berlin
8
* This program is free software; you can redistribute it and/or modify
9
* it under the terms of the GNU General Public License as published by
10
* the Free Software Foundation; either version 2 of the License, or
11
* (at your option) any later version.
13
* This program is distributed in the hope that it will be useful,
14
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16
* GNU General Public License for more details.
18
* You should have received a copy of the GNU General Public License
19
* along with this program; if not, write to the Free Software
20
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
31
usage (char *progname)
39
"-o <output> <input-files ..>\n", progname);
44
* read ppm header of a rawbits ppm file (P6)
47
read_ppm_header (FILE *fp, int *width, int *height)
53
fgets (buff, 128, fp);
56
printf ("Warning.. not a binary ppm file?\n");
57
} else if ((*buff != '#') && (*buff != '\n')) {
59
sscanf (buff, "%d %d", width, height);
60
fgets (buff, 128, fp);
65
if (*width && *height)
71
* todo: renaming of structures
74
write_moov_atom (FILE *fp, int width, int height, int num_frames, int tpf,
85
gt_hdlr_atom *minf_hdlr;
86
gt_hdlr_atom *mdia_hdlr;
97
/* sample description atom */
98
stsd = gt_alloc_atom (GTA_sample_desc, 1);
100
stsd->tab->size = 86;
101
stsd->tab->format = format;
102
stsd->tab->index = 1; /* points to an entry in 'dref' */
103
stsd->tab->width = width;
104
stsd->tab->height = height;
105
stsd->tab->hres.high = 72;
106
stsd->tab->vres.high = 72;
107
stsd->tab->frame_count = 1;
108
strcpy (stsd->tab->comp_name+1, GT_COMP_RAW);
109
stsd->tab->comp_name[0] = strlen (GT_COMP_RAW);
110
stsd->tab->depth =24;
111
stsd->tab->ctab_id = -1;
112
/* time to sample atom */
113
stts = gt_alloc_atom (GTA_time_to_sample, 1);
115
stts->tab->num_samples = num_frames;
116
stts->tab->duration = tpf;
117
/* sample to chunk */
118
stsc = gt_alloc_atom (GTA_sample_to_chunk, 1);
120
stsc->tab->first_chunk = 1;
121
stsc->tab->samples_per_chunk = stts->tab->num_samples;
122
stsc->tab->sample_id = 1; /* point to the first entry in the stsd tab!? */
123
/* sample size atom .. */
124
stsz = gt_alloc_atom (GTA_sample_size, num_frames);
125
stsz->sample_size = 0;
126
stsz->count = num_frames;
127
for (i = 0; i < num_frames; i++ ) {
128
stsz->tab[i].size = width * height * 3;
130
/* sample chunk offset atom */
131
stco = gt_alloc_atom (GTA_chunk_offset, 1);
133
stco->tab[0].offset = 0; /* offset of mdat */
135
stbl = gt_alloc_atom (GTA_sample_table, 5);
137
stbl->suba[0] = (gt_atom*)stsd;
138
stbl->suba[1] = (gt_atom*)stts;
139
stbl->suba[2] = (gt_atom*)stsc;
140
stbl->suba[3] = (gt_atom*)stsz;
141
stbl->suba[4] = (gt_atom*)stco;
143
stsd->size + stts->size + stsc->size + stsz->size + stco->size;
144
/* video media information header */
145
vmhd = gt_alloc_atom (GTA_video_media_header, 0);
147
/* data handler reference atom ??? */
148
minf_hdlr = gt_alloc_atom (GTA_handler_ref, 0);
149
minf_hdlr->comp_type = GT_DATA_REF;
150
minf_hdlr->comp_subtype = GT_ALIAS;
151
minf_hdlr->comp_man = GT_COMP_MAN;
153
dref = gt_alloc_atom (GTA_data_ref, 1);
155
dref->tab->size = 12;
156
dref->tab->type = GT_ALIAS;
157
dref->tab->flags[2]= 0x01; /* self reference */
159
dinf = gt_alloc_atom (GTA_data_info, 1);
161
dinf->suba[0] = (gt_atom *)dref;
162
dinf->size = 8 + dref->size;
164
/* media information atom */
165
minf = gt_alloc_atom (GTA_media_info, 4);
167
minf->suba[0] = (gt_atom *)vmhd;
168
minf->suba[1] = (gt_atom *)minf_hdlr;
169
minf->suba[2] = (gt_atom *)dinf;
170
minf->suba[3] = (gt_atom *)stbl;
171
minf->size += vmhd->size + minf_hdlr->size + dinf->size + stbl->size;
173
mdhd = gt_alloc_atom (GTA_media_header, 0);
174
mdhd->ctime = gt_time();
175
mdhd->mtime = gt_time();
176
mdhd->time_scale = 1000;
177
mdhd->duration = tpf * num_frames;
178
/* media handler reference atom */
179
mdia_hdlr = gt_alloc_atom (GTA_handler_ref, strlen(GT_MID_HDLR_NAME));
180
mdia_hdlr->comp_type = GT_MEDIA_REF;
181
mdia_hdlr->comp_subtype = GT_VIDEO;
182
mdia_hdlr->comp_man = GT_COMP_MAN;
183
mdia_hdlr->comp_flags = 0x40000000; /* ? */
184
mdia_hdlr->comp_flags_mask = 0x00010047; /* ? */
185
strcpy (mdia_hdlr->comp_name+1, GT_MID_HDLR_NAME);
186
mdia_hdlr->comp_name[0] = strlen (GT_MID_HDLR_NAME);
187
mdia_hdlr->size = 32 + 1 +strlen (GT_MID_HDLR_NAME);
189
mdia = gt_alloc_atom (GTA_media, 3);
191
mdia->suba[0] = (gt_atom *)mdhd;
192
mdia->suba[1] = (gt_atom *)mdia_hdlr;
193
mdia->suba[2] = (gt_atom *)minf;
194
mdia->size += mdhd->size + mdia_hdlr->size + minf->size;
196
tkhd = gt_alloc_atom (GTA_track_header,0);
197
tkhd->flags[2] = (char)(0x01 | 0x02);
198
tkhd->ctime = gt_time();
199
tkhd->mtime = gt_time();
201
tkhd->duration = tpf * num_frames;
202
tkhd->matrix[1] = 1; /* 1/1/1 */
203
tkhd->matrix[17] = 1;
204
tkhd->matrix[32] = 64;
205
tkhd->width.high = width;
206
tkhd->height.high= height;
208
trak = gt_alloc_atom (GTA_track, 2);
210
trak->suba[0] = (gt_atom *)tkhd;
211
trak->suba[1] = (gt_atom *)mdia;
212
trak->size += tkhd->size + mdia->size;
214
mvhd = gt_alloc_atom (GTA_movie_header, 0);
215
mvhd->ctime = gt_time();
216
mvhd->mtime = gt_time();
217
mvhd->time_scale = 1000;
218
mvhd->duration = tkhd->duration;
219
mvhd->pref_rate.high = 1;
220
mvhd->matrix[1] = 1; /* 1/1/1 */
221
mvhd->matrix[17] = 1;
222
mvhd->matrix[32] = 64;
223
mvhd->next_track_id = 2;
225
no space for the text pointers is provided! */
226
udta = gt_alloc_atom (GTA_user_data, 3);
227
udta->tab[0]->type = GT_UD_INFO;
228
udta->tab[0]->tlen = strlen ("Made by 'ppm2qt'");
229
udta->tab[0]->size = 8 + 4 + udta->tab[0]->tlen;
230
udta->tab[0]->text = "Made by 'ppm2qt'";
231
udta->tab[1]->type = GT_UD_PRODUCER;
232
udta->tab[1]->tlen = strlen ("ppm2qt User");
233
udta->tab[1]->size = 8 + 4 + udta->tab[1]->tlen;
234
udta->tab[1]->text = "ppm2qt User";
235
udta->tab[2]->type = GT_UD_LOOP;
236
udta->tab[2]->size = 8;
237
udta->size = 8 +udta->tab[0]->size +udta->tab[1]->size +udta->tab[2]->size;
238
/* movie atom, with 3 subatoms */
239
moov = gt_alloc_atom (GTA_movie, 3);
241
moov->suba[0] = (gt_atom *)mvhd;
242
moov->suba[1] = (gt_atom *)udta;
243
moov->suba[2] = (gt_atom *)trak;
244
moov->size += mvhd->size + udta->size + trak->size;
245
stco->tab[0].offset = moov->size + 8 ; /* offset of mdat */
246
if (!gt_write_atom (moov, fp)) {
247
perror ("write_moov_atom()");
254
* ppm2qt, all frames must have the same size and must
255
* be an raw ppm file..
258
main (int argc, char *argv[]) {
259
int c, num_frames, verbose = 0;
260
int width = 0, height = 0;
261
int y, i, ti, time_per_frame=40;
262
char *outfile = NULL, *infile = NULL;
265
int input_is_jpeg = 0;
266
int format = GT_VID_FMT_RAW;
270
while ((c = getopt (argc, argv, "?ho:vt:js:")) != EOF) {
279
/* default = 40 tpf =~ 25 fps */
280
time_per_frame = atoi(optarg);
284
format = GT_VID_FMT_JPEG;
287
sscanf (optarg, "%dx%d", &width, &height);
296
num_frames = argc - optind;
297
if (!outfile || !num_frames)
300
if (input_is_jpeg && (!width || !height)) {
301
fprintf (stderr, "You must specify the size!\n");
303
} else if (!input_is_jpeg) {
304
/* read the first file to get the size
306
if (width || height) {
307
fprintf (stderr, "Size option only allowed for ppm files\n");
310
infile = argv[optind];
312
printf ("reading size from '%s'\n", infile);
313
if ((fp = fopen (infile, "rb")) == NULL) {
318
if (!read_ppm_header (fp, &width, &height)) {
319
printf ("%s: not a ppm file?\n", infile);
323
buf = malloc (width * height * 3);
325
if (!width || !height) {
326
printf ("failed! no width or height found\n");
331
if ((outfp = fopen (outfile, "wb")) == NULL) {
337
moov = write_moov_atom (outfp,
338
width, height, num_frames, time_per_frame, format);
339
/* write mdat size/atom type
341
gt_write4byte (8 + num_frames * width * height * 3, outfp);
342
gt_write4byte (GTA_movie_data, outfp);
344
line = malloc (width * 3);
345
/* loop for every frame
347
for (i = 0; i < num_frames; i++) {
348
infile = argv[optind+i];
350
printf ("infile = '%s'\n", infile);
351
if ((fp = fopen (infile, "rb")) == NULL) {
357
len = fread (buf, 1, width * height * 3, fp);
358
fwrite (buf, 1, len, outfp);
362
suba[1] -> /* mdia */
363
suba[2] -> /* minf */
364
suba[3] -> /* stbl */
365
suba[3]))-> /* stsz */
368
if (!read_ppm_header (fp, &ti, &ti)) {
369
printf ("%s: no ppm file?\n", infile);
371
for (y = 0; y < height; y++) {
372
fread (line, 1, width*3, fp);
373
fwrite (line, 1, width * 3, outfp);
380
fseek (outfp, 0, SEEK_SET);
381
gt_write_atom (moov, outfp);