[svn] / trunk / xvidcore / examples / xvid_enc_dec.c Repository:
ViewVC logotype

Annotation of /trunk/xvidcore/examples/xvid_enc_dec.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3 - (view) (download)

1 : Isibaar 3 /**************************************************************************
2 :     *
3 :     * XVID MPEG-4 VIDEO CODEC - Example for encoding and decoding
4 :     *
5 :     * This program is free software; you can redistribute it and/or modify
6 :     * it under the terms of the GNU General Public License as published by
7 :     * the Free Software Foundation; either version 2 of the License, or
8 :     * (at your option) any later version.
9 :     *
10 :     * This program is distributed in the hope that it will be useful,
11 :     * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 :     * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 :     * GNU General Public License for more details.
14 :     *
15 :     * You should have received a copy of the GNU General Public License
16 :     * along with this program; if not, write to the Free Software
17 :     * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 :     *
19 :     *************************************************************************/
20 :    
21 :     /************************************************************************
22 :     *
23 :     * Test routine for XviD using the XviD-API
24 :     * (C) Christoph Lampert, 2002/01/19
25 :     *
26 :     * A sequence of YUV pics in PGM file format is encoded and decoded
27 :     *
28 :     * The program is plain C and needs no libraries except for libxvidcore,
29 :     * so with UN*X you simply compile by
30 :     *
31 :     * gcc -o xvid_enc_dec xvid_enc_dec.c -lxvidcore
32 :     *
33 :     * Run without parameters, then PGM input input is read from stdin.
34 :     *
35 :     * PGM/xvid-output is saved, if corresponding flags are set
36 :     *
37 :     * input data can be generated e.g. out of MPEG2 with mpeg2dec -o pgmpipe
38 :     *
39 :     ************************************************************************/
40 :    
41 :     #include <stdio.h>
42 :     #include <stdint.h>
43 :     #include <malloc.h>
44 :    
45 :     #include "xvid.h" /* comes with XviD */
46 :    
47 :     #define ARG_FRAMERATE 25
48 :     #define ARG_BITRATE 900
49 :    
50 :     int QUALITY =5;
51 :    
52 :     int XDIM=0;
53 :     int YDIM=0; // will be set when reading first image
54 :     int filenr = 0;
55 :    
56 :     int save_m4v_flag = 0; // save MPEG4-bytestream?
57 :     int save_dec_flag = 0; // save decompressed bytestream?
58 :     char filepath[256] = "./"; // path where to save output
59 :    
60 :     void *enchandle = NULL;
61 :     void *dechandle = NULL;
62 :    
63 :     /*********************************************************************/
64 :     /* Routines for file input/output, nothing specific to XviD */
65 :     /*********************************************************************/
66 :    
67 :     int read_pgmheader(FILE* handle)
68 :     { int bytes,xsize,ysize,depth;
69 :     char dummy[2];
70 :    
71 :     bytes = fread(dummy,1,2,handle);
72 :    
73 :     if ( (bytes < 2) || (dummy[0] != 'P') || (dummy[1] != '5' ))
74 :     return 1;
75 :     fscanf(handle,"%d %d %d",&xsize,&ysize,&depth);
76 :     if ( (xsize > 1440) || (ysize > 2880 ) || (depth != 255) )
77 :     {
78 :     fprintf(stderr,"%d %d %d\n",XDIM,YDIM,depth);
79 :     return 2;
80 :     }
81 :     if ( (XDIM==0) || (YDIM==0) )
82 :     { XDIM=xsize;
83 :     YDIM=ysize;
84 :     }
85 :    
86 :     return 0;
87 :     }
88 :    
89 :     int read_pgmdata(FILE* handle, unsigned char *image)
90 :     { int i;
91 :     char dummy;
92 :    
93 :     unsigned char* buff1_ptr2 = image + XDIM*YDIM;
94 :     unsigned char* buff1_ptr3 = image + XDIM*YDIM + XDIM/2*YDIM/2;
95 :    
96 :     fread(image,XDIM,YDIM,stdin);
97 :    
98 :     for (i=0;i<YDIM/2;i++)
99 :     {
100 :     fread(buff1_ptr2,XDIM/2,1,stdin);
101 :     buff1_ptr2 += XDIM/2;
102 :     fread(buff1_ptr3,XDIM/2,1,stdin);
103 :     buff1_ptr3 += XDIM/2;
104 :     }
105 :     fread(&dummy,1,1,handle); // should be EOF
106 :     return 0;
107 :     }
108 :    
109 :    
110 :     /*********************************************************************/
111 :     /* Routines for encoding: init encoder, frame step, release encoder */
112 :     /*********************************************************************/
113 :    
114 :     #define FRAMERATE_INCR 1001
115 :     int enc_init()
116 :     {
117 :     int xerr;
118 :    
119 :     XVID_INIT_PARAM xinit;
120 :     XVID_ENC_PARAM xparam;
121 :    
122 :     xinit.cpu_flags = 0;
123 :     xvid_init(NULL, 0, &xinit, NULL);
124 :    
125 :     xparam.width = XDIM;
126 :     xparam.height = YDIM;
127 :     if ((ARG_FRAMERATE - (int)ARG_FRAMERATE) == 0)
128 :     {
129 :     xparam.fincr = 1;
130 :     xparam.fbase = (int)ARG_FRAMERATE;
131 :     }
132 :     else
133 :     {
134 :     xparam.fincr = FRAMERATE_INCR;
135 :     xparam.fbase = (int)(FRAMERATE_INCR * ARG_FRAMERATE);
136 :     }
137 :     xparam.bitrate = ARG_BITRATE*1000;
138 :     xparam.rc_period = 2000;
139 :     xparam.rc_reaction_period = 10;
140 :     xparam.rc_reaction_ratio = 20;
141 :     xparam.min_quantizer = 1;
142 :     xparam.max_quantizer = 31;
143 :     xparam.max_key_interval = (int)ARG_FRAMERATE*10;
144 :     xparam.motion_search = QUALITY;
145 :     xparam.lum_masking = 0; // Luminance Masking is still under development
146 :     xparam.quant_type = 0; // 0=h.263, 1=mpeg4
147 :    
148 :     xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xparam, NULL);
149 :     enchandle=xparam.handle;
150 :    
151 :     return xerr;
152 :     }
153 :    
154 :     int enc_stop()
155 :     { int xerr;
156 :    
157 :     xerr = xvid_encore(enchandle, XVID_ENC_DESTROY, NULL, NULL);
158 :     return xerr;
159 :     }
160 :    
161 :     int enc_main(unsigned char* image, unsigned char* bitstream, int *streamlength)
162 :     { int xerr;
163 :    
164 :     XVID_ENC_FRAME xframe;
165 :     XVID_ENC_STATS xstats;
166 :    
167 :     xframe.bitstream = bitstream;
168 :     xframe.length = -1; // this is written by the routine
169 :    
170 :     xframe.image = image;
171 :     xframe.colorspace = XVID_CSP_YV12; // defined in <xvid.h>
172 :    
173 :     xframe.intra = -1; // let the codec decide between I-frame (1) and P-frame (0)
174 :     xframe.quant = 0;
175 :     // xframe.quant = QUANTI; // is quant != 0, use a fixed quant (and ignore bitrate)
176 :    
177 :    
178 :     xerr = xvid_encore(enchandle, XVID_ENC_ENCODE, &xframe, &xstats);
179 :    
180 :     /* enc_result->is_key_frame = xframe.intra;
181 :     enc_result->quantizer = xframe.quant;
182 :     enc_result->total_bits = xframe.length * 8;
183 :     enc_result->motion_bits = xstats.hlength * 8;
184 :     enc_result->texture_bits = enc_result->total_bits - enc_result->motion_bits;
185 :     */
186 :    
187 :     /* This is statictical data, e.g. for 2-pass.
188 :     If you are not interested in any of this, you can use NULL instead of &xstats
189 :     */
190 :    
191 :     *streamlength = xframe.length;
192 :    
193 :     return xerr;
194 :     }
195 :    
196 :    
197 :     /*********************************************************************/
198 :     /* Routines for decoding: init encoder, frame step, release encoder */
199 :     /*********************************************************************/
200 :    
201 :     int dec_init()
202 :     {
203 :     int xerr;
204 :    
205 :     XVID_INIT_PARAM xinit;
206 :     XVID_DEC_PARAM xparam;
207 :    
208 :     xinit.cpu_flags = 0;
209 :     xvid_init(NULL, 0, &xinit, NULL);
210 :     xparam.width = XDIM;
211 :     xparam.height = YDIM;
212 :    
213 :     xerr = xvid_decore(NULL, XVID_DEC_CREATE, &xparam, NULL);
214 :     dechandle = xparam.handle;
215 :    
216 :     return xerr;
217 :     }
218 :    
219 :     int dec_main(unsigned char *m4v_buffer, unsigned char *rgb_buffer, int m4v_size)
220 :     {
221 :     int xerr;
222 :    
223 :     XVID_DEC_FRAME xframe;
224 :    
225 :     xframe.bitstream = m4v_buffer;
226 :     xframe.length = m4v_size;
227 :     xframe.image = rgb_buffer;
228 :     xframe.stride = XDIM;
229 :     xframe.colorspace = XVID_CSP_RGB24; // XVID_CSP_USER is fastest (no memcopy involved)
230 :    
231 :     /*
232 :     xframe.colorspace = XVID_CSP_NULL; // use this if you want to skip a frame (no output)
233 :     */
234 :    
235 :     xerr = xvid_decore(dechandle, XVID_DEC_DECODE, &xframe, NULL);
236 :    
237 :     return xerr;
238 :     }
239 :    
240 :     int dec_stop()
241 :     {
242 :     int xerr;
243 :     xerr = xvid_decore(dechandle, XVID_DEC_DESTROY, NULL, NULL);
244 :    
245 :     return xerr;
246 :     }
247 :    
248 :    
249 :     /*********************************************************************/
250 :     /* Main program */
251 :     /*********************************************************************/
252 :    
253 :     int main()
254 :     {
255 :     unsigned char *divx_buffer = NULL;
256 :     unsigned char *yuv_buffer = NULL;
257 :     unsigned char *rgb_buffer = NULL;
258 :    
259 :     int status;
260 :     int frame_size;
261 :     int m4v_size;
262 :    
263 :     char filename[256];
264 :    
265 :     FILE *filehandle;
266 :    
267 :     /* read YUV in pgm format from stdin */
268 :     if (read_pgmheader(stdin))
269 :     {
270 :     printf("Wrong input format, I want YUV encapsulated in PGM\n");
271 :     return 0;
272 :     }
273 :    
274 :     /* now we know the sizes, so allocate memory */
275 :    
276 :     yuv_buffer = (unsigned char *) malloc(XDIM*YDIM);
277 :     if (!yuv_buffer)
278 :     goto free_all_memory; // goto is one of the most underestimated instructions in C !!!
279 :    
280 :     divx_buffer = (unsigned char *) malloc(XDIM*YDIM*2); // this should really be enough!
281 :     if (!divx_buffer)
282 :     goto free_all_memory; // actually, every program should contain at least one goto
283 :    
284 :     YDIM = YDIM*2/3; // PGM is YUV 4:2:0 format, so real image height is *2/3 of PGM picture
285 :    
286 :     rgb_buffer = (unsigned char *) malloc(XDIM*YDIM*4);
287 :     if (!rgb_buffer)
288 :     goto free_all_memory; // but the more, the better!
289 :    
290 :     /*********************************************************************/
291 :     /* DIVX PART Start */
292 :     /*********************************************************************/
293 :    
294 :     status = enc_init();
295 :     // if (status)
296 :     printf("Encore INIT return %d, handle=%lx\n", status, enchandle);
297 :    
298 :     status = dec_init();
299 :     // if (status)
300 :     printf("Decore INIT return %d\n", status);
301 :    
302 :    
303 :     /*********************************************************************/
304 :     /* Main loop */
305 :     /*********************************************************************/
306 :    
307 :     do
308 :     {
309 :     status = read_pgmdata(stdin, yuv_buffer); // read PGM data (YUV-format)
310 :     if (status)
311 :     {
312 :     fprintf(stderr, "Couldn't read PGM body: %d\n", status); /* this should not happen */
313 :     continue;
314 :     }
315 :    
316 :     /*********************************************************************/
317 :     /* encode and decode this frame */
318 :     /*********************************************************************/
319 :    
320 :     status = enc_main(yuv_buffer, divx_buffer, &m4v_size);
321 :    
322 :     printf("Frame %5d: encore-ENCODE status %d, m4v-stream length=%7d bytes\n",
323 :     filenr, status, m4v_size);
324 :    
325 :     if (save_m4v_flag)
326 :     {
327 :     sprintf(filename, "%sframe%05d.m4v", filepath, filenr);
328 :     filehandle = fopen(filename, "wb");
329 :     fwrite(divx_buffer, m4v_size, 1, filehandle);
330 :     fclose(filehandle);
331 :     }
332 :    
333 :     status = dec_main(divx_buffer, rgb_buffer, m4v_size);
334 :     if (status)
335 :     printf("Frame %5d: decore status %d\n",status);
336 :    
337 :     if (save_dec_flag)
338 :     {
339 :     sprintf(filename, "%sdec%05d.ppm", filepath, filenr);
340 :     filehandle=fopen(filename,"wb");
341 :     if (filehandle)
342 :     {
343 :     fprintf(filehandle,"P6\n"); // rgb24 in PPM format
344 :     fprintf(filehandle,"%d %d 255\n",XDIM,YDIM);
345 :     fwrite(rgb_buffer,XDIM,YDIM*3,filehandle);
346 :     fclose(filehandle);
347 :     }
348 :     }
349 :    
350 :     filenr++;
351 :     status = read_pgmheader(stdin); // if it was the last PGM, stop after it
352 :     if (status)
353 :     {
354 :     fprintf(stderr, "Couldn't read next PGM header: %d\n", status); /* normally, just end of file */
355 :     }
356 :     }
357 :     while (!status);
358 :    
359 :     /*********************************************************************/
360 :     /* DIVX PART Stop */
361 :     /*********************************************************************/
362 :    
363 :     dec_stop();
364 :     // if (status)
365 :     printf("Encore RELEASE return %d\n", status);
366 :    
367 :     enc_stop();
368 :     // if (status)
369 :     printf("Decore RELEASE return %d\n", status);
370 :    
371 :     free_all_memory:
372 :    
373 :     if (rgb_buffer)
374 :     free(rgb_buffer);
375 :     if (divx_buffer)
376 :     free(divx_buffer);
377 :     if (yuv_buffer)
378 :     free(yuv_buffer);
379 :    
380 :     return 0;
381 :     }

No admin address has been configured
ViewVC Help
Powered by ViewVC 1.0.4