[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 123 - (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 XDIM=0;
51 :     int YDIM=0; // will be set when reading first image
52 :     int filenr = 0;
53 :    
54 :     int save_m4v_flag = 0; // save MPEG4-bytestream?
55 :     int save_dec_flag = 0; // save decompressed bytestream?
56 :     char filepath[256] = "./"; // path where to save output
57 :    
58 :     void *enchandle = NULL;
59 :     void *dechandle = NULL;
60 :    
61 :     /*********************************************************************/
62 :     /* Routines for file input/output, nothing specific to XviD */
63 :     /*********************************************************************/
64 :    
65 :     int read_pgmheader(FILE* handle)
66 :     { int bytes,xsize,ysize,depth;
67 :     char dummy[2];
68 :    
69 :     bytes = fread(dummy,1,2,handle);
70 :    
71 :     if ( (bytes < 2) || (dummy[0] != 'P') || (dummy[1] != '5' ))
72 :     return 1;
73 :     fscanf(handle,"%d %d %d",&xsize,&ysize,&depth);
74 :     if ( (xsize > 1440) || (ysize > 2880 ) || (depth != 255) )
75 :     {
76 :     fprintf(stderr,"%d %d %d\n",XDIM,YDIM,depth);
77 :     return 2;
78 :     }
79 :     if ( (XDIM==0) || (YDIM==0) )
80 :     { XDIM=xsize;
81 :     YDIM=ysize;
82 :     }
83 :    
84 :     return 0;
85 :     }
86 :    
87 :     int read_pgmdata(FILE* handle, unsigned char *image)
88 :     { int i;
89 :     char dummy;
90 :    
91 :     unsigned char* buff1_ptr2 = image + XDIM*YDIM;
92 :     unsigned char* buff1_ptr3 = image + XDIM*YDIM + XDIM/2*YDIM/2;
93 :    
94 :     fread(image,XDIM,YDIM,stdin);
95 :    
96 :     for (i=0;i<YDIM/2;i++)
97 :     {
98 :     fread(buff1_ptr2,XDIM/2,1,stdin);
99 :     buff1_ptr2 += XDIM/2;
100 :     fread(buff1_ptr3,XDIM/2,1,stdin);
101 :     buff1_ptr3 += XDIM/2;
102 :     }
103 :     fread(&dummy,1,1,handle); // should be EOF
104 :     return 0;
105 :     }
106 :    
107 :    
108 :     /*********************************************************************/
109 :     /* Routines for encoding: init encoder, frame step, release encoder */
110 :     /*********************************************************************/
111 :    
112 :     #define FRAMERATE_INCR 1001
113 :     int enc_init()
114 :     {
115 :     int xerr;
116 :    
117 :     XVID_INIT_PARAM xinit;
118 :     XVID_ENC_PARAM xparam;
119 :    
120 :     xinit.cpu_flags = 0;
121 :     xvid_init(NULL, 0, &xinit, NULL);
122 :    
123 :     xparam.width = XDIM;
124 :     xparam.height = YDIM;
125 :     if ((ARG_FRAMERATE - (int)ARG_FRAMERATE) == 0)
126 :     {
127 :     xparam.fincr = 1;
128 :     xparam.fbase = (int)ARG_FRAMERATE;
129 :     }
130 :     else
131 :     {
132 :     xparam.fincr = FRAMERATE_INCR;
133 :     xparam.fbase = (int)(FRAMERATE_INCR * ARG_FRAMERATE);
134 :     }
135 : h 123 xparam.rc_bitrate = ARG_BITRATE*1000;
136 :     xparam.rc_reaction_delay_factor = 16;
137 :     xparam.rc_averaging_period = 100;
138 :     xparam.rc_buffer = 100;
139 : Isibaar 50 xparam.min_quantizer = 2;
140 : Isibaar 3 xparam.max_quantizer = 31;
141 :     xparam.max_key_interval = (int)ARG_FRAMERATE*10;
142 :    
143 :     xerr = xvid_encore(NULL, XVID_ENC_CREATE, &xparam, NULL);
144 :     enchandle=xparam.handle;
145 :    
146 :     return xerr;
147 :     }
148 :    
149 :     int enc_stop()
150 :     { int xerr;
151 :    
152 :     xerr = xvid_encore(enchandle, XVID_ENC_DESTROY, NULL, NULL);
153 :     return xerr;
154 :     }
155 :    
156 :     int enc_main(unsigned char* image, unsigned char* bitstream, int *streamlength)
157 :     { int xerr;
158 :    
159 :     XVID_ENC_FRAME xframe;
160 :     XVID_ENC_STATS xstats;
161 :    
162 : Isibaar 50 // general features
163 :     xframe.general = XVID_H263QUANT; // we use h.263 quantisation
164 :     // xframe.general = XVID_MPEGQUANT; // MPEG quantization
165 :    
166 :     xframe.general |= XVID_HALFPEL; // halfpel precision
167 :     xframe.general |= XVID_INTER4V; // four motion vector mode
168 :    
169 :     // motion estimation (pmvfast) settings
170 :     xframe.motion = PMV_HALFPELREFINE16 | PMV_EARLYSTOP16 |
171 :     PMV_HALFPELDIAMOND8 | PMV_EARLYSTOP8;
172 :    
173 : Isibaar 3 xframe.bitstream = bitstream;
174 :     xframe.length = -1; // this is written by the routine
175 :    
176 :     xframe.image = image;
177 : Isibaar 50 xframe.colorspace = XVID_CSP_YV12; // defined in <xvid.h>
178 : Isibaar 3
179 : Isibaar 50 xframe.intra = -1; // let the codec decide between I-frame (1) and P-frame (0)
180 : Isibaar 3 xframe.quant = 0;
181 :     // xframe.quant = QUANTI; // is quant != 0, use a fixed quant (and ignore bitrate)
182 :    
183 :    
184 :     xerr = xvid_encore(enchandle, XVID_ENC_ENCODE, &xframe, &xstats);
185 :    
186 :     /* enc_result->is_key_frame = xframe.intra;
187 :     enc_result->quantizer = xframe.quant;
188 :     enc_result->total_bits = xframe.length * 8;
189 :     enc_result->motion_bits = xstats.hlength * 8;
190 :     enc_result->texture_bits = enc_result->total_bits - enc_result->motion_bits;
191 :     */
192 :    
193 :     /* This is statictical data, e.g. for 2-pass.
194 :     If you are not interested in any of this, you can use NULL instead of &xstats
195 :     */
196 :    
197 :     *streamlength = xframe.length;
198 :    
199 :     return xerr;
200 :     }
201 :    
202 :    
203 :     /*********************************************************************/
204 :     /* Routines for decoding: init encoder, frame step, release encoder */
205 :     /*********************************************************************/
206 :    
207 :     int dec_init()
208 :     {
209 :     int xerr;
210 :    
211 :     XVID_INIT_PARAM xinit;
212 :     XVID_DEC_PARAM xparam;
213 :    
214 :     xinit.cpu_flags = 0;
215 :     xvid_init(NULL, 0, &xinit, NULL);
216 :     xparam.width = XDIM;
217 :     xparam.height = YDIM;
218 :    
219 :     xerr = xvid_decore(NULL, XVID_DEC_CREATE, &xparam, NULL);
220 :     dechandle = xparam.handle;
221 :    
222 :     return xerr;
223 :     }
224 :    
225 :     int dec_main(unsigned char *m4v_buffer, unsigned char *rgb_buffer, int m4v_size)
226 :     {
227 :     int xerr;
228 :    
229 :     XVID_DEC_FRAME xframe;
230 :    
231 :     xframe.bitstream = m4v_buffer;
232 :     xframe.length = m4v_size;
233 :     xframe.image = rgb_buffer;
234 :     xframe.stride = XDIM;
235 :     xframe.colorspace = XVID_CSP_RGB24; // XVID_CSP_USER is fastest (no memcopy involved)
236 :    
237 :     /*
238 :     xframe.colorspace = XVID_CSP_NULL; // use this if you want to skip a frame (no output)
239 :     */
240 :    
241 :     xerr = xvid_decore(dechandle, XVID_DEC_DECODE, &xframe, NULL);
242 :    
243 :     return xerr;
244 :     }
245 :    
246 :     int dec_stop()
247 :     {
248 :     int xerr;
249 :     xerr = xvid_decore(dechandle, XVID_DEC_DESTROY, NULL, NULL);
250 :    
251 :     return xerr;
252 :     }
253 :    
254 :    
255 :     /*********************************************************************/
256 :     /* Main program */
257 :     /*********************************************************************/
258 :    
259 :     int main()
260 :     {
261 :     unsigned char *divx_buffer = NULL;
262 :     unsigned char *yuv_buffer = NULL;
263 :     unsigned char *rgb_buffer = NULL;
264 :    
265 :     int status;
266 :     int frame_size;
267 :     int m4v_size;
268 :    
269 :     char filename[256];
270 :    
271 :     FILE *filehandle;
272 :    
273 :     /* read YUV in pgm format from stdin */
274 :     if (read_pgmheader(stdin))
275 :     {
276 :     printf("Wrong input format, I want YUV encapsulated in PGM\n");
277 :     return 0;
278 :     }
279 :    
280 :     /* now we know the sizes, so allocate memory */
281 :    
282 :     yuv_buffer = (unsigned char *) malloc(XDIM*YDIM);
283 :     if (!yuv_buffer)
284 :     goto free_all_memory; // goto is one of the most underestimated instructions in C !!!
285 :    
286 :     divx_buffer = (unsigned char *) malloc(XDIM*YDIM*2); // this should really be enough!
287 :     if (!divx_buffer)
288 :     goto free_all_memory; // actually, every program should contain at least one goto
289 :    
290 :     YDIM = YDIM*2/3; // PGM is YUV 4:2:0 format, so real image height is *2/3 of PGM picture
291 :    
292 :     rgb_buffer = (unsigned char *) malloc(XDIM*YDIM*4);
293 :     if (!rgb_buffer)
294 :     goto free_all_memory; // but the more, the better!
295 :    
296 :     /*********************************************************************/
297 :     /* DIVX PART Start */
298 :     /*********************************************************************/
299 :    
300 :     status = enc_init();
301 :     // if (status)
302 :     printf("Encore INIT return %d, handle=%lx\n", status, enchandle);
303 :    
304 :     status = dec_init();
305 :     // if (status)
306 :     printf("Decore INIT return %d\n", status);
307 :    
308 :    
309 :     /*********************************************************************/
310 :     /* Main loop */
311 :     /*********************************************************************/
312 :    
313 :     do
314 :     {
315 :     status = read_pgmdata(stdin, yuv_buffer); // read PGM data (YUV-format)
316 :     if (status)
317 :     {
318 :     fprintf(stderr, "Couldn't read PGM body: %d\n", status); /* this should not happen */
319 :     continue;
320 :     }
321 :    
322 :     /*********************************************************************/
323 :     /* encode and decode this frame */
324 :     /*********************************************************************/
325 :    
326 :     status = enc_main(yuv_buffer, divx_buffer, &m4v_size);
327 :    
328 :     printf("Frame %5d: encore-ENCODE status %d, m4v-stream length=%7d bytes\n",
329 :     filenr, status, m4v_size);
330 :    
331 :     if (save_m4v_flag)
332 :     {
333 :     sprintf(filename, "%sframe%05d.m4v", filepath, filenr);
334 :     filehandle = fopen(filename, "wb");
335 :     fwrite(divx_buffer, m4v_size, 1, filehandle);
336 :     fclose(filehandle);
337 :     }
338 :    
339 :     status = dec_main(divx_buffer, rgb_buffer, m4v_size);
340 :     if (status)
341 :     printf("Frame %5d: decore status %d\n",status);
342 :    
343 :     if (save_dec_flag)
344 :     {
345 :     sprintf(filename, "%sdec%05d.ppm", filepath, filenr);
346 :     filehandle=fopen(filename,"wb");
347 :     if (filehandle)
348 :     {
349 :     fprintf(filehandle,"P6\n"); // rgb24 in PPM format
350 :     fprintf(filehandle,"%d %d 255\n",XDIM,YDIM);
351 :     fwrite(rgb_buffer,XDIM,YDIM*3,filehandle);
352 :     fclose(filehandle);
353 :     }
354 :     }
355 :    
356 :     filenr++;
357 :     status = read_pgmheader(stdin); // if it was the last PGM, stop after it
358 :     if (status)
359 :     {
360 :     fprintf(stderr, "Couldn't read next PGM header: %d\n", status); /* normally, just end of file */
361 :     }
362 :     }
363 :     while (!status);
364 :    
365 :     /*********************************************************************/
366 :     /* DIVX PART Stop */
367 :     /*********************************************************************/
368 :    
369 :     dec_stop();
370 :     // if (status)
371 :     printf("Encore RELEASE return %d\n", status);
372 :    
373 :     enc_stop();
374 :     // if (status)
375 :     printf("Decore RELEASE return %d\n", status);
376 :    
377 :     free_all_memory:
378 :    
379 :     if (rgb_buffer)
380 :     free(rgb_buffer);
381 :     if (divx_buffer)
382 :     free(divx_buffer);
383 :     if (yuv_buffer)
384 :     free(yuv_buffer);
385 :    
386 :     return 0;
387 :     }

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