avc2avi.c
上传用户:hjq518
上传日期:2021-12-09
资源大小:5084k
文件大小:22k
源码类别:

Audio

开发平台:

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