ViewVC Help
View File | Revision Log | Show Annotations | View Changeset | Root Listing
root/svn/trunk/xvidcore/examples/odivx_enc_dec.c
Revision: 860
Committed: Sun Feb 16 05:11:39 2003 UTC (21 years, 7 months ago) by suxen_drol
Content type: text/plain
File size: 11097 byte(s)
Log Message:
futher portab.h, ARCH_IS_xxx fixes

File Contents

# Content
1 /**************************************************************************
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 "divx4.h"
45
46 #define ARG_FRAMERATE 25
47 #define ARG_BITRATE 900
48
49 int QUALITY =5;
50 int QUANTI = 0; // used for fixed-quantizer encoding
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
59
60 void *enchandle = NULL; // enchandle is a void*, written by encore
61 const long dechandle = 0x0815; // dechandle is a unique constant!!!
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 status;
118 ENC_PARAM enc_param;
119
120 enc_param.x_dim = XDIM;
121 enc_param.y_dim = YDIM;
122 enc_param.framerate = ARG_FRAMERATE; // a float
123 enc_param.bitrate = ARG_BITRATE*1000;
124
125 enc_param.rc_period = 2000;
126 enc_param.rc_reaction_period = 10;
127 enc_param.rc_reaction_ratio = 20;
128
129 enc_param.max_quantizer = 31;
130 enc_param.min_quantizer = 1;
131
132 enc_param.quality = QUALITY;
133
134 enc_param.use_bidirect = 0; // use bidirectional coding
135 enc_param.deinterlace = 0; // fast deinterlace
136 enc_param.obmc = 0; // flag to enable overlapped block motion compensation mode
137
138 enc_param.max_key_interval = (int)ARG_FRAMERATE*10;
139 enc_param.handle = NULL; //will be filled by encore
140
141 status = encore(enchandle, ENC_OPT_INIT, &enc_param, NULL);
142 enchandle = enc_param.handle;
143
144 // if (status)
145 printf("Encore INIT return %d, handle=%lx\n", status, enchandle);
146
147 return status;
148 }
149
150 int enc_stop()
151 { int status;
152
153 status = encore(enchandle, ENC_OPT_RELEASE, NULL, NULL);
154 // if (status)
155 printf("Encore RELEASE return %d\n", status);
156
157 return status;
158 }
159
160 int enc_main(unsigned char* image, unsigned char* bitstream, int *streamlength)
161 { int status;
162
163 ENC_FRAME enc_frame;
164 ENC_RESULT enc_result;
165
166 enc_frame.image = (void *) image;
167 enc_frame.bitstream = (void *) bitstream;
168 enc_frame.length = 0; // filled by encore
169 enc_frame.colorspace = ENC_CSP_YV12; // input is YUV
170 enc_frame.mvs = NULL; // unsupported
171
172 if (QUANTI==0)
173 {
174 status = encore(enchandle, ENC_OPT_ENCODE, &enc_frame, &enc_result);
175 }
176 else
177 { enc_frame.quant = QUANTI;
178 enc_frame.intra = -1; // let encoder decide if frame is INTER/INTRA
179 status = encore(enchandle, ENC_OPT_ENCODE_VBR, &enc_frame, &enc_result);
180 }
181
182 /* ENC_OPT_ENCODE is used to encode using ratecontrol alg. and bitrate from enc_init,
183 ENC_OPT_ENCODE_VBR is used to encode with fixed quantizer and INTER/INTRA mode
184 */
185
186 *streamlength = enc_frame.length;
187
188 return status;
189 }
190
191
192 /*********************************************************************/
193 /* Routines for decoding: init encoder, frame step, release encoder */
194 /*********************************************************************/
195
196 int dec_init()
197 {
198 int status;
199
200 DEC_PARAM dec_param;
201 DEC_SET dec_set;
202
203 dec_param.x_dim = XDIM;
204 dec_param.y_dim = YDIM;
205 dec_param.output_format = DEC_RGB24; // output color format, , see <decore.h>
206
207 dec_param.time_incr = 20;
208
209 status = decore(dechandle, DEC_OPT_INIT, &dec_param, NULL);
210 // if (status)
211 printf("Decore INIT return %d\n", status);
212
213 // We don't do any postprocessing here...
214
215 /* dec_set.postproc_level = 0;
216 status = decore(dechandle, DEC_OPT_SETPP, &dec_set, NULL);
217 if (status)
218 printf("Decore POSTPROC %d return %d\n", dec_set.postproc_level, status);
219 */
220
221 return status;
222 }
223
224 int dec_main(unsigned char *m4v_buffer, unsigned char *rgb_buffer, int m4v_size)
225 {
226 int status;
227
228 static DEC_FRAME dec_frame;
229 static DEC_FRAME_INFO dec_frame_info;
230
231 dec_frame.length = m4v_size;
232 dec_frame.bitstream = m4v_buffer;
233 dec_frame.bmp = rgb_buffer;
234 dec_frame.render_flag = 1; // 0 means: skip this frame
235 dec_frame.stride = XDIM;
236
237 status = decore(dechandle, DEC_OPT_FRAME, &dec_frame, &dec_frame_info);
238 if (status)
239 printf("Decore Frame status %d!\n", status);
240
241 return status;
242 }
243
244 int dec_stop()
245 {
246 int status;
247 status = decore(dechandle, DEC_OPT_RELEASE, NULL, NULL);
248 // if (status)
249 printf("Decore RELEASE return %d\n", status);
250 return status;
251 }
252
253
254 /*********************************************************************/
255 /* Main program */
256 /*********************************************************************/
257
258 int main()
259 {
260 unsigned char *divx_buffer = NULL;
261 unsigned char *yuv_buffer = NULL;
262 unsigned char *rgb_buffer = NULL;
263
264 int status;
265 int frame_size;
266 int m4v_size;
267
268 char filename[256];
269
270 FILE *filehandle;
271
272 /* read YUV in pgm format from stdin */
273 if (read_pgmheader(stdin))
274 {
275 printf("Wrong input format, I want YUV encapsulated in PGM\n");
276 return 0;
277 }
278
279 /* now we know the sizes, so allocate memory */
280 yuv_buffer = (unsigned char *) malloc(XDIM*YDIM);
281 if (!yuv_buffer)
282 goto free_all_memory; // goto is one of the most underestimated instructions in C !!!
283 divx_buffer = (unsigned char *) malloc(XDIM*YDIM*2); // this should really be enough!
284 if (!divx_buffer)
285 goto free_all_memory; // actually, every program should contain a goto
286
287 YDIM = YDIM*2/3; // PGM is YUV 4:2:0 format, so height is *3/2 too much
288
289 rgb_buffer = (unsigned char *) malloc(XDIM*YDIM*4);
290 if (!rgb_buffer)
291 goto free_all_memory; // the more, the better!
292
293 /*********************************************************************/
294 /* DIVX PART Start */
295 /*********************************************************************/
296
297 status = enc_init();
298 // if (status)
299 printf("Encore INIT return %d, handle=%lx\n", status, enchandle);
300
301 status = dec_init();
302 // if (status)
303 printf("Decore INIT return %d\n", status);
304
305
306 /*********************************************************************/
307 /* Main loop */
308 /*********************************************************************/
309
310 do
311 {
312 status = read_pgmdata(stdin, yuv_buffer); // read PGM data (YUV-format)
313 if (status)
314 {
315 fprintf(stderr, "PGM-Data-Error: %d\n", status); /* this should not happen */
316 continue;
317 }
318
319 /*********************************************************************/
320 /* encode and decode this frame */
321 /*********************************************************************/
322
323 status = enc_main(yuv_buffer, divx_buffer, &m4v_size);
324
325 printf("Frame %5d: encore-ENCODE status %d, m4v-stream length=%7d bytes\n",
326 filenr, status, m4v_size);
327
328 if (save_m4v_flag)
329 {
330 sprintf(filename, "%s/frame%05d.m4v", filepath, filenr);
331 filehandle = fopen(filename, "wb");
332 fwrite(divx_buffer, m4v_size, 1, filehandle);
333 fclose(filehandle);
334 }
335
336 status = dec_main(divx_buffer, rgb_buffer, m4v_size);
337 if (status)
338 printf("Frame %5d: decore status %d\n",status);
339
340 if (save_dec_flag)
341 {
342 sprintf(filename, "%s/dec%05d.ppm", filepath, filenr);
343 filehandle=fopen(filename,"wb");
344 if (filehandle)
345 {
346 fprintf(filehandle,"P6\n"); // rgb24 in PPM format
347 fprintf(filehandle,"%d %d 255\n",XDIM,YDIM);
348 fwrite(rgb_buffer,XDIM,YDIM*3,filehandle);
349 fclose(filehandle);
350 }
351 }
352
353 filenr++;
354 status = read_pgmheader(stdin); // if it was the last PGM, stop after it
355 if (status)
356 {
357 fprintf(stderr, "PGM-Header-Error: %d\n", status); /* normally, just end of file */
358 }
359 }
360 while (!status);
361
362
363 /*********************************************************************/
364 /* DIVX PART Stop */
365 /*********************************************************************/
366
367
368 /* Stop XviD */
369
370 dec_stop();
371 // if (status)
372 printf("Encore RELEASE return %d\n", status);
373
374 enc_stop();
375 // if (status)
376 printf("Decore RELEASE return %d\n", status);
377
378 free_all_memory:
379
380 if (rgb_buffer)
381 free(rgb_buffer);
382 if (divx_buffer)
383 free(divx_buffer);
384 if (yuv_buffer)
385 free(yuv_buffer);
386
387 return 0;
388 }