ViewVC Help
View File | Revision Log | Show Annotations | Root Listing
root/cvs/xvidcore/examples/xvid_enc_dec.c
Revision: 1.1.1.1 (vendor branch)
Committed: Fri Mar 8 02:44:28 2002 UTC (22 years, 7 months ago) by Isibaar
Content type: text/plain
Branch: core
CVS Tags: start
Changes since 1.1: +0 -0 lines
Error occurred while calculating annotation data.
Log Message:
moved sources

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 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 }