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

Annotation of /trunk/xvidcore/examples/odivx_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 OpenDivX/Divx4-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 odivx_enc_dec odivx_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 <malloc.h>
43 :    
44 :     #include "encore2.h"
45 :     #include "decore.h" /* these come with XviD */
46 :    
47 :     #define ARG_FRAMERATE 25
48 :     #define ARG_BITRATE 900
49 :    
50 :     int QUALITY =5;
51 :     int QUANTI = 0; // used for fixed-quantizer encoding
52 :    
53 :     int XDIM=0;
54 :     int YDIM=0; // will be set when reading first image
55 :     int filenr = 0;
56 :    
57 :     int save_m4v_flag = 0; // save MPEG4-bytestream?
58 :     int save_dec_flag = 0; // save decompressed bytestream?
59 :     char filepath[256] = "."; // path where to save
60 :    
61 :     void *enchandle = NULL; // enchandle is a void*, written by encore
62 :     const long dechandle = 0x0815; // dechandle is a unique constant!!!
63 :    
64 :     /*********************************************************************/
65 :     /* Routines for file input/output, nothing specific to XviD */
66 :     /*********************************************************************/
67 :    
68 :     int read_pgmheader(FILE* handle)
69 :     { int bytes,xsize,ysize,depth;
70 :     char dummy[2];
71 :    
72 :     bytes = fread(dummy,1,2,handle);
73 :    
74 :     if ( (bytes < 2) || (dummy[0] != 'P') || (dummy[1] != '5' ))
75 :     return 1;
76 :     fscanf(handle,"%d %d %d",&xsize,&ysize,&depth);
77 :     if ( (xsize > 1440) || (ysize > 2880 ) || (depth != 255) )
78 :     {
79 :     fprintf(stderr,"%d %d %d\n",XDIM,YDIM,depth);
80 :     return 2;
81 :     }
82 :     if ( (XDIM==0) || (YDIM==0) )
83 :     { XDIM=xsize;
84 :     YDIM=ysize;
85 :     }
86 :    
87 :     return 0;
88 :     }
89 :    
90 :     int read_pgmdata(FILE* handle, unsigned char *image)
91 :     { int i;
92 :     char dummy;
93 :    
94 :     unsigned char* buff1_ptr2 = image + XDIM*YDIM;
95 :     unsigned char* buff1_ptr3 = image + XDIM*YDIM + XDIM/2*YDIM/2;
96 :    
97 :     fread(image,XDIM,YDIM,stdin);
98 :    
99 :     for (i=0;i<YDIM/2;i++)
100 :     {
101 :     fread(buff1_ptr2,XDIM/2,1,stdin);
102 :     buff1_ptr2 += XDIM/2;
103 :     fread(buff1_ptr3,XDIM/2,1,stdin);
104 :     buff1_ptr3 += XDIM/2;
105 :     }
106 :     fread(&dummy,1,1,handle); // should be EOF
107 :     return 0;
108 :     }
109 :    
110 :    
111 :     /*********************************************************************/
112 :     /* Routines for encoding: init encoder, frame step, release encoder */
113 :     /*********************************************************************/
114 :    
115 :     #define FRAMERATE_INCR 1001
116 :     int enc_init()
117 :     {
118 :     int status;
119 :     ENC_PARAM enc_param;
120 :    
121 :     enc_param.x_dim = XDIM;
122 :     enc_param.y_dim = YDIM;
123 :     enc_param.framerate = ARG_FRAMERATE; // a float
124 :     enc_param.bitrate = ARG_BITRATE*1000;
125 :    
126 :     enc_param.rc_period = 2000;
127 :     enc_param.rc_reaction_period = 10;
128 :     enc_param.rc_reaction_ratio = 20;
129 :    
130 :     enc_param.max_quantizer = 31;
131 :     enc_param.min_quantizer = 1;
132 :    
133 :     enc_param.quality = QUALITY;
134 :    
135 :     enc_param.use_bidirect = 0; // use bidirectional coding
136 :     enc_param.deinterlace = 0; // fast deinterlace
137 :     enc_param.obmc = 0; // flag to enable overlapped block motion compensation mode
138 :    
139 :     enc_param.max_key_interval = (int)ARG_FRAMERATE*10;
140 :     enc_param.handle = NULL; //will be filled by encore
141 :    
142 :     status = encore(enchandle, ENC_OPT_INIT, &enc_param, NULL);
143 :     enchandle = enc_param.handle;
144 :    
145 :     // if (status)
146 :     printf("Encore INIT return %d, handle=%lx\n", status, enchandle);
147 :    
148 :     return status;
149 :     }
150 :    
151 :     int enc_stop()
152 :     { int status;
153 :    
154 :     status = encore(enchandle, ENC_OPT_RELEASE, NULL, NULL);
155 :     // if (status)
156 :     printf("Encore RELEASE return %d\n", status);
157 :    
158 :     return status;
159 :     }
160 :    
161 :     int enc_main(unsigned char* image, unsigned char* bitstream, int *streamlength)
162 :     { int status;
163 :    
164 :     ENC_FRAME enc_frame;
165 :     ENC_RESULT enc_result;
166 :    
167 :     enc_frame.image = (void *) image;
168 :     enc_frame.bitstream = (void *) bitstream;
169 :     enc_frame.length = 0; // filled by encore
170 :     enc_frame.colorspace = ENC_CSP_YV12; // input is YUV
171 :     enc_frame.mvs = NULL; // unsupported
172 :    
173 :     if (QUANTI==0)
174 :     {
175 :     status = encore(enchandle, ENC_OPT_ENCODE, &enc_frame, &enc_result);
176 :     }
177 :     else
178 :     { enc_frame.quant = QUANTI;
179 :     enc_frame.intra = -1; // let encoder decide if frame is INTER/INTRA
180 :     status = encore(enchandle, ENC_OPT_ENCODE_VBR, &enc_frame, &enc_result);
181 :     }
182 :    
183 :     /* ENC_OPT_ENCODE is used to encode using ratecontrol alg. and bitrate from enc_init,
184 :     ENC_OPT_ENCODE_VBR is used to encode with fixed quantizer and INTER/INTRA mode
185 :     */
186 :    
187 :     *streamlength = enc_frame.length;
188 :    
189 :     return status;
190 :     }
191 :    
192 :    
193 :     /*********************************************************************/
194 :     /* Routines for decoding: init encoder, frame step, release encoder */
195 :     /*********************************************************************/
196 :    
197 :     int dec_init()
198 :     {
199 :     int status;
200 :    
201 :     DEC_PARAM dec_param;
202 :     DEC_SET dec_set;
203 :    
204 :     dec_param.x_dim = XDIM;
205 :     dec_param.y_dim = YDIM;
206 :     dec_param.output_format = DEC_RGB24; // output color format, , see <decore.h>
207 :    
208 :     dec_param.time_incr = 20;
209 :    
210 :     status = decore(dechandle, DEC_OPT_INIT, &dec_param, NULL);
211 :     // if (status)
212 :     printf("Decore INIT return %d\n", status);
213 :    
214 :     // We don't do any postprocessing here...
215 :    
216 :     /* dec_set.postproc_level = 0;
217 :     status = decore(dechandle, DEC_OPT_SETPP, &dec_set, NULL);
218 :     if (status)
219 :     printf("Decore POSTPROC %d return %d\n", dec_set.postproc_level, status);
220 :     */
221 :    
222 :     return status;
223 :     }
224 :    
225 :     int dec_main(unsigned char *m4v_buffer, unsigned char *rgb_buffer, int m4v_size)
226 :     {
227 :     int status;
228 :    
229 :     static DEC_FRAME dec_frame;
230 :     static DEC_FRAME_INFO dec_frame_info;
231 :    
232 :     dec_frame.length = m4v_size;
233 :     dec_frame.bitstream = m4v_buffer;
234 :     dec_frame.bmp = rgb_buffer;
235 :     dec_frame.render_flag = 1; // 0 means: skip this frame
236 :     dec_frame.stride = XDIM;
237 :    
238 :     status = decore(dechandle, DEC_OPT_FRAME, &dec_frame, &dec_frame_info);
239 :     if (status)
240 :     printf("Decore Frame status %d!\n", status);
241 :    
242 :     return status;
243 :     }
244 :    
245 :     int dec_stop()
246 :     {
247 :     int status;
248 :     status = decore(dechandle, DEC_OPT_RELEASE, NULL, NULL);
249 :     // if (status)
250 :     printf("Decore RELEASE return %d\n", status);
251 :     return status;
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 :     yuv_buffer = (unsigned char *) malloc(XDIM*YDIM);
282 :     if (!yuv_buffer)
283 :     goto free_all_memory; // goto is one of the most underestimated instructions in C !!!
284 :     divx_buffer = (unsigned char *) malloc(XDIM*YDIM*2); // this should really be enough!
285 :     if (!divx_buffer)
286 :     goto free_all_memory; // actually, every program should contain a goto
287 :    
288 :     YDIM = YDIM*2/3; // PGM is YUV 4:2:0 format, so height is *3/2 too much
289 :    
290 :     rgb_buffer = (unsigned char *) malloc(XDIM*YDIM*4);
291 :     if (!rgb_buffer)
292 :     goto free_all_memory; // the more, the better!
293 :    
294 :     /*********************************************************************/
295 :     /* DIVX PART Start */
296 :     /*********************************************************************/
297 :    
298 :     status = enc_init();
299 :     // if (status)
300 :     printf("Encore INIT return %d, handle=%lx\n", status, enchandle);
301 :    
302 :     status = dec_init();
303 :     // if (status)
304 :     printf("Decore INIT return %d\n", status);
305 :    
306 :    
307 :     /*********************************************************************/
308 :     /* Main loop */
309 :     /*********************************************************************/
310 :    
311 :     do
312 :     {
313 :     status = read_pgmdata(stdin, yuv_buffer); // read PGM data (YUV-format)
314 :     if (status)
315 :     {
316 :     fprintf(stderr, "PGM-Data-Error: %d\n", status); /* this should not happen */
317 :     continue;
318 :     }
319 :    
320 :     /*********************************************************************/
321 :     /* encode and decode this frame */
322 :     /*********************************************************************/
323 :    
324 :     status = enc_main(yuv_buffer, divx_buffer, &m4v_size);
325 :    
326 :     printf("Frame %5d: encore-ENCODE status %d, m4v-stream length=%7d bytes\n",
327 :     filenr, status, m4v_size);
328 :    
329 :     if (save_m4v_flag)
330 :     {
331 :     sprintf(filename, "%s/frame%05d.m4v", filepath, filenr);
332 :     filehandle = fopen(filename, "wb");
333 :     fwrite(divx_buffer, m4v_size, 1, filehandle);
334 :     fclose(filehandle);
335 :     }
336 :    
337 :     status = dec_main(divx_buffer, rgb_buffer, m4v_size);
338 :     if (status)
339 :     printf("Frame %5d: decore status %d\n",status);
340 :    
341 :     if (save_dec_flag)
342 :     {
343 :     sprintf(filename, "%s/dec%05d.ppm", filepath, filenr);
344 :     filehandle=fopen(filename,"wb");
345 :     if (filehandle)
346 :     {
347 :     fprintf(filehandle,"P6\n"); // rgb24 in PPM format
348 :     fprintf(filehandle,"%d %d 255\n",XDIM,YDIM);
349 :     fwrite(rgb_buffer,XDIM,YDIM*3,filehandle);
350 :     fclose(filehandle);
351 :     }
352 :     }
353 :    
354 :     filenr++;
355 :     status = read_pgmheader(stdin); // if it was the last PGM, stop after it
356 :     if (status)
357 :     {
358 :     fprintf(stderr, "PGM-Header-Error: %d\n", status); /* normally, just end of file */
359 :     }
360 :     }
361 :     while (!status);
362 :    
363 :    
364 :     /*********************************************************************/
365 :     /* DIVX PART Stop */
366 :     /*********************************************************************/
367 :    
368 :    
369 :     /* Stop XviD */
370 :    
371 :     dec_stop();
372 :     // if (status)
373 :     printf("Encore RELEASE return %d\n", status);
374 :    
375 :     enc_stop();
376 :     // if (status)
377 :     printf("Decore RELEASE return %d\n", status);
378 :    
379 :     free_all_memory:
380 :    
381 :     if (rgb_buffer)
382 :     free(rgb_buffer);
383 :     if (divx_buffer)
384 :     free(divx_buffer);
385 :     if (yuv_buffer)
386 :     free(yuv_buffer);
387 :    
388 :     return 0;
389 :     }

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