]> git.sesse.net Git - x264/blob - tools/avc2avi.c
Fix a buffer overrun with very long MVs.
[x264] / tools / avc2avi.c
1 /*****************************************************************************
2  * avc2avi.c: raw h264 -> AVI
3  *****************************************************************************
4  * Copyright (C) 2004 Laurent Aimar
5  * $Id: avc2avi.c,v 1.1 2004/06/03 19:27:08 fenrir Exp $
6  *
7  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 #include <stdlib.h>
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdint.h>
28
29 #include <signal.h>
30 #define _GNU_SOURCE
31 #include <getopt.h>
32
33 #ifdef _MSC_VER
34 #include <io.h>     /* _setmode() */
35 #include <fcntl.h>  /* _O_BINARY */
36 #endif
37
38 #include "../common/bs.h"
39
40 #define DATA_MAX 3000000
41 uint8_t data[DATA_MAX];
42
43 /* Ctrl-C handler */
44 static int     i_ctrl_c = 0;
45 static void    SigIntHandler( int a )
46 {
47     i_ctrl_c = 1;
48 }
49
50 typedef struct
51 {
52     char *psz_fin;
53     char *psz_fout;
54
55     float f_fps;
56     char  fcc[4];
57 } cfg_t;
58
59 typedef struct
60 {
61     int i_data;
62     int i_data_max;
63     uint8_t *p_data;
64 } vbuf_t;
65
66 void vbuf_init( vbuf_t * );
67 void vbuf_add( vbuf_t *, int i_data, void *p_data );
68 void vbuf_reset( vbuf_t * );
69
70 typedef struct
71 {
72     FILE *f;
73
74     float f_fps;
75     char  fcc[4];
76
77     int   i_width;
78     int   i_height;
79
80     int64_t i_movi;
81     int64_t i_movi_end;
82     int64_t i_riff;
83
84     int      i_frame;
85     int      i_idx_max;
86     uint32_t *idx;
87 } avi_t;
88
89 void avi_init( avi_t *, FILE *, float, char fcc[4] );
90 void avi_write( avi_t *, vbuf_t *, int  );
91 void avi_end( avi_t * );
92
93 enum nal_unit_type_e
94 {
95     NAL_UNKNOWN = 0,
96     NAL_SLICE   = 1,
97     NAL_SLICE_DPA   = 2,
98     NAL_SLICE_DPB   = 3,
99     NAL_SLICE_DPC   = 4,
100     NAL_SLICE_IDR   = 5,    /* ref_idc != 0 */
101     NAL_SEI         = 6,    /* ref_idc == 0 */
102     NAL_SPS         = 7,
103     NAL_PPS         = 8
104     /* ref_idc == 0 for 6,9,10,11,12 */
105 };
106 enum nal_priority_e
107 {
108     NAL_PRIORITY_DISPOSABLE = 0,
109     NAL_PRIORITY_LOW        = 1,
110     NAL_PRIORITY_HIGH       = 2,
111     NAL_PRIORITY_HIGHEST    = 3,
112 };
113
114 typedef struct
115 {
116     int i_ref_idc;  /* nal_priority_e */
117     int i_type;     /* nal_unit_type_e */
118
119     /* This data are raw payload */
120     int     i_payload;
121     uint8_t *p_payload;
122 } nal_t;
123
124 typedef struct
125 {
126     int i_width;
127     int i_height;
128
129     int i_nal_type;
130     int i_ref_idc;
131     int i_idr_pic_id;
132     int i_frame_num;
133
134     int b_key;
135     int i_log2_max_frame_num;
136 } h264_t;
137
138 void h264_parser_init( h264_t * );
139 void h264_parser_parse( h264_t *h, nal_t *n, int *pb_nal_start );
140
141
142 static int nal_decode( nal_t *nal, void *p_data, int i_data );
143
144 static void Help( void );
145 static int  Parse( int argc, char **argv, cfg_t * );
146 static int  ParseNAL( nal_t *nal, avi_t *a, h264_t *h, int *pb_slice );
147
148 /****************************************************************************
149  * main:
150  ****************************************************************************/
151 int main( int argc, char **argv )
152 {
153     cfg_t cfg;
154
155     FILE    *fout;
156     FILE    *fin;
157
158     vbuf_t  vb;
159     avi_t   avi;
160     h264_t  h264;
161
162     nal_t nal;
163     int i_frame;
164     int i_data;
165     int b_eof;
166     int b_key;
167     int b_slice;
168
169 #ifdef _MSC_VER
170     _setmode(_fileno(stdin), _O_BINARY);    /* thanks to Marcos Morais <morais at dee.ufcg.edu.br> */
171     _setmode(_fileno(stdout), _O_BINARY);
172 #endif
173
174     /* Parse command line */
175     if( Parse( argc, argv, &cfg ) < 0 )
176     {
177         return -1;
178     }
179
180     /* Open input */
181     if( cfg.psz_fin == NULL || *cfg.psz_fin == '\0' || !strcmp( cfg.psz_fin, "-" ) )
182         fin = stdin;
183     else
184         fin = fopen( cfg.psz_fin, "rb" );
185     if( fin == NULL )
186     {
187         fprintf( stderr, "cannot open input file\n" );
188         return -1;
189     }
190
191     /* Open output */
192     if( cfg.psz_fout == NULL || *cfg.psz_fout == '\0' || !strcmp( cfg.psz_fout, "-" ) )
193         fout = stdin;
194     else
195         fout = fopen( cfg.psz_fout, "wb" );
196     if( fout == NULL )
197     {
198         fprintf( stderr, "cannot open output file\n" );
199         return -1;
200     }
201
202     /* Init avi */
203     avi_init( &avi, fout, cfg.f_fps, cfg.fcc );
204
205     /* Init parser */
206     h264_parser_init( &h264 );
207
208     /* Control-C handler */
209     signal( SIGINT, SigIntHandler );
210
211     /* Init data */
212     b_eof = 0;
213     b_key = 0;
214     b_slice = 0;
215     i_frame = 0;
216     i_data  = 0;
217
218     /* Alloc space for a nal, used for decoding pps/sps/slice header */
219     nal.p_payload = malloc( DATA_MAX );
220
221     vbuf_init( &vb );
222
223     /* split frame */
224     while( !i_ctrl_c )
225     {
226         uint8_t *p, *p_next, *end;
227         int i_size;
228
229         /* fill buffer */
230         if( i_data < DATA_MAX && !b_eof )
231         {
232             int i_read = fread( &data[i_data], 1, DATA_MAX - i_data, fin );
233             if( i_read <= 0 )
234                 b_eof = 1;
235             else
236                 i_data += i_read;
237         }
238         if( i_data < 3 )
239             break;
240
241         end = &data[i_data];
242
243         /* Search begin of a NAL */
244         p = &data[0];
245         while( p < end - 3 )
246         {
247             if( p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x01 )
248             {
249                 break;
250             }
251             p++;
252         }
253
254         if( p >= end - 3 )
255         {
256             fprintf( stderr, "garbage (i_data = %d)\n", i_data );
257             i_data = 0;
258             continue;
259         }
260
261         /* Search end of NAL */
262         p_next = p + 3;
263         while( p_next < end - 3 )
264         {
265             if( p_next[0] == 0x00 && p_next[1] == 0x00 && p_next[2] == 0x01 )
266             {
267                 break;
268             }
269             p_next++;
270         }
271
272         if( p_next == end - 3 && i_data < DATA_MAX )
273             p_next = end;
274
275         /* Compute NAL size */
276         i_size = p_next - p - 3;
277         if( i_size <= 0 )
278         {
279             if( b_eof )
280                 break;
281
282             fprintf( stderr, "nal too large (FIXME) ?\n" );
283             i_data = 0;
284             continue;
285         }
286
287         /* Nal start at p+3 with i_size length */
288         nal_decode( &nal, p +3, i_size < 2048 ? i_size : 2048 );
289
290         b_key = h264.b_key;
291
292         if( b_slice && vb.i_data && ( nal.i_type == NAL_SPS || nal.i_type == NAL_PPS ) )
293         {
294             avi_write( &avi, &vb, b_key );
295             vbuf_reset( &vb );
296             b_slice = 0;
297         }
298
299         /* Parse SPS/PPS/Slice */
300         if( ParseNAL( &nal, &avi, &h264, &b_slice ) && vb.i_data > 0 )
301         {
302             avi_write( &avi, &vb, b_key );
303             vbuf_reset( &vb );
304         }
305
306         /* fprintf( stderr, "nal:%d ref:%d\n", nal.i_type, nal.i_ref_idc ); */
307
308         /* Append NAL to buffer */
309         vbuf_add( &vb, i_size + 3, p );
310
311         /* Remove this nal */
312         memmove( &data[0], p_next, end - p_next );
313         i_data -= p_next - &data[0];
314     }
315
316     if( vb.i_data > 0 )
317     {
318         avi_write( &avi, &vb, h264.b_key );
319     }
320
321     avi.i_width  = h264.i_width;
322     avi.i_height = h264.i_height;
323
324     avi_end( &avi );
325
326     /* free mem */
327     free( nal.p_payload );
328
329     fclose( fin );
330     fclose( fout );
331
332     return 0;
333 }
334
335 /*****************************************************************************
336  * Help:
337  *****************************************************************************/
338 static void Help( void )
339 {
340     fprintf( stderr,
341              "avc2avi\n"
342              "Syntax: avc2avi [options] [ -i input.h264 ] [ -o output.avi ]\n"
343              "\n"
344              "  -h, --help                  Print this help\n"
345              "\n"
346              "  -i, --input                 Specify input file (default: stdin)\n"
347              "  -o, --output                Specify output file (default: stdout)\n"
348              "\n"
349              "  -f, --fps <float>           Set FPS (default: 25.0)\n"
350              "  -c, --codec <string>        Set the codec fourcc (default: 'h264')\n"
351              "\n" );
352 }
353
354 /*****************************************************************************
355  * Parse:
356  *****************************************************************************/
357 static int  Parse( int argc, char **argv, cfg_t *cfg )
358 {
359     /* Set default values */
360     cfg->psz_fin = NULL;
361     cfg->psz_fout = NULL;
362     cfg->f_fps = 25.0;
363     memcpy( cfg->fcc, "h264", 4 );
364
365     /* Parse command line options */
366     opterr = 0; // no error message
367     for( ;; )
368     {
369         int long_options_index;
370         static struct option long_options[] =
371         {
372             { "help",   no_argument,       NULL, 'h' },
373             { "input",  required_argument, NULL, 'i' },
374             { "output", required_argument, NULL, 'o' },
375             { "fps",    required_argument, NULL, 'f' },
376             { "codec",  required_argument, NULL, 'c' },
377             {0, 0, 0, 0}
378         };
379
380         int c;
381
382         c = getopt_long( argc, argv, "hi:o:f:c:",
383                          long_options, &long_options_index);
384
385         if( c == -1 )
386         {
387             break;
388         }
389
390         switch( c )
391         {
392             case 'h':
393                 Help();
394                 return -1;
395
396             case 0:
397                 break;
398             case 'i':
399                 cfg->psz_fin = strdup( optarg );
400                 break;
401             case 'o':
402                 cfg->psz_fout = strdup( optarg );
403                 break;
404             case 'f':
405                 cfg->f_fps = atof( optarg );
406                 break;
407             case 'c':
408                 memset( cfg->fcc, ' ', 4 );
409                 memcpy( cfg->fcc, optarg, strlen( optarg ) < 4 ? strlen( optarg ) : 4 );
410                 break;
411
412             default:
413                 fprintf( stderr, "unknown option (%c)\n", optopt );
414                 return -1;
415         }
416     }
417
418
419     return 0;
420 }
421
422 /*****************************************************************************
423  * h264_parser_*:
424  *****************************************************************************/
425 void h264_parser_init( h264_t *h )
426 {
427     h->i_width = 0;
428     h->i_height = 0;
429     h->b_key = 0;
430     h->i_nal_type = -1;
431     h->i_ref_idc = -1;
432     h->i_idr_pic_id = -1;
433     h->i_frame_num = -1;
434     h->i_log2_max_frame_num = 0;
435 }
436 void h264_parser_parse( h264_t *h, nal_t *nal, int *pb_nal_start )
437 {
438     bs_t s;
439     *pb_nal_start = 0;
440
441     if( nal->i_type == NAL_SPS || nal->i_type == NAL_PPS )
442         *pb_nal_start = 1;
443
444     bs_init( &s, nal->p_payload, nal->i_payload );
445     if( nal->i_type == NAL_SPS )
446     {
447         int i_tmp;
448
449         bs_skip( &s, 8 + 1+1+1 + 5 + 8 );
450         /* sps id */
451         bs_read_ue( &s );
452         /* Skip i_log2_max_frame_num */
453         h->i_log2_max_frame_num = bs_read_ue( &s ) + 4;
454         /* Read poc_type */
455         i_tmp = bs_read_ue( &s );
456         if( i_tmp == 0 )
457         {
458             /* skip i_log2_max_poc_lsb */
459             bs_read_ue( &s );
460         }
461         else if( i_tmp == 1 )
462         {
463             int i_cycle;
464             /* skip b_delta_pic_order_always_zero */
465             bs_skip( &s, 1 );
466             /* skip i_offset_for_non_ref_pic */
467             bs_read_se( &s );
468             /* skip i_offset_for_top_to_bottom_field */
469             bs_read_se( &s );
470             /* read i_num_ref_frames_in_poc_cycle */
471             i_cycle = bs_read_ue( &s ); 
472             if( i_cycle > 256 ) i_cycle = 256;
473             while( i_cycle > 0 )
474             {
475                 /* skip i_offset_for_ref_frame */
476                 bs_read_se(&s );
477             }
478         }
479         /* i_num_ref_frames */
480         bs_read_ue( &s );
481         /* b_gaps_in_frame_num_value_allowed */
482         bs_skip( &s, 1 );
483
484         /* Read size */
485         h->i_width  = 16 * ( bs_read_ue( &s ) + 1 );
486         h->i_height = 16 * ( bs_read_ue( &s ) + 1 );
487
488         /* b_frame_mbs_only */
489         i_tmp = bs_read( &s, 1 );
490         if( i_tmp == 0 )
491         {
492             bs_skip( &s, 1 );
493         }
494         /* b_direct8x8_inference */
495         bs_skip( &s, 1 );
496
497         /* crop ? */
498         i_tmp = bs_read( &s, 1 );
499         if( i_tmp )
500         {
501             /* left */
502             h->i_width -= 2 * bs_read_ue( &s );
503             /* right */
504             h->i_width -= 2 * bs_read_ue( &s );
505             /* top */
506             h->i_height -= 2 * bs_read_ue( &s );
507             /* bottom */
508             h->i_height -= 2 * bs_read_ue( &s );
509         }
510
511         /* vui: ignored */
512     }
513     else if( nal->i_type >= NAL_SLICE && nal->i_type <= NAL_SLICE_IDR )
514     {
515         int i_tmp;
516
517         /* i_first_mb */
518         bs_read_ue( &s );
519         /* picture type */
520         switch( bs_read_ue( &s ) )
521         {
522             case 0: case 5: /* P */
523             case 1: case 6: /* B */
524             case 3: case 8: /* SP */
525                 h->b_key = 0;
526                 break;
527             case 2: case 7: /* I */
528                 h->b_key = 1;
529                 break;
530             case 4: case 9: /* ? */
531                 h->b_key = 1;
532                 break;
533         }
534         /* pps id */
535         bs_read_ue( &s );
536
537         /* frame num */
538         i_tmp = bs_read( &s, h->i_log2_max_frame_num );
539
540         if( i_tmp != h->i_frame_num )
541             *pb_nal_start = 1;
542
543         h->i_frame_num = i_tmp;
544
545         if( nal->i_type == NAL_SLICE_IDR )
546         {
547             i_tmp = bs_read_ue( &s );
548             if( h->i_nal_type == NAL_SLICE_IDR && h->i_idr_pic_id != i_tmp )
549                 *pb_nal_start = 1;
550
551             h->i_idr_pic_id = i_tmp;
552         }
553     }
554     h->i_nal_type = nal->i_type;
555     h->i_ref_idc = nal->i_ref_idc;
556 }
557
558
559 static int  ParseNAL( nal_t *nal, avi_t *a, h264_t *h, int *pb_slice )
560 {
561     int b_flush = 0;
562     int b_start;
563
564     h264_parser_parse( h, nal, &b_start );
565
566     if( b_start && *pb_slice )
567     {
568         b_flush = 1;
569         *pb_slice = 0;
570     }
571
572     if( nal->i_type >= NAL_SLICE && nal->i_type <= NAL_SLICE_IDR )
573         *pb_slice = 1;
574
575     return b_flush;
576 }
577
578 /*****************************************************************************
579  * vbuf: variable buffer
580  *****************************************************************************/
581 void vbuf_init( vbuf_t *v )
582 {
583     v->i_data = 0;
584     v->i_data_max = 10000;
585     v->p_data = malloc( v->i_data_max );
586 }
587 void vbuf_add( vbuf_t *v, int i_data, void *p_data )
588 {
589     if( i_data + v->i_data >= v->i_data_max )
590     {
591         v->i_data_max += i_data;
592         v->p_data = realloc( v->p_data, v->i_data_max );
593     }
594     memcpy( &v->p_data[v->i_data], p_data, i_data );
595
596     v->i_data += i_data;
597 }
598 void vbuf_reset( vbuf_t *v )
599 {
600     v->i_data = 0;
601 }
602
603 /*****************************************************************************
604  * avi:
605  *****************************************************************************/
606 void avi_write_uint16( avi_t *a, uint16_t w )
607 {
608     fputc( ( w      ) & 0xff, a->f );
609     fputc( ( w >> 8 ) & 0xff, a->f );
610 }
611
612 void avi_write_uint32( avi_t *a, uint32_t dw )
613 {
614     fputc( ( dw      ) & 0xff, a->f );
615     fputc( ( dw >> 8 ) & 0xff, a->f );
616     fputc( ( dw >> 16) & 0xff, a->f );
617     fputc( ( dw >> 24) & 0xff, a->f );
618 }
619
620 void avi_write_fourcc( avi_t *a, char fcc[4] )
621 {
622     fputc( fcc[0], a->f );
623     fputc( fcc[1], a->f );
624     fputc( fcc[2], a->f );
625     fputc( fcc[3], a->f );
626 }
627
628 /* Flags in avih */
629 #define AVIF_HASINDEX       0x00000010  // Index at end of file?
630 #define AVIF_ISINTERLEAVED  0x00000100
631 #define AVIF_TRUSTCKTYPE    0x00000800  // Use CKType to find key frames?
632
633 #define AVIIF_KEYFRAME      0x00000010L /* this frame is a key frame.*/
634
635 void avi_write_header( avi_t *a )
636 {
637     avi_write_fourcc( a, "RIFF" );
638     avi_write_uint32( a, a->i_riff > 0 ? a->i_riff - 8 : 0xFFFFFFFF );
639     avi_write_fourcc( a, "AVI " );
640
641     avi_write_fourcc( a, "LIST" );
642     avi_write_uint32( a,  4 + 4*16 + 12 + 4*16 + 4*12 );
643     avi_write_fourcc( a, "hdrl" );
644
645     avi_write_fourcc( a, "avih" );
646     avi_write_uint32( a, 4*16 - 8 );
647     avi_write_uint32( a, 1000000 / a->f_fps );
648     avi_write_uint32( a, 0xffffffff );
649     avi_write_uint32( a, 0 );
650     avi_write_uint32( a, AVIF_HASINDEX|AVIF_ISINTERLEAVED|AVIF_TRUSTCKTYPE);
651     avi_write_uint32( a, a->i_frame );
652     avi_write_uint32( a, 0 );
653     avi_write_uint32( a, 1 );
654     avi_write_uint32( a, 1000000 );
655     avi_write_uint32( a, a->i_width );
656     avi_write_uint32( a, a->i_height );
657     avi_write_uint32( a, 0 );
658     avi_write_uint32( a, 0 );
659     avi_write_uint32( a, 0 );
660     avi_write_uint32( a, 0 );
661
662     avi_write_fourcc( a, "LIST" );
663     avi_write_uint32( a,  4 + 4*16 + 4*12 );
664     avi_write_fourcc( a, "strl" );
665
666     avi_write_fourcc( a, "strh" );
667     avi_write_uint32( a,  4*16 - 8 );
668     avi_write_fourcc( a, "vids" );
669     avi_write_fourcc( a, a->fcc );
670     avi_write_uint32( a, 0 );
671     avi_write_uint32( a, 0 );
672     avi_write_uint32( a, 0 );
673     avi_write_uint32( a, 1000 );
674     avi_write_uint32( a, a->f_fps * 1000 );
675     avi_write_uint32( a, 0 );
676     avi_write_uint32( a, a->i_frame );
677     avi_write_uint32( a, 1024*1024 );
678     avi_write_uint32( a, -1 );
679     avi_write_uint32( a, a->i_width * a->i_height );
680     avi_write_uint32( a, 0 );
681     avi_write_uint16( a, a->i_width );
682     avi_write_uint16( a, a->i_height );
683
684     avi_write_fourcc( a, "strf" );
685     avi_write_uint32( a,  4*12 - 8 );
686     avi_write_uint32( a,  4*12 - 8 );
687     avi_write_uint32( a,  a->i_width );
688     avi_write_uint32( a,  a->i_height );
689     avi_write_uint16( a,  1 );
690     avi_write_uint16( a,  24 );
691     avi_write_fourcc( a,  a->fcc );
692     avi_write_uint32( a, a->i_width * a->i_height );
693     avi_write_uint32( a,  0 );
694     avi_write_uint32( a,  0 );
695     avi_write_uint32( a,  0 );
696     avi_write_uint32( a,  0 );
697
698     avi_write_fourcc( a, "LIST" );
699     avi_write_uint32( a,  a->i_movi_end > 0 ? a->i_movi_end - a->i_movi + 4: 0xFFFFFFFF );
700     avi_write_fourcc( a, "movi" );
701 }
702
703 void avi_write_idx( avi_t *a )
704 {
705     avi_write_fourcc( a, "idx1" );
706     avi_write_uint32( a,  a->i_frame * 16 );
707     fwrite( a->idx, a->i_frame * 16, 1, a->f );
708 }
709
710 void avi_init( avi_t *a, FILE *f, float f_fps, char fcc[4] )
711 {
712     a->f = f;
713     a->f_fps = f_fps;
714     memcpy( a->fcc, fcc, 4 );
715     a->i_width = 0;
716     a->i_height = 0;
717     a->i_frame = 0;
718     a->i_movi = 0;
719     a->i_riff = 0;
720     a->i_movi_end = 0;
721     a->i_idx_max = 0;
722     a->idx = NULL;
723
724     avi_write_header( a );
725
726     a->i_movi = ftell( a->f );
727 }
728
729 static void avi_set_dw( void *_p, uint32_t dw )
730 {
731     uint8_t *p = _p;
732
733     p[0] = ( dw      )&0xff;
734     p[1] = ( dw >> 8 )&0xff;
735     p[2] = ( dw >> 16)&0xff;
736     p[3] = ( dw >> 24)&0xff;
737 }
738
739 void avi_write( avi_t *a, vbuf_t *v, int b_key )
740 {
741     int64_t i_pos = ftell( a->f );
742
743     /* chunk header */
744     avi_write_fourcc( a, "00dc" );
745     avi_write_uint32( a, v->i_data );
746
747     fwrite( v->p_data, v->i_data, 1, a->f );
748
749     if( v->i_data&0x01 )
750     {
751         /* pad */
752         fputc( 0, a->f );
753     }
754
755     /* Append idx chunk */
756     if( a->i_idx_max <= a->i_frame )
757     {
758         a->i_idx_max += 1000;
759         a->idx = realloc( a->idx, a->i_idx_max * 16 );
760     }
761
762     memcpy( &a->idx[4*a->i_frame+0], "00dc", 4 );
763     avi_set_dw( &a->idx[4*a->i_frame+1], b_key ? AVIIF_KEYFRAME : 0 );
764     avi_set_dw( &a->idx[4*a->i_frame+2], i_pos );
765     avi_set_dw( &a->idx[4*a->i_frame+3], v->i_data );
766
767     a->i_frame++;
768 }
769
770 void avi_end( avi_t *a )
771 {
772     a->i_movi_end = ftell( a->f );
773
774     /* write index */
775     avi_write_idx( a );
776
777     a->i_riff = ftell( a->f );
778
779     /* Fix header */
780     fseek( a->f, 0, SEEK_SET );
781     avi_write_header( a );
782
783     fprintf( stderr, "avi file written\n" );
784     fprintf( stderr, "  - codec: %4.4s\n", a->fcc );
785     fprintf( stderr, "  - size: %dx%d\n", a->i_width, a->i_height );
786     fprintf( stderr, "  - fps: %.3f\n", a->f_fps );
787     fprintf( stderr, "  - frames: %d\n", a->i_frame );
788 }
789
790 /*****************************************************************************
791  * nal:
792  *****************************************************************************/
793 int nal_decode( nal_t *nal, void *p_data, int i_data )
794 {
795     uint8_t *src = p_data;
796     uint8_t *end = &src[i_data];
797     uint8_t *dst = nal->p_payload;
798
799     nal->i_type    = src[0]&0x1f;
800     nal->i_ref_idc = (src[0] >> 5)&0x03;
801
802     src++;
803
804     while( src < end )
805     {
806         if( src < end - 3 && src[0] == 0x00 && src[1] == 0x00  && src[2] == 0x03 )
807         {
808             *dst++ = 0x00;
809             *dst++ = 0x00;
810
811             src += 3;
812             continue;
813         }
814         *dst++ = *src++;
815     }
816
817     nal->i_payload = dst - (uint8_t*)p_data;
818     return 0;
819 }
820