]> git.sesse.net Git - x264/blob - tools/avc2avi.c
Update file headers throughout x264
[x264] / tools / avc2avi.c
1 /*****************************************************************************
2  * avc2avi.c: raw h264 -> AVI
3  *****************************************************************************
4  * Copyright (C) 2004-2006 x264 project
5  *
6  * Authors: Laurent Aimar <fenrir@via.ecp.fr>
7  *          Loren Merritt <lorenm@u.washington.edu>
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., 51 Franklin Street, Fifth Floor, 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     int i_poc;
134
135     int b_key;
136     int i_log2_max_frame_num;
137     int i_poc_type;
138     int i_log2_max_poc_lsb;
139 } h264_t;
140
141 void h264_parser_init( h264_t * );
142 void h264_parser_parse( h264_t *h, nal_t *n, int *pb_nal_start );
143
144
145 static int nal_decode( nal_t *nal, void *p_data, int i_data );
146
147 static void Help( void );
148 static int  Parse( int argc, char **argv, cfg_t * );
149 static int  ParseNAL( nal_t *nal, avi_t *a, h264_t *h, int *pb_slice );
150
151 /****************************************************************************
152  * main:
153  ****************************************************************************/
154 int main( int argc, char **argv )
155 {
156     cfg_t cfg;
157
158     FILE    *fout;
159     FILE    *fin;
160
161     vbuf_t  vb;
162     avi_t   avi;
163     h264_t  h264;
164
165     nal_t nal;
166     int i_frame;
167     int i_data;
168     int b_eof;
169     int b_key;
170     int b_slice;
171
172 #ifdef _MSC_VER
173     _setmode(_fileno(stdin), _O_BINARY);    /* thanks to Marcos Morais <morais at dee.ufcg.edu.br> */
174     _setmode(_fileno(stdout), _O_BINARY);
175 #endif
176
177     /* Parse command line */
178     if( Parse( argc, argv, &cfg ) < 0 )
179     {
180         return -1;
181     }
182
183     /* Open input */
184     if( cfg.psz_fin == NULL || *cfg.psz_fin == '\0' || !strcmp( cfg.psz_fin, "-" ) )
185         fin = stdin;
186     else
187         fin = fopen( cfg.psz_fin, "rb" );
188     if( fin == NULL )
189     {
190         fprintf( stderr, "cannot open input file\n" );
191         return -1;
192     }
193
194     /* Open output */
195     if( cfg.psz_fout == NULL || *cfg.psz_fout == '\0' || !strcmp( cfg.psz_fout, "-" ) )
196         fout = stdin;
197     else
198         fout = fopen( cfg.psz_fout, "wb" );
199     if( fout == NULL )
200     {
201         fprintf( stderr, "cannot open output file\n" );
202         return -1;
203     }
204
205     /* Init avi */
206     avi_init( &avi, fout, cfg.f_fps, cfg.fcc );
207
208     /* Init parser */
209     h264_parser_init( &h264 );
210
211     /* Control-C handler */
212     signal( SIGINT, SigIntHandler );
213
214     /* Init data */
215     b_eof = 0;
216     b_key = 0;
217     b_slice = 0;
218     i_frame = 0;
219     i_data  = 0;
220
221     /* Alloc space for a nal, used for decoding pps/sps/slice header */
222     nal.p_payload = malloc( DATA_MAX );
223
224     vbuf_init( &vb );
225
226     /* split frame */
227     while( !i_ctrl_c )
228     {
229         uint8_t *p, *p_next, *end;
230         int i_size;
231
232         /* fill buffer */
233         if( i_data < DATA_MAX && !b_eof )
234         {
235             int i_read = fread( &data[i_data], 1, DATA_MAX - i_data, fin );
236             if( i_read <= 0 )
237                 b_eof = 1;
238             else
239                 i_data += i_read;
240         }
241         if( i_data < 3 )
242             break;
243
244         end = &data[i_data];
245
246         /* Search begin of a NAL */
247         p = &data[0];
248         while( p < end - 3 )
249         {
250             if( p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x01 )
251             {
252                 break;
253             }
254             p++;
255         }
256
257         if( p >= end - 3 )
258         {
259             fprintf( stderr, "garbage (i_data = %d)\n", i_data );
260             i_data = 0;
261             continue;
262         }
263
264         /* Search end of NAL */
265         p_next = p + 3;
266         while( p_next < end - 3 )
267         {
268             if( p_next[0] == 0x00 && p_next[1] == 0x00 && p_next[2] == 0x01 )
269             {
270                 break;
271             }
272             p_next++;
273         }
274
275         if( p_next == end - 3 && i_data < DATA_MAX )
276             p_next = end;
277
278         /* Compute NAL size */
279         i_size = p_next - p - 3;
280         if( i_size <= 0 )
281         {
282             if( b_eof )
283                 break;
284
285             fprintf( stderr, "nal too large (FIXME) ?\n" );
286             i_data = 0;
287             continue;
288         }
289
290         /* Nal start at p+3 with i_size length */
291         nal_decode( &nal, p +3, i_size < 2048 ? i_size : 2048 );
292
293         b_key = h264.b_key;
294
295         if( b_slice && vb.i_data && ( nal.i_type == NAL_SPS || nal.i_type == NAL_PPS ) )
296         {
297             avi_write( &avi, &vb, b_key );
298             vbuf_reset( &vb );
299             b_slice = 0;
300         }
301
302         /* Parse SPS/PPS/Slice */
303         if( ParseNAL( &nal, &avi, &h264, &b_slice ) && vb.i_data > 0 )
304         {
305             avi_write( &avi, &vb, b_key );
306             vbuf_reset( &vb );
307         }
308
309         /* fprintf( stderr, "nal:%d ref:%d\n", nal.i_type, nal.i_ref_idc ); */
310
311         /* Append NAL to buffer */
312         vbuf_add( &vb, i_size + 3, p );
313
314         /* Remove this nal */
315         memmove( &data[0], p_next, end - p_next );
316         i_data -= p_next - &data[0];
317     }
318
319     if( vb.i_data > 0 )
320     {
321         avi_write( &avi, &vb, h264.b_key );
322     }
323
324     avi.i_width  = h264.i_width;
325     avi.i_height = h264.i_height;
326
327     avi_end( &avi );
328
329     /* free mem */
330     free( nal.p_payload );
331
332     fclose( fin );
333     fclose( fout );
334
335     return 0;
336 }
337
338 /*****************************************************************************
339  * Help:
340  *****************************************************************************/
341 static void Help( void )
342 {
343     fprintf( stderr,
344              "avc2avi\n"
345              "Syntax: avc2avi [options] [ -i input.h264 ] [ -o output.avi ]\n"
346              "\n"
347              "  -h, --help                  Print this help\n"
348              "\n"
349              "  -i, --input                 Specify input file (default: stdin)\n"
350              "  -o, --output                Specify output file (default: stdout)\n"
351              "\n"
352              "  -f, --fps <float>           Set FPS (default: 25.0)\n"
353              "  -c, --codec <string>        Set the codec fourcc (default: 'h264')\n"
354              "\n" );
355 }
356
357 /*****************************************************************************
358  * Parse:
359  *****************************************************************************/
360 static int  Parse( int argc, char **argv, cfg_t *cfg )
361 {
362     /* Set default values */
363     cfg->psz_fin = NULL;
364     cfg->psz_fout = NULL;
365     cfg->f_fps = 25.0;
366     memcpy( cfg->fcc, "h264", 4 );
367
368     /* Parse command line options */
369     opterr = 0; // no error message
370     for( ;; )
371     {
372         int long_options_index;
373         static struct option long_options[] =
374         {
375             { "help",   no_argument,       NULL, 'h' },
376             { "input",  required_argument, NULL, 'i' },
377             { "output", required_argument, NULL, 'o' },
378             { "fps",    required_argument, NULL, 'f' },
379             { "codec",  required_argument, NULL, 'c' },
380             {0, 0, 0, 0}
381         };
382
383         int c;
384
385         c = getopt_long( argc, argv, "hi:o:f:c:",
386                          long_options, &long_options_index);
387
388         if( c == -1 )
389         {
390             break;
391         }
392
393         switch( c )
394         {
395             case 'h':
396                 Help();
397                 return -1;
398
399             case 0:
400                 break;
401             case 'i':
402                 cfg->psz_fin = strdup( optarg );
403                 break;
404             case 'o':
405                 cfg->psz_fout = strdup( optarg );
406                 break;
407             case 'f':
408                 cfg->f_fps = atof( optarg );
409                 break;
410             case 'c':
411                 memset( cfg->fcc, ' ', 4 );
412                 memcpy( cfg->fcc, optarg, strlen( optarg ) < 4 ? strlen( optarg ) : 4 );
413                 break;
414
415             default:
416                 fprintf( stderr, "unknown option (%c)\n", optopt );
417                 return -1;
418         }
419     }
420
421
422     return 0;
423 }
424
425 /*****************************************************************************
426  * h264_parser_*:
427  *****************************************************************************/
428 void h264_parser_init( h264_t *h )
429 {
430     h->i_width = 0;
431     h->i_height = 0;
432     h->b_key = 0;
433     h->i_nal_type = -1;
434     h->i_ref_idc = -1;
435     h->i_idr_pic_id = -1;
436     h->i_frame_num = -1;
437     h->i_log2_max_frame_num = 0;
438     h->i_poc = -1;
439     h->i_poc_type = -1;
440 }
441 void h264_parser_parse( h264_t *h, nal_t *nal, int *pb_nal_start )
442 {
443     bs_t s;
444     *pb_nal_start = 0;
445
446     if( nal->i_type == NAL_SPS || nal->i_type == NAL_PPS )
447         *pb_nal_start = 1;
448
449     bs_init( &s, nal->p_payload, nal->i_payload );
450     if( nal->i_type == NAL_SPS )
451     {
452         int i_tmp;
453
454         i_tmp = bs_read( &s, 8 );
455         bs_skip( &s, 1+1+1 + 5 + 8 );
456         /* sps id */
457         bs_read_ue( &s );
458
459         if( i_tmp >= 100 )
460         {
461             bs_read_ue( &s ); // chroma_format_idc
462             bs_read_ue( &s ); // bit_depth_luma_minus8
463             bs_read_ue( &s ); // bit_depth_chroma_minus8
464             bs_skip( &s, 1 ); // qpprime_y_zero_transform_bypass_flag
465             if( bs_read( &s, 1 ) ) // seq_scaling_matrix_present_flag
466             {
467                 int i, j;
468                 for( i = 0; i < 8; i++ )
469                 {
470                     if( bs_read( &s, 1 ) ) // seq_scaling_list_present_flag[i]
471                     {
472                         uint8_t i_tmp = 8;
473                         for( j = 0; j < (i<6?16:64); j++ )
474                         {
475                             i_tmp += bs_read_se( &s );
476                             if( i_tmp == 0 )
477                                 break;
478                         }
479                     }
480                 }
481             }
482         }
483
484         /* Skip i_log2_max_frame_num */
485         h->i_log2_max_frame_num = bs_read_ue( &s ) + 4;
486         /* Read poc_type */
487         h->i_poc_type = bs_read_ue( &s );
488         if( h->i_poc_type == 0 )
489         {
490             h->i_log2_max_poc_lsb = bs_read_ue( &s ) + 4;
491         }
492         else if( h->i_poc_type == 1 )
493         {
494             int i_cycle;
495             /* skip b_delta_pic_order_always_zero */
496             bs_skip( &s, 1 );
497             /* skip i_offset_for_non_ref_pic */
498             bs_read_se( &s );
499             /* skip i_offset_for_top_to_bottom_field */
500             bs_read_se( &s );
501             /* read i_num_ref_frames_in_poc_cycle */
502             i_cycle = bs_read_ue( &s ); 
503             if( i_cycle > 256 ) i_cycle = 256;
504             while( i_cycle > 0 )
505             {
506                 /* skip i_offset_for_ref_frame */
507                 bs_read_se(&s );
508             }
509         }
510         /* i_num_ref_frames */
511         bs_read_ue( &s );
512         /* b_gaps_in_frame_num_value_allowed */
513         bs_skip( &s, 1 );
514
515         /* Read size */
516         h->i_width  = 16 * ( bs_read_ue( &s ) + 1 );
517         h->i_height = 16 * ( bs_read_ue( &s ) + 1 );
518
519         /* b_frame_mbs_only */
520         i_tmp = bs_read( &s, 1 );
521         if( i_tmp == 0 )
522         {
523             bs_skip( &s, 1 );
524         }
525         /* b_direct8x8_inference */
526         bs_skip( &s, 1 );
527
528         /* crop ? */
529         i_tmp = bs_read( &s, 1 );
530         if( i_tmp )
531         {
532             /* left */
533             h->i_width -= 2 * bs_read_ue( &s );
534             /* right */
535             h->i_width -= 2 * bs_read_ue( &s );
536             /* top */
537             h->i_height -= 2 * bs_read_ue( &s );
538             /* bottom */
539             h->i_height -= 2 * bs_read_ue( &s );
540         }
541
542         /* vui: ignored */
543     }
544     else if( nal->i_type >= NAL_SLICE && nal->i_type <= NAL_SLICE_IDR )
545     {
546         int i_tmp;
547
548         /* i_first_mb */
549         bs_read_ue( &s );
550         /* picture type */
551         switch( bs_read_ue( &s ) )
552         {
553             case 0: case 5: /* P */
554             case 1: case 6: /* B */
555             case 3: case 8: /* SP */
556                 h->b_key = 0;
557                 break;
558             case 2: case 7: /* I */
559             case 4: case 9: /* SI */
560                 h->b_key = (nal->i_type == NAL_SLICE_IDR);
561                 break;
562         }
563         /* pps id */
564         bs_read_ue( &s );
565
566         /* frame num */
567         i_tmp = bs_read( &s, h->i_log2_max_frame_num );
568
569         if( i_tmp != h->i_frame_num )
570             *pb_nal_start = 1;
571
572         h->i_frame_num = i_tmp;
573
574         if( nal->i_type == NAL_SLICE_IDR )
575         {
576             i_tmp = bs_read_ue( &s );
577             if( h->i_nal_type == NAL_SLICE_IDR && h->i_idr_pic_id != i_tmp )
578                 *pb_nal_start = 1;
579
580             h->i_idr_pic_id = i_tmp;
581         }
582
583         if( h->i_poc_type == 0 )
584         {
585             i_tmp = bs_read( &s, h->i_log2_max_poc_lsb );
586             if( i_tmp != h->i_poc )
587                 *pb_nal_start = 1;
588             h->i_poc = i_tmp;
589         }
590     }
591     h->i_nal_type = nal->i_type;
592     h->i_ref_idc = nal->i_ref_idc;
593 }
594
595
596 static int  ParseNAL( nal_t *nal, avi_t *a, h264_t *h, int *pb_slice )
597 {
598     int b_flush = 0;
599     int b_start;
600
601     h264_parser_parse( h, nal, &b_start );
602
603     if( b_start && *pb_slice )
604     {
605         b_flush = 1;
606         *pb_slice = 0;
607     }
608
609     if( nal->i_type >= NAL_SLICE && nal->i_type <= NAL_SLICE_IDR )
610         *pb_slice = 1;
611
612     return b_flush;
613 }
614
615 /*****************************************************************************
616  * vbuf: variable buffer
617  *****************************************************************************/
618 void vbuf_init( vbuf_t *v )
619 {
620     v->i_data = 0;
621     v->i_data_max = 10000;
622     v->p_data = malloc( v->i_data_max );
623 }
624 void vbuf_add( vbuf_t *v, int i_data, void *p_data )
625 {
626     if( i_data + v->i_data >= v->i_data_max )
627     {
628         v->i_data_max += i_data;
629         v->p_data = realloc( v->p_data, v->i_data_max );
630     }
631     memcpy( &v->p_data[v->i_data], p_data, i_data );
632
633     v->i_data += i_data;
634 }
635 void vbuf_reset( vbuf_t *v )
636 {
637     v->i_data = 0;
638 }
639
640 /*****************************************************************************
641  * avi:
642  *****************************************************************************/
643 void avi_write_uint16( avi_t *a, uint16_t w )
644 {
645     fputc( ( w      ) & 0xff, a->f );
646     fputc( ( w >> 8 ) & 0xff, a->f );
647 }
648
649 void avi_write_uint32( avi_t *a, uint32_t dw )
650 {
651     fputc( ( dw      ) & 0xff, a->f );
652     fputc( ( dw >> 8 ) & 0xff, a->f );
653     fputc( ( dw >> 16) & 0xff, a->f );
654     fputc( ( dw >> 24) & 0xff, a->f );
655 }
656
657 void avi_write_fourcc( avi_t *a, char fcc[4] )
658 {
659     fputc( fcc[0], a->f );
660     fputc( fcc[1], a->f );
661     fputc( fcc[2], a->f );
662     fputc( fcc[3], a->f );
663 }
664
665 /* Flags in avih */
666 #define AVIF_HASINDEX       0x00000010  // Index at end of file?
667 #define AVIF_ISINTERLEAVED  0x00000100
668 #define AVIF_TRUSTCKTYPE    0x00000800  // Use CKType to find key frames?
669
670 #define AVIIF_KEYFRAME      0x00000010L /* this frame is a key frame.*/
671
672 void avi_write_header( avi_t *a )
673 {
674     avi_write_fourcc( a, "RIFF" );
675     avi_write_uint32( a, a->i_riff > 0 ? a->i_riff - 8 : 0xFFFFFFFF );
676     avi_write_fourcc( a, "AVI " );
677
678     avi_write_fourcc( a, "LIST" );
679     avi_write_uint32( a,  4 + 4*16 + 12 + 4*16 + 4*12 );
680     avi_write_fourcc( a, "hdrl" );
681
682     avi_write_fourcc( a, "avih" );
683     avi_write_uint32( a, 4*16 - 8 );
684     avi_write_uint32( a, 1000000 / a->f_fps );
685     avi_write_uint32( a, 0xffffffff );
686     avi_write_uint32( a, 0 );
687     avi_write_uint32( a, AVIF_HASINDEX|AVIF_ISINTERLEAVED|AVIF_TRUSTCKTYPE);
688     avi_write_uint32( a, a->i_frame );
689     avi_write_uint32( a, 0 );
690     avi_write_uint32( a, 1 );
691     avi_write_uint32( a, 1000000 );
692     avi_write_uint32( a, a->i_width );
693     avi_write_uint32( a, a->i_height );
694     avi_write_uint32( a, 0 );
695     avi_write_uint32( a, 0 );
696     avi_write_uint32( a, 0 );
697     avi_write_uint32( a, 0 );
698
699     avi_write_fourcc( a, "LIST" );
700     avi_write_uint32( a,  4 + 4*16 + 4*12 );
701     avi_write_fourcc( a, "strl" );
702
703     avi_write_fourcc( a, "strh" );
704     avi_write_uint32( a,  4*16 - 8 );
705     avi_write_fourcc( a, "vids" );
706     avi_write_fourcc( a, a->fcc );
707     avi_write_uint32( a, 0 );
708     avi_write_uint32( a, 0 );
709     avi_write_uint32( a, 0 );
710     avi_write_uint32( a, 1000 );
711     avi_write_uint32( a, a->f_fps * 1000 );
712     avi_write_uint32( a, 0 );
713     avi_write_uint32( a, a->i_frame );
714     avi_write_uint32( a, 1024*1024 );
715     avi_write_uint32( a, -1 );
716     avi_write_uint32( a, a->i_width * a->i_height );
717     avi_write_uint32( a, 0 );
718     avi_write_uint16( a, a->i_width );
719     avi_write_uint16( a, a->i_height );
720
721     avi_write_fourcc( a, "strf" );
722     avi_write_uint32( a,  4*12 - 8 );
723     avi_write_uint32( a,  4*12 - 8 );
724     avi_write_uint32( a,  a->i_width );
725     avi_write_uint32( a,  a->i_height );
726     avi_write_uint16( a,  1 );
727     avi_write_uint16( a,  24 );
728     avi_write_fourcc( a,  a->fcc );
729     avi_write_uint32( a, a->i_width * a->i_height );
730     avi_write_uint32( a,  0 );
731     avi_write_uint32( a,  0 );
732     avi_write_uint32( a,  0 );
733     avi_write_uint32( a,  0 );
734
735     avi_write_fourcc( a, "LIST" );
736     avi_write_uint32( a,  a->i_movi_end > 0 ? a->i_movi_end - a->i_movi + 4: 0xFFFFFFFF );
737     avi_write_fourcc( a, "movi" );
738 }
739
740 void avi_write_idx( avi_t *a )
741 {
742     avi_write_fourcc( a, "idx1" );
743     avi_write_uint32( a,  a->i_frame * 16 );
744     fwrite( a->idx, a->i_frame * 16, 1, a->f );
745 }
746
747 void avi_init( avi_t *a, FILE *f, float f_fps, char fcc[4] )
748 {
749     a->f = f;
750     a->f_fps = f_fps;
751     memcpy( a->fcc, fcc, 4 );
752     a->i_width = 0;
753     a->i_height = 0;
754     a->i_frame = 0;
755     a->i_movi = 0;
756     a->i_riff = 0;
757     a->i_movi_end = 0;
758     a->i_idx_max = 0;
759     a->idx = NULL;
760
761     avi_write_header( a );
762
763     a->i_movi = ftell( a->f );
764 }
765
766 static void avi_set_dw( void *_p, uint32_t dw )
767 {
768     uint8_t *p = _p;
769
770     p[0] = ( dw      )&0xff;
771     p[1] = ( dw >> 8 )&0xff;
772     p[2] = ( dw >> 16)&0xff;
773     p[3] = ( dw >> 24)&0xff;
774 }
775
776 void avi_write( avi_t *a, vbuf_t *v, int b_key )
777 {
778     int64_t i_pos = ftell( a->f );
779
780     /* chunk header */
781     avi_write_fourcc( a, "00dc" );
782     avi_write_uint32( a, v->i_data );
783
784     fwrite( v->p_data, v->i_data, 1, a->f );
785
786     if( v->i_data&0x01 )
787     {
788         /* pad */
789         fputc( 0, a->f );
790     }
791
792     /* Append idx chunk */
793     if( a->i_idx_max <= a->i_frame )
794     {
795         a->i_idx_max += 1000;
796         a->idx = realloc( a->idx, a->i_idx_max * 16 );
797     }
798
799     memcpy( &a->idx[4*a->i_frame+0], "00dc", 4 );
800     avi_set_dw( &a->idx[4*a->i_frame+1], b_key ? AVIIF_KEYFRAME : 0 );
801     avi_set_dw( &a->idx[4*a->i_frame+2], i_pos );
802     avi_set_dw( &a->idx[4*a->i_frame+3], v->i_data );
803
804     a->i_frame++;
805 }
806
807 void avi_end( avi_t *a )
808 {
809     a->i_movi_end = ftell( a->f );
810
811     /* write index */
812     avi_write_idx( a );
813
814     a->i_riff = ftell( a->f );
815
816     /* Fix header */
817     fseek( a->f, 0, SEEK_SET );
818     avi_write_header( a );
819
820     fprintf( stderr, "avi file written\n" );
821     fprintf( stderr, "  - codec: %4.4s\n", a->fcc );
822     fprintf( stderr, "  - size: %dx%d\n", a->i_width, a->i_height );
823     fprintf( stderr, "  - fps: %.3f\n", a->f_fps );
824     fprintf( stderr, "  - frames: %d\n", a->i_frame );
825 }
826
827 /*****************************************************************************
828  * nal:
829  *****************************************************************************/
830 int nal_decode( nal_t *nal, void *p_data, int i_data )
831 {
832     uint8_t *src = p_data;
833     uint8_t *end = &src[i_data];
834     uint8_t *dst = nal->p_payload;
835
836     nal->i_type    = src[0]&0x1f;
837     nal->i_ref_idc = (src[0] >> 5)&0x03;
838
839     src++;
840
841     while( src < end )
842     {
843         if( src < end - 3 && src[0] == 0x00 && src[1] == 0x00  && src[2] == 0x03 )
844         {
845             *dst++ = 0x00;
846             *dst++ = 0x00;
847
848             src += 3;
849             continue;
850         }
851         *dst++ = *src++;
852     }
853
854     nal->i_payload = dst - (uint8_t*)nal->p_payload;
855     return 0;
856 }
857