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