1 /*
2  * sample6.c
3  * Copyright (C) 2003      Regis Duchesne <hpreg@zoy.org>
4  * Copyright (C) 2000-2003 Michel Lespinasse <walken@zoy.org>
5  * Copyright (C) 1999-2000 Aaron Holtzman <aholtzma@ess.engr.uvic.ca>
6  *
7  * This file is part of mpeg2dec, a free MPEG-2 video stream decoder.
8  * See http://libmpeg2.sourceforge.net/ for updates.
9  *
10  * mpeg2dec is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  *
15  * mpeg2dec is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
23  *
24  * This program reads a MPEG-2 stream, and saves each of its frames as
25  * an image file using the PPM format (color).
26  *
27  * It demonstrates how to use the following features of libmpeg2:
28  * - Output buffers use the RGB 24-bit chunky format.
29  * - Output buffers are allocated and managed by the caller.
30  */
31 
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <inttypes.h>
35 
36 #include "mpeg2.h"
37 #include "mpeg2convert.h"
38 
save_ppm(int width,int height,uint8_t * buf,int num)39 static void save_ppm (int width, int height, uint8_t * buf, int num)
40 {
41     char filename[100];
42     FILE * ppmfile;
43 
44     sprintf (filename, "%d.ppm", num);
45     ppmfile = fopen (filename, "wb");
46     if (!ppmfile) {
47 	fprintf (stderr, "Could not open file \"%s\".\n", filename);
48 	exit (1);
49     }
50     fprintf (ppmfile, "P6\n%d %d\n255\n", width, height);
51     fwrite (buf, 3 * width, height, ppmfile);
52     fclose (ppmfile);
53 }
54 
55 static struct fbuf_s {
56     uint8_t * rgb[3];
57     int used;
58 } fbuf[3];
59 
get_fbuf(void)60 static struct fbuf_s * get_fbuf (void)
61 {
62     int i;
63 
64     for (i = 0; i < 3; i++)
65 	if (!fbuf[i].used) {
66 	    fbuf[i].used = 1;
67 	    return fbuf + i;
68 	}
69     fprintf (stderr, "Could not find a free fbuf.\n");
70     exit (1);
71 }
72 
sample6(FILE * mpgfile)73 static void sample6 (FILE * mpgfile)
74 {
75 #define BUFFER_SIZE 4096
76     uint8_t buffer[BUFFER_SIZE];
77     mpeg2dec_t * decoder;
78     const mpeg2_info_t * info;
79     mpeg2_state_t state;
80     size_t size;
81     int framenum = 0;
82     int pixels;
83     int i;
84     struct fbuf_s * current_fbuf;
85 
86     decoder = mpeg2_init ();
87     if (decoder == NULL) {
88 	fprintf (stderr, "Could not allocate a decoder object.\n");
89 	exit (1);
90     }
91     info = mpeg2_info (decoder);
92 
93     size = (size_t)-1;
94     do {
95 	state = mpeg2_parse (decoder);
96 	switch (state) {
97 	case STATE_BUFFER:
98 	    size = fread (buffer, 1, BUFFER_SIZE, mpgfile);
99 	    mpeg2_buffer (decoder, buffer, buffer + size);
100 	    break;
101 	case STATE_SEQUENCE:
102 	    mpeg2_convert (decoder, mpeg2convert_rgb24, NULL);
103 	    mpeg2_custom_fbuf (decoder, 1);
104 	    pixels = info->sequence->width * info->sequence->height;
105 	    for (i = 0; i < 3; i++) {
106 		fbuf[i].rgb[0] = (uint8_t *) malloc (3 * pixels);
107 		fbuf[i].rgb[1] = fbuf[i].rgb[2] = NULL;
108 		if (!fbuf[i].rgb[0]) {
109 		    fprintf (stderr, "Could not allocate an output buffer.\n");
110 		    exit (1);
111 		}
112 		fbuf[i].used = 0;
113 	    }
114 	    for (i = 0; i < 2; i++) {
115 		current_fbuf = get_fbuf ();
116 		mpeg2_set_buf (decoder, current_fbuf->rgb, current_fbuf);
117 	    }
118 	    break;
119 	case STATE_PICTURE:
120 	    current_fbuf = get_fbuf ();
121 	    mpeg2_set_buf (decoder, current_fbuf->rgb, current_fbuf);
122 	    break;
123 	case STATE_SLICE:
124 	case STATE_END:
125 	case STATE_INVALID_END:
126 	    if (info->display_fbuf)
127 		save_ppm (info->sequence->width, info->sequence->height,
128 			  info->display_fbuf->buf[0], framenum++);
129 	    if (info->discard_fbuf)
130                 ((struct fbuf_s *)info->discard_fbuf->id)->used = 0;
131 	    if (state != STATE_SLICE)
132 		for (i = 0; i < 3; i++)
133 		    free (fbuf[i].rgb[0]);
134 	    break;
135 	default:
136 	    break;
137 	}
138     } while (size);
139 
140     mpeg2_close (decoder);
141 }
142 
main(int argc,char ** argv)143 int main (int argc, char ** argv)
144 {
145     FILE * mpgfile;
146 
147     if (argc > 1) {
148 	mpgfile = fopen (argv[1], "rb");
149 	if (!mpgfile) {
150 	    fprintf (stderr, "Could not open file \"%s\".\n", argv[1]);
151 	    exit (1);
152 	}
153     } else
154 	mpgfile = stdin;
155 
156     sample6 (mpgfile);
157 
158     return 0;
159 }
160